@mengine/medeo-client 2.0.1-alpha.8 → 2.0.1-alpha.9

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.
@@ -1448,62 +1448,84 @@ function emptyLaneTracks() {
1448
1448
  //#endregion
1449
1449
  //#region ../medeo-dsl/src/entities.ts
1450
1450
  /**
1451
- * The declared trait set of every known kind.
1451
+ * What every known entity kind declares.
1452
1452
  *
1453
- * `caption` carries `sequence` on purpose: a Caption owns the display timing of
1454
- * the one AudioScript segment it shows, which is what admits it into a Clip.
1455
- * `voice` carries no media or sequence trait — it is a timbre identity, not
1456
- * playable content; a rendered voiceover is an `audio` entity.
1453
+ * `kinds` is a multi-declaration: every entry holds at the same time, the first
1454
+ * naming the object and the rest the properties it shares with others. The
1455
+ * order carries no priority, endpoint role, or edit sequence — an operation
1456
+ * asks whether the entity declares the kind it needs, never what its "main
1457
+ * type" is.
1458
+ *
1459
+ * `Caption` declares `Sequence` on purpose: it owns the display timing of the
1460
+ * one AudioScript segment it shows, which is what admits it into a Clip.
1461
+ * `Voice` declares neither `MediaFile` nor `Sequence` — it is a timbre
1462
+ * identity, not playable content; a rendered voiceover is an `audio` entity.
1457
1463
  */
1458
- const ENTITY_TRAIT_KINDS = Object.freeze({
1464
+ const ENTITY_KINDS = Object.freeze({
1459
1465
  axvideo: Object.freeze([
1460
- "container",
1461
- "sequence",
1462
- "visual",
1463
- "audible"
1466
+ "AXVideo",
1467
+ "Container",
1468
+ "Sequence",
1469
+ "Visual",
1470
+ "Audible"
1471
+ ]),
1472
+ timeline: Object.freeze(["Timeline", "Container"]),
1473
+ track: Object.freeze([
1474
+ "Track",
1475
+ "Container",
1476
+ "Sequence"
1464
1477
  ]),
1465
- timeline: Object.freeze(["container"]),
1466
- track: Object.freeze(["container", "sequence"]),
1467
- clip: Object.freeze(["container"]),
1468
- asset: Object.freeze([]),
1478
+ clip: Object.freeze(["Clip", "Container"]),
1479
+ asset: Object.freeze(["Asset"]),
1469
1480
  video: Object.freeze([
1470
- "media-file",
1471
- "sequence",
1472
- "visual",
1473
- "audible"
1481
+ "Video",
1482
+ "MediaFile",
1483
+ "Sequence",
1484
+ "Visual",
1485
+ "Audible"
1474
1486
  ]),
1475
1487
  audio: Object.freeze([
1476
- "media-file",
1477
- "sequence",
1478
- "audible"
1488
+ "Audio",
1489
+ "MediaFile",
1490
+ "Sequence",
1491
+ "Audible"
1479
1492
  ]),
1480
1493
  image: Object.freeze([
1481
- "media-file",
1482
- "sequence",
1483
- "visual"
1494
+ "Image",
1495
+ "MediaFile",
1496
+ "Sequence",
1497
+ "Visual"
1484
1498
  ]),
1485
- voice: Object.freeze(["container", "ip-bound"]),
1486
- "sequence-marker": Object.freeze([]),
1487
- viewport: Object.freeze([]),
1488
- "audio-script": Object.freeze(["segment-text"]),
1489
- "phonetic-script": Object.freeze(["segment-text"]),
1490
- caption: Object.freeze(["segment-text", "sequence"])
1499
+ voice: Object.freeze([
1500
+ "Voice",
1501
+ "Container",
1502
+ "IPBound"
1503
+ ]),
1504
+ "sequence-marker": Object.freeze(["SequenceMarker"]),
1505
+ viewport: Object.freeze(["Viewport"]),
1506
+ "audio-script": Object.freeze(["AudioScript", "SegmentText"]),
1507
+ "phonetic-script": Object.freeze(["PhoneticScript", "SegmentText"]),
1508
+ caption: Object.freeze([
1509
+ "Caption",
1510
+ "SegmentText",
1511
+ "Sequence"
1512
+ ])
1491
1513
  });
1492
- /** Declared traits of a known kind; extension kinds declare none through this table. */
1493
- function traitKindsOf(entityKind) {
1494
- return isKnownEntityKind(entityKind) ? ENTITY_TRAIT_KINDS[entityKind] : [];
1514
+ /** What a known kind declares; extension kinds declare nothing through this table. */
1515
+ function kindsOf(entityKind) {
1516
+ return isKnownEntityKind(entityKind) ? ENTITY_KINDS[entityKind] : [];
1495
1517
  }
1496
- function hasTraitKind(entityKind, trait) {
1497
- return traitKindsOf(entityKind).includes(trait);
1518
+ function declaresKind(entityKind, kind) {
1519
+ return kindsOf(entityKind).includes(kind);
1498
1520
  }
1499
1521
  /**
1500
- * Sequence admission asks the declared traits first, so a kind that does not
1501
- * declare `sequence` can never buy its way in by carrying the fields. Extension
1502
- * kinds declare no traits and stay structurally detected.
1522
+ * Sequence admission asks `kinds` first, so an entity that does not declare
1523
+ * `Sequence` can never buy its way in by carrying the fields. Extension kinds
1524
+ * declare nothing and stay structurally detected.
1503
1525
  */
1504
1526
  function hasSequence(entity) {
1505
1527
  if (isReservedEntityKind(entity.entityKind)) return false;
1506
- if (isKnownEntityKind(entity.entityKind) && !hasTraitKind(entity.entityKind, "sequence")) return false;
1528
+ if (isKnownEntityKind(entity.entityKind) && !declaresKind(entity.entityKind, "Sequence")) return false;
1507
1529
  return isSequenceFields(entity);
1508
1530
  }
1509
1531
  function isSequenceFields(value) {
@@ -1520,7 +1542,7 @@ function isMediaAssetVariantKind(kind) {
1520
1542
  return kind === "video" || kind === "image" || kind === "audio";
1521
1543
  }
1522
1544
  function isKnownEntityKind(kind) {
1523
- return Object.hasOwn(ENTITY_TRAIT_KINDS, kind);
1545
+ return Object.hasOwn(ENTITY_KINDS, kind);
1524
1546
  }
1525
1547
  function isReservedEntityKind(kind) {
1526
1548
  const normalized = kind.toLowerCase().replaceAll("-", "").replaceAll("_", "");
@@ -1709,14 +1731,17 @@ function assembleCaptionContent(rows, captionEntityId) {
1709
1731
  requireEntityKind(rows, captionEntityId, "caption");
1710
1732
  const caption = assembleEntityContent(rows, captionEntityId);
1711
1733
  const script = findComposedAudioScript(rows, captionEntityId, "caption");
1712
- const segment = selectAudioScriptSegment({
1734
+ const selection = captionSelection(caption);
1735
+ const composed = {
1713
1736
  ...script,
1714
1737
  payload: caption.payload
1715
- }, captionSelection(caption));
1738
+ };
1739
+ const segment = selectAudioScriptSegment(composed, selection);
1716
1740
  return {
1717
1741
  caption,
1718
1742
  audioScript: script,
1719
1743
  segments: [segment],
1744
+ segmentIndex: scriptSegments(composed).findIndex((entry) => entry.segmentId === selection.segmentId),
1720
1745
  text: segment.text
1721
1746
  };
1722
1747
  }
package/dist/index.d.ts CHANGED
@@ -192,6 +192,16 @@ interface AssembledCaptionContent {
192
192
  readonly audioScript: EntityRow<'audio-script'>;
193
193
  /** Selected AudioScript segments in Caption selection order. */
194
194
  readonly segments: readonly ScriptTextSegment[];
195
+ /**
196
+ * Where the selected segment sits in the AudioScript's ordered segments.
197
+ *
198
+ * A Caption locates its text as AudioScript plus index. The selection is
199
+ * stored as the segment's own stable id rather than this ordinal, so a
200
+ * concurrent insert or re-segmentation cannot silently slide a Caption onto
201
+ * different text; the ordinal is derived here for readers that want the
202
+ * position.
203
+ */
204
+ readonly segmentIndex: number;
195
205
  /** Complete display text: the selected segments' text joined in order. */
196
206
  readonly text: string;
197
207
  }
package/dist/index.js CHANGED
@@ -1,4 +1,4 @@
1
- import { $ as findLaneTrack, A as assemblePhoneticScriptContent, B as isMediaAssetVariantKind, C as EntityProjectionGraph, D as ScriptCompositionError, E as decodeEntityRelationRows, F as variantBaseEntityIds, G as toVideoDocument, H as buildSpeechHostMap, I as isJsonObject, J as validateVideoDocument, K as VideoDocumentValidationError, L as createEntityId, M as findComposedAudioScript, N as selectAudioScriptSegment, O as assembleCaptionContent, P as updateEntityFields, Q as ensureLaneTrack, R as createRelationId, S as projectEntityTimeline, St as bytesToBase64, T as EntityTimelineProjectionError, U as derivePositionFromAbs, V as buildInitialVideoDocument, W as fromVideoDocument, X as videoDocumentSchema, Y as partUnionSchema, Z as LANE_KINDS_IN_STACK_ORDER, _ as hasAudioScriptAsset, _t as speedOf, a as createMirrorVideoDocument, at as fillMainTrackTimeGaps, b as assertFieldChanges, bt as videoDocumentMirrorSchema, c as DocumentMutationGuard, ct as resolveAllSpeechOverlaps, d as LoroEntityDraft, dt as TIMELINE_SKELETON_DURATION_MS, et as hasResolvedPlacement, f as readEntityDocument, ft as isEmptyVideoClip, g as audioScriptAssetHash, gt as effectiveVideoClipDurationMs, h as audioScriptAssetFields, ht as DEFAULT_UNIT_TIME_MS, i as MirrorVideoDocumentAdapter, it as arrangeMainTrackSeamlessly, j as assembleScriptText, k as assembleEntityContent, l as LORO_ENTITY_SCHEMA, lt as resolveSpeechOverlapByShiftingVideos, m as audioScriptAssetContent, mt as safeDurationMs, n as createPlainMemoryAdapter, nt as solveVideoDocument, o as createMirrorVideoDocumentAdapter, ot as reassignSpeechesToVideoClipsByTime, p as entityOrderGroups, pt as partDurationMs, q as assertValidVideoDocument, r as generatePartId, rt as cascadeAfterVideoClipChanges, s as readVideoDocumentFromDraft, st as recalculateTimelineDuration, t as PlainMemoryAdapter, tt as laneTrackId, u as LoroEntityDocument, ut as syncAggregatedClipsTimePosition, v as equalJson, vt as partUnionToDraft, w as resolveEntityTimelineLayout, x as resolveFieldPath, xt as base64ToBytes, y as applyFieldChanges, yt as recordEntries, z as hasSequence } from "./document-DdwzfZ1g.js";
1
+ import { $ as findLaneTrack, A as assemblePhoneticScriptContent, B as isMediaAssetVariantKind, C as EntityProjectionGraph, D as ScriptCompositionError, E as decodeEntityRelationRows, F as variantBaseEntityIds, G as toVideoDocument, H as buildSpeechHostMap, I as isJsonObject, J as validateVideoDocument, K as VideoDocumentValidationError, L as createEntityId, M as findComposedAudioScript, N as selectAudioScriptSegment, O as assembleCaptionContent, P as updateEntityFields, Q as ensureLaneTrack, R as createRelationId, S as projectEntityTimeline, St as bytesToBase64, T as EntityTimelineProjectionError, U as derivePositionFromAbs, V as buildInitialVideoDocument, W as fromVideoDocument, X as videoDocumentSchema, Y as partUnionSchema, Z as LANE_KINDS_IN_STACK_ORDER, _ as hasAudioScriptAsset, _t as speedOf, a as createMirrorVideoDocument, at as fillMainTrackTimeGaps, b as assertFieldChanges, bt as videoDocumentMirrorSchema, c as DocumentMutationGuard, ct as resolveAllSpeechOverlaps, d as LoroEntityDraft, dt as TIMELINE_SKELETON_DURATION_MS, et as hasResolvedPlacement, f as readEntityDocument, ft as isEmptyVideoClip, g as audioScriptAssetHash, gt as effectiveVideoClipDurationMs, h as audioScriptAssetFields, ht as DEFAULT_UNIT_TIME_MS, i as MirrorVideoDocumentAdapter, it as arrangeMainTrackSeamlessly, j as assembleScriptText, k as assembleEntityContent, l as LORO_ENTITY_SCHEMA, lt as resolveSpeechOverlapByShiftingVideos, m as audioScriptAssetContent, mt as safeDurationMs, n as createPlainMemoryAdapter, nt as solveVideoDocument, o as createMirrorVideoDocumentAdapter, ot as reassignSpeechesToVideoClipsByTime, p as entityOrderGroups, pt as partDurationMs, q as assertValidVideoDocument, r as generatePartId, rt as cascadeAfterVideoClipChanges, s as readVideoDocumentFromDraft, st as recalculateTimelineDuration, t as PlainMemoryAdapter, tt as laneTrackId, u as LoroEntityDocument, ut as syncAggregatedClipsTimePosition, v as equalJson, vt as partUnionToDraft, w as resolveEntityTimelineLayout, x as resolveFieldPath, xt as base64ToBytes, y as applyFieldChanges, yt as recordEntries, z as hasSequence } from "./document-C30rnewk.js";
2
2
  import { addSpeechesInputSchema, addVideoClipsInputSchema, adjustBgmVolumeInputSchema, adjustSpeechVolumeInputSchema, adjustVideoClipDurationInputSchema, adjustVideoClipVolumeInputSchema, changeSpeechScriptInputSchema, changeSpeechVoiceInputSchema, deleteBgmInputSchema, deleteSpeechesInputSchema, deleteVideoClipsInputSchema, moveSpeechesInputSchema, moveVideoClipsByAnchorInputSchema, moveVideoClipsInputSchema, replaceVideoClipContentInputSchema, replaceVideoClipSequenceInputSchema, setBgmInputSchema, setCaptionStyleInputSchema, setCaptionVisibilityInputSchema, setVideoClipSpeedShiftInputSchema, t as schemas_exports } from "./schemas.js";
3
3
  import { LoroDoc, UndoManager, VersionVector } from "loro-crdt";
4
4
  import { ClientServerSynchronizer, DocManager } from "@mengine/sync";
package/dist/testing.js CHANGED
@@ -1,4 +1,4 @@
1
- import { St as bytesToBase64, o as createMirrorVideoDocumentAdapter, xt as base64ToBytes } from "./document-DdwzfZ1g.js";
1
+ import { St as bytesToBase64, o as createMirrorVideoDocumentAdapter, xt as base64ToBytes } from "./document-C30rnewk.js";
2
2
  import { t as classifyUpdate } from "./loro-relay-doc-cJSY-uau.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": "2.0.1-alpha.8",
3
+ "version": "2.0.1-alpha.9",
4
4
  "license": "UNLICENSED",
5
5
  "repository": {
6
6
  "type": "git",
@@ -28,9 +28,9 @@
28
28
  "immer": "^10.2.0",
29
29
  "loro-mirror": "^2.3.3",
30
30
  "zod": "^4.4.3",
31
- "@mengine/sync": "2.0.1-alpha.8",
32
- "@mengine/utils": "2.0.1-alpha.8",
33
- "@mengine/storage": "2.0.1-alpha.8"
31
+ "@mengine/storage": "2.0.1-alpha.9",
32
+ "@mengine/sync": "2.0.1-alpha.9",
33
+ "@mengine/utils": "2.0.1-alpha.9"
34
34
  },
35
35
  "devDependencies": {
36
36
  "@types/node": "^25.9.1",
@@ -40,8 +40,8 @@
40
40
  "typescript": "^6.0.3",
41
41
  "vite-plugin-wasm": "^3.6.0",
42
42
  "vite-plus": "^0.1.23",
43
- "@mengine/idl-codegen": "0.0.0",
44
- "@mengine/medeo-dsl": "0.0.0"
43
+ "@mengine/medeo-dsl": "0.0.0",
44
+ "@mengine/idl-codegen": "0.0.0"
45
45
  },
46
46
  "peerDependencies": {
47
47
  "loro-crdt": "^1.16.1"