@mengine/medeo-client 2.0.1-alpha.6 → 2.0.1-alpha.8
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 +31 -0
- package/dist/{document-N-8GwtOX.js → document-DdwzfZ1g.js} +259 -211
- package/dist/{index-B31KeDzA.d.ts → index-CDrPUhBH.d.ts} +276 -181
- package/dist/index.d.ts +113 -143
- package/dist/index.js +469 -164
- package/dist/{loro-relay-doc-ssdYpuef.js → loro-relay-doc-cJSY-uau.js} +7 -2
- package/dist/relay.js +1 -1
- package/dist/testing.d.ts +2 -2
- package/dist/testing.js +4 -19
- package/package.json +7 -7
|
@@ -442,10 +442,6 @@ interface VideoDraft$1 {
|
|
|
442
442
|
}
|
|
443
443
|
//#endregion
|
|
444
444
|
//#region src/document/types.d.ts
|
|
445
|
-
declare const VIDEO_DOCUMENT_SCHEMA_VERSION: "video-document/v0";
|
|
446
|
-
/** A server-derived compatibility view, never an editor write authority. */
|
|
447
|
-
declare const ENTITY_TIMELINE_PROJECTION_SCHEMA_VERSION: "video-document/entity-projection-v1";
|
|
448
|
-
type VideoDocumentSchemaVersion = typeof VIDEO_DOCUMENT_SCHEMA_VERSION | typeof ENTITY_TIMELINE_PROJECTION_SCHEMA_VERSION;
|
|
449
445
|
type PartKind = 'video_clip' | 'speech' | 'caption' | 'bgm';
|
|
450
446
|
/**
|
|
451
447
|
* Project-level creation settings. Mirrors the IDL, but keeps the two fields the
|
|
@@ -645,17 +641,52 @@ type VideoDraftPartUnion = {
|
|
|
645
641
|
};
|
|
646
642
|
};
|
|
647
643
|
/**
|
|
648
|
-
*
|
|
649
|
-
*
|
|
650
|
-
*
|
|
651
|
-
* authoritative parts with the derived `duration_ms` re-injected (reference/17 §7)
|
|
652
|
-
* plus the engine extensions (`media_duration_ms`, the looser `SpeedShift`). This
|
|
653
|
-
* is the intentional superset over the IDL `VideoDraft` (see the extensions note).
|
|
644
|
+
* Legacy Draft import shape. It allows omitted durations and engine extensions
|
|
645
|
+
* so existing fixtures and migrations can state only the facts they have.
|
|
646
|
+
* Projection returns the narrower `VideoDraftContent` contract instead.
|
|
654
647
|
*/
|
|
655
648
|
type VideoDraft = Omit<VideoDraft$1, 'part_library' | 'video_creation_settings'> & {
|
|
656
649
|
part_library: Record<string, VideoDraftPartUnion> | undefined;
|
|
657
650
|
video_creation_settings?: VideoCreationSettings | undefined;
|
|
658
651
|
};
|
|
652
|
+
/**
|
|
653
|
+
* The complete content read model produced by the shared projection. Business
|
|
654
|
+
* identity, settings, thumbnail and revision counters are assembled by Director;
|
|
655
|
+
* keeping an explicit field list prevents new business DTO fields entering here.
|
|
656
|
+
*/
|
|
657
|
+
type VideoDraftContent = Pick<VideoDraft, 'timeline' | 'main_track' | 'above_main_tracks' | 'below_main_tracks' | 'part_aggregations'> & {
|
|
658
|
+
part_library: Record<string, VideoDraftContentPartUnion> | undefined;
|
|
659
|
+
};
|
|
660
|
+
/** Projection always states the duration field; legacy imports may omit it. */
|
|
661
|
+
type VideoDraftContentPartUnion = {
|
|
662
|
+
video_clip: VideoClipPart & {
|
|
663
|
+
duration_ms: number | undefined;
|
|
664
|
+
};
|
|
665
|
+
speech?: never;
|
|
666
|
+
caption?: never;
|
|
667
|
+
bgm?: never;
|
|
668
|
+
} | {
|
|
669
|
+
video_clip?: never;
|
|
670
|
+
speech: SpeechPart & {
|
|
671
|
+
duration_ms: number | undefined;
|
|
672
|
+
};
|
|
673
|
+
caption?: never;
|
|
674
|
+
bgm?: never;
|
|
675
|
+
} | {
|
|
676
|
+
video_clip?: never;
|
|
677
|
+
speech?: never;
|
|
678
|
+
caption: CaptionPart & {
|
|
679
|
+
duration_ms: number | undefined;
|
|
680
|
+
};
|
|
681
|
+
bgm?: never;
|
|
682
|
+
} | {
|
|
683
|
+
video_clip?: never;
|
|
684
|
+
speech?: never;
|
|
685
|
+
caption?: never;
|
|
686
|
+
bgm: BgmPart & {
|
|
687
|
+
duration_ms: number | undefined;
|
|
688
|
+
};
|
|
689
|
+
};
|
|
659
690
|
/** Authoritative timeline: `duration_ms` is derived (= longest track), not stored. */
|
|
660
691
|
interface Timeline {
|
|
661
692
|
unit_time_ms: number | undefined;
|
|
@@ -670,39 +701,19 @@ interface Timeline {
|
|
|
670
701
|
* is not, and passes any `>= 0` guard on its way to an editor that cannot use it.
|
|
671
702
|
*/
|
|
672
703
|
declare const DEFAULT_UNIT_TIME_MS = 33.333;
|
|
673
|
-
/**
|
|
674
|
-
* Project-level scalars that do not participate in track ordering. Grouped under
|
|
675
|
-
* `meta` because the loro-mirror `schema()` root only accepts container schemas,
|
|
676
|
-
* not bare scalars — so these must live inside a map container in storage. The
|
|
677
|
-
* domain type mirrors that storage shape 1:1 (RFC 03 §4) rather than flattening,
|
|
678
|
-
* keeping `VideoDocument` and the loro draft isomorphic and the mapping layer a
|
|
679
|
-
* near-identity. `schema_version` lives here too (it is a scalar fact).
|
|
680
|
-
*/
|
|
681
|
-
interface VideoDocumentMeta {
|
|
682
|
-
schema_version: VideoDocumentSchemaVersion;
|
|
683
|
-
draft_id?: string | undefined;
|
|
684
|
-
project_id: VideoDraft['project_id'];
|
|
685
|
-
owner_id: VideoDraft['owner_id'];
|
|
686
|
-
thumbnail_storage_key: VideoDraft['thumbnail_storage_key'];
|
|
687
|
-
chat_session_id: VideoDraft['chat_session_id'];
|
|
688
|
-
video_creation_settings: VideoDraft['video_creation_settings'];
|
|
689
|
-
/** Legacy imported version for v0; committed Entity revision for entity-projection-v1. */
|
|
690
|
-
version: VideoDraft['version'];
|
|
691
|
-
}
|
|
692
704
|
/**
|
|
693
705
|
* Authoritative collaborative document: only facts. Positioning lives on each
|
|
694
706
|
* `TrackItem.time_position`; absolute time, `part_aggregations`, and total
|
|
695
707
|
* duration are derived in the `VideoDraft` projection, not stored here (RFC 02 §6).
|
|
696
708
|
*
|
|
697
|
-
* The
|
|
698
|
-
*
|
|
709
|
+
* The content mirrors Loro storage: timeline, part library, and a single
|
|
710
|
+
* ordered `tracks` list (reference/17 §4). Business metadata stays in Director. A
|
|
699
711
|
* track's lane is expressed by its `parts_kind`, not by which container it lives
|
|
700
712
|
* in — the `main` / `above` / `below` three-pane view is reconstructed at
|
|
701
713
|
* projection time. Order is the list order itself, so there is no `lane` /
|
|
702
714
|
* `lane_order` field to diverge under concurrent edits.
|
|
703
715
|
*/
|
|
704
716
|
interface VideoDocument {
|
|
705
|
-
meta: VideoDocumentMeta;
|
|
706
717
|
timeline: Timeline | undefined;
|
|
707
718
|
tracks: Track[] | undefined;
|
|
708
719
|
part_library: Record<string, PartUnion> | undefined;
|
|
@@ -724,15 +735,193 @@ interface VideoDocumentValidationIssue {
|
|
|
724
735
|
severity?: VideoDocumentValidationIssueSeverity;
|
|
725
736
|
}
|
|
726
737
|
//#endregion
|
|
738
|
+
//#region src/document/mirror-schema.d.ts
|
|
739
|
+
declare const videoDocumentMirrorSchema: import("loro-mirror").RootSchemaType<{
|
|
740
|
+
timeline: import("loro-mirror").LoroMapSchema<{
|
|
741
|
+
unit_time_ms: /*elided*/any;
|
|
742
|
+
}> & {
|
|
743
|
+
options: {};
|
|
744
|
+
} & {
|
|
745
|
+
catchall: <C extends import("loro-mirror").SchemaType>(catchallSchema: C) => import("loro-mirror").LoroMapSchemaWithCatchall<{
|
|
746
|
+
unit_time_ms: /*elided*/any;
|
|
747
|
+
}, C>;
|
|
748
|
+
};
|
|
749
|
+
tracks: import("loro-mirror").LoroMovableListSchema<import("loro-mirror").LoroMapSchema<{
|
|
750
|
+
id: /*elided*/any;
|
|
751
|
+
parts_kind: /*elided*/any;
|
|
752
|
+
is_hidden: /*elided*/any;
|
|
753
|
+
items: /*elided*/any;
|
|
754
|
+
}> & {
|
|
755
|
+
options: {};
|
|
756
|
+
} & {
|
|
757
|
+
catchall: <C extends import("loro-mirror").SchemaType>(catchallSchema: C) => import("loro-mirror").LoroMapSchemaWithCatchall<{
|
|
758
|
+
id: /*elided*/any;
|
|
759
|
+
parts_kind: /*elided*/any;
|
|
760
|
+
is_hidden: /*elided*/any;
|
|
761
|
+
items: /*elided*/any;
|
|
762
|
+
}, C>;
|
|
763
|
+
}> & {
|
|
764
|
+
options: {};
|
|
765
|
+
};
|
|
766
|
+
part_library: import("loro-mirror").LoroMapSchemaWithCatchall<{}, import("loro-mirror").LoroMapSchema<{
|
|
767
|
+
video_clip: /*elided*/any;
|
|
768
|
+
speech: /*elided*/any;
|
|
769
|
+
caption: /*elided*/any;
|
|
770
|
+
bgm: /*elided*/any;
|
|
771
|
+
}> & {
|
|
772
|
+
options: {};
|
|
773
|
+
} & {
|
|
774
|
+
catchall: <C extends import("loro-mirror").SchemaType>(catchallSchema: C) => import("loro-mirror").LoroMapSchemaWithCatchall<{
|
|
775
|
+
video_clip: /*elided*/any;
|
|
776
|
+
speech: /*elided*/any;
|
|
777
|
+
caption: /*elided*/any;
|
|
778
|
+
bgm: /*elided*/any;
|
|
779
|
+
}, C>;
|
|
780
|
+
}> & {
|
|
781
|
+
options: {};
|
|
782
|
+
};
|
|
783
|
+
}> & {
|
|
784
|
+
options: {};
|
|
785
|
+
};
|
|
786
|
+
type VideoDocumentMirrorSchema = typeof videoDocumentMirrorSchema;
|
|
787
|
+
/**
|
|
788
|
+
* The mutable draft an op's `transact` callback edits, inferred from the schema.
|
|
789
|
+
*
|
|
790
|
+
* `InferInputType` is the schema's *input* shape: the declared business fields
|
|
791
|
+
* with the `$cid` container ids (which mirror injects into its output
|
|
792
|
+
* `InferType`) made optional, so ops assign plain objects without supplying
|
|
793
|
+
* `$cid`. Deriving it from the schema keeps draft and storage in lockstep — a
|
|
794
|
+
* schema change is a compile error at every edit site, not a silent drift.
|
|
795
|
+
* Reorders within `items` still diff to real Loro `move` ops because the schema
|
|
796
|
+
* keys items by `part_id`.
|
|
797
|
+
*/
|
|
798
|
+
type VideoDocumentDraft = InferInputType<VideoDocumentMirrorSchema>;
|
|
799
|
+
/** Track value as it appears in a draft. Derived from the single `tracks` movable list. */
|
|
800
|
+
type TrackDraft = NonNullable<NonNullable<VideoDocumentDraft['tracks']>[number]>;
|
|
801
|
+
/** A single track item in a draft. */
|
|
802
|
+
type TrackItemDraft = NonNullable<NonNullable<TrackDraft['items']>[number]>;
|
|
803
|
+
//#endregion
|
|
804
|
+
//#region src/timeline-core/bridge.d.ts
|
|
805
|
+
/**
|
|
806
|
+
* Bridge between the authoritative `VideoDocument` (position-only facts) and the
|
|
807
|
+
* flat `TimelineDoc` the cascade primitives solve over.
|
|
808
|
+
*
|
|
809
|
+
* The data flow is single-directional (RFC 02 §7/§10): ops write only facts
|
|
810
|
+
* (`time_position`, parts) to `VideoDocument`; absolute time, `part_aggregations`,
|
|
811
|
+
* total duration, and gap fillers are NOT stored — the projection derives them
|
|
812
|
+
* on read by running the cascade. There is no write-back of solved positions.
|
|
813
|
+
*
|
|
814
|
+
* - `solveVideoDocument` seeds a `TimelineDoc` from each item's `time_position`,
|
|
815
|
+
* runs the full cascade, and returns the derived read-view (abs / aggregations
|
|
816
|
+
* / duration). It is the single solve shared by the legacy `VideoDraft`
|
|
817
|
+
* projection.
|
|
818
|
+
* - `ensureLaneTrack` / `findLaneTrack` locate (or mint) a secondary lane's
|
|
819
|
+
* track row in the draft, so ops can write authoritative facts onto the right
|
|
820
|
+
* named container (lane = container).
|
|
821
|
+
*/
|
|
822
|
+
/** The projection-derived read-view of a `VideoDocument` (RFC 02 §7). */
|
|
823
|
+
interface SolvedVideoDocument {
|
|
824
|
+
absByPartId: Map<string, number>;
|
|
825
|
+
aggregations: PartAggregation[];
|
|
826
|
+
durationMs: number;
|
|
827
|
+
partLibrary: Record<string, PartUnion>;
|
|
828
|
+
/**
|
|
829
|
+
* Part ids of the gap fillers this solve minted.
|
|
830
|
+
*
|
|
831
|
+
* They exist only inside the solve: gap filling needs them so the clips after a
|
|
832
|
+
* gap land at the right absolute time, but they are not authoritative state and
|
|
833
|
+
* the read view does not carry them (see `fromVideoDocument`).
|
|
834
|
+
*
|
|
835
|
+
* Reported as ids rather than left for the caller to detect, because the caller
|
|
836
|
+
* *cannot* detect them. The obvious predicate — `origin_media_id === ''` — also
|
|
837
|
+
* matches an empty clip a writer placed on purpose (`batch_replace_video_clip_sequence`
|
|
838
|
+
* documents "Omit to create an empty clip placeholder"), and those are
|
|
839
|
+
* authoritative parts that must survive the projection. The mint callback is the
|
|
840
|
+
* only place that knows the difference.
|
|
841
|
+
*
|
|
842
|
+
* Note this deliberately excludes the fillers that gap filling *extended* rather
|
|
843
|
+
* than minted (`fillMainTrackTimeGaps` cases 1 and 2): those are authoritative
|
|
844
|
+
* empty clips already in `part_library`, and only their length is derived.
|
|
845
|
+
*/
|
|
846
|
+
derivedFillerPartIds: Set<string>;
|
|
847
|
+
}
|
|
848
|
+
/** How the caller obtained the document it is asking to be solved. */
|
|
849
|
+
interface SolveVideoDocumentOptions {
|
|
850
|
+
/**
|
|
851
|
+
* The producer already resolved every placement, so the legacy cascade must
|
|
852
|
+
* not run. Only an Entity projection can state this: its placement comes from
|
|
853
|
+
* Clip order / clip-anchor offsets / Marker targetRange, and re-solving would
|
|
854
|
+
* overwrite those and synthesize gap fillers the Entity graph never had.
|
|
855
|
+
*
|
|
856
|
+
* The document itself no longer carries its provenance (P7M14 moved business
|
|
857
|
+
* metadata out of the CRDT), so the caller states it. `hasResolvedPlacement`
|
|
858
|
+
* only verifies the claim — it is never the branch condition, because a
|
|
859
|
+
* legacy draft can satisfy it by accident and a broken projection can fail it.
|
|
860
|
+
*/
|
|
861
|
+
readonly placementResolved?: boolean;
|
|
862
|
+
}
|
|
863
|
+
/**
|
|
864
|
+
* Solve a `VideoDocument` (authoritative, position-only) into its derived
|
|
865
|
+
* read-view: absolute time per item, `part_aggregations`, and total duration.
|
|
866
|
+
* This is the read side of the single-directional flow — never written back.
|
|
867
|
+
*/
|
|
868
|
+
declare function solveVideoDocument(document: VideoDocument, options?: SolveVideoDocumentOptions): SolvedVideoDocument;
|
|
869
|
+
/** The named container a secondary lane lives in. */
|
|
870
|
+
type SecondaryLane = 'speech' | 'caption' | 'bgm';
|
|
871
|
+
/** A lane's track kind: the `video_clip` main lane plus the three secondary lanes. */
|
|
872
|
+
type LaneKind = SecondaryLane | 'video_clip';
|
|
873
|
+
/**
|
|
874
|
+
* The four lanes in top-to-bottom stack order — the order a `tracks` list holds
|
|
875
|
+
* them in (see {@link laneRank}).
|
|
876
|
+
*
|
|
877
|
+
* Exported so a document can be seeded with all four lanes up front. That seed is
|
|
878
|
+
* not cosmetic: {@link ensureLaneTrack} is find-then-mint over a `LoroMovableList`,
|
|
879
|
+
* so two concurrent writers that each mint the same absent lane both keep their
|
|
880
|
+
* row, and the merged document holds two tracks for one lane. For the main lane
|
|
881
|
+
* that is fatal — `videoDocumentSchema` allows at most one `video_clip` track, so
|
|
882
|
+
* the merged document stops being projectable at all, symmetrically on both
|
|
883
|
+
* replicas. Pre-seeding every lane makes `ensureLaneTrack` always take its find
|
|
884
|
+
* branch, which removes the race by construction rather than by detection.
|
|
885
|
+
*
|
|
886
|
+
* What closes the race is that a track with the lane's `parts_kind` EXISTS — the
|
|
887
|
+
* lookup is by kind, not by id. So a seed is only safe if it covers every lane:
|
|
888
|
+
* a partial seed leaves the uncovered lanes exactly as exposed as before.
|
|
889
|
+
*/
|
|
890
|
+
declare const LANE_KINDS_IN_STACK_ORDER: readonly LaneKind[];
|
|
891
|
+
/**
|
|
892
|
+
* The conventional track id for a lane (`main_track`, `<kind>_track`). Shared by
|
|
893
|
+
* the up-front seed and {@link ensureLaneTrack}'s lazy mint so a document's lane
|
|
894
|
+
* ids do not depend on which of the two created the track.
|
|
895
|
+
*
|
|
896
|
+
* Ids are cosmetic to the merge itself — lane lookup goes by `parts_kind`, so
|
|
897
|
+
* drifting them apart would not reopen the concurrent-mint race. They matter to
|
|
898
|
+
* readers that address a lane by id (the FE editor's panes, fixtures), which is
|
|
899
|
+
* why there is one convention rather than two.
|
|
900
|
+
*/
|
|
901
|
+
declare function laneTrackId(kind: LaneKind): string;
|
|
902
|
+
/**
|
|
903
|
+
* Locate a lane's track row in the single `tracks` list by kind, minting an empty
|
|
904
|
+
* row in lane-stacking order if absent (reference/17 §4: lane = `parts_kind`).
|
|
905
|
+
* Ops use this to write authoritative items onto the right lane. The track id
|
|
906
|
+
* comes from {@link laneTrackId}, shared with the up-front seed.
|
|
907
|
+
*
|
|
908
|
+
* The mint branch is a concurrency hazard, not a convenience: see
|
|
909
|
+
* {@link LANE_KINDS_IN_STACK_ORDER}. A document seeded with all four lanes never
|
|
910
|
+
* reaches it.
|
|
911
|
+
*/
|
|
912
|
+
declare function ensureLaneTrack(draft: VideoDocumentDraft, kind: LaneKind): TrackDraft;
|
|
913
|
+
/** Find a secondary lane's track row without minting it. */
|
|
914
|
+
declare function findLaneTrack(draft: VideoDocumentDraft, kind: SecondaryLane): TrackDraft | undefined;
|
|
915
|
+
//#endregion
|
|
727
916
|
//#region src/document/projection.d.ts
|
|
728
917
|
/**
|
|
729
|
-
* Projection between
|
|
730
|
-
*
|
|
918
|
+
* Projection between authoritative `VideoDocument` and compatible content
|
|
919
|
+
* layouts (RFC 02 §5/§7). Both directions live here:
|
|
731
920
|
*
|
|
732
921
|
* - `toVideoDocument` ingests a `VideoDraft`, deriving each item's `position`
|
|
733
922
|
* from the legacy absolute layout + aggregations; derived values (abs time,
|
|
734
923
|
* `part_aggregations`, total duration) are dropped.
|
|
735
|
-
* - `fromVideoDocument` solves a `VideoDocument`
|
|
924
|
+
* - `fromVideoDocument` solves a `VideoDocument` into `VideoDraftContent` via the
|
|
736
925
|
* timeline-core cascade, re-deriving exactly those values.
|
|
737
926
|
*
|
|
738
927
|
* Business validation lives in `validation.ts`; `fromVideoDocument` asserts a
|
|
@@ -744,7 +933,7 @@ interface VideoDocumentValidationIssue {
|
|
|
744
933
|
* aggregations (RFC 02 §4/§5). Absolute time, `part_aggregations`, and total
|
|
745
934
|
* duration are dropped — they are re-derived by the projection.
|
|
746
935
|
*/
|
|
747
|
-
declare function toVideoDocument(draft: VideoDraft): VideoDocument;
|
|
936
|
+
declare function toVideoDocument(draft: Pick<VideoDraft, keyof VideoDraftContent>): VideoDocument;
|
|
748
937
|
/** speech/attachment part_id → its host video part_id + relative offset. */
|
|
749
938
|
type SpeechHostMap = Map<string, {
|
|
750
939
|
hostPartId: string;
|
|
@@ -784,8 +973,8 @@ interface DerivedItemPosition {
|
|
|
784
973
|
*/
|
|
785
974
|
declare function derivePositionFromAbs(partId: string, abs: number, isMain: boolean, speechHost: SpeechHostMap, partLibrary: Record<string, PartUnion | string | undefined>): DerivedItemPosition;
|
|
786
975
|
/**
|
|
787
|
-
* Project
|
|
788
|
-
*
|
|
976
|
+
* Project `VideoDocument` into `VideoDraftContent`, solving each item's
|
|
977
|
+
* absolute position, the `part_aggregations`, and
|
|
789
978
|
* the total duration via the timeline-core cascade.
|
|
790
979
|
*
|
|
791
980
|
* The read-view is a compatibility contract, and the IDL declares
|
|
@@ -799,32 +988,15 @@ declare function derivePositionFromAbs(partId: string, abs: number, isMain: bool
|
|
|
799
988
|
* These two are defaultable because the projection knows their values on its own:
|
|
800
989
|
* absent `unit_time_ms` means "no display granularity was ever stated" and absent
|
|
801
990
|
* `is_hidden` means "this track was never hidden". `version` is NOT defaultable
|
|
802
|
-
* here —
|
|
803
|
-
*
|
|
991
|
+
* here — it belongs to Director assembly using the server envelope update_seq.
|
|
992
|
+
* Neither business metadata nor a revision counter belongs in content projection.
|
|
804
993
|
*/
|
|
805
|
-
declare function fromVideoDocument(document: VideoDocument):
|
|
994
|
+
declare function fromVideoDocument(document: VideoDocument, options?: SolveVideoDocumentOptions): VideoDraftContent;
|
|
806
995
|
//#endregion
|
|
807
996
|
//#region src/document/initial-document.d.ts
|
|
808
|
-
/**
|
|
809
|
-
* The project facts a freshly created document is built from — exactly the five
|
|
810
|
-
* fields Director sets when it creates a draft row, and nothing else.
|
|
811
|
-
*
|
|
812
|
-
* Deliberately not a whole `VideoDraft`: tracks and the part library of a new
|
|
813
|
-
* document are empty by definition, so accepting them would mean accepting
|
|
814
|
-
* values that must always be empty, and every such field is a place for a future
|
|
815
|
-
* caller to send something that is silently dropped. The narrow shape makes the
|
|
816
|
-
* "a new document has no content" rule structural instead of a convention.
|
|
817
|
-
*/
|
|
818
|
-
interface InitialDocumentFacts {
|
|
819
|
-
draftId: string;
|
|
820
|
-
projectId: string | undefined;
|
|
821
|
-
ownerId: string | undefined;
|
|
822
|
-
chatSessionId: string | undefined;
|
|
823
|
-
videoCreationSettings: VideoCreationSettings | undefined;
|
|
824
|
-
}
|
|
825
997
|
/**
|
|
826
998
|
* Build the `VideoDocument` a newly created project starts from: the caller's
|
|
827
|
-
*
|
|
999
|
+
* no parts and one empty track per lane. Business facts remain in Director.
|
|
828
1000
|
*
|
|
829
1001
|
* The empty lane tracks are the reason this function exists rather than callers
|
|
830
1002
|
* assembling a document inline. Lane tracks are otherwise minted lazily by the
|
|
@@ -845,7 +1017,7 @@ interface InitialDocumentFacts {
|
|
|
845
1017
|
* supplies, and total duration is derived on read (RFC 02 §6), so a new document
|
|
846
1018
|
* has no timeline fact to state.
|
|
847
1019
|
*/
|
|
848
|
-
declare function buildInitialVideoDocument(
|
|
1020
|
+
declare function buildInitialVideoDocument(): VideoDocument;
|
|
849
1021
|
//#endregion
|
|
850
1022
|
//#region ../medeo-dsl/src/ids.d.ts
|
|
851
1023
|
declare const entityIdBrand: unique symbol;
|
|
@@ -976,7 +1148,7 @@ declare class EntityTimelineProjectionError extends Error {
|
|
|
976
1148
|
* consulted as an editing fact. Peer IDs appear only in this derived read
|
|
977
1149
|
* contract, reconstructed from relations; they are not stored in payloads.
|
|
978
1150
|
*/
|
|
979
|
-
declare function projectEntityTimeline(rows: EntityRelationRows
|
|
1151
|
+
declare function projectEntityTimeline(rows: EntityRelationRows): VideoDocument;
|
|
980
1152
|
//#endregion
|
|
981
1153
|
//#region src/document/entity-timeline-layout.d.ts
|
|
982
1154
|
type EntityTimelineTrackRole = 'video_clip' | 'speech' | 'caption' | 'bgm';
|
|
@@ -1039,95 +1211,6 @@ declare class VideoDocumentValidationError extends Error {
|
|
|
1039
1211
|
declare function assertValidVideoDocument(document: unknown): asserts document is VideoDocument;
|
|
1040
1212
|
declare function validateVideoDocument(document: unknown): VideoDocumentValidationIssue[];
|
|
1041
1213
|
//#endregion
|
|
1042
|
-
//#region src/document/mirror-schema.d.ts
|
|
1043
|
-
declare const videoDocumentMirrorSchema: import("loro-mirror").RootSchemaType<{
|
|
1044
|
-
meta: import("loro-mirror").LoroMapSchema<{
|
|
1045
|
-
schema_version: /*elided*/any;
|
|
1046
|
-
draft_id: /*elided*/any;
|
|
1047
|
-
project_id: /*elided*/any;
|
|
1048
|
-
owner_id: /*elided*/any;
|
|
1049
|
-
thumbnail_storage_key: /*elided*/any;
|
|
1050
|
-
chat_session_id: /*elided*/any;
|
|
1051
|
-
video_creation_settings: /*elided*/any;
|
|
1052
|
-
version: /*elided*/any;
|
|
1053
|
-
}> & {
|
|
1054
|
-
options: {};
|
|
1055
|
-
} & {
|
|
1056
|
-
catchall: <C extends import("loro-mirror").SchemaType>(catchallSchema: C) => import("loro-mirror").LoroMapSchemaWithCatchall<{
|
|
1057
|
-
schema_version: /*elided*/any;
|
|
1058
|
-
draft_id: /*elided*/any;
|
|
1059
|
-
project_id: /*elided*/any;
|
|
1060
|
-
owner_id: /*elided*/any;
|
|
1061
|
-
thumbnail_storage_key: /*elided*/any;
|
|
1062
|
-
chat_session_id: /*elided*/any;
|
|
1063
|
-
video_creation_settings: /*elided*/any;
|
|
1064
|
-
version: /*elided*/any;
|
|
1065
|
-
}, C>;
|
|
1066
|
-
};
|
|
1067
|
-
timeline: import("loro-mirror").LoroMapSchema<{
|
|
1068
|
-
unit_time_ms: /*elided*/any;
|
|
1069
|
-
}> & {
|
|
1070
|
-
options: {};
|
|
1071
|
-
} & {
|
|
1072
|
-
catchall: <C extends import("loro-mirror").SchemaType>(catchallSchema: C) => import("loro-mirror").LoroMapSchemaWithCatchall<{
|
|
1073
|
-
unit_time_ms: /*elided*/any;
|
|
1074
|
-
}, C>;
|
|
1075
|
-
};
|
|
1076
|
-
tracks: import("loro-mirror").LoroMovableListSchema<import("loro-mirror").LoroMapSchema<{
|
|
1077
|
-
id: /*elided*/any;
|
|
1078
|
-
parts_kind: /*elided*/any;
|
|
1079
|
-
is_hidden: /*elided*/any;
|
|
1080
|
-
items: /*elided*/any;
|
|
1081
|
-
}> & {
|
|
1082
|
-
options: {};
|
|
1083
|
-
} & {
|
|
1084
|
-
catchall: <C extends import("loro-mirror").SchemaType>(catchallSchema: C) => import("loro-mirror").LoroMapSchemaWithCatchall<{
|
|
1085
|
-
id: /*elided*/any;
|
|
1086
|
-
parts_kind: /*elided*/any;
|
|
1087
|
-
is_hidden: /*elided*/any;
|
|
1088
|
-
items: /*elided*/any;
|
|
1089
|
-
}, C>;
|
|
1090
|
-
}> & {
|
|
1091
|
-
options: {};
|
|
1092
|
-
};
|
|
1093
|
-
part_library: import("loro-mirror").LoroMapSchemaWithCatchall<{}, import("loro-mirror").LoroMapSchema<{
|
|
1094
|
-
video_clip: /*elided*/any;
|
|
1095
|
-
speech: /*elided*/any;
|
|
1096
|
-
caption: /*elided*/any;
|
|
1097
|
-
bgm: /*elided*/any;
|
|
1098
|
-
}> & {
|
|
1099
|
-
options: {};
|
|
1100
|
-
} & {
|
|
1101
|
-
catchall: <C extends import("loro-mirror").SchemaType>(catchallSchema: C) => import("loro-mirror").LoroMapSchemaWithCatchall<{
|
|
1102
|
-
video_clip: /*elided*/any;
|
|
1103
|
-
speech: /*elided*/any;
|
|
1104
|
-
caption: /*elided*/any;
|
|
1105
|
-
bgm: /*elided*/any;
|
|
1106
|
-
}, C>;
|
|
1107
|
-
}> & {
|
|
1108
|
-
options: {};
|
|
1109
|
-
};
|
|
1110
|
-
}> & {
|
|
1111
|
-
options: {};
|
|
1112
|
-
};
|
|
1113
|
-
type VideoDocumentMirrorSchema = typeof videoDocumentMirrorSchema;
|
|
1114
|
-
/**
|
|
1115
|
-
* The mutable draft an op's `transact` callback edits, inferred from the schema.
|
|
1116
|
-
*
|
|
1117
|
-
* `InferInputType` is the schema's *input* shape: the declared business fields
|
|
1118
|
-
* with the `$cid` container ids (which mirror injects into its output
|
|
1119
|
-
* `InferType`) made optional, so ops assign plain objects without supplying
|
|
1120
|
-
* `$cid`. Deriving it from the schema keeps draft and storage in lockstep — a
|
|
1121
|
-
* schema change is a compile error at every edit site, not a silent drift.
|
|
1122
|
-
* Reorders within `items` still diff to real Loro `move` ops because the schema
|
|
1123
|
-
* keys items by `part_id`.
|
|
1124
|
-
*/
|
|
1125
|
-
type VideoDocumentDraft = InferInputType<VideoDocumentMirrorSchema>;
|
|
1126
|
-
/** Track value as it appears in a draft. Derived from the single `tracks` movable list. */
|
|
1127
|
-
type TrackDraft = NonNullable<NonNullable<VideoDocumentDraft['tracks']>[number]>;
|
|
1128
|
-
/** A single track item in a draft. */
|
|
1129
|
-
type TrackItemDraft = NonNullable<NonNullable<TrackDraft['items']>[number]>;
|
|
1130
|
-
//#endregion
|
|
1131
1214
|
//#region src/editor/id-gen.d.ts
|
|
1132
1215
|
/**
|
|
1133
1216
|
* Part-id generation, aligned with the online ecosystem.
|
|
@@ -1350,13 +1433,12 @@ interface TransactAudit {
|
|
|
1350
1433
|
* position. The caller never materializes a layout (ADR 0009).
|
|
1351
1434
|
*/
|
|
1352
1435
|
interface SemanticDocumentAdapter extends SnapshotReadable {
|
|
1353
|
-
/** True once the document holds real content (a bootstrapped/synced snapshot). */
|
|
1354
|
-
hasContent(): boolean;
|
|
1355
1436
|
/**
|
|
1356
|
-
* Apply one op's
|
|
1357
|
-
*
|
|
1437
|
+
* Apply one op's domain mutation in a single synchronous transaction. `edit`
|
|
1438
|
+
* must finish before returning; async callbacks/await are unsupported. The
|
|
1439
|
+
* adapter diffs the resulting draft and commits once with `audit`.
|
|
1358
1440
|
* A throw in `edit` rolls back (the draft is discarded, Loro untouched). An
|
|
1359
|
-
* edit that changes nothing produces no commit (no phantom
|
|
1441
|
+
* edit that changes nothing produces no domain commit (no phantom undo step).
|
|
1360
1442
|
*/
|
|
1361
1443
|
transact(edit: (draft: VideoDocumentDraft) => void, audit: TransactAudit): void;
|
|
1362
1444
|
}
|
|
@@ -1492,6 +1574,19 @@ declare class SemanticEditor {
|
|
|
1492
1574
|
private computeAddInsertIndex;
|
|
1493
1575
|
}
|
|
1494
1576
|
//#endregion
|
|
1577
|
+
//#region src/document/document-mutation-guard.d.ts
|
|
1578
|
+
/**
|
|
1579
|
+
* @internal
|
|
1580
|
+
* Shared by synchronous mutation entry points for one document. The session
|
|
1581
|
+
* closes it before teardown callbacks can attempt another write.
|
|
1582
|
+
*/
|
|
1583
|
+
declare class DocumentMutationGuard {
|
|
1584
|
+
private running;
|
|
1585
|
+
private closed;
|
|
1586
|
+
run<T>(mutation: () => T): T;
|
|
1587
|
+
close(): void;
|
|
1588
|
+
}
|
|
1589
|
+
//#endregion
|
|
1495
1590
|
//#region src/document/mirror-adapter.d.ts
|
|
1496
1591
|
interface MirrorVideoDocumentOptions {
|
|
1497
1592
|
peerId?: PeerID;
|
|
@@ -1507,22 +1602,31 @@ interface MirrorVideoDocumentOptions {
|
|
|
1507
1602
|
* - `transact(edit, audit)` runs the whole op in one `mirror.setState` callback:
|
|
1508
1603
|
* one diff, one `doc.commit` carrying the audit message. The callback edits an
|
|
1509
1604
|
* immer draft, so a throw inside it discards the draft and never touches Loro
|
|
1510
|
-
* (natural rollback)
|
|
1605
|
+
* (natural rollback) without a document checkout or compensating commit.
|
|
1511
1606
|
* - mirror's `idSelector` (track items keyed by `part_id`) diffs reorders to
|
|
1512
1607
|
* real Loro `move` ops on every lane, so per-item CRDT identity survives on
|
|
1513
1608
|
* main and secondary tracks alike.
|
|
1514
1609
|
*/
|
|
1515
1610
|
declare class MirrorVideoDocumentAdapter implements SemanticDocumentAdapter {
|
|
1516
1611
|
readonly doc: LoroDoc;
|
|
1612
|
+
private readonly mutationGuard;
|
|
1517
1613
|
private readonly mirror;
|
|
1518
|
-
|
|
1614
|
+
private disposed;
|
|
1615
|
+
constructor(doc: LoroDoc, mutationGuard?: DocumentMutationGuard);
|
|
1519
1616
|
snapshot(): VideoDocument;
|
|
1520
1617
|
/**
|
|
1521
|
-
*
|
|
1522
|
-
*
|
|
1523
|
-
*
|
|
1618
|
+
* Native Entity authority: placement is already solved by the Entity graph.
|
|
1619
|
+
*
|
|
1620
|
+
* The root check goes through `getShallowValue` first because `getMap` creates
|
|
1621
|
+
* the container on access — probing a legacy document for `medeo` would
|
|
1622
|
+
* otherwise mutate it, which a read must never do.
|
|
1524
1623
|
*/
|
|
1525
|
-
|
|
1624
|
+
isEntityDocument(): boolean;
|
|
1625
|
+
/**
|
|
1626
|
+
* Release mirror subscriptions; do not reuse this adapter afterwards.
|
|
1627
|
+
* The caller still owns the borrowed LoroDoc.
|
|
1628
|
+
*/
|
|
1629
|
+
dispose(): void;
|
|
1526
1630
|
/**
|
|
1527
1631
|
* Apply one op as a single transaction. `edit` mutates the immer draft; mirror
|
|
1528
1632
|
* diffs the result and commits once with the audit `message`. A throw in `edit`
|
|
@@ -1530,15 +1634,12 @@ declare class MirrorVideoDocumentAdapter implements SemanticDocumentAdapter {
|
|
|
1530
1634
|
* skips the commit — matching the prior "empty op leaves no audit" behavior.
|
|
1531
1635
|
*/
|
|
1532
1636
|
transact(edit: (draft: VideoDocumentDraft) => void, audit: TransactAudit): void;
|
|
1637
|
+
private assertActive;
|
|
1533
1638
|
}
|
|
1534
1639
|
/** Build a fresh Loro doc seeded with `document` through the mirror. */
|
|
1535
1640
|
declare function createMirrorVideoDocument(document: VideoDocument, options?: MirrorVideoDocumentOptions): LoroDoc;
|
|
1536
1641
|
/** Build a `MirrorVideoDocumentAdapter` over a fresh doc seeded with `document`. */
|
|
1537
1642
|
declare function createMirrorVideoDocumentAdapter(document: VideoDocument, options?: MirrorVideoDocumentOptions): MirrorVideoDocumentAdapter;
|
|
1538
|
-
/** Host-only replacement of a derived view, retaining the existing Loro history. */
|
|
1539
|
-
declare function applyEntityTimelineProjection(doc: LoroDoc, projection: VideoDocument, entityRevision: number): Uint8Array;
|
|
1540
|
-
/** Write a whole `VideoDocument` into a draft (seed a fresh doc / plain-memory state). */
|
|
1541
|
-
declare function writeVideoDocumentToDraft(draft: VideoDocumentDraft, document: VideoDocument): void;
|
|
1542
1643
|
//#endregion
|
|
1543
1644
|
//#region src/document/plain-memory-adapter.d.ts
|
|
1544
1645
|
/**
|
|
@@ -1552,6 +1653,12 @@ interface JournalEntry extends TransactAudit {
|
|
|
1552
1653
|
interface PlainMemoryAdapterOptions {
|
|
1553
1654
|
/** Underlying id mint; wrapped so each call inside a transact is journaled. */
|
|
1554
1655
|
idFactory?: PartIdFactory;
|
|
1656
|
+
/**
|
|
1657
|
+
* Refuse every `transact`. Set when the seed document is an Entity projection:
|
|
1658
|
+
* its timeline is owned by the Entity graph, and the document itself no longer
|
|
1659
|
+
* states its provenance (business metadata left the CRDT), so the caller does.
|
|
1660
|
+
*/
|
|
1661
|
+
readOnly?: boolean;
|
|
1555
1662
|
}
|
|
1556
1663
|
/**
|
|
1557
1664
|
* Pure in-memory `SemanticDocumentAdapter` — no Loro/WASM. Holds a
|
|
@@ -1575,6 +1682,7 @@ declare class PlainMemoryAdapter implements SemanticDocumentAdapter {
|
|
|
1575
1682
|
* use this so every minted id is appended to the current transact's list.
|
|
1576
1683
|
*/
|
|
1577
1684
|
readonly idFactory: PartIdFactory;
|
|
1685
|
+
private readonly readOnly;
|
|
1578
1686
|
constructor(document: VideoDocument, options?: PlainMemoryAdapterOptions);
|
|
1579
1687
|
get journal(): readonly JournalEntry[];
|
|
1580
1688
|
hasContent(): boolean;
|
|
@@ -1593,9 +1701,9 @@ declare function createPlainMemoryAdapter(document: VideoDocument, options?: Pla
|
|
|
1593
1701
|
/**
|
|
1594
1702
|
* Project the mirror state (`VideoDocumentDraft`) into the authoritative
|
|
1595
1703
|
* `VideoDocument`. The storage shape is isomorphic to the domain shape (RFC 03
|
|
1596
|
-
* §4, reference/17 §4:
|
|
1704
|
+
* §4, reference/17 §4: timeline + a single `tracks` list + part_library), so this
|
|
1597
1705
|
* is a near-identity — it reads `time_position` / `fallback_abs_ms` JSON blobs
|
|
1598
|
-
* back into structured values and
|
|
1706
|
+
* back into structured values and selects content fields. Legacy meta is ignored.
|
|
1599
1707
|
*
|
|
1600
1708
|
* It maps only authoritative facts (RFC 02 §6): `part_id` + `time_position`. The
|
|
1601
1709
|
* projection-derived `VideoDraft` read-view (absolute time, `part_aggregations`,
|
|
@@ -1671,19 +1779,6 @@ declare const partUnionSchema: z.ZodUnion<readonly [z.ZodObject<{
|
|
|
1671
1779
|
}, z.core.$loose>;
|
|
1672
1780
|
}, z.core.$loose>]>;
|
|
1673
1781
|
declare const videoDocumentSchema: z.ZodObject<{
|
|
1674
|
-
meta: z.ZodObject<{
|
|
1675
|
-
schema_version: z.ZodEnum<{
|
|
1676
|
-
"video-document/v0": "video-document/v0";
|
|
1677
|
-
"video-document/entity-projection-v1": "video-document/entity-projection-v1";
|
|
1678
|
-
}>;
|
|
1679
|
-
draft_id: z.ZodOptional<z.ZodString>;
|
|
1680
|
-
project_id: z.ZodOptional<z.ZodString>;
|
|
1681
|
-
owner_id: z.ZodOptional<z.ZodString>;
|
|
1682
|
-
thumbnail_storage_key: z.ZodOptional<z.ZodString>;
|
|
1683
|
-
chat_session_id: z.ZodOptional<z.ZodString>;
|
|
1684
|
-
video_creation_settings: z.ZodOptional<z.ZodUnknown>;
|
|
1685
|
-
version: z.ZodOptional<z.ZodNumber>;
|
|
1686
|
-
}, z.core.$loose>;
|
|
1687
1782
|
timeline: z.ZodOptional<z.ZodObject<{
|
|
1688
1783
|
unit_time_ms: z.ZodOptional<z.ZodNumber>;
|
|
1689
1784
|
}, z.core.$loose>>;
|
|
@@ -1775,4 +1870,4 @@ declare const videoDocumentSchema: z.ZodObject<{
|
|
|
1775
1870
|
}, z.core.$loose>]>>>;
|
|
1776
1871
|
}, z.core.$loose>;
|
|
1777
1872
|
//#endregion
|
|
1778
|
-
export {
|
|
1873
|
+
export { SpeechHostMap as $, assertValidVideoDocument as A, VideoDocumentValidationIssueCode as At, EntityRow as B, SpeedShift as Bt, isImplementedSemanticOpKind as C, Timeline as Ct, PartIdFactory as D, VideoClipPart as Dt, ValidationError as E, TrackItemTimePosition as Et, ResolvedEntityTrack as F, speedOf as Ft, SequenceDuration as G, CaptionSegmentSelection as H, Track$1 as Ht, resolveEntityTimelineLayout as I, Attachment as It, JsonObject as J, SequenceRange as K, projectEntityTimeline as L, CaptionPart$1 as Lt, EntityTimelineTrackRole as M, VideoDraftContent as Mt, ResolvedEntityClipPlacement as N, VideoDraftPartUnion as Nt, generatePartId as O, VideoDocument as Ot, ResolvedEntityTimelineLayout as P, effectiveVideoClipDurationMs as Pt, DerivedItemPosition as Q, EntityTimelineProjectionError as R, CaptionStyle as Rt, SemanticOpKind as S, SpeechPart as St, SnapshotReadable as T, TrackItem as Tt, CaptionStyleFields as U, TrackItem$1 as Ut, RelationRow as V, Timeline$1 as Vt, ScriptTextSegment as W, EntityId as X, JsonValue as Y, buildInitialVideoDocument as Z, SemanticOpName as _, CaptionDisplayCue as _t, PlainMemoryAdapter as a, LaneKind as at, ImplementedSemanticOpKind as b, PartKind as bt, MirrorVideoDocumentAdapter as c, findLaneTrack as ct, createMirrorVideoDocumentAdapter as d, TrackDraft as dt, buildSpeechHostMap as et, CommitOptions as f, TrackItemDraft as ft, SemanticOpInput as g, BgmPart as gt, SemanticEditor as h, videoDocumentMirrorSchema as ht, JournalEntry as i, LANE_KINDS_IN_STACK_ORDER as it, validateVideoDocument as j, VideoDraft as jt, VideoDocumentValidationError as k, VideoDocumentValidationIssue as kt, MirrorVideoDocumentOptions as l, laneTrackId as lt, SemanticDocumentAdapter as m, VideoDocumentMirrorSchema as mt, videoDocumentSchema as n, fromVideoDocument as nt, PlainMemoryAdapterOptions as o, SolvedVideoDocument as ot, OpActor as p, VideoDocumentDraft as pt, VoiceDescriptor as q, readVideoDocumentFromDraft as r, toVideoDocument as rt, createPlainMemoryAdapter as s, ensureLaneTrack as st, partUnionSchema as t, derivePositionFromAbs as tt, createMirrorVideoDocument as u, solveVideoDocument as ut, TransactAudit as v, CaptionPart as vt, SchemaValidator as w, Track as wt, PlannedSemanticOpKind as x, PartUnion as xt, IMPLEMENTED_SEMANTIC_OP_KINDS as y, DEFAULT_UNIT_TIME_MS as yt, EntityRelationRows as z, PartAggregation as zt };
|