@mengine/medeo-client 2.1.1-dsl.1 → 2.1.1-dsl.10
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 +26 -11
- package/dist/{dsl-EV6kCdr6.js → dsl-COyzz7Fp.js} +1074 -531
- package/dist/dsl.d.ts +3 -3
- package/dist/dsl.js +3 -3
- package/dist/{index-Cu7SdKN5.d.ts → index-C5wDKYqC.d.ts} +183 -170
- package/dist/{index-yifEtZSP.d.ts → index-CHiPztZr.d.ts} +53 -56
- package/dist/{index-B7fC7q7P.d.ts → index-DAfOkcnZ.d.ts} +23 -4
- package/dist/index.d.ts +5 -5
- package/dist/index.js +65 -9
- package/dist/legacy.d.ts +2 -2
- package/dist/legacy.js +1 -1
- package/dist/testing.d.ts +2 -2
- package/dist/testing.js +4 -7
- package/dist/{video-draft-types-TXRv3wS6.js → video-draft-types-BnbfWrBx.js} +178 -111
- package/dist/{video-draft-types-c_shaRyq.d.ts → video-draft-types-GqXnsOzA.d.ts} +114 -54
- package/package.json +4 -4
|
@@ -21,29 +21,22 @@ function resourceId(kind, system, key) {
|
|
|
21
21
|
function relationId(table, value) {
|
|
22
22
|
const v = value;
|
|
23
23
|
switch (table) {
|
|
24
|
-
case "clip-source-relations": return `cs:${v.clipId}`;
|
|
25
|
-
case "time-anchor-relations": return `ta:${v.from}`;
|
|
26
|
-
case "caption-content-relations": return `cc:${v.captionId}`;
|
|
27
|
-
case "caption-alignment-relations": return `ca:${v.captionId}`;
|
|
28
24
|
case "voice-timbre-relations": return `voice-timbre:${tupleHash([v.recordingId, v.voiceId])}`;
|
|
29
25
|
case "derived-from-relations": return `derived-from:${tupleHash([v.entityId, v.sourceId])}`;
|
|
30
|
-
case "from-asset-relations": return `from-asset:${v.audioScriptId}`;
|
|
31
|
-
case "to-asset-relations": return `to-asset:${v.audioScriptId}`;
|
|
32
26
|
}
|
|
33
27
|
throw new Error(`Unknown relation table: ${table}`);
|
|
34
28
|
}
|
|
35
29
|
const defaultIdFactory = (kind) => `${kind}_${globalThis.crypto.randomUUID()}`;
|
|
36
30
|
const resourceKinds = {
|
|
37
31
|
"media-entities": "media",
|
|
38
|
-
"voice-entities": "voice"
|
|
39
|
-
"asset-entities": "asset"
|
|
32
|
+
"voice-entities": "voice"
|
|
40
33
|
};
|
|
41
34
|
/** A resource row's ID is derived from its locator, so one external resource is one entity. */
|
|
42
35
|
function assertResourceIdentity(table, id, value) {
|
|
43
36
|
const kind = resourceKinds[table];
|
|
44
37
|
if (kind && id !== resourceId(kind, value.system, value.key)) throw new Error("Resource identity does not match locator");
|
|
45
38
|
}
|
|
46
|
-
/** A relation row's ID is derived from its
|
|
39
|
+
/** A relation row's ID is derived from its two ends. */
|
|
47
40
|
function assertRelationIdentity(table, id, value) {
|
|
48
41
|
if (id !== relationId(table, value)) throw new Error("Relation ID does not match endpoints");
|
|
49
42
|
}
|
|
@@ -61,16 +54,19 @@ const optional$1 = (check) => ({
|
|
|
61
54
|
check,
|
|
62
55
|
optional: true
|
|
63
56
|
});
|
|
57
|
+
const reservedIds = [
|
|
58
|
+
"$cid",
|
|
59
|
+
"__proto__",
|
|
60
|
+
"constructor",
|
|
61
|
+
"prototype"
|
|
62
|
+
];
|
|
63
|
+
const id = (v) => nonempty(v) && !reservedIds.includes(v);
|
|
64
|
+
const cursor = (v) => v instanceof Cursor;
|
|
64
65
|
function isRecord(value) {
|
|
65
66
|
return value !== null && typeof value === "object" && !Array.isArray(value) && !(value instanceof Cursor);
|
|
66
67
|
}
|
|
67
68
|
function assertId(value) {
|
|
68
|
-
if (!
|
|
69
|
-
"$cid",
|
|
70
|
-
"__proto__",
|
|
71
|
-
"constructor",
|
|
72
|
-
"prototype"
|
|
73
|
-
].includes(value)) throw new Error("Expected a nonempty, non-reserved ID");
|
|
69
|
+
if (!id(value)) throw new Error("Expected a nonempty, non-reserved ID");
|
|
74
70
|
}
|
|
75
71
|
function validLanguage(value) {
|
|
76
72
|
if (typeof value !== "string") return false;
|
|
@@ -126,6 +122,39 @@ const seqMarkerFields = {
|
|
|
126
122
|
function assertSeqMarker(value) {
|
|
127
123
|
checkFields(value, seqMarkerFields);
|
|
128
124
|
}
|
|
125
|
+
const timeAnchorFields = {
|
|
126
|
+
to: required(id),
|
|
127
|
+
offsetMs: required(integer),
|
|
128
|
+
fallback_abs_ms: required(nonnegative)
|
|
129
|
+
};
|
|
130
|
+
/** A time anchor's own fields; what it points at is checked by `assertReferenceAdmitted`. */
|
|
131
|
+
function assertTimeAnchor(value) {
|
|
132
|
+
checkFields(value, timeAnchorFields);
|
|
133
|
+
}
|
|
134
|
+
const selectionFields = {
|
|
135
|
+
audioScriptId: required(id),
|
|
136
|
+
segmentId: required(id),
|
|
137
|
+
start: optional$1(cursor),
|
|
138
|
+
end: optional$1(cursor)
|
|
139
|
+
};
|
|
140
|
+
/** A whole segment, or a run inside it: both ends or neither. */
|
|
141
|
+
const segmentSelection = (fields) => (v) => object(fields)(v) && v.start === void 0 === (v.end === void 0);
|
|
142
|
+
function assertCaptionContent(value) {
|
|
143
|
+
if (!segmentSelection(selectionFields)(value)) throw new Error("Invalid segment selection");
|
|
144
|
+
}
|
|
145
|
+
const phonemeFields = {
|
|
146
|
+
...selectionFields,
|
|
147
|
+
phonemeScript: optional$1(string)
|
|
148
|
+
};
|
|
149
|
+
function assertPhoneme(value) {
|
|
150
|
+
if (!segmentSelection(phonemeFields)(value)) throw new Error("Invalid phoneme");
|
|
151
|
+
}
|
|
152
|
+
const segmentFields = {
|
|
153
|
+
id: required(id),
|
|
154
|
+
text: required(string)
|
|
155
|
+
};
|
|
156
|
+
/** A script's segments: each with its own id, unique within the script. */
|
|
157
|
+
const segments = (v) => Array.isArray(v) && v.every(object(segmentFields)) && new Set(v.map((segment) => segment.id)).size === v.length;
|
|
129
158
|
const locator = {
|
|
130
159
|
system: required(oneOf("memota", "memota-speech")),
|
|
131
160
|
key: required(nonempty)
|
|
@@ -138,7 +167,9 @@ const entityFields = {
|
|
|
138
167
|
},
|
|
139
168
|
"clip-entities": {
|
|
140
169
|
seqMarker: required(object(seqMarkerFields)),
|
|
141
|
-
volume: optional$1(finite)
|
|
170
|
+
volume: optional$1(finite),
|
|
171
|
+
source: required(id),
|
|
172
|
+
anchor: optional$1(object(timeAnchorFields))
|
|
142
173
|
},
|
|
143
174
|
"media-entities": {
|
|
144
175
|
...locator,
|
|
@@ -148,10 +179,18 @@ const entityFields = {
|
|
|
148
179
|
digest: optional$1(nonempty)
|
|
149
180
|
},
|
|
150
181
|
"audio-script-entities": {
|
|
151
|
-
|
|
182
|
+
segments: required(segments),
|
|
152
183
|
defaultLanguage: optional$1(validLanguage)
|
|
153
184
|
},
|
|
185
|
+
"phonetic-script-entities": {
|
|
186
|
+
phoneme: optional$1(segmentSelection(phonemeFields)),
|
|
187
|
+
system: optional$1(oneOf("memota")),
|
|
188
|
+
key: optional$1(nonempty),
|
|
189
|
+
storageKey: optional$1(nonempty),
|
|
190
|
+
digest: optional$1(nonempty)
|
|
191
|
+
},
|
|
154
192
|
"caption-entities": {
|
|
193
|
+
selection: optional$1(segmentSelection(selectionFields)),
|
|
155
194
|
text: optional$1(string),
|
|
156
195
|
style: optional$1(object(styleFields))
|
|
157
196
|
},
|
|
@@ -159,55 +198,49 @@ const entityFields = {
|
|
|
159
198
|
system: required(oneOf("voice-library")),
|
|
160
199
|
key: required(nonempty),
|
|
161
200
|
name: optional$1(string)
|
|
162
|
-
},
|
|
163
|
-
"asset-entities": {
|
|
164
|
-
...locator,
|
|
165
|
-
storageKey: optional$1(nonempty),
|
|
166
|
-
digest: optional$1(nonempty)
|
|
167
201
|
}
|
|
168
202
|
};
|
|
169
203
|
const entityTables = Object.keys(entityFields);
|
|
204
|
+
/**
|
|
205
|
+
* Fields stored as one encoded string: written whole, never merged field by field. A patch to one
|
|
206
|
+
* is merged into the current value first, then the whole value is written.
|
|
207
|
+
*/
|
|
208
|
+
const atomicFields = {
|
|
209
|
+
"clip-entities": ["seqMarker", "anchor"],
|
|
210
|
+
"phonetic-script-entities": ["phoneme"],
|
|
211
|
+
"caption-entities": ["selection"]
|
|
212
|
+
};
|
|
170
213
|
const relationFields = {
|
|
171
|
-
"clip-source-relations": {
|
|
172
|
-
clipId: required(nonempty),
|
|
173
|
-
sourceId: required(nonempty)
|
|
174
|
-
},
|
|
175
|
-
"time-anchor-relations": {
|
|
176
|
-
from: required(nonempty),
|
|
177
|
-
to: required(nonempty),
|
|
178
|
-
offsetMs: required(integer),
|
|
179
|
-
fallback_abs_ms: required(nonnegative)
|
|
180
|
-
},
|
|
181
|
-
"caption-content-relations": {
|
|
182
|
-
captionId: required(nonempty),
|
|
183
|
-
audioScriptId: required(nonempty),
|
|
184
|
-
start: required((v) => v instanceof Cursor),
|
|
185
|
-
end: required((v) => v instanceof Cursor)
|
|
186
|
-
},
|
|
187
|
-
"caption-alignment-relations": {
|
|
188
|
-
captionId: required(nonempty),
|
|
189
|
-
mediaId: required(nonempty),
|
|
190
|
-
startMs: required(nonnegative),
|
|
191
|
-
endMs: required(nonnegative)
|
|
192
|
-
},
|
|
193
214
|
"voice-timbre-relations": {
|
|
194
|
-
recordingId: required(
|
|
195
|
-
voiceId: required(
|
|
215
|
+
recordingId: required(id),
|
|
216
|
+
voiceId: required(id)
|
|
196
217
|
},
|
|
197
218
|
"derived-from-relations": {
|
|
198
|
-
entityId: required(
|
|
199
|
-
sourceId: required(
|
|
200
|
-
|
|
201
|
-
"from-asset-relations": {
|
|
202
|
-
audioScriptId: required(nonempty),
|
|
203
|
-
assetId: required(nonempty)
|
|
204
|
-
},
|
|
205
|
-
"to-asset-relations": {
|
|
206
|
-
audioScriptId: required(nonempty),
|
|
207
|
-
assetId: required(nonempty)
|
|
219
|
+
entityId: required(id),
|
|
220
|
+
sourceId: required(id),
|
|
221
|
+
sourceDigest: optional$1(nonempty)
|
|
208
222
|
}
|
|
209
223
|
};
|
|
210
224
|
const relationTables = Object.keys(relationFields);
|
|
225
|
+
const fileFields = [
|
|
226
|
+
"system",
|
|
227
|
+
"key",
|
|
228
|
+
"storageKey",
|
|
229
|
+
"digest"
|
|
230
|
+
];
|
|
231
|
+
const phonemeScriptOf = (row) => isRecord(row.phoneme) ? row.phoneme.phonemeScript : void 0;
|
|
232
|
+
/**
|
|
233
|
+
* A PhoneticScript as a write leaves it: written for a segment (D181), and its phonemeScript is raw
|
|
234
|
+
* content stored as its file (D178) — with text the row names that file and its digest, without
|
|
235
|
+
* text it has no file, and rewritten text is a new file.
|
|
236
|
+
*/
|
|
237
|
+
function assertPhoneticScript(before, after) {
|
|
238
|
+
if (!isRecord(after.phoneme)) throw new Error("A PhoneticScript is written for a segment of its base script");
|
|
239
|
+
if (phonemeScriptOf(after) === void 0) {
|
|
240
|
+
if (fileFields.some((field) => after[field] !== void 0)) throw new Error("A PhoneticScript without text has no file");
|
|
241
|
+
} else if (after.system === void 0 || after.key === void 0 || after.digest === void 0) throw new Error("A PhoneticScript stores its phonemeScript as a file: name it by system and key with its digest");
|
|
242
|
+
if (before !== void 0 && phonemeScriptOf(after) !== phonemeScriptOf(before) && after.digest !== void 0 && after.digest === before.digest) throw new Error("A rewritten phonemeScript is stored again: write its new file");
|
|
243
|
+
}
|
|
211
244
|
function assertEntity(table, value) {
|
|
212
245
|
checkFields(value, entityFields[table]);
|
|
213
246
|
if (table === "media-entities") {
|
|
@@ -219,15 +252,15 @@ function assertEntity(table, value) {
|
|
|
219
252
|
/** Validate only touched fields, so an unrelated edit can proceed in a merged, invalid document. */
|
|
220
253
|
function assertEntityPatch(table, patch, current) {
|
|
221
254
|
if (!isRecord(patch)) throw new Error("Expected an entity patch");
|
|
222
|
-
if (table === "audio-script-entities" && Object.hasOwn(patch, "
|
|
255
|
+
if (table === "audio-script-entities" && Object.hasOwn(patch, "segments")) throw new Error("Change segments with segment mutations and edit their text through the Text adapter");
|
|
223
256
|
if (table === "caption-entities" && current.style !== void 0 && Object.hasOwn(patch, "style") && patch.style === void 0) throw new Error("Reset individual style fields; retain the style Map");
|
|
224
257
|
if (table === "caption-entities" && current.text !== void 0 && patch.text !== void 0) throw new Error("Edit Caption text through the Text adapter");
|
|
225
|
-
const next =
|
|
258
|
+
const next = patchRow(table, current, patch);
|
|
226
259
|
for (const key of Object.keys(patch)) {
|
|
227
260
|
const field = entityFields[table][key];
|
|
228
261
|
if (!field || !field.optional && next[key] === void 0 || next[key] !== void 0 && !field.check(next[key])) throw new Error(`Invalid patch field: ${key}`);
|
|
229
262
|
}
|
|
230
|
-
if (table === "media-entities" || table === "voice-entities"
|
|
263
|
+
if (table === "media-entities" || table === "voice-entities") {
|
|
231
264
|
for (const key of [
|
|
232
265
|
"system",
|
|
233
266
|
"key",
|
|
@@ -243,18 +276,25 @@ function assertEntityPatch(table, patch, current) {
|
|
|
243
276
|
}
|
|
244
277
|
function assertRelation(table, value) {
|
|
245
278
|
checkFields(value, relationFields[table]);
|
|
246
|
-
|
|
279
|
+
}
|
|
280
|
+
/**
|
|
281
|
+
* The row after a patch. An atomic field merges into its current value, so a partial patch keeps
|
|
282
|
+
* the rest of it; an unreadable stored value is replaced instead, so writing a whole value repairs it.
|
|
283
|
+
*/
|
|
284
|
+
function patchRow(table, current, patch) {
|
|
285
|
+
const next = mergeFields(current, patch);
|
|
286
|
+
for (const key of atomicFields[table] ?? []) {
|
|
287
|
+
const old = current[key];
|
|
288
|
+
const value = patch[key];
|
|
289
|
+
if (value !== void 0 && isRecord(old) && old.invalid === true) next[key] = isRecord(value) ? mergeFields({}, value) : value;
|
|
290
|
+
}
|
|
291
|
+
return next;
|
|
247
292
|
}
|
|
248
293
|
/** Undefined deletes; nested patches retain sibling fields and an existing empty style Map. */
|
|
249
294
|
function mergeFields(target, patch) {
|
|
250
295
|
const result = { ...target };
|
|
251
296
|
for (const [key, value] of Object.entries(patch)) {
|
|
252
|
-
if (
|
|
253
|
-
"$cid",
|
|
254
|
-
"__proto__",
|
|
255
|
-
"constructor",
|
|
256
|
-
"prototype"
|
|
257
|
-
].includes(key)) throw new Error(`Reserved field: ${key}`);
|
|
297
|
+
if (reservedIds.includes(key)) throw new Error(`Reserved field: ${key}`);
|
|
258
298
|
if (value === void 0) delete result[key];
|
|
259
299
|
else result[key] = isRecord(value) ? mergeFields(isRecord(result[key]) ? result[key] : {}, value) : value;
|
|
260
300
|
}
|
|
@@ -1252,36 +1292,60 @@ function codec(encode, decode) {
|
|
|
1252
1292
|
}
|
|
1253
1293
|
};
|
|
1254
1294
|
}
|
|
1295
|
+
/** A Clip's time anchor; the Clip holding it is the anchored end. */
|
|
1255
1296
|
const timeAnchorCodec = codec((v) => {
|
|
1256
|
-
|
|
1297
|
+
assertTimeAnchor(v);
|
|
1257
1298
|
return JSON.stringify({
|
|
1258
|
-
from: v.from,
|
|
1259
1299
|
to: v.to,
|
|
1260
1300
|
offsetMs: v.offsetMs,
|
|
1261
1301
|
fallback_abs_ms: v.fallback_abs_ms
|
|
1262
1302
|
});
|
|
1263
1303
|
}, (raw) => {
|
|
1264
1304
|
const v = JSON.parse(raw);
|
|
1265
|
-
|
|
1305
|
+
assertTimeAnchor(v);
|
|
1266
1306
|
return v;
|
|
1267
1307
|
});
|
|
1308
|
+
/** A segment selection as stored: a run's Cursors as their native bytes in unpadded base64url. */
|
|
1309
|
+
function encodeSelection(v) {
|
|
1310
|
+
return {
|
|
1311
|
+
audioScriptId: v.audioScriptId,
|
|
1312
|
+
segmentId: v.segmentId,
|
|
1313
|
+
...v.start === void 0 || v.end === void 0 ? {} : {
|
|
1314
|
+
start: bytesToBase64url(v.start.encode()),
|
|
1315
|
+
end: bytesToBase64url(v.end.encode())
|
|
1316
|
+
}
|
|
1317
|
+
};
|
|
1318
|
+
}
|
|
1319
|
+
function decodeSelection(v) {
|
|
1320
|
+
if (!v || typeof v !== "object") throw new Error("Expected a segment selection");
|
|
1321
|
+
const { start, end, ...rest } = v;
|
|
1322
|
+
if (start === void 0 && end === void 0) return rest;
|
|
1323
|
+
if (typeof start !== "string" || typeof end !== "string") throw new Error("Expected encoded Cursor pair");
|
|
1324
|
+
return {
|
|
1325
|
+
...rest,
|
|
1326
|
+
start: Cursor.decode(base64urlToBytes(start)),
|
|
1327
|
+
end: Cursor.decode(base64urlToBytes(end))
|
|
1328
|
+
};
|
|
1329
|
+
}
|
|
1330
|
+
/** A Caption's selection. */
|
|
1268
1331
|
const captionContentCodec = codec((v) => {
|
|
1269
|
-
|
|
1332
|
+
assertCaptionContent(v);
|
|
1333
|
+
return JSON.stringify(encodeSelection(v));
|
|
1334
|
+
}, (raw) => {
|
|
1335
|
+
const value = decodeSelection(JSON.parse(raw));
|
|
1336
|
+
assertCaptionContent(value);
|
|
1337
|
+
return value;
|
|
1338
|
+
});
|
|
1339
|
+
/** A PhoneticScript's selection and what to synthesize for it, stored as one string so they move together. */
|
|
1340
|
+
const phonemeCodec = codec((v) => {
|
|
1341
|
+
assertPhoneme(v);
|
|
1270
1342
|
return JSON.stringify({
|
|
1271
|
-
|
|
1272
|
-
|
|
1273
|
-
start: bytesToBase64url(v.start.encode()),
|
|
1274
|
-
end: bytesToBase64url(v.end.encode())
|
|
1343
|
+
...encodeSelection(v),
|
|
1344
|
+
...v.phonemeScript === void 0 ? {} : { phonemeScript: v.phonemeScript }
|
|
1275
1345
|
});
|
|
1276
1346
|
}, (raw) => {
|
|
1277
|
-
const
|
|
1278
|
-
|
|
1279
|
-
const value = {
|
|
1280
|
-
...v,
|
|
1281
|
-
start: Cursor.decode(base64urlToBytes(v.start)),
|
|
1282
|
-
end: Cursor.decode(base64urlToBytes(v.end))
|
|
1283
|
-
};
|
|
1284
|
-
assertRelation("caption-content-relations", value);
|
|
1347
|
+
const value = decodeSelection(JSON.parse(raw));
|
|
1348
|
+
assertPhoneme(value);
|
|
1285
1349
|
return value;
|
|
1286
1350
|
});
|
|
1287
1351
|
/** A Clip's sequence marker is stored as one string, so it is taken or replaced whole. */
|
|
@@ -1304,13 +1368,19 @@ const optional = { required: false };
|
|
|
1304
1368
|
const mergeable = { mergeableMapChildContainers: true };
|
|
1305
1369
|
const strings = (keys) => Object.fromEntries(keys.map((key) => [key, schema.String()]));
|
|
1306
1370
|
const relation = (keys) => schema.LoroMapRecord(schema.LoroMap(strings(keys)), mergeable);
|
|
1307
|
-
const
|
|
1371
|
+
const transform = (codec) => ({
|
|
1308
1372
|
...codec,
|
|
1309
1373
|
isEqual: "encoded-value-equality",
|
|
1310
1374
|
validateEncodedType: true
|
|
1311
1375
|
});
|
|
1312
|
-
|
|
1313
|
-
|
|
1376
|
+
/** One field stored as one encoded string, so it is taken or replaced whole. */
|
|
1377
|
+
const atomicValue = (codec) => schema.String().transform(transform(codec));
|
|
1378
|
+
const optionalAtomicValue = (codec) => schema.String(optional).transform(transform(codec));
|
|
1379
|
+
/**
|
|
1380
|
+
* Only direct children inherit mergeable identity. Text and ordinary entity rows keep normal
|
|
1381
|
+
* identities, so deleting a row also drops what a peer wrote into it concurrently: a relation an
|
|
1382
|
+
* entity holds at most one of is a field of that row and never outlives it.
|
|
1383
|
+
*/
|
|
1314
1384
|
const medeoDslLoroShape = schema({
|
|
1315
1385
|
"timeline-entities": schema.LoroMapRecord(schema.LoroMap({})),
|
|
1316
1386
|
"track-entities": schema.LoroMapRecord(schema.LoroMap({
|
|
@@ -1319,7 +1389,9 @@ const medeoDslLoroShape = schema({
|
|
|
1319
1389
|
})),
|
|
1320
1390
|
"clip-entities": schema.LoroMapRecord(schema.LoroMap({
|
|
1321
1391
|
seqMarker: atomicValue(seqMarkerCodec),
|
|
1322
|
-
volume: schema.Number(optional)
|
|
1392
|
+
volume: schema.Number(optional),
|
|
1393
|
+
source: schema.String(),
|
|
1394
|
+
anchor: optionalAtomicValue(timeAnchorCodec)
|
|
1323
1395
|
})),
|
|
1324
1396
|
"media-entities": schema.LoroMapRecord(schema.LoroMap({
|
|
1325
1397
|
kind: schema.String(),
|
|
@@ -1330,10 +1402,21 @@ const medeoDslLoroShape = schema({
|
|
|
1330
1402
|
digest: schema.String(optional)
|
|
1331
1403
|
}), mergeable),
|
|
1332
1404
|
"audio-script-entities": schema.LoroMapRecord(schema.LoroMap({
|
|
1333
|
-
|
|
1405
|
+
segments: schema.LoroMovableList(schema.LoroMap({
|
|
1406
|
+
id: schema.String(),
|
|
1407
|
+
text: schema.LoroText()
|
|
1408
|
+
}), (segment) => segment.id),
|
|
1334
1409
|
defaultLanguage: schema.String(optional)
|
|
1335
1410
|
})),
|
|
1411
|
+
"phonetic-script-entities": schema.LoroMapRecord(schema.LoroMap({
|
|
1412
|
+
phoneme: atomicValue(phonemeCodec),
|
|
1413
|
+
system: schema.String(optional),
|
|
1414
|
+
key: schema.String(optional),
|
|
1415
|
+
storageKey: schema.String(optional),
|
|
1416
|
+
digest: schema.String(optional)
|
|
1417
|
+
})),
|
|
1336
1418
|
"caption-entities": schema.LoroMapRecord(schema.LoroMap({
|
|
1419
|
+
selection: optionalAtomicValue(captionContentCodec),
|
|
1337
1420
|
text: schema.LoroText(optional),
|
|
1338
1421
|
style: schema.LoroMap({
|
|
1339
1422
|
font: schema.LoroMap({
|
|
@@ -1359,26 +1442,13 @@ const medeoDslLoroShape = schema({
|
|
|
1359
1442
|
key: schema.String(),
|
|
1360
1443
|
name: schema.String(optional)
|
|
1361
1444
|
}), mergeable),
|
|
1362
|
-
"asset-entities": schema.LoroMapRecord(schema.LoroMap({
|
|
1363
|
-
system: schema.String(),
|
|
1364
|
-
key: schema.String(),
|
|
1365
|
-
storageKey: schema.String(optional),
|
|
1366
|
-
digest: schema.String(optional)
|
|
1367
|
-
}), mergeable),
|
|
1368
1445
|
"contain-relations": schema.LoroTree(schema.LoroMap({ entityId: schema.String() })),
|
|
1369
|
-
"clip-source-relations": relation(["clipId", "sourceId"]),
|
|
1370
|
-
"time-anchor-relations": atomic(timeAnchorCodec),
|
|
1371
|
-
"caption-content-relations": atomic(captionContentCodec),
|
|
1372
|
-
"caption-alignment-relations": schema.LoroMapRecord(schema.LoroMap({
|
|
1373
|
-
captionId: schema.String(),
|
|
1374
|
-
mediaId: schema.String(),
|
|
1375
|
-
startMs: schema.Number(),
|
|
1376
|
-
endMs: schema.Number()
|
|
1377
|
-
}), mergeable),
|
|
1378
1446
|
"voice-timbre-relations": relation(["recordingId", "voiceId"]),
|
|
1379
|
-
"derived-from-relations":
|
|
1380
|
-
|
|
1381
|
-
|
|
1447
|
+
"derived-from-relations": schema.LoroMapRecord(schema.LoroMap({
|
|
1448
|
+
entityId: schema.String(),
|
|
1449
|
+
sourceId: schema.String(),
|
|
1450
|
+
sourceDigest: schema.String(optional)
|
|
1451
|
+
}), mergeable)
|
|
1382
1452
|
});
|
|
1383
1453
|
//#endregion
|
|
1384
1454
|
//#region ../medeo-dsl/src/schema/document-format.ts
|
|
@@ -1407,13 +1477,10 @@ function assertDslDocument(doc) {
|
|
|
1407
1477
|
}
|
|
1408
1478
|
//#endregion
|
|
1409
1479
|
//#region ../medeo-dsl/src/schema/text-styles.ts
|
|
1410
|
-
/** How rich-text marks extend at their edges: a language runs on into
|
|
1411
|
-
const textStyles = {
|
|
1412
|
-
language: { expand: "after" },
|
|
1413
|
-
pauseMs: { expand: "none" }
|
|
1414
|
-
};
|
|
1480
|
+
/** How rich-text marks extend at their edges: a language runs on into text typed after it. */
|
|
1481
|
+
const textStyles = { language: { expand: "after" } };
|
|
1415
1482
|
//#endregion
|
|
1416
1483
|
//#region src/dsl/projection/video-draft-types.ts
|
|
1417
1484
|
const DEFAULT_UNIT_TIME_MS = 33.333;
|
|
1418
1485
|
//#endregion
|
|
1419
|
-
export {
|
|
1486
|
+
export { assertEntityPatch as $, getRootContainerByType as A, isValueOfContainerType as B, applyEncode as C, decodeNestedJsonValues as D, containerIdToContainerType as E, isArrayLike as F, tryUpdateToContainer as G, schemaToContainerType as H, isObject as I, getChildContainerSchema as J, valuesEqual as K, isObjectLike as L, hasTransform as M, inferContainerTypeFromValue as N, deepEqual as O, insertChildToMap as P, assertEntity as Q, isStateAndSchemaOfType as R, applyDecode as S, cidsEqual as T, stripUndefined as U, safeStringify as V, tryInferContainerType as W, getMapFieldSchema as X, getChildSchema as Y, assertCaptionContent as Z, isLoroMovableListSchema as _, tupleHash as _t, documentFormat as a, atomicFields as at, schemaContainsIgnoreField as b, isInvalidAtomic as c, mergeFields as ct, schema as d, validLanguage as dt, assertId as et, getDefaultValue as f, assertRelationIdentity as ft, isLoroMapSchema as g, resourceId as gt, isLoroListSchema as h, relationId as ht, assertDslDocument as i, assertTimeAnchor as it, hardenCidDescriptors as j, defineCidProperty as k, phonemeCodec as l, patchRow as lt, isListLikeSchema as m, defaultIdFactory as mt, textStyles as n, assertPhoneticScript as nt, medeoDslLoroShape as o, entityTables as ot, isContainerSchema as p, assertResourceIdentity as pt, CID_KEY as q, UnsupportedDocumentFormatError as r, assertRelation as rt, captionContentCodec as s, isRecord as st, DEFAULT_UNIT_TIME_MS as t, assertPhoneme as tt, timeAnchorCodec as u, relationTables as ut, isLoroTreeSchema as v, applySchemaToInferOptions as w, validateSchema as x, isRootSchemaType as y, isTreeID as z };
|