@svta/cml-cmcd 2.4.0 → 2.5.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/dist/index.d.ts +289 -15
- package/dist/index.d.ts.map +1 -1
- package/dist/index.js +224 -35
- package/dist/index.js.map +1 -1
- package/dist/tsdoc-metadata.json +1 -1
- package/package.json +3 -3
package/dist/index.js
CHANGED
|
@@ -217,7 +217,7 @@ const CmcdEventType = {
|
|
|
217
217
|
*
|
|
218
218
|
* @internal
|
|
219
219
|
*/
|
|
220
|
-
const CMCD_STATE_EVENT_FIELDS = new Map([
|
|
220
|
+
const CMCD_STATE_EVENT_FIELDS = /* @__PURE__ */ new Map([
|
|
221
221
|
[CMCD_EVENT_PLAY_STATE, "sta"],
|
|
222
222
|
[CMCD_EVENT_PLAYBACK_RATE, "pr"],
|
|
223
223
|
[CMCD_EVENT_CONTENT_ID, "cid"],
|
|
@@ -315,23 +315,30 @@ const CMCD_REQUEST_KEYS = [
|
|
|
315
315
|
|
|
316
316
|
//#endregion
|
|
317
317
|
//#region src/isCmcdCustomKey.ts
|
|
318
|
-
const CUSTOM_KEY_REGEX = /^[a-
|
|
318
|
+
const CUSTOM_KEY_REGEX = /^[a-z][a-z0-9.-]*$/;
|
|
319
319
|
/**
|
|
320
|
-
* Check if a key is a custom key
|
|
320
|
+
* Check if a key is a valid custom key: a lowercase first letter, then
|
|
321
|
+
* characters from `a-z 0-9 . -`, with a hyphen that is neither the first
|
|
322
|
+
* nor the last character. These are the CTA-5004-B custom-key rules
|
|
323
|
+
* restricted to names that survive RFC 8941 key serialization.
|
|
321
324
|
*
|
|
322
325
|
* @param key - The key to check.
|
|
323
326
|
*
|
|
324
327
|
* @returns `true` if the key is a custom key, `false` otherwise.
|
|
325
328
|
*
|
|
326
329
|
* @public
|
|
330
|
+
*
|
|
331
|
+
* @example
|
|
332
|
+
* {@includeCode ../test/isCmcdCustomKey.test.ts#example}
|
|
327
333
|
*/
|
|
328
334
|
function isCmcdCustomKey(key) {
|
|
329
|
-
|
|
335
|
+
const separator = key.indexOf("-", 1);
|
|
336
|
+
return separator > 0 && separator < key.length - 1 && CUSTOM_KEY_REGEX.test(key);
|
|
330
337
|
}
|
|
331
338
|
|
|
332
339
|
//#endregion
|
|
333
340
|
//#region src/isCmcdRequestKey.ts
|
|
334
|
-
const CMCD_REQUEST_KEY_SET = new Set(CMCD_REQUEST_KEYS);
|
|
341
|
+
const CMCD_REQUEST_KEY_SET = /* @__PURE__ */ new Set(CMCD_REQUEST_KEYS);
|
|
335
342
|
/**
|
|
336
343
|
* Check if a key is a valid CMCD request key.
|
|
337
344
|
*
|
|
@@ -368,7 +375,7 @@ const CMCD_RESPONSE_KEYS = [
|
|
|
368
375
|
|
|
369
376
|
//#endregion
|
|
370
377
|
//#region src/isCmcdResponseReceivedKey.ts
|
|
371
|
-
const CMCD_RESPONSE_KEY_SET = new Set(CMCD_RESPONSE_KEYS);
|
|
378
|
+
const CMCD_RESPONSE_KEY_SET = /* @__PURE__ */ new Set(CMCD_RESPONSE_KEYS);
|
|
372
379
|
/**
|
|
373
380
|
* Check if a key is a valid CMCD response key.
|
|
374
381
|
*
|
|
@@ -387,7 +394,7 @@ function isCmcdResponseReceivedKey(key) {
|
|
|
387
394
|
|
|
388
395
|
//#endregion
|
|
389
396
|
//#region src/isCmcdEventKey.ts
|
|
390
|
-
const CMCD_EVENT_KEY_SET = new Set(CMCD_EVENT_KEYS);
|
|
397
|
+
const CMCD_EVENT_KEY_SET = /* @__PURE__ */ new Set(CMCD_EVENT_KEYS);
|
|
391
398
|
/**
|
|
392
399
|
* Check if a key is a valid CMCD event key.
|
|
393
400
|
*
|
|
@@ -460,7 +467,7 @@ const CMCD_V1_KEYS = [
|
|
|
460
467
|
|
|
461
468
|
//#endregion
|
|
462
469
|
//#region src/isCmcdV1Key.ts
|
|
463
|
-
const CMCD_V1_KEY_SET$1 = new Set(CMCD_V1_KEYS);
|
|
470
|
+
const CMCD_V1_KEY_SET$1 = /* @__PURE__ */ new Set(CMCD_V1_KEYS);
|
|
464
471
|
/**
|
|
465
472
|
* Filter function for CMCD v1 keys.
|
|
466
473
|
*
|
|
@@ -479,7 +486,7 @@ function isCmcdV1Key(key) {
|
|
|
479
486
|
|
|
480
487
|
//#endregion
|
|
481
488
|
//#region src/isTokenField.ts
|
|
482
|
-
const TOKEN_FIELDS = new Set([
|
|
489
|
+
const TOKEN_FIELDS = /* @__PURE__ */ new Set([
|
|
483
490
|
"ot",
|
|
484
491
|
"sf",
|
|
485
492
|
"st",
|
|
@@ -565,6 +572,9 @@ function downConvertToV1(obj) {
|
|
|
565
572
|
* @param options - Options for encoding.
|
|
566
573
|
*
|
|
567
574
|
* @public
|
|
575
|
+
*
|
|
576
|
+
* @example
|
|
577
|
+
* {@includeCode ../test/prepareCmcdData.test.ts#example}
|
|
568
578
|
*/
|
|
569
579
|
function prepareCmcdData(obj, options = {}) {
|
|
570
580
|
const results = {};
|
|
@@ -583,6 +593,8 @@ function prepareCmcdData(obj, options = {}) {
|
|
|
583
593
|
if (!keys.includes("e") && eventType != null) keys.push("e");
|
|
584
594
|
if (!keys.includes("ts")) keys.push("ts");
|
|
585
595
|
if (!keys.includes("cen") && data["cen"] != null && eventType === CMCD_EVENT_CUSTOM_EVENT) keys.push("cen");
|
|
596
|
+
if (!keys.includes("ec") && data["ec"] != null && eventType === CMCD_EVENT_ERROR) keys.push("ec");
|
|
597
|
+
if (!keys.includes("url") && data["url"] != null && eventType === CMCD_EVENT_RESPONSE_RECEIVED) keys.push("url");
|
|
586
598
|
const requiredField = eventType ? CMCD_STATE_EVENT_FIELDS.get(eventType) : void 0;
|
|
587
599
|
if (requiredField && data[requiredField] != null && !keys.includes(requiredField)) keys.push(requiredField);
|
|
588
600
|
}
|
|
@@ -942,7 +954,7 @@ const CMCD_DEFAULT_TIME_INTERVAL = 30;
|
|
|
942
954
|
*
|
|
943
955
|
* @public
|
|
944
956
|
*/
|
|
945
|
-
const CMCD_KEYS = [
|
|
957
|
+
const CMCD_KEYS = /* @__PURE__ */ [
|
|
946
958
|
...CMCD_V1_KEYS,
|
|
947
959
|
...CMCD_REQUEST_KEYS,
|
|
948
960
|
...CMCD_RESPONSE_KEYS,
|
|
@@ -1469,7 +1481,8 @@ function createEncodingOptions(reportingMode, config, baseUrl) {
|
|
|
1469
1481
|
version: config.version || CMCD_V2,
|
|
1470
1482
|
reportingMode,
|
|
1471
1483
|
filter: (key) => enabledKeySet.has(key),
|
|
1472
|
-
baseUrl
|
|
1484
|
+
baseUrl,
|
|
1485
|
+
customHeaderMap: config.customHeaderMap
|
|
1473
1486
|
};
|
|
1474
1487
|
}
|
|
1475
1488
|
/**
|
|
@@ -1504,7 +1517,7 @@ const identity = (v) => v;
|
|
|
1504
1517
|
* Maps each tracked state field to its event type and equality function.
|
|
1505
1518
|
* Order matters: `update()` fires events in this order for multi-field updates.
|
|
1506
1519
|
*/
|
|
1507
|
-
const STATE_FIELDS = Array.from(CMCD_STATE_EVENT_FIELDS, ([event, field]) => {
|
|
1520
|
+
const STATE_FIELDS = /* @__PURE__ */ Array.from(CMCD_STATE_EVENT_FIELDS, ([event, field]) => {
|
|
1508
1521
|
if (field === "br") return {
|
|
1509
1522
|
event,
|
|
1510
1523
|
field,
|
|
@@ -1518,7 +1531,69 @@ const STATE_FIELDS = Array.from(CMCD_STATE_EVENT_FIELDS, ([event, field]) => {
|
|
|
1518
1531
|
snapshot: identity
|
|
1519
1532
|
};
|
|
1520
1533
|
});
|
|
1521
|
-
const STATE_FIELDS_BY_EVENT = new Map(STATE_FIELDS.map((e) => [e.event, e]));
|
|
1534
|
+
const STATE_FIELDS_BY_EVENT = /* @__PURE__ */ new Map(/* @__PURE__ */ STATE_FIELDS.map((e) => [e.event, e]));
|
|
1535
|
+
/**
|
|
1536
|
+
* Maps each event type to the key CTA-5004-B requires beyond `e` and `ts`.
|
|
1537
|
+
* Built from the state-change table plus the three event types whose
|
|
1538
|
+
* required key rides the caller's per-event data.
|
|
1539
|
+
*/
|
|
1540
|
+
const CMCD_REQUIRED_EVENT_KEYS = /* @__PURE__ */ new Map([
|
|
1541
|
+
...CMCD_STATE_EVENT_FIELDS,
|
|
1542
|
+
[CMCD_EVENT_CUSTOM_EVENT, "cen"],
|
|
1543
|
+
[CMCD_EVENT_ERROR, "ec"],
|
|
1544
|
+
[CMCD_EVENT_RESPONSE_RECEIVED, "url"]
|
|
1545
|
+
]);
|
|
1546
|
+
/**
|
|
1547
|
+
* Whether a required key's value will survive report preparation.
|
|
1548
|
+
*
|
|
1549
|
+
* This is `isValid` minus its `false` exclusion, plus an empty-array check.
|
|
1550
|
+
* `false` must count as usable because `bg: false` is a legitimate value on a
|
|
1551
|
+
* backgrounded-mode event, which the encoder emits as `?0`; treating it as
|
|
1552
|
+
* unusable would let restoration silently revert a transform that cleared it.
|
|
1553
|
+
* Empty strings, empty lists and non-finite numbers are dropped downstream, so
|
|
1554
|
+
* a transform substituting one leaves the report short a required key.
|
|
1555
|
+
*/
|
|
1556
|
+
function isUsableRequiredValue(value) {
|
|
1557
|
+
if (value == null || value === "") return false;
|
|
1558
|
+
if (typeof value === "number") return Number.isFinite(value);
|
|
1559
|
+
return !Array.isArray(value) || value.length > 0;
|
|
1560
|
+
}
|
|
1561
|
+
/**
|
|
1562
|
+
* Copies an `SfItem`-shaped value and its `params` record.
|
|
1563
|
+
*
|
|
1564
|
+
* The prototype is preserved because `prepareCmcdData`, the formatter map,
|
|
1565
|
+
* validation, and the structured-field encoder all branch on
|
|
1566
|
+
* `instanceof SfItem`. A plain spread (and `structuredClone`) would return a
|
|
1567
|
+
* prototype-less object and silently change what goes on the wire.
|
|
1568
|
+
*/
|
|
1569
|
+
function copyItemValue(value) {
|
|
1570
|
+
if (value === null || typeof value !== "object") return value;
|
|
1571
|
+
const copy = Object.assign(Object.create(Object.getPrototypeOf(value)), value);
|
|
1572
|
+
if (copy.params !== null && typeof copy.params === "object") copy.params = { ...copy.params };
|
|
1573
|
+
return copy;
|
|
1574
|
+
}
|
|
1575
|
+
/**
|
|
1576
|
+
* Copies the nested values of a report in place so a transform cannot mutate
|
|
1577
|
+
* the reporter's persistent data, or another target's report for the same
|
|
1578
|
+
* event, by mutating an array or an `SfItem` it was handed.
|
|
1579
|
+
*
|
|
1580
|
+
* Complete for the CMCD value space rather than best-effort: `CmcdValue` and
|
|
1581
|
+
* `CmcdCustomValue` admit only primitives, `SfItem<primitive>`, and arrays of
|
|
1582
|
+
* those, and `SfItem.params` is a flat record. Only called where a transform
|
|
1583
|
+
* is configured.
|
|
1584
|
+
*/
|
|
1585
|
+
function copyReportValues(data) {
|
|
1586
|
+
const record = data;
|
|
1587
|
+
for (const key in record) {
|
|
1588
|
+
const value = record[key];
|
|
1589
|
+
if (Array.isArray(value)) {
|
|
1590
|
+
const copy = new Array(value.length);
|
|
1591
|
+
for (let i = 0; i < value.length; i++) copy[i] = copyItemValue(value[i]);
|
|
1592
|
+
record[key] = copy;
|
|
1593
|
+
} else if (value !== null && typeof value === "object") record[key] = copyItemValue(value);
|
|
1594
|
+
}
|
|
1595
|
+
return data;
|
|
1596
|
+
}
|
|
1522
1597
|
function defaultRequester(request) {
|
|
1523
1598
|
const { url,...init } = request;
|
|
1524
1599
|
return fetch(url, init);
|
|
@@ -1537,7 +1612,8 @@ function createCmcdReporterConfig(config) {
|
|
|
1537
1612
|
url: target.url,
|
|
1538
1613
|
events: target.events.slice(),
|
|
1539
1614
|
interval: target.interval ?? CMCD_DEFAULT_TIME_INTERVAL,
|
|
1540
|
-
batchSize: target.batchSize || 1
|
|
1615
|
+
batchSize: target.batchSize || 1,
|
|
1616
|
+
transform: target.transform
|
|
1541
1617
|
});
|
|
1542
1618
|
return acc;
|
|
1543
1619
|
}, [])
|
|
@@ -1546,6 +1622,14 @@ function createCmcdReporterConfig(config) {
|
|
|
1546
1622
|
/**
|
|
1547
1623
|
* The CMCD reporter.
|
|
1548
1624
|
*
|
|
1625
|
+
* `C` describes the player's own `customData`, which the reporter passes
|
|
1626
|
+
* through to each configured `transform`. It is inferred from the
|
|
1627
|
+
* configuration, so annotating a single `transform` types the request in every
|
|
1628
|
+
* other one; the default leaves `customData` values `unknown`.
|
|
1629
|
+
*
|
|
1630
|
+
* @typeParam C - The shape of the player's `customData`. Defaults to
|
|
1631
|
+
* `Record<string, unknown>`.
|
|
1632
|
+
*
|
|
1549
1633
|
* @see {@link https://cta-wave.github.io/Resources/common-media-client-data--cta-5004-b.html#reporting-modes-when-we-send-data | CTA-5004-B Reporting Modes}
|
|
1550
1634
|
*
|
|
1551
1635
|
* @public
|
|
@@ -1591,6 +1675,7 @@ var CmcdReporter = class {
|
|
|
1591
1675
|
* populated before calling start().
|
|
1592
1676
|
*/
|
|
1593
1677
|
start() {
|
|
1678
|
+
let failure;
|
|
1594
1679
|
this.eventTargets.forEach((target, config) => {
|
|
1595
1680
|
this.disarmInterval(target);
|
|
1596
1681
|
if (config.interval === 0 || !config.events.includes(CMCD_EVENT_TIME_INTERVAL)) return;
|
|
@@ -1599,8 +1684,13 @@ var CmcdReporter = class {
|
|
|
1599
1684
|
this.processEventTargets();
|
|
1600
1685
|
};
|
|
1601
1686
|
target.intervalId = setInterval(timeIntervalEvent, config.interval * 1e3);
|
|
1602
|
-
|
|
1687
|
+
try {
|
|
1688
|
+
timeIntervalEvent();
|
|
1689
|
+
} catch (error) {
|
|
1690
|
+
failure ??= { error };
|
|
1691
|
+
}
|
|
1603
1692
|
});
|
|
1693
|
+
if (failure) throw failure.error;
|
|
1604
1694
|
}
|
|
1605
1695
|
/**
|
|
1606
1696
|
* Stops the CMCD reporter. Called by the player when the reporter is disabled.
|
|
@@ -1637,6 +1727,16 @@ var CmcdReporter = class {
|
|
|
1637
1727
|
* `cid` → `bg` → `br`. The order of keys in the input object does not
|
|
1638
1728
|
* affect the firing order.
|
|
1639
1729
|
*
|
|
1730
|
+
* To attach snapshot context (e.g., `bl`, `mtp`, `pt`, `ltc`) to a
|
|
1731
|
+
* state-change event, ensure those fields are in the reporter's data
|
|
1732
|
+
* before the state field changes. Either include them alongside the
|
|
1733
|
+
* state field in the same `update()` call, or persist them via earlier
|
|
1734
|
+
* `update()` calls — auto-fired events emit whatever is currently in
|
|
1735
|
+
* the persistent data store. This is also how to keep `TIME_INTERVAL`
|
|
1736
|
+
* reports useful — those events draw from the persistent data store
|
|
1737
|
+
* with no caller hook for per-event data, so fields the player wants
|
|
1738
|
+
* in periodic reports must be kept fresh here.
|
|
1739
|
+
*
|
|
1640
1740
|
* A `sid` change resets the dedup baseline.
|
|
1641
1741
|
*
|
|
1642
1742
|
* @param data - The data to update.
|
|
@@ -1666,9 +1766,19 @@ var CmcdReporter = class {
|
|
|
1666
1766
|
*
|
|
1667
1767
|
* For all other event types, the event is always emitted.
|
|
1668
1768
|
*
|
|
1669
|
-
*
|
|
1670
|
-
*
|
|
1671
|
-
*
|
|
1769
|
+
* For state-change events, prefer {@link CmcdReporter.update} — including
|
|
1770
|
+
* for snapshot enrichment via a combined call like
|
|
1771
|
+
* `update({ sta: 'p', bl: [3000], mtp: [8500] })`. Calling `recordEvent()`
|
|
1772
|
+
* for a state-change event after `update()` has already auto-fired it
|
|
1773
|
+
* silently drops the second call's `data`, because dedup suppresses the
|
|
1774
|
+
* second emission.
|
|
1775
|
+
*
|
|
1776
|
+
* Use `recordEvent()` directly for events whose payload is intrinsic to
|
|
1777
|
+
* the event call — `CUSTOM_EVENT` with `cen`, `ERROR` with `ec`,
|
|
1778
|
+
* ad-lifecycle events, `MUTE`/`UNMUTE`, `PLAYER_EXPAND`/`PLAYER_COLLAPSE`,
|
|
1779
|
+
* `SKIP`. For `RESPONSE_RECEIVED`, prefer
|
|
1780
|
+
* {@link CmcdReporter.recordResponseReceived}, which derives the
|
|
1781
|
+
* per-response fields automatically.
|
|
1672
1782
|
*
|
|
1673
1783
|
* @param type - The type of event to record.
|
|
1674
1784
|
* @param data - Additional data to record with the event. This data
|
|
@@ -1677,6 +1787,20 @@ var CmcdReporter = class {
|
|
|
1677
1787
|
* into the reporter's data store.
|
|
1678
1788
|
*/
|
|
1679
1789
|
recordEvent(type, data = {}) {
|
|
1790
|
+
this.emitEvent(type, data);
|
|
1791
|
+
}
|
|
1792
|
+
/**
|
|
1793
|
+
* Records an event across every configured target, applying
|
|
1794
|
+
* state-change dedup once before per-target fan-out.
|
|
1795
|
+
*
|
|
1796
|
+
* @param type - The type of event to record.
|
|
1797
|
+
* @param data - Additional data to record with the event.
|
|
1798
|
+
* @param request - The media request that triggered the event, when
|
|
1799
|
+
* one exists. Only `recordResponseReceived()`
|
|
1800
|
+
* populates this; it is threaded through to each
|
|
1801
|
+
* target's `transform`.
|
|
1802
|
+
*/
|
|
1803
|
+
emitEvent(type, data, request) {
|
|
1680
1804
|
const entry = STATE_FIELDS_BY_EVENT.get(type);
|
|
1681
1805
|
if (entry) {
|
|
1682
1806
|
const field = entry.field;
|
|
@@ -1687,10 +1811,16 @@ var CmcdReporter = class {
|
|
|
1687
1811
|
if (entry.equal(current, this.lastEmitted[field])) return;
|
|
1688
1812
|
Object.assign(this.lastEmitted, { [field]: entry.snapshot(current) });
|
|
1689
1813
|
}
|
|
1814
|
+
let failure;
|
|
1690
1815
|
this.eventTargets.forEach((target, config) => {
|
|
1691
|
-
|
|
1816
|
+
try {
|
|
1817
|
+
this.recordTargetEvent(target, config, type, data, request);
|
|
1818
|
+
} catch (error) {
|
|
1819
|
+
failure ??= { error };
|
|
1820
|
+
}
|
|
1692
1821
|
});
|
|
1693
1822
|
this.processEventTargets();
|
|
1823
|
+
if (failure) throw failure.error;
|
|
1694
1824
|
}
|
|
1695
1825
|
/**
|
|
1696
1826
|
* Records an event for a target. Called by the reporter when an event occurs.
|
|
@@ -1701,21 +1831,51 @@ var CmcdReporter = class {
|
|
|
1701
1831
|
* @param data - Additional data to record with the event. This data
|
|
1702
1832
|
* only applies to this event report. Persistent data should
|
|
1703
1833
|
* be updated using `update()`.
|
|
1834
|
+
* @param request - The media request that triggered the event, when
|
|
1835
|
+
* one exists. Passed to the target's `transform`.
|
|
1704
1836
|
*/
|
|
1705
|
-
recordTargetEvent(target, config, type, data = {}) {
|
|
1837
|
+
recordTargetEvent(target, config, type, data = {}, request) {
|
|
1706
1838
|
if (!config.events.includes(type)) return;
|
|
1707
1839
|
const item = {
|
|
1708
1840
|
...this.data,
|
|
1709
1841
|
...data,
|
|
1710
1842
|
e: type,
|
|
1711
|
-
ts: data.ts ?? Date.now()
|
|
1712
|
-
sn: target.sn++
|
|
1843
|
+
ts: data.ts ?? Date.now()
|
|
1713
1844
|
};
|
|
1845
|
+
const { transform } = config;
|
|
1846
|
+
if (!transform) {
|
|
1847
|
+
this.queueTargetEvent(target, item, type);
|
|
1848
|
+
return;
|
|
1849
|
+
}
|
|
1850
|
+
copyReportValues(item);
|
|
1851
|
+
const requiredKey = CMCD_REQUIRED_EVENT_KEYS.get(type);
|
|
1852
|
+
const requiredValue = requiredKey ? item[requiredKey] : void 0;
|
|
1853
|
+
const ts = item.ts;
|
|
1854
|
+
const report = transform(item, request);
|
|
1855
|
+
if (report == null) return;
|
|
1856
|
+
if (!isUsableRequiredValue(report.ts)) report.ts = ts;
|
|
1857
|
+
if (requiredKey && isUsableRequiredValue(requiredValue) && !isUsableRequiredValue(report[requiredKey])) Object.assign(report, { [requiredKey]: requiredValue });
|
|
1858
|
+
this.queueTargetEvent(target, report, type);
|
|
1859
|
+
}
|
|
1860
|
+
/**
|
|
1861
|
+
* Stamps the reporter-owned fields on a finished event report and pushes it
|
|
1862
|
+
* to the target's queue.
|
|
1863
|
+
*
|
|
1864
|
+
* Called after any transform has run, so a transform cannot bypass the
|
|
1865
|
+
* target's `events` filter via `e` or break `sn` continuity.
|
|
1866
|
+
*
|
|
1867
|
+
* @param target - The target to queue the report for.
|
|
1868
|
+
* @param report - The finished report data.
|
|
1869
|
+
* @param type - The type of event being reported.
|
|
1870
|
+
*/
|
|
1871
|
+
queueTargetEvent(target, report, type) {
|
|
1872
|
+
report.e = type;
|
|
1873
|
+
report.sn = target.sn++;
|
|
1714
1874
|
if (!isNaN(this.msd) && !target.msdSent) {
|
|
1715
|
-
|
|
1875
|
+
report.msd = this.msd;
|
|
1716
1876
|
target.msdSent = true;
|
|
1717
1877
|
}
|
|
1718
|
-
target.queue.push(
|
|
1878
|
+
target.queue.push(report);
|
|
1719
1879
|
}
|
|
1720
1880
|
/**
|
|
1721
1881
|
* Records a response-received event. Called by the player when a media
|
|
@@ -1732,6 +1892,20 @@ var CmcdReporter = class {
|
|
|
1732
1892
|
* Additional keys like `ttfbb`, `cmsdd`, `cmsds`, and `smrt` can be
|
|
1733
1893
|
* supplied via the `data` parameter if the player has access to them.
|
|
1734
1894
|
*
|
|
1895
|
+
* The request's `customData` is generic, so a player can pass a request
|
|
1896
|
+
* carrying its own taxonomy (e.g. `{ requestType: 'segment' }`) without a
|
|
1897
|
+
* cast. The reporter only reads the optional `cmcd` key that
|
|
1898
|
+
* {@link CmcdReporter.createRequestReport} writes there; every other key is
|
|
1899
|
+
* left untouched and stays visible to an event target's `transform` via
|
|
1900
|
+
* its `request` argument.
|
|
1901
|
+
*
|
|
1902
|
+
* A reporter given a concrete `C` requires the request to satisfy it, so a
|
|
1903
|
+
* request the configured transforms could not read is rejected here rather
|
|
1904
|
+
* than reaching them; see {@link CmcdReporterCustomData}.
|
|
1905
|
+
*
|
|
1906
|
+
* @typeParam RD - The `customData` this request carries. Defaults to the
|
|
1907
|
+
* reporter's own `C`.
|
|
1908
|
+
*
|
|
1735
1909
|
* @param response - The HTTP response received.
|
|
1736
1910
|
* @param data - Additional CMCD data to include with the event.
|
|
1737
1911
|
* Values provided here override any auto-derived values.
|
|
@@ -1755,11 +1929,11 @@ var CmcdReporter = class {
|
|
|
1755
1929
|
if (timing.duration != null) derived.ttlb = Math.round(timing.duration);
|
|
1756
1930
|
}
|
|
1757
1931
|
const cmcd = request.customData?.cmcd ?? {};
|
|
1758
|
-
this.
|
|
1932
|
+
this.emitEvent(CMCD_EVENT_RESPONSE_RECEIVED, {
|
|
1759
1933
|
...cmcd,
|
|
1760
1934
|
...derived,
|
|
1761
1935
|
...data
|
|
1762
|
-
});
|
|
1936
|
+
}, request);
|
|
1763
1937
|
}
|
|
1764
1938
|
/**
|
|
1765
1939
|
* Applies the CMCD request report data to the request. Called by the player
|
|
@@ -1785,6 +1959,14 @@ var CmcdReporter = class {
|
|
|
1785
1959
|
* Creates a new request with the CMCD request report data applied. Called by the player
|
|
1786
1960
|
* before sending the request.
|
|
1787
1961
|
*
|
|
1962
|
+
* A reporter given a concrete `C` requires the request's `customData` to
|
|
1963
|
+
* satisfy it, so a request the configured transform could not read is
|
|
1964
|
+
* rejected here rather than reaching it; see
|
|
1965
|
+
* {@link CmcdReporterCustomData}.
|
|
1966
|
+
*
|
|
1967
|
+
* @typeParam R - The request being decorated. Its `customData` must satisfy
|
|
1968
|
+
* the reporter's `C`.
|
|
1969
|
+
*
|
|
1788
1970
|
* @param request - The request to apply the CMCD request report to.
|
|
1789
1971
|
* @param data - The data to apply to the request. This data only
|
|
1790
1972
|
* applies to this request report. Persistent data
|
|
@@ -1802,17 +1984,24 @@ var CmcdReporter = class {
|
|
|
1802
1984
|
}
|
|
1803
1985
|
};
|
|
1804
1986
|
if (!this.config.enabledKeys?.length || !report.url) return report;
|
|
1805
|
-
const
|
|
1806
|
-
const cmcdData = {
|
|
1987
|
+
const merged = {
|
|
1807
1988
|
...this.data,
|
|
1808
|
-
...data
|
|
1809
|
-
sn: this.requestTarget.sn++
|
|
1989
|
+
...data
|
|
1810
1990
|
};
|
|
1811
|
-
const
|
|
1991
|
+
const { transform } = this.config;
|
|
1992
|
+
let cmcdData = merged;
|
|
1993
|
+
if (transform) {
|
|
1994
|
+
copyReportValues(merged);
|
|
1995
|
+
cmcdData = transform(merged, request);
|
|
1996
|
+
if (cmcdData == null) return report;
|
|
1997
|
+
}
|
|
1998
|
+
cmcdData.sn = this.requestTarget.sn++;
|
|
1812
1999
|
if (!isNaN(this.msd) && !this.requestTarget.msdSent) {
|
|
1813
2000
|
cmcdData.msd = this.msd;
|
|
1814
2001
|
this.requestTarget.msdSent = true;
|
|
1815
2002
|
}
|
|
2003
|
+
const url = new URL(report.url);
|
|
2004
|
+
const options = createEncodingOptions(CMCD_REQUEST_MODE, this.config, report.url);
|
|
1816
2005
|
const cmcd = report.customData.cmcd = prepareCmcdData(cmcdData, options);
|
|
1817
2006
|
switch (this.config.transmissionMode) {
|
|
1818
2007
|
case CMCD_QUERY:
|
|
@@ -2119,8 +2308,8 @@ function resolveVersion(data, options) {
|
|
|
2119
2308
|
|
|
2120
2309
|
//#endregion
|
|
2121
2310
|
//#region src/validateCmcdKeys.ts
|
|
2122
|
-
const CMCD_V1_KEY_SET = new Set(CMCD_V1_KEYS);
|
|
2123
|
-
const CMCD_KEY_SET = new Set(CMCD_KEYS);
|
|
2311
|
+
const CMCD_V1_KEY_SET = /* @__PURE__ */ new Set(CMCD_V1_KEYS);
|
|
2312
|
+
const CMCD_KEY_SET = /* @__PURE__ */ new Set(CMCD_KEYS);
|
|
2124
2313
|
/**
|
|
2125
2314
|
* Validates that all keys in a CMCD payload are recognized spec keys or valid custom keys.
|
|
2126
2315
|
*
|
|
@@ -2454,14 +2643,14 @@ const CMCD_TOKEN_VALUES = {
|
|
|
2454
2643
|
|
|
2455
2644
|
//#endregion
|
|
2456
2645
|
//#region src/validateCmcdValues.ts
|
|
2457
|
-
const HUNDRED_ROUNDING_KEYS = new Set([
|
|
2646
|
+
const HUNDRED_ROUNDING_KEYS = /* @__PURE__ */ new Set([
|
|
2458
2647
|
"bl",
|
|
2459
2648
|
"dl",
|
|
2460
2649
|
"mtp",
|
|
2461
2650
|
"rtp",
|
|
2462
2651
|
"tbl"
|
|
2463
2652
|
]);
|
|
2464
|
-
const INTEGER_ROUNDING_KEYS = new Set([
|
|
2653
|
+
const INTEGER_ROUNDING_KEYS = /* @__PURE__ */ new Set([
|
|
2465
2654
|
"br",
|
|
2466
2655
|
"d",
|
|
2467
2656
|
"tb"
|