@mengine/medeo-client 1.2.1-alpha.1 → 1.2.1-alpha.11
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.
|
@@ -87,8 +87,7 @@ function jsonTransform() {
|
|
|
87
87
|
const trackItem = schema.LoroMap({
|
|
88
88
|
part_id: schema.String(),
|
|
89
89
|
time_position: schema.String().transform(jsonTransform()),
|
|
90
|
-
fallback_abs_ms: schema.Number({ required: false })
|
|
91
|
-
duration_override_ms: schema.Number({ required: false })
|
|
90
|
+
fallback_abs_ms: schema.Number({ required: false })
|
|
92
91
|
});
|
|
93
92
|
const track = schema.LoroMap({
|
|
94
93
|
id: schema.String(),
|
|
@@ -774,8 +773,7 @@ const trackItemTimePositionSchema = z.discriminatedUnion("mode", [
|
|
|
774
773
|
const trackItemSchema = z.object({
|
|
775
774
|
part_id: z.string(),
|
|
776
775
|
time_position: trackItemTimePositionSchema,
|
|
777
|
-
fallback_abs_ms: finiteNumber.optional()
|
|
778
|
-
duration_override_ms: z.number().finite().positive().optional()
|
|
776
|
+
fallback_abs_ms: finiteNumber.optional()
|
|
779
777
|
}).passthrough();
|
|
780
778
|
const trackSchema = z.object({
|
|
781
779
|
id: z.string().optional(),
|
|
@@ -1328,7 +1326,7 @@ function fromVideoDocument(document) {
|
|
|
1328
1326
|
above_main_tracks: aboveTracks.map((t) => draftTrack(t, view.absByPartId)),
|
|
1329
1327
|
below_main_tracks: belowTracks.map((t) => draftTrack(t, view.absByPartId)),
|
|
1330
1328
|
part_aggregations: view.aggregations,
|
|
1331
|
-
part_library: toReadViewPartLibrary(view.partLibrary, view.durationMs, view.derivedFillerPartIds
|
|
1329
|
+
part_library: toReadViewPartLibrary(view.partLibrary, view.durationMs, view.derivedFillerPartIds),
|
|
1332
1330
|
version: document.meta.version
|
|
1333
1331
|
};
|
|
1334
1332
|
}
|
|
@@ -1349,7 +1347,7 @@ function fromVideoDocument(document) {
|
|
|
1349
1347
|
* and they are not part of the document (see `fromVideoDocument`). An empty clip a
|
|
1350
1348
|
* writer placed deliberately is NOT in that set and is projected normally.
|
|
1351
1349
|
*/
|
|
1352
|
-
function toReadViewPartLibrary(partLibrary, durationMs, derivedFillerPartIds
|
|
1350
|
+
function toReadViewPartLibrary(partLibrary, durationMs, derivedFillerPartIds) {
|
|
1353
1351
|
const out = {};
|
|
1354
1352
|
for (const [partId, part] of Object.entries(partLibrary)) {
|
|
1355
1353
|
if (derivedFillerPartIds.has(partId)) continue;
|
|
@@ -1369,7 +1367,7 @@ function toReadViewPartLibrary(partLibrary, durationMs, derivedFillerPartIds, ca
|
|
|
1369
1367
|
const caption = clone(part.caption);
|
|
1370
1368
|
out[partId] = { caption: {
|
|
1371
1369
|
...caption,
|
|
1372
|
-
duration_ms:
|
|
1370
|
+
duration_ms: caption.initial_duration_ms
|
|
1373
1371
|
} };
|
|
1374
1372
|
} else if (part.bgm != null) out[partId] = { bgm: {
|
|
1375
1373
|
...clone(part.bgm),
|
|
@@ -1378,14 +1376,6 @@ function toReadViewPartLibrary(partLibrary, durationMs, derivedFillerPartIds, ca
|
|
|
1378
1376
|
}
|
|
1379
1377
|
return out;
|
|
1380
1378
|
}
|
|
1381
|
-
function captionDurationOverrides(document) {
|
|
1382
|
-
const result = /* @__PURE__ */ new Map();
|
|
1383
|
-
for (const track of document.tracks ?? []) {
|
|
1384
|
-
if (track.parts_kind !== "caption") continue;
|
|
1385
|
-
for (const item of track.items ?? []) if (item.duration_override_ms != null) result.set(item.part_id, item.duration_override_ms);
|
|
1386
|
-
}
|
|
1387
|
-
return result;
|
|
1388
|
-
}
|
|
1389
1379
|
/** Deep-clone a part payload, dropping the derived read-view `duration_ms`. */
|
|
1390
1380
|
function omitDurationMs(part) {
|
|
1391
1381
|
const { duration_ms: _drop, ...rest } = clone(part);
|
|
@@ -1548,7 +1538,6 @@ function rowToTrack(row) {
|
|
|
1548
1538
|
time_position: item.time_position
|
|
1549
1539
|
};
|
|
1550
1540
|
if (item.fallback_abs_ms != null) result.fallback_abs_ms = item.fallback_abs_ms;
|
|
1551
|
-
if (item.duration_override_ms != null) result.duration_override_ms = item.duration_override_ms;
|
|
1552
1541
|
return result;
|
|
1553
1542
|
})
|
|
1554
1543
|
};
|
|
@@ -1657,8 +1646,7 @@ function toTrackRow(track) {
|
|
|
1657
1646
|
items: (track.items ?? []).map((item) => ({
|
|
1658
1647
|
part_id: item.part_id,
|
|
1659
1648
|
time_position: item.time_position,
|
|
1660
|
-
fallback_abs_ms: item.fallback_abs_ms
|
|
1661
|
-
duration_override_ms: item.duration_override_ms
|
|
1649
|
+
fallback_abs_ms: item.fallback_abs_ms
|
|
1662
1650
|
}))
|
|
1663
1651
|
};
|
|
1664
1652
|
}
|
|
@@ -545,8 +545,6 @@ interface TrackItem {
|
|
|
545
545
|
part_id: string;
|
|
546
546
|
time_position: TrackItemTimePosition;
|
|
547
547
|
fallback_abs_ms?: number | undefined;
|
|
548
|
-
/** Presentation window for this placement; currently used by caption resize. */
|
|
549
|
-
duration_override_ms?: number | undefined;
|
|
550
548
|
}
|
|
551
549
|
interface Track {
|
|
552
550
|
id: string | undefined;
|
|
@@ -1322,14 +1320,6 @@ declare const replaceVideoClipSequenceInputSchema: z.ZodObject<{
|
|
|
1322
1320
|
}, z.core.$strip>;
|
|
1323
1321
|
type ReplaceVideoClipSequenceInput = z.infer<typeof replaceVideoClipSequenceInputSchema>;
|
|
1324
1322
|
//#endregion
|
|
1325
|
-
//#region src/editor/schemas/resize-caption.d.ts
|
|
1326
|
-
/** Resize one caption placement without changing its cue/source duration. */
|
|
1327
|
-
declare const resizeCaptionInputSchema: z.ZodObject<{
|
|
1328
|
-
caption_id: z.ZodString;
|
|
1329
|
-
duration_ms: z.ZodNumber;
|
|
1330
|
-
}, z.core.$strip>;
|
|
1331
|
-
type ResizeCaptionInput = z.infer<typeof resizeCaptionInputSchema>;
|
|
1332
|
-
//#endregion
|
|
1333
1323
|
//#region src/editor/schemas/set-bgm.d.ts
|
|
1334
1324
|
/**
|
|
1335
1325
|
* Set the document BGM. The media's stable result (storage key) arrives
|
|
@@ -1548,7 +1538,7 @@ type SpeechAsset = z.infer<typeof speechAssetSchema>;
|
|
|
1548
1538
|
type CaptionAsset = z.infer<typeof captionAssetSchema>;
|
|
1549
1539
|
type SpeechAssets = z.infer<typeof speechAssetsSchema>;
|
|
1550
1540
|
declare namespace index_d_exports {
|
|
1551
|
-
export { AddSpeechesInput, AddVideoClipsInput, AdjustBgmVolumeInput, AdjustSpeechVolumeInput, AdjustVideoClipDurationInput, AdjustVideoClipVolumeInput, AnchoredDeletePolicy, AnchoredReplacePolicy, CaptionAsset, ChangeSpeechScriptInput, ChangeSpeechVoiceInput, DeleteBgmInput, DeleteSpeechesInput, DeleteVideoClipsInput, MoveAnchor, MoveSpeechesInput, MoveVideoClipsByAnchorInput, MoveVideoClipsInput, MovedClipAnchoredPolicy, ReplaceVideoClipContentInput, ReplaceVideoClipSequenceInput,
|
|
1541
|
+
export { AddSpeechesInput, AddVideoClipsInput, AdjustBgmVolumeInput, AdjustSpeechVolumeInput, AdjustVideoClipDurationInput, AdjustVideoClipVolumeInput, AnchoredDeletePolicy, AnchoredReplacePolicy, CaptionAsset, ChangeSpeechScriptInput, ChangeSpeechVoiceInput, DeleteBgmInput, DeleteSpeechesInput, DeleteVideoClipsInput, MoveAnchor, MoveSpeechesInput, MoveVideoClipsByAnchorInput, MoveVideoClipsInput, MovedClipAnchoredPolicy, ReplaceVideoClipContentInput, ReplaceVideoClipSequenceInput, SetBgmInput, SetCaptionStyleInput, SetCaptionVisibilityInput, SetVideoClipSpeedShiftInput, SpeechAsset, SpeechAssets, addSpeechesInputSchema, addVideoClipsInputSchema, adjustBgmVolumeInputSchema, adjustSpeechVolumeInputSchema, adjustVideoClipDurationInputSchema, adjustVideoClipVolumeInputSchema, anchoredDeletePolicySchema, anchoredReplacePolicySchema, changeSpeechScriptInputSchema, changeSpeechVoiceInputSchema, clipIdSchema, clipIdsSchema, deleteBgmInputSchema, deleteSpeechesInputSchema, deleteVideoClipsInputSchema, mediaIdSchema, moveAnchorSchema, moveSpeechesInputSchema, moveVideoClipsByAnchorInputSchema, moveVideoClipsInputSchema, movedClipAnchoredPolicySchema, positiveMsSchema, replaceVideoClipContentInputSchema, replaceVideoClipSequenceInputSchema, setBgmInputSchema, setCaptionStyleInputSchema, setCaptionVisibilityInputSchema, setVideoClipSpeedShiftInputSchema, speechAssetsSchema, speechIdSchema, speechIdsSchema, speedShiftSchema, timelineMsSchema, voiceSchema, volumeSchema };
|
|
1552
1542
|
}
|
|
1553
1543
|
//#endregion
|
|
1554
1544
|
//#region src/editor/schema-validator.d.ts
|
|
@@ -1600,7 +1590,6 @@ declare class SchemaValidator {
|
|
|
1600
1590
|
validateSetBgm(input: SetBgmInput, _doc: SnapshotReadable): void;
|
|
1601
1591
|
validateDeleteBgm(input: DeleteBgmInput, _doc: SnapshotReadable): void;
|
|
1602
1592
|
validateSetCaptionVisibility(input: SetCaptionVisibilityInput, _doc: SnapshotReadable): void;
|
|
1603
|
-
validateResizeCaption(input: ResizeCaptionInput, doc: SnapshotReadable): void;
|
|
1604
1593
|
validateSetCaptionStyle(input: SetCaptionStyleInput, _doc: SnapshotReadable): void;
|
|
1605
1594
|
private parse;
|
|
1606
1595
|
private mainTrackIds;
|
|
@@ -1649,7 +1638,7 @@ declare class SchemaValidator {
|
|
|
1649
1638
|
* side-effect payload contract in
|
|
1650
1639
|
* `docs/projects/medeo-integration/results/phase-4-side-effect-payload-contract.md`.
|
|
1651
1640
|
*/
|
|
1652
|
-
type ImplementedSemanticOpKind = 'MoveVideoClips' | 'MoveVideoClipsByAnchor' | 'DeleteVideoClips' | 'AddVideoClips' | 'AdjustVideoClipVolume' | 'SetVideoClipSpeedShift' | 'ReplaceVideoClipContent' | 'ReplaceVideoClipSequence' | 'AdjustVideoClipDuration' | 'AddSpeeches' | 'DeleteSpeeches' | 'MoveSpeeches' | 'ChangeSpeechScript' | 'ChangeSpeechVoice' | 'AdjustSpeechVolume' | '
|
|
1641
|
+
type ImplementedSemanticOpKind = 'MoveVideoClips' | 'MoveVideoClipsByAnchor' | 'DeleteVideoClips' | 'AddVideoClips' | 'AdjustVideoClipVolume' | 'SetVideoClipSpeedShift' | 'ReplaceVideoClipContent' | 'ReplaceVideoClipSequence' | 'AdjustVideoClipDuration' | 'AddSpeeches' | 'DeleteSpeeches' | 'MoveSpeeches' | 'ChangeSpeechScript' | 'ChangeSpeechVoice' | 'AdjustSpeechVolume' | 'SetCaptionVisibility' | 'SetCaptionStyle' | 'SetBgm' | 'DeleteBgm' | 'AdjustBgmVolume';
|
|
1653
1642
|
/**
|
|
1654
1643
|
* Operations on the roadmap but NOT yet implemented by `SemanticEditor`. Empty:
|
|
1655
1644
|
* Phase 4 covers every op with a real entry point. Kept as a named type so the
|
|
@@ -1711,7 +1700,7 @@ interface CommitOptions {
|
|
|
1711
1700
|
/** Author of this op; omitted for writes with no acting user (bootstrap, repair). */
|
|
1712
1701
|
actor?: OpActor;
|
|
1713
1702
|
}
|
|
1714
|
-
type SemanticOpInput = MoveVideoClipsInput | MoveVideoClipsByAnchorInput | DeleteVideoClipsInput | AddVideoClipsInput | AdjustVideoClipVolumeInput | AdjustSpeechVolumeInput | AdjustBgmVolumeInput | SetVideoClipSpeedShiftInput | ReplaceVideoClipContentInput | ReplaceVideoClipSequenceInput | AdjustVideoClipDurationInput | AddSpeechesInput | DeleteSpeechesInput | MoveSpeechesInput |
|
|
1703
|
+
type SemanticOpInput = MoveVideoClipsInput | MoveVideoClipsByAnchorInput | DeleteVideoClipsInput | AddVideoClipsInput | AdjustVideoClipVolumeInput | AdjustSpeechVolumeInput | AdjustBgmVolumeInput | SetVideoClipSpeedShiftInput | ReplaceVideoClipContentInput | ReplaceVideoClipSequenceInput | AdjustVideoClipDurationInput | AddSpeechesInput | DeleteSpeechesInput | MoveSpeechesInput | SetCaptionVisibilityInput | SetCaptionStyleInput | SetBgmInput | DeleteBgmInput;
|
|
1715
1704
|
type SemanticOpName = ImplementedSemanticOpKind;
|
|
1716
1705
|
/** Audit metadata committed alongside an op's writes. */
|
|
1717
1706
|
interface TransactAudit {
|
|
@@ -1857,8 +1846,6 @@ declare class SemanticEditor {
|
|
|
1857
1846
|
deleteBgm(input: DeleteBgmInput, options?: CommitOptions): Promise<void>;
|
|
1858
1847
|
/** Toggle caption visibility (caption track `is_hidden`). */
|
|
1859
1848
|
setCaptionVisibility(input: SetCaptionVisibilityInput, options?: CommitOptions): Promise<void>;
|
|
1860
|
-
/** Resize the caption placement window; cue/source duration stays immutable. */
|
|
1861
|
-
resizeCaption(input: ResizeCaptionInput, options?: CommitOptions): Promise<void>;
|
|
1862
1849
|
/**
|
|
1863
1850
|
* Set the document-wide caption style. GLOBAL (no `caption_id`): the patch is
|
|
1864
1851
|
* merged onto EVERY caption part's `style`, mirroring the FE, which applies a
|
|
@@ -2043,7 +2030,6 @@ declare const videoDocumentSchema: z.ZodObject<{
|
|
|
2043
2030
|
offsetMs: z.ZodNumber;
|
|
2044
2031
|
}, z.core.$loose>], "mode">;
|
|
2045
2032
|
fallback_abs_ms: z.ZodOptional<z.ZodNumber>;
|
|
2046
|
-
duration_override_ms: z.ZodOptional<z.ZodNumber>;
|
|
2047
2033
|
}, z.core.$loose>>>;
|
|
2048
2034
|
}, z.core.$loose>>>;
|
|
2049
2035
|
part_library: z.ZodOptional<z.ZodRecord<z.ZodString, z.ZodUnion<readonly [z.ZodObject<{
|
package/dist/index.d.ts
CHANGED
|
@@ -1,4 +1,4 @@
|
|
|
1
|
-
import { $ as VideoDocumentSchemaVersion, A as assertValidVideoDocument, B as BgmPart, C as index_d_exports, D as VideoDocumentMirrorSchema, E as VideoDocumentDraft, F as SpeechHostMap, G as SpeechPart, H as DEFAULT_UNIT_TIME_MS, I as buildSpeechHostMap, J as TrackItem, K as Timeline, L as derivePositionFromAbs, M as InitialDocumentFacts, N as buildInitialVideoDocument, O as videoDocumentMirrorSchema, P as DerivedItemPosition, Q as VideoDocument, R as fromVideoDocument, S as ValidationError, T as TrackItemDraft, U as PartKind, V as CaptionPart, W as PartUnion, X as VIDEO_DOCUMENT_SCHEMA_VERSION, Y as TrackItemTimePosition, Z as VideoClipPart, _ as PlannedSemanticOpKind, a as MirrorVideoDocumentOptions, at as CaptionPart$1, b as SchemaValidator, c as CommitOptions, ct as SpeedShift, d as SemanticEditor, dt as TrackItem$1, et as VideoDocumentValidationIssue, f as SemanticOpInput, g as ImplementedSemanticOpKind, h as IMPLEMENTED_SEMANTIC_OP_KINDS, i as MirrorVideoDocumentAdapter, it as Attachment, j as validateVideoDocument, k as VideoDocumentValidationError, l as OpActor, lt as Timeline$1, m as TransactAudit, n as videoDocumentSchema, nt as VideoDraft, o as createMirrorVideoDocument, ot as CaptionStyle, p as SemanticOpName, q as Track, r as readVideoDocumentFromDraft, rt as VideoDraftPartUnion, s as createMirrorVideoDocumentAdapter, st as PartAggregation, t as partUnionSchema, tt as VideoDocumentValidationIssueCode, u as SemanticDocumentAdapter, ut as Track$1, v as SemanticOpKind, w as TrackDraft, x as SnapshotReadable, y as isImplementedSemanticOpKind, z as toVideoDocument } from "./index-
|
|
1
|
+
import { $ as VideoDocumentSchemaVersion, A as assertValidVideoDocument, B as BgmPart, C as index_d_exports, D as VideoDocumentMirrorSchema, E as VideoDocumentDraft, F as SpeechHostMap, G as SpeechPart, H as DEFAULT_UNIT_TIME_MS, I as buildSpeechHostMap, J as TrackItem, K as Timeline, L as derivePositionFromAbs, M as InitialDocumentFacts, N as buildInitialVideoDocument, O as videoDocumentMirrorSchema, P as DerivedItemPosition, Q as VideoDocument, R as fromVideoDocument, S as ValidationError, T as TrackItemDraft, U as PartKind, V as CaptionPart, W as PartUnion, X as VIDEO_DOCUMENT_SCHEMA_VERSION, Y as TrackItemTimePosition, Z as VideoClipPart, _ as PlannedSemanticOpKind, a as MirrorVideoDocumentOptions, at as CaptionPart$1, b as SchemaValidator, c as CommitOptions, ct as SpeedShift, d as SemanticEditor, dt as TrackItem$1, et as VideoDocumentValidationIssue, f as SemanticOpInput, g as ImplementedSemanticOpKind, h as IMPLEMENTED_SEMANTIC_OP_KINDS, i as MirrorVideoDocumentAdapter, it as Attachment, j as validateVideoDocument, k as VideoDocumentValidationError, l as OpActor, lt as Timeline$1, m as TransactAudit, n as videoDocumentSchema, nt as VideoDraft, o as createMirrorVideoDocument, ot as CaptionStyle, p as SemanticOpName, q as Track, r as readVideoDocumentFromDraft, rt as VideoDraftPartUnion, s as createMirrorVideoDocumentAdapter, st as PartAggregation, t as partUnionSchema, tt as VideoDocumentValidationIssueCode, u as SemanticDocumentAdapter, ut as Track$1, v as SemanticOpKind, w as TrackDraft, x as SnapshotReadable, y as isImplementedSemanticOpKind, z as toVideoDocument } from "./index-DWVYLTjv.js";
|
|
2
2
|
import { PeerID } from "loro-crdt";
|
|
3
3
|
import { DocState } from "@mengine/sync";
|
|
4
4
|
import { BaseDocStorage, Connection, DocDiff, DocPushReceipt, DocSnapshotRecord, DocStorage, DocStorageOptions, DocUpdate, DocUpdateRecord } from "@mengine/storage";
|
|
@@ -296,7 +296,9 @@ type PushResultKind = 'ack' | 'duplicate' | 'rejected' | 'failed' | 'nothing_to_
|
|
|
296
296
|
*/
|
|
297
297
|
interface PushResult {
|
|
298
298
|
kind: PushResultKind;
|
|
299
|
-
/** Server
|
|
299
|
+
/** Server document sequence observed after a successful `ack` or `duplicate`. */
|
|
300
|
+
mengineUpdateSeq?: number | undefined;
|
|
301
|
+
/** @deprecated Ack-only sequence retained until consumers adopt `mengineUpdateSeq`. */
|
|
300
302
|
updateSeq?: number | undefined;
|
|
301
303
|
/** Whether the server held ops the local document lacked. See above. */
|
|
302
304
|
collaborated: boolean;
|
|
@@ -575,6 +577,9 @@ declare class MedeoHttpDocStorage implements DocStorage {
|
|
|
575
577
|
* tool-level ack wait) subscribe here.
|
|
576
578
|
*/
|
|
577
579
|
subscribePushOutcome(callback: (outcome: PushOutcome) => void): () => void;
|
|
580
|
+
/** Authoritative HTTP reads and accepted pushes, never inferred from SSE bytes. */
|
|
581
|
+
subscribeServerVersion(callback: (version: Uint8Array) => void): () => void;
|
|
582
|
+
private reportServerVersion;
|
|
578
583
|
deleteDoc(_docId: string): Promise<void>;
|
|
579
584
|
subscribeDocUpdate(callback: (update: DocUpdate, origin: unknown) => void): () => void;
|
|
580
585
|
private assertDocId;
|
|
@@ -623,6 +628,14 @@ interface WaitForServerAckOptions {
|
|
|
623
628
|
/** Deadline in ms. Rejects with reason `timeout` when it elapses. */
|
|
624
629
|
timeoutMs?: number;
|
|
625
630
|
}
|
|
631
|
+
/** Document-level confirmation is independent of local operation completion. */
|
|
632
|
+
interface MengineDocSyncState {
|
|
633
|
+
/** Remote-only imports do not create a new local confirmation obligation. */
|
|
634
|
+
readonly confirmation: 'unknown' | 'pending' | 'confirmed';
|
|
635
|
+
/** Transport/activity phase. Idle does not imply confirmation; failure details
|
|
636
|
+
* remain available through push outcomes and confirmation wait errors. */
|
|
637
|
+
readonly phase: 'connecting' | 'idle' | 'syncing' | 'offline' | 'failed';
|
|
638
|
+
}
|
|
626
639
|
interface MengineDocSessionOptions {
|
|
627
640
|
docId: string;
|
|
628
641
|
client: MengineHttpClient;
|
|
@@ -668,8 +681,14 @@ declare class MengineDocSession {
|
|
|
668
681
|
private adapterValue;
|
|
669
682
|
private editorValue;
|
|
670
683
|
private started;
|
|
684
|
+
private destroyed;
|
|
685
|
+
private lifetime;
|
|
686
|
+
private hasConnected;
|
|
687
|
+
private initialVersionValue;
|
|
688
|
+
private localVersionValue;
|
|
689
|
+
private pushErrorValue;
|
|
671
690
|
/**
|
|
672
|
-
* Latest server oplog version seen on
|
|
691
|
+
* Latest server oplog version seen on an authoritative HTTP response. Lets `waitForServerAck`
|
|
673
692
|
* return without waiting when the server is already known to cover the local
|
|
674
693
|
* doc (e.g. nothing was edited since the last confirmed push).
|
|
675
694
|
*/
|
|
@@ -684,14 +703,14 @@ declare class MengineDocSession {
|
|
|
684
703
|
*/
|
|
685
704
|
subscribePushOutcome(callback: (outcome: PushOutcome) => void): () => void;
|
|
686
705
|
/**
|
|
687
|
-
* Resolve once the server has durably accepted the local
|
|
706
|
+
* Resolve once the server has durably accepted the local commits as of
|
|
688
707
|
* *now* — the capability an Agent tool needs to answer "did my edit land?"
|
|
689
708
|
* before reporting success.
|
|
690
709
|
*
|
|
691
710
|
* Call it right after the editor ops whose durability matters. It snapshots the
|
|
692
|
-
* local
|
|
693
|
-
*
|
|
694
|
-
*
|
|
711
|
+
* latest local commit's version (or the loaded baseline before any edit) and
|
|
712
|
+
* resolves when an authoritative server version covers it. Remote-only
|
|
713
|
+
* imports do not extend this target, matching the displayed confirmation state.
|
|
695
714
|
*
|
|
696
715
|
* Version coverage, not byte identity, is the acceptance test — for two reasons:
|
|
697
716
|
* the ops may reach the server inside a merged blob rather than as the exact
|
|
@@ -723,6 +742,11 @@ declare class MengineDocSession {
|
|
|
723
742
|
* surfaces through `subscribe`.
|
|
724
743
|
*/
|
|
725
744
|
start(): Promise<VideoDocument>;
|
|
745
|
+
getSyncState(): MengineDocSyncState;
|
|
746
|
+
private confirmationTarget;
|
|
747
|
+
/** Immediately supplies current state; unsubscribe when the host changes docs. */
|
|
748
|
+
subscribeSyncState(cb: (state: MengineDocSyncState) => void): () => void;
|
|
749
|
+
private emitSyncState;
|
|
726
750
|
subscribe(cb: (event: MengineDocSessionUpdateEvent) => void): () => void;
|
|
727
751
|
onStateChange(cb: (state: DocState) => void): () => void;
|
|
728
752
|
getState(): DocState;
|
|
@@ -1064,4 +1088,4 @@ declare function hostForAbsMs(ranges: MainClipRange[], absMs: number): MainClipR
|
|
|
1064
1088
|
*/
|
|
1065
1089
|
declare function relativePositionForAbs(ranges: MainClipRange[], absMs: number): TrackItemTimePosition;
|
|
1066
1090
|
//#endregion
|
|
1067
|
-
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, type InitialDocumentFacts, 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 MengineDocumentVersion, type MengineEventStreamOptions, MengineHttpClient, type MengineHttpClientOptions, MengineHttpRequestError, MenginePushRejectedError, type MenginePushResponse, type MenginePushUpdateResponse, type MengineRejectedResponse, type MengineSnapshotResponse, type MengineSseUpdateEvent, type MengineSyncResponse, 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, VIDEO_DOCUMENT_SCHEMA_VERSION, ValidationError, type VideoClipPart, type VideoDocument, type VideoDocumentDraft, type VideoDocumentMirrorSchema, type VideoDocumentSchemaVersion, VideoDocumentValidationError, type VideoDocumentValidationIssue, type VideoDocumentValidationIssueCode, type VideoDraft, type CaptionPart$1 as VideoDraftCaptionPart, 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 };
|
|
1091
|
+
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, type InitialDocumentFacts, 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 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, VIDEO_DOCUMENT_SCHEMA_VERSION, ValidationError, type VideoClipPart, type VideoDocument, type VideoDocumentDraft, type VideoDocumentMirrorSchema, type VideoDocumentSchemaVersion, VideoDocumentValidationError, type VideoDocumentValidationIssue, type VideoDocumentValidationIssueCode, type VideoDraft, type CaptionPart$1 as VideoDraftCaptionPart, 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 };
|
package/dist/index.js
CHANGED
|
@@ -1,5 +1,5 @@
|
|
|
1
1
|
import { t as __exportAll } from "./chunk-D7D4PA-g.js";
|
|
2
|
-
import { A as partDurationMs, C as reassignSpeechesToVideoClipsByTime, D as syncAggregatedClipsTimePosition, E as resolveSpeechOverlapByShiftingVideos, F as partUnionToDraft, I as recordEntries, L as videoDocumentMirrorSchema, M as DEFAULT_UNIT_TIME_MS, N as VIDEO_DOCUMENT_SCHEMA_VERSION, O as TIMELINE_SKELETON_DURATION_MS, P as effectiveVideoClipDurationMs, R as base64ToBytes, S as fillMainTrackTimeGaps, T as resolveAllSpeechOverlaps, _ as findLaneTrack, a as buildInitialVideoDocument, b as cascadeAfterVideoClipChanges, c as fromVideoDocument, d as assertValidVideoDocument, f as validateVideoDocument, g as ensureLaneTrack, h as LANE_KINDS_IN_STACK_ORDER, i as readVideoDocumentFromDraft, j as safeDurationMs, k as isEmptyVideoClip, l as toVideoDocument, m as videoDocumentSchema, n as createMirrorVideoDocument, o as buildSpeechHostMap, p as partUnionSchema, r as createMirrorVideoDocumentAdapter, s as derivePositionFromAbs, t as MirrorVideoDocumentAdapter, u as VideoDocumentValidationError, v as laneTrackId, w as recalculateTimelineDuration, x as arrangeMainTrackSeamlessly, y as solveVideoDocument, z as bytesToBase64 } from "./document-
|
|
2
|
+
import { A as partDurationMs, C as reassignSpeechesToVideoClipsByTime, D as syncAggregatedClipsTimePosition, E as resolveSpeechOverlapByShiftingVideos, F as partUnionToDraft, I as recordEntries, L as videoDocumentMirrorSchema, M as DEFAULT_UNIT_TIME_MS, N as VIDEO_DOCUMENT_SCHEMA_VERSION, O as TIMELINE_SKELETON_DURATION_MS, P as effectiveVideoClipDurationMs, R as base64ToBytes, S as fillMainTrackTimeGaps, T as resolveAllSpeechOverlaps, _ as findLaneTrack, a as buildInitialVideoDocument, b as cascadeAfterVideoClipChanges, c as fromVideoDocument, d as assertValidVideoDocument, f as validateVideoDocument, g as ensureLaneTrack, h as LANE_KINDS_IN_STACK_ORDER, i as readVideoDocumentFromDraft, j as safeDurationMs, k as isEmptyVideoClip, l as toVideoDocument, m as videoDocumentSchema, n as createMirrorVideoDocument, o as buildSpeechHostMap, p as partUnionSchema, r as createMirrorVideoDocumentAdapter, s as derivePositionFromAbs, t as MirrorVideoDocumentAdapter, u as VideoDocumentValidationError, v as laneTrackId, w as recalculateTimelineDuration, x as arrangeMainTrackSeamlessly, y as solveVideoDocument, z as bytesToBase64 } from "./document-C0o_cjAH.js";
|
|
3
3
|
import { z } from "zod";
|
|
4
4
|
import { LoroDoc, VersionVector } from "loro-crdt";
|
|
5
5
|
import { ClientServerSynchronizer, DocManager } from "@mengine/sync";
|
|
@@ -670,13 +670,6 @@ const replaceVideoClipSequenceInputSchema = z.object({
|
|
|
670
670
|
}
|
|
671
671
|
});
|
|
672
672
|
//#endregion
|
|
673
|
-
//#region src/editor/schemas/resize-caption.ts
|
|
674
|
-
/** Resize one caption placement without changing its cue/source duration. */
|
|
675
|
-
const resizeCaptionInputSchema = z.object({
|
|
676
|
-
caption_id: z.string().min(1),
|
|
677
|
-
duration_ms: z.number().finite().positive()
|
|
678
|
-
});
|
|
679
|
-
//#endregion
|
|
680
673
|
//#region src/editor/schemas/set-bgm.ts
|
|
681
674
|
/**
|
|
682
675
|
* Set the document BGM. The media's stable result (storage key) arrives
|
|
@@ -772,7 +765,6 @@ var schemas_exports = /* @__PURE__ */ __exportAll({
|
|
|
772
765
|
positiveMsSchema: () => positiveMsSchema,
|
|
773
766
|
replaceVideoClipContentInputSchema: () => replaceVideoClipContentInputSchema,
|
|
774
767
|
replaceVideoClipSequenceInputSchema: () => replaceVideoClipSequenceInputSchema,
|
|
775
|
-
resizeCaptionInputSchema: () => resizeCaptionInputSchema,
|
|
776
768
|
setBgmInputSchema: () => setBgmInputSchema,
|
|
777
769
|
setCaptionStyleInputSchema: () => setCaptionStyleInputSchema,
|
|
778
770
|
setCaptionVisibilityInputSchema: () => setCaptionVisibilityInputSchema,
|
|
@@ -1023,18 +1015,6 @@ var SchemaValidator = class {
|
|
|
1023
1015
|
validateSetCaptionVisibility(input, _doc) {
|
|
1024
1016
|
this.parse(setCaptionVisibilityInputSchema, input, "set_caption_visibility_invalid_input");
|
|
1025
1017
|
}
|
|
1026
|
-
validateResizeCaption(input, doc) {
|
|
1027
|
-
const parsed = this.parse(resizeCaptionInputSchema, input, "resize_caption_invalid_input");
|
|
1028
|
-
const snapshot = doc.snapshot();
|
|
1029
|
-
this.assertPartKind(snapshot, parsed.caption_id, "caption", "resize_caption");
|
|
1030
|
-
if (snapshot.tracks?.find((track) => track.parts_kind === "caption")?.items?.find((row) => row.part_id === parsed.caption_id) == null) throw new ValidationError("resize_caption_placement_not_found", `caption_id "${parsed.caption_id}" is not placed on the caption track`, { caption_id: parsed.caption_id });
|
|
1031
|
-
const cueDuration = snapshot.part_library?.[parsed.caption_id]?.caption?.initial_duration_ms ?? 0;
|
|
1032
|
-
if (parsed.duration_ms < cueDuration) throw new ValidationError("resize_caption_below_cue", `duration_ms ${parsed.duration_ms} is shorter than cue duration ${cueDuration}`, {
|
|
1033
|
-
caption_id: parsed.caption_id,
|
|
1034
|
-
duration_ms: parsed.duration_ms,
|
|
1035
|
-
cue_duration_ms: cueDuration
|
|
1036
|
-
});
|
|
1037
|
-
}
|
|
1038
1018
|
validateSetCaptionStyle(input, _doc) {
|
|
1039
1019
|
this.parse(setCaptionStyleInputSchema, input, "set_caption_style_invalid_input");
|
|
1040
1020
|
}
|
|
@@ -1240,8 +1220,7 @@ var SemanticEditor = class {
|
|
|
1240
1220
|
track.items.splice(at, 0, {
|
|
1241
1221
|
part_id: partId,
|
|
1242
1222
|
time_position: { mode: "sequential" },
|
|
1243
|
-
fallback_abs_ms: void 0
|
|
1244
|
-
duration_override_ms: void 0
|
|
1223
|
+
fallback_abs_ms: void 0
|
|
1245
1224
|
});
|
|
1246
1225
|
at += 1;
|
|
1247
1226
|
}
|
|
@@ -1288,8 +1267,7 @@ var SemanticEditor = class {
|
|
|
1288
1267
|
newItems.push({
|
|
1289
1268
|
part_id: partId,
|
|
1290
1269
|
time_position: { mode: "sequential" },
|
|
1291
|
-
fallback_abs_ms: void 0
|
|
1292
|
-
duration_override_ms: void 0
|
|
1270
|
+
fallback_abs_ms: void 0
|
|
1293
1271
|
});
|
|
1294
1272
|
newClipIds.push(partId);
|
|
1295
1273
|
}
|
|
@@ -1502,8 +1480,7 @@ var SemanticEditor = class {
|
|
|
1502
1480
|
mode: "absolute",
|
|
1503
1481
|
offsetMs: 0
|
|
1504
1482
|
},
|
|
1505
|
-
fallback_abs_ms: void 0
|
|
1506
|
-
duration_override_ms: void 0
|
|
1483
|
+
fallback_abs_ms: void 0
|
|
1507
1484
|
}];
|
|
1508
1485
|
}, audit("SetBgm", input, options));
|
|
1509
1486
|
}
|
|
@@ -1526,15 +1503,6 @@ var SemanticEditor = class {
|
|
|
1526
1503
|
track.is_hidden = input.is_hidden;
|
|
1527
1504
|
}, audit("SetCaptionVisibility", input, options));
|
|
1528
1505
|
}
|
|
1529
|
-
/** Resize the caption placement window; cue/source duration stays immutable. */
|
|
1530
|
-
async resizeCaption(input, options) {
|
|
1531
|
-
this.validator.validateResizeCaption(input, this.doc);
|
|
1532
|
-
this.doc.transact((draft) => {
|
|
1533
|
-
const item = findLaneTrack(draft, "caption")?.items?.find((row) => row.part_id === input.caption_id);
|
|
1534
|
-
if (item == null) return;
|
|
1535
|
-
item.duration_override_ms = input.duration_ms;
|
|
1536
|
-
}, audit("ResizeCaption", input, options));
|
|
1537
|
-
}
|
|
1538
1506
|
/**
|
|
1539
1507
|
* Set the document-wide caption style. GLOBAL (no `caption_id`): the patch is
|
|
1540
1508
|
* merged onto EVERY caption part's `style`, mirroring the FE, which applies a
|
|
@@ -1781,8 +1749,7 @@ function placeRelative(items, partId, anchorPartId, offsetMs, fallbackAbsMs) {
|
|
|
1781
1749
|
items.push({
|
|
1782
1750
|
part_id: partId,
|
|
1783
1751
|
time_position: timePosition,
|
|
1784
|
-
fallback_abs_ms: fallbackAbsMs
|
|
1785
|
-
duration_override_ms: void 0
|
|
1752
|
+
fallback_abs_ms: fallbackAbsMs
|
|
1786
1753
|
});
|
|
1787
1754
|
}
|
|
1788
1755
|
/**
|
|
@@ -1926,7 +1893,6 @@ const IMPLEMENTED_SEMANTIC_OP_KINDS = [
|
|
|
1926
1893
|
"ChangeSpeechScript",
|
|
1927
1894
|
"ChangeSpeechVoice",
|
|
1928
1895
|
"AdjustSpeechVolume",
|
|
1929
|
-
"ResizeCaption",
|
|
1930
1896
|
"SetCaptionVisibility",
|
|
1931
1897
|
"SetCaptionStyle",
|
|
1932
1898
|
"SetBgm",
|
|
@@ -2194,6 +2160,7 @@ var ManualSyncDoc = class ManualSyncDoc {
|
|
|
2194
2160
|
if (serverVV != null) this.watermark = serverVV;
|
|
2195
2161
|
return {
|
|
2196
2162
|
kind: response.kind,
|
|
2163
|
+
mengineUpdateSeq: response.version?.update_seq ?? response.update_seq ?? void 0,
|
|
2197
2164
|
updateSeq: response.update_seq ?? void 0,
|
|
2198
2165
|
collaborated: serverVV != null && !covers(localVersion, serverVV)
|
|
2199
2166
|
};
|
|
@@ -2312,6 +2279,7 @@ var SseConnection = class {
|
|
|
2312
2279
|
for (const update of event.updates) this.onUpdate(update);
|
|
2313
2280
|
}
|
|
2314
2281
|
});
|
|
2282
|
+
if (!signal.aborted) this.setStatus("connecting", /* @__PURE__ */ new Error("SSE stream closed"));
|
|
2315
2283
|
} catch (error) {
|
|
2316
2284
|
if (signal.aborted) break;
|
|
2317
2285
|
this.setStatus("connecting", error instanceof Error ? error : new Error(String(error)));
|
|
@@ -2364,6 +2332,7 @@ var MedeoHttpDocStorage = class {
|
|
|
2364
2332
|
async getDoc(docId) {
|
|
2365
2333
|
this.assertDocId(docId);
|
|
2366
2334
|
const snapshot = await this.client.fetchSnapshot();
|
|
2335
|
+
this.reportServerVersion(snapshot.version?.server_vv);
|
|
2367
2336
|
const now = /* @__PURE__ */ new Date();
|
|
2368
2337
|
return {
|
|
2369
2338
|
docId,
|
|
@@ -2375,6 +2344,7 @@ var MedeoHttpDocStorage = class {
|
|
|
2375
2344
|
async getDocDiff(docId, knownVersion) {
|
|
2376
2345
|
this.assertDocId(docId);
|
|
2377
2346
|
const response = await this.client.sync(knownVersion);
|
|
2347
|
+
this.reportServerVersion(response.server_vv);
|
|
2378
2348
|
return {
|
|
2379
2349
|
docId,
|
|
2380
2350
|
missing: base64ToBytes(response.update),
|
|
@@ -2405,7 +2375,7 @@ var MedeoHttpDocStorage = class {
|
|
|
2405
2375
|
if (update.data.byteLength === 0) return {};
|
|
2406
2376
|
try {
|
|
2407
2377
|
const response = await this.client.pushUpdate(update.data);
|
|
2408
|
-
const serverVV =
|
|
2378
|
+
const serverVV = this.reportServerVersion(response.version?.server_vv);
|
|
2409
2379
|
this.events.emit("pushOutcome", {
|
|
2410
2380
|
kind: response.kind,
|
|
2411
2381
|
updateSeq: response.update_seq ?? void 0,
|
|
@@ -2433,6 +2403,15 @@ var MedeoHttpDocStorage = class {
|
|
|
2433
2403
|
subscribePushOutcome(callback) {
|
|
2434
2404
|
return this.events.on("pushOutcome", callback);
|
|
2435
2405
|
}
|
|
2406
|
+
/** Authoritative HTTP reads and accepted pushes, never inferred from SSE bytes. */
|
|
2407
|
+
subscribeServerVersion(callback) {
|
|
2408
|
+
return this.events.on("serverVersion", callback);
|
|
2409
|
+
}
|
|
2410
|
+
reportServerVersion(encoded) {
|
|
2411
|
+
const version = decodeServerVV(encoded);
|
|
2412
|
+
if (version != null) this.events.emit("serverVersion", version);
|
|
2413
|
+
return version;
|
|
2414
|
+
}
|
|
2436
2415
|
async deleteDoc(_docId) {
|
|
2437
2416
|
throw new Error("MedeoHttpDocStorage does not support deleteDoc");
|
|
2438
2417
|
}
|
|
@@ -2614,8 +2593,14 @@ var MengineDocSession = class {
|
|
|
2614
2593
|
adapterValue = null;
|
|
2615
2594
|
editorValue = null;
|
|
2616
2595
|
started = false;
|
|
2596
|
+
destroyed = false;
|
|
2597
|
+
lifetime = null;
|
|
2598
|
+
hasConnected = false;
|
|
2599
|
+
initialVersionValue = null;
|
|
2600
|
+
localVersionValue = null;
|
|
2601
|
+
pushErrorValue = null;
|
|
2617
2602
|
/**
|
|
2618
|
-
* Latest server oplog version seen on
|
|
2603
|
+
* Latest server oplog version seen on an authoritative HTTP response. Lets `waitForServerAck`
|
|
2619
2604
|
* return without waiting when the server is already known to cover the local
|
|
2620
2605
|
* doc (e.g. nothing was edited since the last confirmed push).
|
|
2621
2606
|
*/
|
|
@@ -2643,14 +2628,14 @@ var MengineDocSession = class {
|
|
|
2643
2628
|
return this.server.subscribePushOutcome(callback);
|
|
2644
2629
|
}
|
|
2645
2630
|
/**
|
|
2646
|
-
* Resolve once the server has durably accepted the local
|
|
2631
|
+
* Resolve once the server has durably accepted the local commits as of
|
|
2647
2632
|
* *now* — the capability an Agent tool needs to answer "did my edit land?"
|
|
2648
2633
|
* before reporting success.
|
|
2649
2634
|
*
|
|
2650
2635
|
* Call it right after the editor ops whose durability matters. It snapshots the
|
|
2651
|
-
* local
|
|
2652
|
-
*
|
|
2653
|
-
*
|
|
2636
|
+
* latest local commit's version (or the loaded baseline before any edit) and
|
|
2637
|
+
* resolves when an authoritative server version covers it. Remote-only
|
|
2638
|
+
* imports do not extend this target, matching the displayed confirmation state.
|
|
2654
2639
|
*
|
|
2655
2640
|
* Version coverage, not byte identity, is the acceptance test — for two reasons:
|
|
2656
2641
|
* the ops may reach the server inside a merged blob rather than as the exact
|
|
@@ -2665,31 +2650,39 @@ var MengineDocSession = class {
|
|
|
2665
2650
|
* @throws {MengineAckFailedError} on timeout, rejection, or transport failure.
|
|
2666
2651
|
*/
|
|
2667
2652
|
async waitForServerAck(options = {}) {
|
|
2668
|
-
if (this.adapterValue == null) throw new Error("mengine doc session is not started");
|
|
2653
|
+
if (this.adapterValue == null || this.lifetime == null) throw new Error("mengine doc session is not started");
|
|
2669
2654
|
const timeoutMs = options.timeoutMs ?? 15e3;
|
|
2670
|
-
const target = this.manager.connectDoc(this.docId).version();
|
|
2655
|
+
const target = this.confirmationTarget() ?? this.manager.connectDoc(this.docId).version();
|
|
2656
|
+
const signal = this.lifetime.signal;
|
|
2671
2657
|
if (this.serverVVValue != null && serverCovers(this.serverVVValue, target)) return;
|
|
2672
2658
|
await new Promise((resolve, reject) => {
|
|
2673
|
-
|
|
2659
|
+
const cleanup = [];
|
|
2674
2660
|
let done = false;
|
|
2675
2661
|
const settle = (error) => {
|
|
2676
2662
|
if (done) return;
|
|
2677
2663
|
done = true;
|
|
2678
2664
|
clearTimeout(timer);
|
|
2679
|
-
off();
|
|
2665
|
+
cleanup.forEach((off) => off());
|
|
2680
2666
|
if (error == null) resolve();
|
|
2681
2667
|
else reject(error);
|
|
2682
2668
|
};
|
|
2683
2669
|
const timer = setTimeout(() => {
|
|
2684
2670
|
settle(new MengineAckFailedError("timeout", void 0, void 0, `mengine did not acknowledge the update within ${timeoutMs}ms`));
|
|
2685
2671
|
}, timeoutMs);
|
|
2686
|
-
|
|
2672
|
+
const onAbort = () => settle(new MengineAckFailedError("failed", void 0, void 0, "mengine doc session destroyed"));
|
|
2673
|
+
signal.addEventListener("abort", onAbort, { once: true });
|
|
2674
|
+
cleanup.push(() => signal.removeEventListener("abort", onAbort));
|
|
2675
|
+
cleanup.push(this.events.on("syncState", () => {
|
|
2676
|
+
if (this.serverVVValue != null && serverCovers(this.serverVVValue, target)) settle(void 0);
|
|
2677
|
+
}));
|
|
2678
|
+
cleanup.push(this.server.subscribePushOutcome((outcome) => {
|
|
2687
2679
|
if (outcome.kind === "rejected" || outcome.kind === "failed") {
|
|
2688
2680
|
settle(new MengineAckFailedError(outcome.kind, outcome.code, outcome.error, outcome.error?.message ?? `mengine push ${outcome.kind}`));
|
|
2689
2681
|
return;
|
|
2690
2682
|
}
|
|
2691
|
-
|
|
2692
|
-
|
|
2683
|
+
}));
|
|
2684
|
+
if (signal.aborted) onAbort();
|
|
2685
|
+
else this.synchronizer.requestSync(this.docId);
|
|
2693
2686
|
});
|
|
2694
2687
|
}
|
|
2695
2688
|
/**
|
|
@@ -2715,8 +2708,23 @@ var MengineDocSession = class {
|
|
|
2715
2708
|
* surfaces through `subscribe`.
|
|
2716
2709
|
*/
|
|
2717
2710
|
async start() {
|
|
2711
|
+
if (this.destroyed) throw new Error("mengine doc session destroyed");
|
|
2718
2712
|
if (this.started) return this.snapshot();
|
|
2719
2713
|
this.started = true;
|
|
2714
|
+
this.lifetime = new AbortController();
|
|
2715
|
+
this.disposables.add(this.server.subscribeServerVersion((version) => {
|
|
2716
|
+
this.serverVVValue = version;
|
|
2717
|
+
if (this.getSyncState().confirmation === "confirmed") this.pushErrorValue = null;
|
|
2718
|
+
this.emitSyncState();
|
|
2719
|
+
}));
|
|
2720
|
+
this.disposables.add(this.server.subscribePushOutcome((outcome) => {
|
|
2721
|
+
this.pushErrorValue = outcome.kind === "failed" || outcome.kind === "rejected" ? outcome.error ?? /* @__PURE__ */ new Error(`mengine push ${outcome.kind}`) : null;
|
|
2722
|
+
this.emitSyncState();
|
|
2723
|
+
}));
|
|
2724
|
+
this.disposables.add(this.server.connection.onStatusChanged((status) => {
|
|
2725
|
+
if (status === "connected") this.hasConnected = true;
|
|
2726
|
+
this.emitSyncState();
|
|
2727
|
+
}));
|
|
2720
2728
|
this.local.connection.connect();
|
|
2721
2729
|
this.server.connection.connect();
|
|
2722
2730
|
this.disposables.add(() => this.local.connection.disconnect());
|
|
@@ -2732,19 +2740,46 @@ var MengineDocSession = class {
|
|
|
2732
2740
|
this.disposables.add(() => this.manager.disconnectDoc(this.docId));
|
|
2733
2741
|
const unsubscribe = doc.subscribe((event) => {
|
|
2734
2742
|
if (this.adapterValue == null) return;
|
|
2743
|
+
if (this.initialVersionValue == null && this.hasContent()) this.initialVersionValue = doc.version();
|
|
2744
|
+
if (event.by === "local") this.localVersionValue = doc.version();
|
|
2745
|
+
this.emitSyncState();
|
|
2735
2746
|
this.events.emit("update", {
|
|
2736
2747
|
source: event.by === "local" ? "local" : "remote",
|
|
2737
2748
|
snapshot: this.adapterValue.snapshot()
|
|
2738
2749
|
});
|
|
2739
2750
|
});
|
|
2740
2751
|
this.disposables.add(unsubscribe);
|
|
2741
|
-
this.disposables.add(this.manager.onDocStateChange(this.docId, (state) =>
|
|
2742
|
-
|
|
2743
|
-
|
|
2752
|
+
this.disposables.add(this.manager.onDocStateChange(this.docId, (state) => {
|
|
2753
|
+
this.events.emit("state", state);
|
|
2754
|
+
this.emitSyncState();
|
|
2744
2755
|
}));
|
|
2745
2756
|
await this.waitForContent();
|
|
2757
|
+
this.initialVersionValue ??= doc.version();
|
|
2758
|
+
this.emitSyncState();
|
|
2746
2759
|
return this.snapshot();
|
|
2747
2760
|
}
|
|
2761
|
+
getSyncState() {
|
|
2762
|
+
const state = this.getState();
|
|
2763
|
+
const target = this.confirmationTarget();
|
|
2764
|
+
const confirmation = this.serverVVValue == null || target == null ? this.localVersionValue == null ? "unknown" : "pending" : serverCovers(this.serverVVValue, target) ? "confirmed" : "pending";
|
|
2765
|
+
const connection = !this.started ? "disconnected" : this.server.connection.status === "connected" ? "connected" : this.hasConnected || this.server.connection.error != null ? "disconnected" : "connecting";
|
|
2766
|
+
return {
|
|
2767
|
+
confirmation,
|
|
2768
|
+
phase: connection === "disconnected" ? "offline" : this.pushErrorValue != null || state.error != null ? "failed" : connection === "connecting" ? "connecting" : state.syncing ? "syncing" : "idle"
|
|
2769
|
+
};
|
|
2770
|
+
}
|
|
2771
|
+
confirmationTarget() {
|
|
2772
|
+
return this.localVersionValue ?? this.initialVersionValue;
|
|
2773
|
+
}
|
|
2774
|
+
/** Immediately supplies current state; unsubscribe when the host changes docs. */
|
|
2775
|
+
subscribeSyncState(cb) {
|
|
2776
|
+
const off = this.events.on("syncState", cb);
|
|
2777
|
+
cb(this.getSyncState());
|
|
2778
|
+
return off;
|
|
2779
|
+
}
|
|
2780
|
+
emitSyncState() {
|
|
2781
|
+
this.events.emit("syncState", this.getSyncState());
|
|
2782
|
+
}
|
|
2748
2783
|
subscribe(cb) {
|
|
2749
2784
|
return this.events.on("update", cb);
|
|
2750
2785
|
}
|
|
@@ -2755,7 +2790,12 @@ var MengineDocSession = class {
|
|
|
2755
2790
|
return this.manager.getDocState(this.docId);
|
|
2756
2791
|
}
|
|
2757
2792
|
destroy() {
|
|
2793
|
+
if (this.destroyed) return;
|
|
2794
|
+
this.destroyed = true;
|
|
2795
|
+
this.started = false;
|
|
2796
|
+
this.lifetime?.abort();
|
|
2758
2797
|
this.disposables.dispose();
|
|
2798
|
+
this.emitSyncState();
|
|
2759
2799
|
this.events.clearAll();
|
|
2760
2800
|
this.adapterValue = null;
|
|
2761
2801
|
this.editorValue = null;
|
|
@@ -2772,13 +2812,21 @@ var MengineDocSession = class {
|
|
|
2772
2812
|
*/
|
|
2773
2813
|
async waitForContent() {
|
|
2774
2814
|
if (this.hasContent()) return;
|
|
2775
|
-
|
|
2815
|
+
const signal = this.lifetime.signal;
|
|
2816
|
+
await new Promise((resolve, reject) => {
|
|
2817
|
+
const onAbort = () => {
|
|
2818
|
+
off();
|
|
2819
|
+
reject(/* @__PURE__ */ new Error("mengine doc session destroyed"));
|
|
2820
|
+
};
|
|
2776
2821
|
const off = this.events.on("update", () => {
|
|
2777
2822
|
if (this.hasContent()) {
|
|
2778
2823
|
off();
|
|
2824
|
+
signal.removeEventListener("abort", onAbort);
|
|
2779
2825
|
resolve();
|
|
2780
2826
|
}
|
|
2781
2827
|
});
|
|
2828
|
+
signal.addEventListener("abort", onAbort, { once: true });
|
|
2829
|
+
if (signal.aborted) onAbort();
|
|
2782
2830
|
});
|
|
2783
2831
|
}
|
|
2784
2832
|
hasContent() {
|
package/dist/testing.d.ts
CHANGED
package/dist/testing.js
CHANGED
|
@@ -1,4 +1,4 @@
|
|
|
1
|
-
import { N as VIDEO_DOCUMENT_SCHEMA_VERSION, R as base64ToBytes, r as createMirrorVideoDocumentAdapter, z as bytesToBase64 } from "./document-
|
|
1
|
+
import { N as VIDEO_DOCUMENT_SCHEMA_VERSION, R as base64ToBytes, r as createMirrorVideoDocumentAdapter, z as bytesToBase64 } from "./document-C0o_cjAH.js";
|
|
2
2
|
import { t as classifyUpdate } from "./loro-relay-doc-ssdYpuef.js";
|
|
3
3
|
import { LoroDoc, VersionVector, encodeFrontiers } from "loro-crdt";
|
|
4
4
|
//#region src/testing/in-memory-mengine-server.ts
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@mengine/medeo-client",
|
|
3
|
-
"version": "1.2.1-alpha.
|
|
3
|
+
"version": "1.2.1-alpha.11",
|
|
4
4
|
"license": "UNLICENSED",
|
|
5
5
|
"repository": {
|
|
6
6
|
"type": "git",
|
|
@@ -25,9 +25,9 @@
|
|
|
25
25
|
"dependencies": {
|
|
26
26
|
"loro-mirror": "^2.2.0",
|
|
27
27
|
"zod": "^4.4.3",
|
|
28
|
-
"@mengine/
|
|
29
|
-
"@mengine/
|
|
30
|
-
"@mengine/utils": "1.2.1-alpha.
|
|
28
|
+
"@mengine/sync": "1.2.1-alpha.11",
|
|
29
|
+
"@mengine/storage": "1.2.1-alpha.11",
|
|
30
|
+
"@mengine/utils": "1.2.1-alpha.11"
|
|
31
31
|
},
|
|
32
32
|
"devDependencies": {
|
|
33
33
|
"@types/node": "^25.9.1",
|