@svta/cml-cmcd 2.8.1 → 2.8.3
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 +2665 -2616
- package/dist/index.d.ts.map +1 -1
- package/dist/index.js +381 -223
- package/dist/index.js.map +1 -1
- package/package.json +3 -3
package/dist/index.js.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"index.js","names":["CMCD_INNER_LIST_KEYS: Set<string>","CMCD_KEY_SPECS: Readonly<Record<string, CmcdKeySpec>>","fallback: unknown","result: Record<string, any>","CUSTOM_KEY_SPEC: CmcdKeySpec","list: CmcdNorEntry[]","list: unknown[]","formatted: unknown","results: Record<string, unknown>","formatterOptions: CmcdFormatterOptions","objectTypeValue: unknown","objectType: string | undefined","keys: string[]","specs: CmcdKeySpec[]","values: unknown[]","CMCD_HEADER_FIELDS: readonly CmcdHeaderField[]","CMCD_HEADER_MAP: Record<CmcdRequestKey | 'nrr', CmcdHeaderField>","custom: Partial<Record<CmcdHeaderKey, CmcdHeaderField>>","encoded: string","params: string[]","list: (number | SfItem<number>)[]","CMCD_FORMATTER_MAP: Record<string, CmcdFormatter>","CMCD_KEYS: CmcdKey[]","CMCD_REQUEST_PROVENANCE: unique symbol","headers: Record<string, string>","body: string | undefined","ProgressEventCtor: typeof ProgressEvent | typeof Event","#deliver","#eventTargetUrls","captured: CmcdRecordedReport","#reports","#onReport","#notifyWaiters","#waiters","#getMatching","#waitTimeout","#attached","#detachers","#waitFor","CMCD_STATE_EVENT_FIELDS: ReadonlyMap<CmcdEventType, CmcdKey>","result: Record<string, any>","result: Record<string, unknown>","STATE_FIELDS: readonly StateFieldEntry[]","STATE_FIELDS_BY_EVENT: ReadonlyMap<CmcdEventType, StateFieldEntry>","CMCD_REQUIRED_EVENT_KEYS: ReadonlyMap<CmcdEventType, CmcdKey>","failure: { error: unknown; } | undefined","item: Cmcd","derived: Partial<Cmcd>","merged: Cmcd","cmcdData: Cmcd | null","result: Record<string, unknown>","CMCD_REQUEST_KEY_SET: ReadonlySet<string>","CMCD_RESPONSE_KEY_SET: ReadonlySet<string>","CMCD_EVENT_KEY_SET: ReadonlySet<string>","CMCD_V1_KEY_SET: ReadonlySet<string>","CMCD_V1_KEY_SET","CMCD_V1_KEY_SET: ReadonlySet<string>","CMCD_KEY_SET: ReadonlySet<string>","issues: CmcdValidationResult['issues']","CMCD_AGGREGATE_BITRATE_KEYS: Record<string, CmcdKey>","CMCD_KEY_OBJECT_TYPES: Record<string, readonly string[]>","issues: CmcdValidationIssue[]","CMCD_KEY_TYPES: Record<string, string>","CMCD_V1_KEY_TYPE_OVERRIDES: Record<string, string>","CMCD_STRING_LENGTH_LIMITS: Record<string, number>","CMCD_TOKEN_VALUES: Record<string, readonly string[]>","HUNDRED_ROUNDING_UNITS: Record<string, string>","issues: CmcdValidationIssue[]","bodyIssues: CmcdValidationIssue[]","decodedLines: CmcdData[]","lineResults: CmcdValidationResult[]","issues: CmcdEventsValidationResult['issues']","issues: CmcdValidationResult['issues']","decoded: Partial<Record<CmcdHeaderField, Record<string, unknown>>>","shard: Record<string, unknown>","shardResult: CmcdValidationResult","merged: Record<string, unknown>","data: CmcdData","result: Partial<Record<CmcdHeaderField, string>>"],"sources":["../src/CMCD_INNER_LIST_KEYS.ts","../src/CMCD_KEY_SPECS.ts","../src/CMCD_V2.ts","../src/CmcdReportingMode.ts","../src/downConvertToV1.ts","../src/isCmcdCustomKey.ts","../src/getKeySpec.ts","../src/isValid.ts","../src/formatNor.ts","../src/toTokenString.ts","../src/normalizeValue.ts","../src/toBareValue.ts","../src/prepareCmcdData.ts","../src/CmcdHeaderField.ts","../src/CMCD_HEADER_MAP.ts","../src/groupCmcdHeaders.ts","../src/toPreparedCmcdHeaders.ts","../src/toCmcdHeaders.ts","../src/appendCmcdHeaders.ts","../src/encodePreparedCmcd.ts","../src/encodeCmcd.ts","../src/CMCD_PARAM.ts","../src/percentEncode.ts","../src/replaceCmcdParam.ts","../src/appendCmcdQuery.ts","../src/CMCD_DEFAULT_TIME_INTERVAL.ts","../src/CMCD_EVENT_KEYS.ts","../src/CMCD_FORMATTER_MAP.ts","../src/CMCD_REQUEST_KEYS.ts","../src/CMCD_RESPONSE_KEYS.ts","../src/CMCD_V1_KEYS.ts","../src/CMCD_KEYS.ts","../src/CMCD_MIME_TYPE.ts","../src/CMCD_REQUEST_PROVENANCE.ts","../src/CMCD_V1.ts","../src/CmcdEventType.ts","../src/CmcdObjectType.ts","../src/CmcdPlayerState.ts","../src/CmcdRecordedReportMode.ts","../src/CmcdRecordedRequestType.ts","../src/createFetchTransport.ts","../src/createXhrTransport.ts","../src/CmcdReportRecorder.ts","../src/CMCD_STATE_EVENT_FIELDS.ts","../src/CmcdTransmissionMode.ts","../src/upConvertToV2.ts","../src/decodeCmcd.ts","../src/CmcdReporter.ts","../src/CmcdStreamingFormat.ts","../src/CmcdStreamType.ts","../src/CmcdValidationSeverity.ts","../src/ensureHeaders.ts","../src/fromCmcdHeaders.ts","../src/fromCmcdQuery.ts","../src/fromCmcdUrl.ts","../src/isCmcdRequestKey.ts","../src/isCmcdResponseReceivedKey.ts","../src/isCmcdEventKey.ts","../src/isCmcdV1Data.ts","../src/isCmcdV1Key.ts","../src/isCmcdV2Data.ts","../src/toCmcdUrl.ts","../src/toCmcdQuery.ts","../src/toCmcdValue.ts","../src/mergeValidationResults.ts","../src/resolveVersion.ts","../src/validateCmcdKeys.ts","../src/CMCD_AGGREGATE_BITRATE_KEYS.ts","../src/CMCD_KEY_OBJECT_TYPES.ts","../src/validateCmcdStructure.ts","../src/CMCD_KEY_TYPES.ts","../src/CMCD_STRING_LENGTH_LIMITS.ts","../src/CMCD_TOKEN_VALUES.ts","../src/validateCmcdValues.ts","../src/validateCmcd.ts","../src/validateCmcdEvents.ts","../src/validateCmcdEventReport.ts","../src/validateCmcdHeaders.ts","../src/validateCmcdRequest.ts"],"sourcesContent":["/**\n * Inner-list keys in version 2 that are scalars in version 1.\n *\n * Used by both encoding (down-conversion) and decoding (up-conversion).\n *\n * @internal\n */\nexport const CMCD_INNER_LIST_KEYS: Set<string> = new Set<string>([\n\t'ab', 'bl', 'br', 'bsa', 'bsd', 'bsda', 'lab', 'lb', 'mtp', 'pb', 'tab', 'tb', 'tbl', 'tpb',\n])\n","import type { CmcdKeySpec } from './CmcdKeySpec.ts'\n\nconst MEDIA = ['a', 'v', 'av', 'tt', 'c', 'o']\n\n/**\n * The encoder rules of each key. The table has one row for each key of CTA-5004-B Table 1, plus `nrr` of CTA-5004 and `cdn`.\n *\n * @internal\n */\nexport const CMCD_KEY_SPECS: Readonly<Record<string, CmcdKeySpec>> = {\n\tab: { type: 'ot-list', round: 1, supersededBy: 'br', version: 2 },\n\tbg: { type: 'boolean', omitDefault: false, requiredOn: 'b', version: 2 },\n\tbl: { type: 'ot-list', round: 100 },\n\tbr: { type: 'ot-list', round: 1, requiredOn: 'bc' },\n\tbs: { type: 'boolean', omitDefault: false },\n\tbsa: { type: 'ot-list', round: 1, version: 2 },\n\tbsd: { type: 'ot-list', round: 1, version: 2 },\n\tbsda: { type: 'ot-list', round: 1, version: 2 },\n\tcdn: { type: 'string', max: 128, version: 2 },\n\tcen: { type: 'string', max: 64, mode: 'event', onlyOn: 'ce', requiredOn: 'ce', version: 2 },\n\tcid: { type: 'string', max: 128, v1Max: 64, requiredOn: 'c' },\n\tcmsdd: { type: 'string', mode: 'event', onlyOn: 'rr', version: 2 },\n\tcmsds: { type: 'string', mode: 'event', onlyOn: 'rr', version: 2 },\n\tcs: { type: 'string', version: 2 },\n\td: { type: 'integer', round: 1, ot: MEDIA },\n\tdfa: { type: 'integer', round: 1, version: 2 },\n\tdl: { type: 'integer', round: 100 },\n\te: { type: 'token', mode: 'event', requiredOn: 'always', version: 2 },\n\tec: { type: 'string-list', requiredOn: 'e', version: 2 },\n\th: { type: 'string', max: 128, mode: 'event', requiredOn: 'h', version: 2 },\n\tlab: { type: 'ot-list', round: 1, supersededBy: 'lb', version: 2 },\n\tlb: { type: 'ot-list', round: 1, version: 2 },\n\tltc: { type: 'integer', round: 1, version: 2 },\n\tmsd: { type: 'integer', round: 1, version: 2 },\n\tmtp: { type: 'ot-list', round: 100 },\n\tnor: { type: 'nor' },\n\tnr: { type: 'boolean', omitDefault: false, version: 2 },\n\tnrr: { type: 'string', version: 1 },\n\tot: { type: 'token' },\n\tpb: { type: 'ot-list', round: 1, version: 2 },\n\tpr: { type: 'decimal', omitDefault: 1, requiredOn: 'pr' },\n\tpt: { type: 'integer', round: 1, version: 2 },\n\trc: { type: 'integer', round: 1, mode: 'event', onlyOn: 'rr', version: 2 },\n\trtp: { type: 'integer', round: 100 },\n\tsf: { type: 'token', v1Map: { e: 'o' } },\n\tsid: { type: 'string', max: 64 },\n\tsmrt: { type: 'string', mode: 'event', onlyOn: 'rr', version: 2 },\n\tsn: { type: 'integer', round: 1, version: 2 },\n\tst: { type: 'token', v1Map: { ll: 'l' } },\n\tsta: { type: 'token', requiredOn: 'ps', version: 2 },\n\tsu: { type: 'boolean', omitDefault: false },\n\ttab: { type: 'ot-list', round: 1, supersededBy: 'tb', version: 2 },\n\ttb: { type: 'ot-list', round: 1 },\n\ttbl: { type: 'ot-list', round: 100, version: 2 },\n\ttpb: { type: 'ot-list', round: 1, ot: ['a', 'v', 'av', 'c'], version: 2 },\n\tts: { type: 'integer', round: 1, mode: 'event', requiredOn: 'always', version: 2 },\n\tttfb: { type: 'integer', round: 1, mode: 'event', onlyOn: 'rr', version: 2 },\n\tttfbb: { type: 'integer', round: 1, mode: 'event', onlyOn: 'rr', version: 2 },\n\tttlb: { type: 'integer', round: 1, mode: 'event', onlyOn: 'rr', version: 2 },\n\turl: { type: 'string', mode: 'event', onlyOn: 'rr', requiredOn: 'rr', version: 2 },\n\tv: { type: 'integer', round: 1, requiredOn: 'always', version: 2 },\n}\n","/**\n * CMCD Version 2\n *\n * @public\n */\nexport const CMCD_V2 = 2 as const\n","import type { ValueOf } from '@svta/cml-utils'\n\n/**\n * CMCD event mode variable name.\n *\n * @public\n */\nexport const CMCD_EVENT_MODE = 'event' as const\n\n/**\n * CMCD request mode variable name.\n *\n * @public\n */\nexport const CMCD_REQUEST_MODE = 'request' as const\n\n/**\n * CMCD reporting mode types.\n *\n * @enum\n *\n * @public\n */\nexport const CmcdReportingMode = {\n\t/**\n\t * Request mode\n\t */\n\tREQUEST: CMCD_REQUEST_MODE as typeof CMCD_REQUEST_MODE,\n\n\t/**\n\t * Event mode\n\t */\n\tEVENT: CMCD_EVENT_MODE as typeof CMCD_EVENT_MODE,\n} as const\n\n/**\n * @public\n */\nexport type CmcdReportingMode = ValueOf<typeof CmcdReportingMode>;\n","import { SfItem } from '@svta/cml-structured-field-values'\nimport { CMCD_INNER_LIST_KEYS } from './CMCD_INNER_LIST_KEYS.ts'\n\nfunction hasParams(params: object | undefined): boolean {\n\tfor (const _ in params) {\n\t\treturn true\n\t}\n\n\treturn false\n}\n\n/**\n * Unwrap an inner list or SfItem value to a scalar.\n *\n * The scalar is the value of the item with the object type flag of `ot`\n * (CTA-5004-B section 4.1, item 14). Without that item, it is the value\n * of the first item without parameters. Otherwise it is `undefined`.\n */\nfunction unwrapValue(value: unknown, ot: string | undefined): unknown {\n\tif (value instanceof SfItem) {\n\t\tvalue = value.value\n\t}\n\n\tif (!Array.isArray(value)) {\n\t\treturn value\n\t}\n\n\tlet fallback: unknown\n\n\tfor (const item of value) {\n\t\tif (!(item instanceof SfItem)) {\n\t\t\tif (fallback === undefined) {\n\t\t\t\tfallback = item\n\t\t\t}\n\t\t\tcontinue\n\t\t}\n\n\t\tif (ot && item.params?.[ot] === true) {\n\t\t\treturn item.value\n\t\t}\n\n\t\tif (fallback === undefined && !hasParams(item.params)) {\n\t\t\tfallback = item.value\n\t\t}\n\t}\n\n\treturn fallback\n}\n\n/**\n * Down-convert version 2 CMCD data to version 1.\n *\n * - Extracts `nrr` from the `nor` SfItem's `r` parameter.\n * - Unwraps inner-list values to scalars for the object type `ot`.\n *\n * @internal\n */\nexport function downConvertToV1(obj: Record<string, any>, ot: string | undefined): Record<string, any> {\n\tconst result: Record<string, any> = {}\n\n\tfor (const [key, value] of Object.entries(obj)) {\n\t\tif (value == null) {\n\t\t\tresult[key] = value\n\t\t\tcontinue\n\t\t}\n\n\t\tif (key === 'nor') {\n\t\t\tconst list = value instanceof SfItem && Array.isArray(value.value) ? value.value : value\n\t\t\tconst first = Array.isArray(list) ? list[0] : list\n\n\t\t\tif (first instanceof SfItem) {\n\t\t\t\tresult['nor'] = first.value\n\t\t\t\tif (first.params?.r) {\n\t\t\t\t\tresult['nrr'] = first.params.r\n\t\t\t\t}\n\t\t\t}\n\t\t\telse {\n\t\t\t\tresult['nor'] = first\n\t\t\t}\n\t\t}\n\t\telse if (CMCD_INNER_LIST_KEYS.has(key)) {\n\t\t\tresult[key] = unwrapValue(value, ot)\n\t\t}\n\t\telse {\n\t\t\tresult[key] = value\n\t\t}\n\t}\n\n\treturn result\n}\n","import type { CmcdKey } from './CmcdKey.ts'\n\n// The CMCD custom-key charset restricted to RFC 8941 key serialization\n// (serializeKey): a lowercase first letter, then `a-z 0-9 . -`.\nconst CUSTOM_KEY_REGEX = /^[a-z][a-z0-9.-]*$/\n\n/**\n * Check if a key is a valid custom key: a lowercase first letter, then\n * characters from `a-z 0-9 . -`. The key needs a hyphen, not at the start\n * or end. This check applies the CTA-5004-B custom-key rules, restricted\n * to names that RFC 8941 key serialization accepts.\n *\n * @param key - The key to check.\n *\n * @returns `true` if the key is a custom key, `false` otherwise.\n *\n * @public\n *\n * @example\n * {@includeCode ../test/isCmcdCustomKey.test.ts#example}\n */\nexport function isCmcdCustomKey(key: CmcdKey): boolean {\n\t// The separator is checked outside the regex to keep matching linear (CodeQL js/polynomial-redos).\n\tconst separator = key.indexOf('-', 1)\n\treturn separator > 0 && separator < key.length - 1 && CUSTOM_KEY_REGEX.test(key)\n}\n","import { CMCD_KEY_SPECS } from './CMCD_KEY_SPECS.ts'\nimport type { CmcdKey } from './CmcdKey.ts'\nimport type { CmcdKeySpec } from './CmcdKeySpec.ts'\nimport { isCmcdCustomKey } from './isCmcdCustomKey.ts'\n\nconst CUSTOM_KEY_SPEC: CmcdKeySpec = { type: 'custom', omitDefault: false, max: 64, v1Max: Infinity }\n\n/**\n * Returns the row of a key in the key table.\n *\n * @param key - The key to look up.\n *\n * @returns The row of a reserved key, the custom row for a valid custom key, or `undefined`.\n *\n * @internal\n */\nexport function getKeySpec(key: string): CmcdKeySpec | undefined {\n\tif (Object.prototype.hasOwnProperty.call(CMCD_KEY_SPECS, key)) {\n\t\treturn CMCD_KEY_SPECS[key]\n\t}\n\n\treturn isCmcdCustomKey(key as CmcdKey) ? CUSTOM_KEY_SPEC : undefined\n}\n","/**\n * Checks if the given value is valid to send as a CMCD value.\n *\n * `undefined`, `null`, an empty string, `false`, an empty array, and a\n * number that is not finite are not valid. CTA-5004-B requires omitting\n * the key when its value is unknown.\n *\n * @param value - The value to check.\n *\n * @returns `true` if the value is valid.\n *\n * @internal\n */\nexport function isValid(value: unknown): boolean {\n\tif (typeof value === 'number') {\n\t\treturn Number.isFinite(value)\n\t}\n\n\tif (Array.isArray(value)) {\n\t\treturn value.length > 0\n\t}\n\n\treturn value != null && value !== '' && value !== false\n}\n","import { SfItem } from '@svta/cml-structured-field-values'\nimport { getBaseUrl, urlToRelativePath, type ValueOrArray } from '@svta/cml-utils'\nimport type { CmcdFormatterOptions } from './CmcdFormatterOptions.ts'\nimport type { CmcdVersion } from './CmcdVersion.ts'\n\ntype CmcdNorEntry = string | SfItem<string>\n\nfunction toBase(baseUrl: string | undefined): string | undefined {\n\tif (!baseUrl) {\n\t\treturn undefined\n\t}\n\n\ttry {\n\t\treturn new URL(getBaseUrl(baseUrl)).href\n\t}\n\tcatch {\n\t\treturn undefined\n\t}\n}\n\nfunction formatPath(path: unknown, base: string | undefined, version: CmcdVersion): string | undefined {\n\tif (typeof path !== 'string' || path === '') {\n\t\treturn undefined\n\t}\n\n\tconst relative = base ? urlToRelativePath(path, base) : path\n\n\treturn version === 1 ? encodeURIComponent(relative) : relative\n}\n\nfunction formatEntry(entry: unknown, base: string | undefined, version: CmcdVersion): CmcdNorEntry | undefined {\n\tif (entry instanceof SfItem) {\n\t\tconst path = formatPath(entry.value, base, version)\n\n\t\treturn path === undefined ? undefined : new SfItem(path, entry.params)\n\t}\n\n\treturn formatPath(entry, base, version)\n}\n\nfunction formatEntries(entries: unknown[], base: string | undefined, version: CmcdVersion): CmcdNorEntry[] | undefined {\n\tconst list: CmcdNorEntry[] = []\n\n\tfor (const entry of entries) {\n\t\tconst formatted = formatEntry(entry, base, version)\n\n\t\tif (formatted !== undefined) {\n\t\t\tlist.push(formatted)\n\t\t}\n\t}\n\n\treturn list.length > 0 ? list : undefined\n}\n\n/**\n * Formats a `nor` value. Each path becomes relative to `baseUrl` when `baseUrl` is a valid URL.\n * Version 1 encodes the path with `encodeURIComponent`. Version 2 wraps one path in a list.\n * The parameters of an entry and of an inner list stay on the value.\n *\n * @param value - A path, an `SfItem` of a path, or a list of them. An `SfItem` can also wrap the list.\n * @param options - The version and `baseUrl` of the report.\n *\n * @returns The formatted value, or `undefined` when no entry is a non-empty string.\n *\n * @internal\n */\nexport function formatNor(value: unknown, options: Pick<CmcdFormatterOptions, 'version' | 'baseUrl'>): ValueOrArray<CmcdNorEntry> | undefined {\n\tconst base = toBase(options.baseUrl)\n\tconst version = options.version\n\n\tif (Array.isArray(value)) {\n\t\treturn formatEntries(value, base, version)\n\t}\n\n\tif (value instanceof SfItem && Array.isArray(value.value)) {\n\t\tconst list = formatEntries(value.value, base, version)\n\n\t\treturn list && new SfItem(list, value.params)\n\t}\n\n\tconst entry = formatEntry(value, base, version)\n\n\treturn version === 1 || entry === undefined ? entry : [entry]\n}\n","import { SfItem, SfToken, symbolToStr } from '@svta/cml-structured-field-values'\n\n/**\n * Resolve the text of a token value.\n *\n * A token may be a plain string, a registry `Symbol`, an `SfToken`, or an\n * `SfItem` that wraps such a value.\n *\n * @param value - The value to resolve.\n *\n * @returns The token text, or `undefined` when the value is not a token.\n *\n * @internal\n */\nexport function toTokenString(value: unknown): string | undefined {\n\tif (value instanceof SfItem) {\n\t\treturn toTokenString(value.value)\n\t}\n\n\tif (typeof value === 'string') {\n\t\treturn value\n\t}\n\n\tif (typeof value === 'symbol' || value instanceof SfToken) {\n\t\treturn symbolToStr(value)\n\t}\n\n\treturn undefined\n}\n","import { SfItem, SfToken } from '@svta/cml-structured-field-values'\nimport type { CmcdFormatterOptions } from './CmcdFormatterOptions.ts'\nimport type { CmcdKeySpec } from './CmcdKeySpec.ts'\nimport type { CmcdVersion } from './CmcdVersion.ts'\nimport { formatNor } from './formatNor.ts'\nimport { toTokenString } from './toTokenString.ts'\n\ntype CmcdStringKeySpec = Extract<CmcdKeySpec, { type: 'string' | 'custom' }>\n\nfunction toText(value: unknown, spec: CmcdStringKeySpec, version: CmcdVersion): string | undefined {\n\tconst max = (version === 1 ? spec.v1Max : undefined) ?? spec.max ?? Infinity\n\n\treturn typeof value === 'string' && value !== '' && value.length <= max ? value : undefined\n}\n\nfunction normalizeBare(value: unknown, spec: CmcdKeySpec, version: CmcdVersion): unknown {\n\tswitch (spec.type) {\n\t\tcase 'boolean':\n\t\t\treturn typeof value === 'boolean' ? value : undefined\n\n\t\tcase 'integer':\n\t\tcase 'ot-list':\n\t\t\treturn typeof value === 'number' && Number.isFinite(value) ? Math.round(value / spec.round) * spec.round : undefined\n\n\t\tcase 'decimal':\n\t\t\treturn typeof value === 'number' && Number.isFinite(value) ? value : undefined\n\n\t\tcase 'string':\n\t\t\treturn toText(value, spec, version)\n\n\t\tcase 'string-list':\n\t\t\treturn typeof value === 'string' && value !== '' ? value : undefined\n\n\t\tcase 'token': {\n\t\t\tconst text = toTokenString(value)\n\t\t\tconst v1Map = version === 1 ? spec.v1Map : undefined\n\t\t\tconst token = text !== undefined && v1Map !== undefined && Object.prototype.hasOwnProperty.call(v1Map, text) ? v1Map[text] : text\n\n\t\t\treturn token ? new SfToken(token) : undefined\n\t\t}\n\n\t\tcase 'custom':\n\t\t\tif (typeof value === 'string') {\n\t\t\t\treturn toText(value, spec, version)\n\t\t\t}\n\n\t\t\tif (typeof value === 'number') {\n\t\t\t\treturn Number.isFinite(value) ? value : undefined\n\t\t\t}\n\n\t\t\tif (Array.isArray(value)) {\n\t\t\t\treturn value.length > 0 ? value : undefined\n\t\t\t}\n\n\t\t\treturn typeof value === 'boolean' || typeof value === 'symbol' || value instanceof SfToken ? value : undefined\n\n\t\tdefault:\n\t\t\treturn undefined\n\t}\n}\n\nfunction normalizeItem(value: unknown, spec: CmcdKeySpec, version: CmcdVersion): unknown {\n\tif (value instanceof SfItem) {\n\t\tconst bare = normalizeBare(value.value, spec, version)\n\n\t\treturn bare === undefined ? undefined : new SfItem(bare, value.params)\n\t}\n\n\treturn normalizeBare(value, spec, version)\n}\n\nfunction normalizeList(value: unknown, spec: CmcdKeySpec, version: CmcdVersion): unknown {\n\tconst wrapper = value instanceof SfItem && Array.isArray(value.value) ? value : undefined\n\tconst items = wrapper ? wrapper.value as unknown as unknown[] : Array.isArray(value) ? value : [value]\n\tconst list: unknown[] = []\n\n\tfor (const item of items) {\n\t\tconst normalized = normalizeItem(item, spec, version)\n\n\t\tif (normalized !== undefined) {\n\t\t\tlist.push(normalized)\n\t\t}\n\t}\n\n\tif (list.length === 0) {\n\t\treturn undefined\n\t}\n\n\treturn wrapper ? new SfItem(list, wrapper.params) : list\n}\n\n/**\n * Applies the value rule of a key type from the key table.\n *\n * An `SfItem` keeps its parameters, and the rule applies to the value inside it.\n * In version 2, a list key wraps one value in a list.\n * The rules do not check the limits of RFC 8941, such as the integer range.\n *\n * @param value - The value to prepare.\n * @param spec - The row of the key in the key table.\n * @param options - The version and `baseUrl` of the report.\n *\n * @returns The value to send, or `undefined` when the value fails the rule.\n *\n * @internal\n */\nexport function normalizeValue(value: unknown, spec: CmcdKeySpec, options: CmcdFormatterOptions): unknown {\n\tif (spec.type === 'nor') {\n\t\treturn formatNor(value, options)\n\t}\n\n\tif (spec.type === 'string-list' || (spec.type === 'ot-list' && options.version !== 1)) {\n\t\treturn normalizeList(value, spec, options.version)\n\t}\n\n\treturn normalizeItem(value, spec, options.version)\n}\n","import { SfItem } from '@svta/cml-structured-field-values'\n\n/**\n * Returns the value inside an `SfItem`, or the value itself.\n *\n * `decodeCmcd` returns a member with parameters as an `SfItem`. For an\n * inner list with parameters, the value of the `SfItem` is the list.\n *\n * @param value - The value to read.\n * @returns The value without its parameters.\n *\n * @internal\n */\nexport function toBareValue(value: unknown): unknown {\n\treturn value instanceof SfItem ? value.value : value\n}\n","import { SfItem, SfToken } from '@svta/cml-structured-field-values'\nimport { CMCD_INNER_LIST_KEYS } from './CMCD_INNER_LIST_KEYS.ts'\nimport { CMCD_KEY_SPECS } from './CMCD_KEY_SPECS.ts'\nimport { CMCD_V2 } from './CMCD_V2.ts'\nimport type { Cmcd } from './Cmcd.ts'\nimport type { CmcdEncodeOptions } from './CmcdEncodeOptions.ts'\nimport type { CmcdFormatterOptions } from './CmcdFormatterOptions.ts'\nimport type { CmcdKey } from './CmcdKey.ts'\nimport type { CmcdKeySpec } from './CmcdKeySpec.ts'\nimport { CMCD_EVENT_MODE, CMCD_REQUEST_MODE, type CmcdReportingMode } from './CmcdReportingMode.ts'\nimport type { CmcdValue } from './CmcdValue.ts'\nimport type { CmcdVersion } from './CmcdVersion.ts'\nimport { downConvertToV1 } from './downConvertToV1.ts'\nimport { getKeySpec } from './getKeySpec.ts'\nimport { isValid } from './isValid.ts'\nimport { normalizeValue } from './normalizeValue.ts'\nimport { toBareValue } from './toBareValue.ts'\nimport { toTokenString } from './toTokenString.ts'\n\nfunction hasKey(spec: CmcdKeySpec, reportingMode: CmcdReportingMode, isV1: boolean): boolean {\n\treturn (spec.mode === undefined || spec.mode === reportingMode)\n\t\t&& (spec.version === undefined || (spec.version === 1) === isV1)\n}\n\nfunction isRequired(spec: CmcdKeySpec, event: string | undefined): boolean {\n\treturn spec.requiredOn === 'always' || (event !== undefined && spec.requiredOn === event)\n}\n\nfunction hasObjectTypes(spec: CmcdKeySpec): boolean {\n\treturn (spec.type === 'integer' || spec.type === 'ot-list') && spec.ot !== undefined\n}\n\nfunction needsV1ObjectType(obj: Record<string, any>, filter: CmcdEncodeOptions['filter']): boolean {\n\tif (typeof filter !== 'function' || filter('ot')) {\n\t\treturn true\n\t}\n\n\tfor (const key of CMCD_INNER_LIST_KEYS) {\n\t\tif (Array.isArray(toBareValue(obj[key])) && filter(key as CmcdKey)) {\n\t\t\treturn true\n\t\t}\n\t}\n\n\treturn false\n}\n\nfunction allowsObjectType(spec: CmcdKeySpec, objectType: string | undefined): boolean {\n\tif (objectType === undefined || (spec.type !== 'integer' && spec.type !== 'ot-list') || spec.ot === undefined) {\n\t\treturn true\n\t}\n\n\treturn spec.ot.includes(objectType)\n}\n\nfunction isDefaultValue(spec: CmcdKeySpec, value: unknown): boolean {\n\treturn 'omitDefault' in spec && toBareValue(value) === spec.omitDefault\n}\n\nfunction insertKey(keys: string[], specs: CmcdKeySpec[], key: string): void {\n\tlet index = 0\n\n\twhile (index < keys.length && keys[index] < key) {\n\t\tindex++\n\t}\n\n\tkeys.splice(index, 0, key)\n\tspecs.splice(index, 0, CMCD_KEY_SPECS[key])\n}\n\nfunction prepareValue(key: string, value: unknown, spec: CmcdKeySpec, options: CmcdEncodeOptions, formatterOptions: CmcdFormatterOptions): unknown {\n\tconst formatter = options.formatters?.[key as CmcdKey]\n\n\tif (typeof formatter !== 'function') {\n\t\treturn value == null ? undefined : normalizeValue(value, spec, formatterOptions)\n\t}\n\n\tconst formatted: unknown = isValid(value) ? formatter(value as CmcdValue, formatterOptions) : value\n\n\tif (!isValid(formatted) && !(formatted === false && spec.type === 'boolean')) {\n\t\treturn undefined\n\t}\n\n\tif (spec.type === 'token') {\n\t\tif (typeof formatted === 'string') {\n\t\t\treturn new SfToken(formatted)\n\t\t}\n\n\t\tif (formatted instanceof SfItem && typeof formatted.value === 'string') {\n\t\t\treturn new SfItem(new SfToken(formatted.value), formatted.params)\n\t\t}\n\t}\n\n\treturn formatted\n}\n\n/**\n * Convert a generic object to CMCD data.\n *\n * @param obj - The CMCD object to process.\n * @param options - Options for encoding.\n *\n * @public\n *\n * @example\n * {@includeCode ../test/prepareCmcdData.test.ts#example}\n */\nexport function prepareCmcdData(obj: Record<string, any>, options: CmcdEncodeOptions = {}): Cmcd {\n\tconst results: Record<string, unknown> = {}\n\n\tif (obj == null || typeof obj !== 'object') {\n\t\treturn results as Cmcd\n\t}\n\n\tconst version = options.version || toBareValue(obj['v']) as CmcdVersion || CMCD_V2\n\tconst reportingMode = options.reportingMode || CMCD_REQUEST_MODE\n\tconst isV1 = version === 1\n\tconst isEventReport = !isV1 && reportingMode === CMCD_EVENT_MODE\n\tconst formatterOptions: CmcdFormatterOptions = { version, reportingMode, baseUrl: options.baseUrl }\n\tconst filter = options.filter\n\n\tlet objectTypeValue: unknown\n\tlet objectType: string | undefined\n\n\tif (isV1 && needsV1ObjectType(obj, filter)) {\n\t\tobjectTypeValue = prepareValue('ot', obj['ot'], CMCD_KEY_SPECS['ot'], options, formatterOptions)\n\t\tobjectType = toTokenString(objectTypeValue)\n\t}\n\n\tconst data = isV1 ? downConvertToV1(obj, objectType) : obj\n\tconst eventValue = isEventReport ? prepareValue('e', data['e'], CMCD_KEY_SPECS['e'], options, formatterOptions) : undefined\n\tconst event = toTokenString(eventValue)\n\tconst keys: string[] = []\n\tconst specs: CmcdKeySpec[] = []\n\tlet passed = false\n\tlet needsObjectType = false\n\n\tfor (const key of Object.keys(data).sort()) {\n\t\tconst spec = getKeySpec(key)\n\n\t\tif (spec === undefined || !hasKey(spec, reportingMode, isV1)) {\n\t\t\tcontinue\n\t\t}\n\n\t\tif (typeof filter !== 'function' || filter(key as CmcdKey)) {\n\t\t\tpassed = true\n\t\t}\n\t\telse if (!isRequired(spec, event)) {\n\t\t\tcontinue\n\t\t}\n\n\t\tif (spec.onlyOn !== undefined && spec.onlyOn !== event) {\n\t\t\tcontinue\n\t\t}\n\n\t\tif (key === 'ot' || hasObjectTypes(spec)) {\n\t\t\tneedsObjectType = true\n\t\t}\n\n\t\tkeys.push(key)\n\t\tspecs.push(spec)\n\t}\n\n\tif (!passed && !isEventReport) {\n\t\treturn results as Cmcd\n\t}\n\n\tif (needsObjectType && !isV1) {\n\t\tobjectTypeValue = prepareValue('ot', data['ot'], CMCD_KEY_SPECS['ot'], options, formatterOptions)\n\t\tobjectType = toTokenString(objectTypeValue)\n\t}\n\n\tif (isEventReport && !keys.includes('ts')) {\n\t\tinsertKey(keys, specs, 'ts')\n\t}\n\n\tif (!isV1 && !keys.includes('v')) {\n\t\tinsertKey(keys, specs, 'v')\n\t}\n\n\tconst values: unknown[] = new Array(keys.length)\n\n\tfor (let i = keys.length - 1; i >= 0; i--) {\n\t\tconst key = keys[i]\n\t\tconst spec = specs[i]\n\n\t\tif (spec.type === 'ot-list' && spec.supersededBy !== undefined) {\n\t\t\tconst exact = keys.indexOf(spec.supersededBy, i + 1)\n\n\t\t\tif (exact !== -1 && values[exact] !== undefined) {\n\t\t\t\tcontinue\n\t\t\t}\n\t\t}\n\n\t\tif (key === 'v') {\n\t\t\tvalues[i] = version\n\t\t}\n\t\telse if (key === 'ot') {\n\t\t\tvalues[i] = objectTypeValue\n\t\t}\n\t\telse if (key === 'e') {\n\t\t\tvalues[i] = eventValue\n\t\t}\n\t\telse if (isV1 || allowsObjectType(spec, objectType)) {\n\t\t\tvalues[i] = prepareValue(key, data[key], spec, options, formatterOptions)\n\t\t}\n\n\t\tif (key === 'ts') {\n\t\t\tconst timestamp = toBareValue(values[i])\n\n\t\t\tif (typeof timestamp !== 'number' || !Number.isFinite(timestamp)) {\n\t\t\t\tvalues[i] = Date.now()\n\t\t\t}\n\t\t}\n\t}\n\n\tfor (let i = 0; i < keys.length; i++) {\n\t\tconst value = values[i]\n\n\t\tif (value !== undefined && (!isDefaultValue(specs[i], value) || isRequired(specs[i], event))) {\n\t\t\tresults[keys[i]] = value\n\t\t}\n\t}\n\n\treturn results as Cmcd\n}\n","import type { ValueOf } from '@svta/cml-utils'\n\n/**\n * CMCD object header name.\n *\n * @public\n */\nexport const CMCD_OBJECT = 'CMCD-Object' as const\n\n/**\n * CMCD request header name.\n *\n * @public\n */\nexport const CMCD_REQUEST = 'CMCD-Request' as const\n\n/**\n * CMCD session header name.\n *\n * @public\n */\nexport const CMCD_SESSION = 'CMCD-Session' as const\n\n/**\n * CMCD status header name.\n *\n * @public\n */\nexport const CMCD_STATUS = 'CMCD-Status' as const\n\n/**\n * CMCD header fields.\n *\n *\n * @enum\n *\n * @public\n */\nexport const CmcdHeaderField = {\n\t/**\n\t * keys whose values vary with the object being requested.\n\t */\n\tOBJECT: CMCD_OBJECT as typeof CMCD_OBJECT,\n\n\t/**\n\t * keys whose values vary with each request.\n\t */\n\tREQUEST: CMCD_REQUEST as typeof CMCD_REQUEST,\n\n\t/**\n\t * keys whose values are expected to be invariant over the life of the session.\n\t */\n\tSESSION: CMCD_SESSION as typeof CMCD_SESSION,\n\n\t/**\n\t * keys whose values do not vary with every request or object.\n\t */\n\tSTATUS: CMCD_STATUS as typeof CMCD_STATUS,\n} as const\n\n/**\n * @public\n */\nexport type CmcdHeaderField = ValueOf<typeof CmcdHeaderField>;\n\n/**\n * All CMCD header fields as an array.\n *\n * @public\n */\nexport const CMCD_HEADER_FIELDS: readonly CmcdHeaderField[] = [CMCD_OBJECT, CMCD_REQUEST, CMCD_SESSION, CMCD_STATUS]\n","import { type CmcdHeaderField, CMCD_OBJECT, CMCD_REQUEST, CMCD_SESSION, CMCD_STATUS } from './CmcdHeaderField.ts'\nimport type { CmcdRequestKey } from './CmcdRequestKey.ts'\n\n/**\n * The map of CMCD keys to their appropriate header shard.\n *\n * Event-only keys (e, ts, cen, h) and response-received keys (rc, ttfb,\n * ttlb, url, and others) are intentionally absent. They are transmitted\n * in the event-mode POST body, not HTTP headers.\n *\n * @public\n */\nexport const CMCD_HEADER_MAP: Record<CmcdRequestKey | 'nrr', CmcdHeaderField> = {\n\t// Object\n\tab: CMCD_OBJECT,\n\tbr: CMCD_OBJECT,\n\td: CMCD_OBJECT,\n\tlab: CMCD_OBJECT,\n\tlb: CMCD_OBJECT,\n\tot: CMCD_OBJECT,\n\ttab: CMCD_OBJECT,\n\ttb: CMCD_OBJECT,\n\ttpb: CMCD_OBJECT,\n\n\t// Request\n\tbl: CMCD_REQUEST,\n\tcs: CMCD_REQUEST,\n\tdfa: CMCD_REQUEST,\n\tdl: CMCD_REQUEST,\n\tltc: CMCD_REQUEST,\n\tmtp: CMCD_REQUEST,\n\tnor: CMCD_REQUEST,\n\tnrr: CMCD_REQUEST,\n\tpb: CMCD_REQUEST,\n\tsn: CMCD_REQUEST,\n\tsta: CMCD_REQUEST,\n\tsu: CMCD_REQUEST,\n\ttbl: CMCD_REQUEST,\n\n\t// Session\n\tcid: CMCD_SESSION,\n\tmsd: CMCD_SESSION,\n\tsf: CMCD_SESSION,\n\tsid: CMCD_SESSION,\n\tst: CMCD_SESSION,\n\tv: CMCD_SESSION,\n\n\t// Status\n\tbg: CMCD_STATUS,\n\tbs: CMCD_STATUS,\n\tbsa: CMCD_STATUS,\n\tbsd: CMCD_STATUS,\n\tbsda: CMCD_STATUS,\n\tcdn: CMCD_STATUS,\n\tec: CMCD_STATUS,\n\tnr: CMCD_STATUS,\n\tpr: CMCD_STATUS,\n\tpt: CMCD_STATUS,\n\trtp: CMCD_STATUS,\n}\n","import type { Cmcd } from './Cmcd.ts'\nimport { CMCD_HEADER_MAP } from './CMCD_HEADER_MAP.ts'\nimport { CmcdHeaderField } from './CmcdHeaderField.ts'\nimport type { CmcdHeaderKey } from './CmcdHeaderKey.ts'\nimport type { CmcdHeaderMap } from './CmcdHeaderMap.ts'\nimport type { CmcdHeaderValue } from './CmcdHeaderValue.ts'\nimport type { CmcdKey } from './CmcdKey.ts'\n\nfunction createHeaderMap(headerMap: Partial<CmcdHeaderMap>): Record<CmcdHeaderKey, CmcdHeaderField> {\n\treturn Object.keys(headerMap)\n\t\t.reduce((acc, field) => {\n\t\t\theaderMap[field as CmcdHeaderField]?.forEach(key => acc[key] = field as CmcdHeaderField)\n\t\t\treturn acc\n\t\t}, {} as Record<CmcdKey, CmcdHeaderField>)\n}\n\n/**\n * Group a CMCD object into header shards\n *\n * @param cmcd - The CMCD object to convert.\n * @param customHeaderMap - A map of CMCD header fields to custom CMCD keys.\n *\n * @returns The CMCD header shards.\n *\n * @see {@link https://cta-wave.github.io/Resources/common-media-client-data--cta-5004-b.html#header-field-definition | CTA-5004-B Header Field Definition}\n *\n * @public\n */\nexport function groupCmcdHeaders(cmcd: Cmcd, customHeaderMap?: Partial<CmcdHeaderMap>): Record<CmcdHeaderField, CmcdHeaderValue> {\n\tconst result = {} as Record<CmcdHeaderField, CmcdHeaderValue>\n\n\tif (!cmcd) {\n\t\treturn result\n\t}\n\n\tconst keys = Object.keys(cmcd) as CmcdHeaderKey[]\n\tconst custom: Partial<Record<CmcdHeaderKey, CmcdHeaderField>> = customHeaderMap ? createHeaderMap(customHeaderMap) : {}\n\n\tfor (const key of keys) {\n\t\tconst field = CMCD_HEADER_MAP[key] || custom[key] || CmcdHeaderField.REQUEST\n\t\tconst data = result[field] ??= {};\n\t\t(data as Record<string, unknown>)[key] = (cmcd as Record<string, unknown>)[key]\n\t}\n\n\treturn result\n}\n","import { encodeSfDict } from '@svta/cml-structured-field-values'\nimport type { Cmcd } from './Cmcd.ts'\nimport type { CmcdHeaderField } from './CmcdHeaderField.ts'\nimport type { CmcdHeaderMap } from './CmcdHeaderMap.ts'\nimport type { CmcdHeaderValue } from './CmcdHeaderValue.ts'\nimport { groupCmcdHeaders } from './groupCmcdHeaders.ts'\n\n/**\n * Encode already-prepared CMCD data to CMCD header shards.\n *\n * @param data - The prepared CMCD data to encode.\n * @param customHeaderMap - A map of CMCD header fields to custom CMCD keys.\n * @returns The CMCD header shards.\n *\n * @internal\n */\nexport function toPreparedCmcdHeaders(data: Cmcd, customHeaderMap?: Partial<CmcdHeaderMap>): Record<CmcdHeaderField, string> {\n\tconst result = {} as Record<CmcdHeaderField, string>\n\tconst shards = groupCmcdHeaders(data, customHeaderMap)\n\n\tfor (const [field, value] of Object.entries(shards)) {\n\t\tconst shard = encodeSfDict(value as CmcdHeaderValue, { whitespace: false })\n\t\tif (shard) {\n\t\t\tresult[field as CmcdHeaderField] = shard\n\t\t}\n\t}\n\n\treturn result\n}\n","import type { Cmcd } from './Cmcd.ts'\nimport type { CmcdEncodeOptions } from './CmcdEncodeOptions.ts'\nimport type { CmcdHeaderField } from './CmcdHeaderField.ts'\nimport { prepareCmcdData } from './prepareCmcdData.ts'\nimport { toPreparedCmcdHeaders } from './toPreparedCmcdHeaders.ts'\n\n/**\n * Convert a CMCD object to request headers\n *\n * @param cmcd - The CMCD object to convert.\n * @param options - Options for encoding.\n *\n * @returns The CMCD header shards.\n *\n * @see {@link https://cta-wave.github.io/Resources/common-media-client-data--cta-5004-b.html#header-field-definition | CTA-5004-B Header Field Definition}\n *\n * @public\n *\n * @example\n * {@includeCode ../test/toCmcdHeaders.test.ts#example}\n */\nexport function toCmcdHeaders(cmcd: Cmcd, options: CmcdEncodeOptions = {}): Record<CmcdHeaderField, string> {\n\tif (!cmcd) {\n\t\treturn {} as Record<CmcdHeaderField, string>\n\t}\n\n\treturn toPreparedCmcdHeaders(prepareCmcdData(cmcd, options), options?.customHeaderMap)\n}\n","import type { Cmcd } from './Cmcd.ts'\nimport type { CmcdEncodeOptions } from './CmcdEncodeOptions.ts'\nimport { toCmcdHeaders } from './toCmcdHeaders.ts'\n\n/**\n * Append CMCD header shards to a header object.\n *\n * @param headers - The headers to append to.\n * @param cmcd - The CMCD object to append.\n * @param options - Options for encoding.\n *\n * @returns The headers with CMCD header shards appended.\n *\n * @public\n *\n * @example\n * {@includeCode ../test/appendCmcdHeaders.test.ts#example}\n *\n * @see {@link https://cta-wave.github.io/Resources/common-media-client-data--cta-5004-b.html#header-field-definition | CTA-5004-B Header Field Definition}\n */\nexport function appendCmcdHeaders(headers: Record<string, string>, cmcd: Cmcd, options?: CmcdEncodeOptions): Record<string, string> {\n\treturn Object.assign(headers, toCmcdHeaders(cmcd, options))\n}\n","import { encodeSfDict } from '@svta/cml-structured-field-values'\nimport type { Cmcd } from './Cmcd.ts'\n\n/**\n * Encode already-prepared CMCD data to a structured field dictionary string.\n *\n * @param data - The prepared CMCD data to encode.\n * @returns The encoded CMCD string.\n *\n * @internal\n */\nexport function encodePreparedCmcd(data: Cmcd): string {\n\treturn encodeSfDict(data, { whitespace: false })\n}\n","import type { Cmcd } from './Cmcd.ts'\nimport type { CmcdEncodeOptions } from './CmcdEncodeOptions.ts'\nimport { encodePreparedCmcd } from './encodePreparedCmcd.ts'\nimport { prepareCmcdData } from './prepareCmcdData.ts'\n\n/**\n * Encode a CMCD object to a string.\n *\n * @param cmcd - The CMCD object to encode.\n * @param options - Options for encoding.\n *\n * @returns The encoded CMCD string.\n *\n * @see {@link https://cta-wave.github.io/Resources/common-media-client-data--cta-5004-b.html#payload-definition-for-headers-and-query-argument-transmission | CTA-5004-B Payload Definition}\n *\n * @public\n *\n * @example\n * {@includeCode ../test/encodeCmcd.test.ts#example}\n */\nexport function encodeCmcd(cmcd: Cmcd, options: CmcdEncodeOptions = {}): string {\n\tif (!cmcd) {\n\t\treturn ''\n\t}\n\n\treturn encodePreparedCmcd(prepareCmcdData(cmcd, options))\n}\n","/**\n * CMCD parameter name.\n *\n * @public\n */\nexport const CMCD_PARAM = 'CMCD'\n","// The sub-delims of RFC 3986 that `encodeURIComponent` does not encode.\nconst SUB_DELIMS_REGEX = /[!'()*]/g\nconst SURROGATE_REGEX = /[\\uD800-\\uDBFF][\\uDC00-\\uDFFF]|[\\uD800-\\uDFFF]/g\n\nfunction encodeSubDelim(char: string): string {\n\treturn `%${char.charCodeAt(0).toString(16).toUpperCase()}`\n}\n\nfunction replaceUnpaired(match: string): string {\n\treturn match.length === 2 ? match : '�'\n}\n\n/**\n * Percent-encode a string for the `CMCD` query parameter.\n *\n * Only the unreserved characters of RFC 3986 stay unencoded: letters, digits,\n * `-`, `.`, `_`, and `~`. The query examples of CTA-5004-B use this encoding.\n * An unpaired surrogate becomes U+FFFD.\n *\n * @param value - The string to encode.\n * @returns The encoded string.\n *\n * @internal\n */\nexport function percentEncode(value: string): string {\n\tlet encoded: string\n\n\ttry {\n\t\tencoded = encodeURIComponent(value)\n\t}\n\tcatch {\n\t\tencoded = encodeURIComponent(value.replace(SURROGATE_REGEX, replaceUnpaired))\n\t}\n\n\treturn encoded.replace(SUB_DELIMS_REGEX, encodeSubDelim)\n}\n","import { CMCD_PARAM } from './CMCD_PARAM.ts'\nimport { percentEncode } from './percentEncode.ts'\n\nfunction isCmcdParam(param: string): boolean {\n\treturn param === CMCD_PARAM || param.startsWith(`${CMCD_PARAM}=`)\n}\n\n/**\n * Replace the `CMCD` query parameter of a URL.\n *\n * The first `CMCD` parameter takes the new value in place. The function\n * removes the other `CMCD` parameters. If the URL has no `CMCD` parameter,\n * the new parameter goes at the end of the query. An empty `value` only\n * removes the parameters. The function does not change the rest of the URL.\n * The URL can be relative.\n *\n * @param url - The URL.\n * @param value - The encoded CMCD data, before percent-encoding.\n * @returns The URL with at most one `CMCD` parameter.\n *\n * @internal\n */\nexport function replaceCmcdParam(url: string, value?: string): string {\n\tconst hashIndex = url.indexOf('#')\n\tconst end = hashIndex === -1 ? url.length : hashIndex\n\tconst queryIndex = url.indexOf('?')\n\tconst start = queryIndex === -1 || queryIndex > end ? end : queryIndex\n\tconst params: string[] = []\n\tlet param = value ? `${CMCD_PARAM}=${percentEncode(value)}` : ''\n\tlet found = false\n\n\tfor (const item of start < end ? url.slice(start + 1, end).split('&') : []) {\n\t\tif (!isCmcdParam(item)) {\n\t\t\tparams.push(item)\n\t\t}\n\t\telse {\n\t\t\tfound = true\n\n\t\t\tif (param) {\n\t\t\t\tparams.push(param)\n\t\t\t\tparam = ''\n\t\t\t}\n\t\t}\n\t}\n\n\tif (param) {\n\t\tif (params[params.length - 1] === '') {\n\t\t\tparams.pop()\n\t\t}\n\n\t\tparams.push(param)\n\t}\n\telse if (!found) {\n\t\treturn url\n\t}\n\n\tconst query = params.join('&')\n\n\treturn `${url.slice(0, start)}${query ? `?${query}` : ''}${url.slice(end)}`\n}\n","import type { Cmcd } from './Cmcd.ts'\nimport type { CmcdEncodeOptions } from './CmcdEncodeOptions.ts'\nimport { encodeCmcd } from './encodeCmcd.ts'\nimport { replaceCmcdParam } from './replaceCmcdParam.ts'\n\n/**\n * Append CMCD query args to a URL.\n *\n * If the URL has a `CMCD` parameter, the new value replaces it in place. The\n * other parameters and the fragment stay as they are. If the data has no keys\n * to send, the function returns the URL unchanged.\n *\n * @param url - The URL to append to.\n * @param cmcd - The CMCD object to append.\n * @param options - Options for encoding.\n *\n * @returns The URL with the CMCD query args appended.\n *\n * @public\n *\n * @example\n * {@includeCode ../test/appendCmcdQuery.test.ts#example}\n *\n * @see {@link https://cta-wave.github.io/Resources/common-media-client-data--cta-5004-b.html#query-argument-definition | CTA-5004-B Query Argument Definition}\n */\nexport function appendCmcdQuery(url: string, cmcd: Cmcd, options?: CmcdEncodeOptions): string {\n\tconst value = cmcd ? encodeCmcd(cmcd, options) : ''\n\n\treturn value ? replaceCmcdParam(url, value) : url\n}\n","/**\n * The default time interval in seconds when using event mode\n *\n * @public\n */\nexport const CMCD_DEFAULT_TIME_INTERVAL = 30\n","/**\n * Defines the event-specific keys for CMCD (Common Media Client Data) version 2.\n *\n * @public\n */\nexport const CMCD_EVENT_KEYS = [\n\t'cen',\n\t'e',\n\t'h',\n\t'ts',\n] as const\n","import { SfItem } from '@svta/cml-structured-field-values'\nimport type { ValueOrArray } from '@svta/cml-utils'\nimport type { CmcdFormatter } from './CmcdFormatter.ts'\nimport type { CmcdFormatterOptions } from './CmcdFormatterOptions.ts'\nimport type { CmcdValue } from './CmcdValue.ts'\nimport { formatNor } from './formatNor.ts'\nimport { isValid } from './isValid.ts'\n\nconst formatNumbers = (value: CmcdValue, format: (value: number) => number): ValueOrArray<number | SfItem<number>> => {\n\tif (Array.isArray(value)) {\n\t\tconst list: (number | SfItem<number>)[] = []\n\n\t\tfor (const item of value) {\n\t\t\tconst formatted = formatNumbers(item, format) as number | SfItem<number>\n\n\t\t\tif (Number.isFinite(formatted instanceof SfItem ? formatted.value : formatted)) {\n\t\t\t\tlist.push(formatted)\n\t\t\t}\n\t\t}\n\n\t\treturn list\n\t}\n\n\tif (value instanceof SfItem) {\n\t\tconst formatted = formatNumbers(value.value as CmcdValue, format)\n\t\treturn isValid(formatted) ? new SfItem(formatted, value.params) : NaN\n\t}\n\n\treturn typeof value === 'number' ? format(value) : NaN\n}\n\nconst toRounded = (value: CmcdValue) => formatNumbers(value, Math.round)\n\nconst toNumber = (value: CmcdValue) => formatNumbers(value, Number)\n\nconst roundToHundred = (value: number): number => Math.round(value / 100) * 100\n\nconst toHundred = (value: CmcdValue) => formatNumbers(value, roundToHundred)\n\n/**\n * Formatters for CMCD values.\n *\n * The encoder applies the same rounding through its key table, and `nor` is the `nor` rule of the encoder.\n * Use an entry to build a custom formatter for `CmcdEncodeOptions.formatters`.\n * The formatter of a numeric key drops a value or a list element that is not a finite number.\n *\n * @public\n */\nexport const CMCD_FORMATTER_MAP: Record<string, CmcdFormatter> = {\n\t/**\n\t * Bitrate (kbps) rounded integer\n\t */\n\tbr: toRounded,\n\n\t/**\n\t * Duration (milliseconds) rounded integer\n\t */\n\td: toRounded,\n\n\t/**\n\t * Buffer Length (milliseconds) rounded nearest 100ms\n\t */\n\tbl: toHundred,\n\n\t/**\n\t * Deadline (milliseconds) rounded nearest 100ms\n\t */\n\tdl: toHundred,\n\n\t/**\n\t * Measured Throughput (kbps) rounded nearest 100kbps\n\t */\n\tmtp: toHundred,\n\n\t/**\n\t * Next Object Request URL encoded\n\t */\n\tnor: (value: CmcdValue, options: CmcdFormatterOptions) => formatNor(value, options) ?? '',\n\n\t/**\n\t * Requested maximum throughput (kbps) rounded nearest 100kbps\n\t */\n\trtp: toHundred,\n\n\t/**\n\t * Top Bitrate (kbps) rounded integer\n\t */\n\ttb: toRounded,\n\n\t/**\n\t * Target Buffer Length (milliseconds) rounded nearest 100ms\n\t */\n\ttbl: toHundred,\n\n\t/**\n\t * Aggregate Encoded Bitrate (kbps) rounded integer\n\t */\n\tab: toRounded,\n\n\t/**\n\t * Buffer Starvation Absolute (count) rounded integer\n\t */\n\tbsa: toRounded,\n\n\t/**\n\t * Buffer Starvation Duration (milliseconds) rounded integer\n\t */\n\tbsd: toRounded,\n\n\t/**\n\t * Buffer Starvation Duration Absolute (milliseconds) rounded integer\n\t */\n\tbsda: toRounded,\n\n\t/**\n\t * Dropped Frames Absolute (count) rounded integer\n\t */\n\tdfa: toRounded,\n\n\t/**\n\t * Lowest Aggregated Encoded Bitrate (kbps) rounded integer\n\t */\n\tlab: toRounded,\n\n\t/**\n\t * Lowest Encoded Bitrate (kbps) rounded integer\n\t */\n\tlb: toRounded,\n\n\t/**\n\t * Live Stream Latency (milliseconds) rounded integer\n\t */\n\tltc: toRounded,\n\n\t/**\n\t * Media Start Delay (milliseconds) rounded integer\n\t */\n\tmsd: toRounded,\n\n\t/**\n\t * Playhead Bitrate (kbps) rounded integer\n\t */\n\tpb: toRounded,\n\n\t/**\n\t * Playback Rate decimal, not rounded\n\t */\n\tpr: toNumber,\n\n\t/**\n\t * Playhead Time (milliseconds) rounded integer\n\t */\n\tpt: toRounded,\n\n\t/**\n\t * Response Code rounded integer\n\t */\n\trc: toRounded,\n\n\t/**\n\t * Sequence Number rounded integer\n\t */\n\tsn: toRounded,\n\n\t/**\n\t * Top Aggregated Encoded Bitrate (kbps) rounded integer\n\t */\n\ttab: toRounded,\n\n\t/**\n\t * Top Playable Bitrate (kbps) rounded integer\n\t */\n\ttpb: toRounded,\n\n\t/**\n\t * Timestamp (milliseconds) rounded integer\n\t */\n\tts: toRounded,\n\n\t/**\n\t * Time To First Byte (milliseconds) rounded integer\n\t */\n\tttfb: toRounded,\n\n\t/**\n\t * Time To First Body Byte (milliseconds) rounded integer\n\t */\n\tttfbb: toRounded,\n\n\t/**\n\t * Time To Last Byte (milliseconds) rounded integer\n\t */\n\tttlb: toRounded,\n} as const\n","/**\n * Defines the request-specific keys for CMCD (Common Media Client Data) version 2.\n *\n * @public\n */\nexport const CMCD_REQUEST_KEYS = [\n\t'ab',\n\t'bg',\n\t'bl',\n\t'br',\n\t'bs',\n\t'bsa',\n\t'bsd',\n\t'bsda',\n\t'cdn',\n\t'cid',\n\t'cs',\n\t'd',\n\t'dfa',\n\t'dl',\n\t'ec',\n\t'lab',\n\t'lb',\n\t'ltc',\n\t'msd',\n\t'mtp',\n\t'nor',\n\t'nr',\n\t'ot',\n\t'pb',\n\t'pr',\n\t'pt',\n\t'rtp',\n\t'sf',\n\t'sid',\n\t'sn',\n\t'st',\n\t'sta',\n\t'su',\n\t'tab',\n\t'tb',\n\t'tbl',\n\t'tpb',\n\t'v',\n] as const\n","/**\n * Response-only and timing keys for version 2.\n *\n * @public\n */\nexport const CMCD_RESPONSE_KEYS = [\n\t'cmsdd',\n\t'cmsds',\n\t'rc',\n\t'smrt',\n\t'ttfb',\n\t'ttfbb',\n\t'ttlb',\n\t'url',\n] as const\n","/**\n * Defines the keys for CMCD (Common Media Client Data) version 1.\n *\n * @public\n */\nexport const CMCD_V1_KEYS = [\n\t'bl',\n\t'br',\n\t'bs',\n\t'cid',\n\t'd',\n\t'dl',\n\t'mtp',\n\t'nor',\n\t'nrr',\n\t'ot',\n\t'pr',\n\t'rtp',\n\t'sf',\n\t'sid',\n\t'st',\n\t'su',\n\t'tb',\n\t'v',\n] as const\n","import { CMCD_EVENT_KEYS } from './CMCD_EVENT_KEYS.ts'\nimport { CMCD_REQUEST_KEYS } from './CMCD_REQUEST_KEYS.ts'\nimport { CMCD_RESPONSE_KEYS } from './CMCD_RESPONSE_KEYS.ts'\nimport { CMCD_V1_KEYS } from './CMCD_V1_KEYS.ts'\nimport type { CmcdKey } from './CmcdKey.ts'\n\n/**\n * A list of all CMCD keys.\n *\n * @public\n */\nexport const CMCD_KEYS: CmcdKey[] = /* @__PURE__ */ [\n\t...CMCD_V1_KEYS,\n\t...CMCD_REQUEST_KEYS,\n\t...CMCD_RESPONSE_KEYS,\n\t...CMCD_EVENT_KEYS,\n].filter((key, index, arr) => arr.indexOf(key) === index)\n","/**\n * CMCD MIME type for event report payloads.\n *\n * @public\n */\nexport const CMCD_MIME_TYPE = 'application/cmcd'\n","/**\n * The `customData` property where `CmcdReporter.createRequestReport()`\n * writes session provenance on every request it returns.\n *\n * The value is a frozen `CmcdRequestProvenance` record. `sid` names the\n * session that issued the request. `cid` is the content id at the time the\n * request was issued. `data` is the request's per-call data as an encoded\n * CMCD string. `CmcdReporter.recordResponseReceived()` reads the record to\n * attribute a late response to its session and to rebuild the request-time\n * report keys.\n * Spread and `Object.assign` copy the record into ordinary request clones.\n * `JSON.stringify` and structured clone drop symbol-keyed properties. Before\n * either operation, read the value and restore it afterward. JSON preserves\n * the record's fields. Attribution uses the `sid` value rather than object\n * identity, so a parsed plain-object copy attributes correctly. For a record\n * naming a `sid` the reporter does not retain, the reporter drops the\n * response rather than reattributing it.\n *\n * The symbol registry provides the symbol, so duplicated copies of this\n * library in one bundle interoperate. The registry key is stable across\n * versions.\n *\n * @public\n */\nexport const CMCD_REQUEST_PROVENANCE: unique symbol = /* @__PURE__ */ Symbol.for('@svta/cml-cmcd/request-provenance')\n","/**\n * CMCD Version 1\n *\n * @public\n */\nexport const CMCD_V1 = 1 as const\n","import type { ValueOf } from '@svta/cml-utils'\n\n/**\n * CMCD event type 'bc' (bitrate change).\n *\n * @public\n */\nexport const CMCD_EVENT_BITRATE_CHANGE = 'bc' as const\n\n/**\n * CMCD event type 'ps' (play state change).\n *\n * @public\n */\nexport const CMCD_EVENT_PLAY_STATE = 'ps' as const\n\n/**\n * CMCD event type 'pr' (playback rate change).\n *\n * @public\n */\nexport const CMCD_EVENT_PLAYBACK_RATE = 'pr' as const\n\n/**\n * CMCD event type 'e' (error).\n *\n * @public\n */\nexport const CMCD_EVENT_ERROR = 'e' as const\n\n/**\n * CMCD event type 't' (time interval).\n *\n * @public\n */\nexport const CMCD_EVENT_TIME_INTERVAL = 't' as const\n\n/**\n * CMCD event type 'c' (content ID).\n *\n * @public\n */\nexport const CMCD_EVENT_CONTENT_ID = 'c' as const\n\n/**\n * CMCD event type 'b' (backgrounded mode).\n *\n * @public\n */\nexport const CMCD_EVENT_BACKGROUNDED_MODE = 'b' as const\n\n/**\n * CMCD event type 'm' (mute).\n *\n * @public\n */\nexport const CMCD_EVENT_MUTE = 'm' as const\n\n/**\n * CMCD event type 'um' (unmute).\n *\n * @public\n */\nexport const CMCD_EVENT_UNMUTE = 'um' as const\n\n/**\n * CMCD event type 'pe' (player expand).\n *\n * @public\n */\nexport const CMCD_EVENT_PLAYER_EXPAND = 'pe' as const\n\n/**\n * CMCD event type 'pc' (player collapse).\n *\n * @public\n */\nexport const CMCD_EVENT_PLAYER_COLLAPSE = 'pc' as const\n\n/**\n * CMCD event type 'rr' (response received).\n *\n * @public\n */\nexport const CMCD_EVENT_RESPONSE_RECEIVED = 'rr' as const\n\n/**\n * CMCD event type 'as' (ad start).\n *\n * @public\n */\nexport const CMCD_EVENT_AD_START = 'as' as const\n\n/**\n * CMCD event type 'ae' (ad end).\n *\n * @public\n */\nexport const CMCD_EVENT_AD_END = 'ae' as const\n\n/**\n * CMCD event type 'abs' (ad break start).\n *\n * @public\n */\nexport const CMCD_EVENT_AD_BREAK_START = 'abs' as const\n\n/**\n * CMCD event type 'abe' (ad break end).\n *\n * @public\n */\nexport const CMCD_EVENT_AD_BREAK_END = 'abe' as const\n\n/**\n * CMCD event type 'sk' (skip).\n *\n * @public\n */\nexport const CMCD_EVENT_SKIP = 'sk' as const\n\n/**\n * CMCD event type 'ce' (custom event).\n *\n * @public\n */\nexport const CMCD_EVENT_CUSTOM_EVENT = 'ce' as const\n\n/**\n * CMCD event types for the 'e' key (event mode).\n *\n * @enum\n *\n * @see {@link https://cta-wave.github.io/Resources/common-media-client-data--cta-5004-b.html#event | CTA-5004-B Event}\n *\n * @public\n */\nexport const CmcdEventType = {\n\t/**\n\t * A change in the bitrate.\n\t */\n\tBITRATE_CHANGE: CMCD_EVENT_BITRATE_CHANGE as typeof CMCD_EVENT_BITRATE_CHANGE,\n\n\t/**\n\t * A change in the player state.\n\t */\n\tPLAY_STATE: CMCD_EVENT_PLAY_STATE as typeof CMCD_EVENT_PLAY_STATE,\n\n\t/**\n\t * A change in the playback rate.\n\t */\n\tPLAYBACK_RATE: CMCD_EVENT_PLAYBACK_RATE as typeof CMCD_EVENT_PLAYBACK_RATE,\n\n\t/**\n\t * An error event.\n\t */\n\tERROR: CMCD_EVENT_ERROR as typeof CMCD_EVENT_ERROR,\n\n\t/**\n\t * A periodic report sent on a time interval.\n\t */\n\tTIME_INTERVAL: CMCD_EVENT_TIME_INTERVAL as typeof CMCD_EVENT_TIME_INTERVAL,\n\n\t/**\n\t * A change of the content ID.\n\t */\n\tCONTENT_ID: CMCD_EVENT_CONTENT_ID as typeof CMCD_EVENT_CONTENT_ID,\n\n\t/**\n\t * A change in the player's backgrounded state.\n\t */\n\tBACKGROUNDED_MODE: CMCD_EVENT_BACKGROUNDED_MODE as typeof CMCD_EVENT_BACKGROUNDED_MODE,\n\n\t/**\n\t * The player was muted.\n\t */\n\tMUTE: CMCD_EVENT_MUTE as typeof CMCD_EVENT_MUTE,\n\n\t/**\n\t * The player was unmuted.\n\t */\n\tUNMUTE: CMCD_EVENT_UNMUTE as typeof CMCD_EVENT_UNMUTE,\n\n\t/**\n\t * The player view was expanded.\n\t */\n\tPLAYER_EXPAND: CMCD_EVENT_PLAYER_EXPAND as typeof CMCD_EVENT_PLAYER_EXPAND,\n\n\t/**\n\t * The player view was collapsed.\n\t */\n\tPLAYER_COLLAPSE: CMCD_EVENT_PLAYER_COLLAPSE as typeof CMCD_EVENT_PLAYER_COLLAPSE,\n\n\t/**\n\t * The receipt of a response.\n\t */\n\tRESPONSE_RECEIVED: CMCD_EVENT_RESPONSE_RECEIVED as typeof CMCD_EVENT_RESPONSE_RECEIVED,\n\n\t/**\n\t * The start of an ad.\n\t */\n\tAD_START: CMCD_EVENT_AD_START as typeof CMCD_EVENT_AD_START,\n\n\t/**\n\t * The end of an ad.\n\t */\n\tAD_END: CMCD_EVENT_AD_END as typeof CMCD_EVENT_AD_END,\n\n\t/**\n\t * The start of an ad break.\n\t */\n\tAD_BREAK_START: CMCD_EVENT_AD_BREAK_START as typeof CMCD_EVENT_AD_BREAK_START,\n\n\t/**\n\t * The end of an ad break.\n\t */\n\tAD_BREAK_END: CMCD_EVENT_AD_BREAK_END as typeof CMCD_EVENT_AD_BREAK_END,\n\n\t/**\n\t * The user skipped an ad.\n\t */\n\tSKIP: CMCD_EVENT_SKIP as typeof CMCD_EVENT_SKIP,\n\n\t/**\n\t * A custom event.\n\t */\n\tCUSTOM_EVENT: CMCD_EVENT_CUSTOM_EVENT as typeof CMCD_EVENT_CUSTOM_EVENT,\n} as const\n\n/**\n * @public\n */\nexport type CmcdEventType = ValueOf<typeof CmcdEventType>;\n","import type { ValueOf } from '@svta/cml-utils'\n\n/**\n * Common Media Client Data Object Type\n *\n * @public\n *\n * @enum\n *\n * @see {@link https://cta-wave.github.io/Resources/common-media-client-data--cta-5004-b.html#object-type | CTA-5004-B Object Type}\n */\nexport const CmcdObjectType = {\n\t/**\n\t * text file, such as a manifest or playlist\n\t */\n\tMANIFEST: 'm',\n\n\t/**\n\t * audio only\n\t */\n\tAUDIO: 'a',\n\n\t/**\n\t * video only\n\t */\n\tVIDEO: 'v',\n\n\t/**\n\t * muxed audio and video\n\t */\n\tMUXED: 'av',\n\n\t/**\n\t * init segment\n\t */\n\tINIT: 'i',\n\n\t/**\n\t * caption or subtitle\n\t */\n\tCAPTION: 'c',\n\n\t/**\n\t * ISOBMFF timed text track\n\t */\n\tTIMED_TEXT: 'tt',\n\n\t/**\n\t * cryptographic key, license or certificate.\n\t */\n\tKEY: 'k',\n\n\t/**\n\t * other\n\t */\n\tOTHER: 'o',\n} as const\n\n/**\n * @public\n */\nexport type CmcdObjectType = ValueOf<typeof CmcdObjectType>;\n","import type { ValueOf } from '@svta/cml-utils'\n\n/**\n * CMCD version 2 player states for the 'sta' key.\n *\n *\n * @enum\n *\n * @public\n *\n * @see {@link https://cta-wave.github.io/Resources/common-media-client-data--cta-5004-b.html#state | CTA-5004-B State}\n */\nexport const CmcdPlayerState = {\n\t/**\n\t * Starting: Initial startup of the player.\n\t */\n\tSTARTING: 's',\n\n\t/**\n\t * Playing: The player is actively rendering content.\n\t */\n\tPLAYING: 'p',\n\n\t/**\n\t * Seeking: The player is seeking to a new position.\n\t */\n\tSEEKING: 'k',\n\n\t/**\n\t * Rebuffering: The player is buffering data during playback.\n\t */\n\tREBUFFERING: 'r',\n\n\t/**\n\t * Paused: The player is paused.\n\t */\n\tPAUSED: 'a',\n\n\t/**\n\t * Waiting: The player is waiting for a user action or another event.\n\t */\n\tWAITING: 'w',\n\n\t/**\n\t * Ended: The media has finished playing.\n\t */\n\tENDED: 'e',\n\n\t/**\n\t * Fatal Error: The player has encountered a fatal error.\n\t */\n\tFATAL_ERROR: 'f',\n\n\t/**\n\t * Quit: User initiated end of playback before media asset completion.\n\t */\n\tQUIT: 'q',\n\n\t/**\n\t * Preloading: The player is loading assets ahead of starting to provide a fast startup. The expectation is that playback will commence at a future time.\n\t */\n\tPRELOADING: 'd',\n} as const\n\n/**\n * @public\n */\nexport type CmcdPlayerState = ValueOf<typeof CmcdPlayerState>;\n","import type { ValueOf } from '@svta/cml-utils'\n\n/**\n * CMCD query reporting mode: CMCD data transmitted as a `CMCD=` URL\n * query parameter.\n *\n * @public\n */\nexport const CMCD_RECORDED_REPORT_MODE_QUERY = 'query' as const\n\n/**\n * CMCD header reporting mode: CMCD data transmitted as `CMCD-*` HTTP\n * headers.\n *\n * @public\n */\nexport const CMCD_RECORDED_REPORT_MODE_HEADER = 'header' as const\n\n/**\n * CMCD event reporting mode: CMCD data transmitted as a POST body to an\n * event-target URL.\n *\n * @public\n */\nexport const CMCD_RECORDED_REPORT_MODE_EVENT = 'event' as const\n\n/**\n * Reporting mode in which `CmcdReportRecorder` observed a captured\n * report.\n *\n * @enum\n *\n * @public\n */\nexport const CmcdRecordedReportMode = {\n\tQUERY: CMCD_RECORDED_REPORT_MODE_QUERY as typeof CMCD_RECORDED_REPORT_MODE_QUERY,\n\tHEADER: CMCD_RECORDED_REPORT_MODE_HEADER as typeof CMCD_RECORDED_REPORT_MODE_HEADER,\n\tEVENT: CMCD_RECORDED_REPORT_MODE_EVENT as typeof CMCD_RECORDED_REPORT_MODE_EVENT,\n} as const\n\n/**\n * @public\n */\nexport type CmcdRecordedReportMode = ValueOf<typeof CmcdRecordedReportMode>\n","import type { ValueOf } from '@svta/cml-utils'\n\n/**\n * Manifest or playlist request classification.\n *\n * @public\n */\nexport const CMCD_RECORDED_REQUEST_TYPE_MANIFEST = 'manifest' as const\n\n/**\n * Media segment request classification.\n *\n * @public\n */\nexport const CMCD_RECORDED_REQUEST_TYPE_SEGMENT = 'segment' as const\n\n/**\n * CMCD event-mode report request classification (POST to a URL in\n * `eventTargetUrls`).\n *\n * @public\n */\nexport const CMCD_RECORDED_REQUEST_TYPE_EVENT = 'event' as const\n\n/**\n * Default classification for requests the recorder did not recognize\n * as manifest, segment, or event.\n *\n * @public\n */\nexport const CMCD_RECORDED_REQUEST_TYPE_UNKNOWN = 'unknown' as const\n\n/**\n * Classification of a captured request, used by `CmcdReportRecorder`\n * for filtering.\n *\n * @enum\n *\n * @public\n */\nexport const CmcdRecordedRequestType = {\n\tMANIFEST: CMCD_RECORDED_REQUEST_TYPE_MANIFEST as typeof CMCD_RECORDED_REQUEST_TYPE_MANIFEST,\n\tSEGMENT: CMCD_RECORDED_REQUEST_TYPE_SEGMENT as typeof CMCD_RECORDED_REQUEST_TYPE_SEGMENT,\n\tEVENT: CMCD_RECORDED_REQUEST_TYPE_EVENT as typeof CMCD_RECORDED_REQUEST_TYPE_EVENT,\n\tUNKNOWN: CMCD_RECORDED_REQUEST_TYPE_UNKNOWN as typeof CMCD_RECORDED_REQUEST_TYPE_UNKNOWN,\n} as const\n\n/**\n * @public\n */\nexport type CmcdRecordedRequestType = ValueOf<typeof CmcdRecordedRequestType>\n","import type { HttpRequest } from '@svta/cml-utils'\nimport type { CmcdRequestDeliver, CmcdTransportAdapter } from './CmcdTransportAdapter.ts'\n\nasync function toHttpRequest(request: Request): Promise<HttpRequest> {\n\tconst headers: Record<string, string> = {}\n\trequest.headers.forEach((value, name) => {\n\t\theaders[name.toLowerCase()] = value\n\t})\n\n\tlet body: string | undefined\n\tif (request.body) {\n\t\ttry {\n\t\t\tbody = await request.text()\n\t\t} catch {\n\t\t\tbody = undefined\n\t\t}\n\t}\n\n\treturn {\n\t\turl: request.url,\n\t\tmethod: request.method,\n\t\theaders,\n\t\tbody,\n\t}\n}\n\n/**\n * Create a transport adapter for `CmcdReportRecorder` that patches\n * `globalThis.fetch` to capture requests with CMCD data. The patched\n * `fetch` normalizes each request to `HttpRequest` (lowercase headers,\n * body read as a UTF-8 string).\n *\n * The patched `fetch` reads each body once with `Request.text()` for\n * inspection. This read is safe for the body types that CMCD reports use\n * in practice: `string`, `Blob`, `ArrayBuffer`, `FormData`, and\n * `URLSearchParams`. The underlying `fetch` can read those bodies again.\n * Do not pass a `ReadableStream` as `init.body`. The patched `fetch`\n * consumes the stream, and the underlying `fetch` receives an\n * already-disturbed stream.\n *\n * @public\n */\nexport function createFetchTransport(): CmcdTransportAdapter {\n\treturn {\n\t\tattach(deliver: CmcdRequestDeliver): () => void {\n\t\t\tconst origFetch = globalThis.fetch\n\n\t\t\tglobalThis.fetch = async (\n\t\t\t\tinput: RequestInfo | URL,\n\t\t\t\tinit?: RequestInit,\n\t\t\t): Promise<Response> => {\n\t\t\t\tconst inspect = input instanceof Request\n\t\t\t\t\t? input.clone()\n\t\t\t\t\t: new Request(input, init)\n\t\t\t\tconst httpRequest = await toHttpRequest(inspect)\n\t\t\t\tconst synthetic = deliver(httpRequest)\n\t\t\t\tif (synthetic) {\n\t\t\t\t\treturn synthetic\n\t\t\t\t}\n\t\t\t\treturn origFetch.call(globalThis, input as RequestInfo, init)\n\t\t\t}\n\n\t\t\treturn () => {\n\t\t\t\tglobalThis.fetch = origFetch\n\t\t\t}\n\t\t},\n\t}\n}\n","import type { HttpRequest } from '@svta/cml-utils'\nimport type { CmcdRequestDeliver, CmcdTransportAdapter } from './CmcdTransportAdapter.ts'\n\ntype XhrInstance = XMLHttpRequest & {\n\t_cmcdMethod?: string;\n\t_cmcdUrl?: string;\n\t_cmcdHeaders?: Record<string, string>;\n}\n\nasync function completeXhrWith(xhr: XhrInstance, response: Response): Promise<void> {\n\tconst text = await response.clone().text().catch(() => '')\n\tconst ProgressEventCtor: typeof ProgressEvent | typeof Event =\n\t\ttypeof ProgressEvent !== 'undefined' ? ProgressEvent : Event\n\n\tqueueMicrotask(() => {\n\t\ttry {\n\t\t\tObject.defineProperty(xhr, 'status', { value: response.status, configurable: true })\n\t\t\tObject.defineProperty(xhr, 'statusText', { value: response.statusText, configurable: true })\n\t\t\tObject.defineProperty(xhr, 'readyState', { value: 4, configurable: true })\n\t\t\tObject.defineProperty(xhr, 'responseURL', { value: xhr._cmcdUrl ?? '', configurable: true })\n\t\t\tObject.defineProperty(xhr, 'response', { value: text, configurable: true })\n\t\t\tObject.defineProperty(xhr, 'responseText', { value: text, configurable: true })\n\n\t\t\tif (typeof xhr.onload === 'function') {\n\t\t\t\txhr.onload.call(xhr, new ProgressEventCtor('load') as ProgressEvent<EventTarget>)\n\t\t\t}\n\t\t\tif (typeof xhr.onloadend === 'function') {\n\t\t\t\txhr.onloadend.call(xhr, new ProgressEventCtor('loadend') as ProgressEvent<EventTarget>)\n\t\t\t}\n\t\t} catch {\n\t\t\t// MockXhr may not allow defineProperty on some properties;\n\t\t\t// for shim simplicity we set them directly as a fallback.\n\t\t\tconst target = xhr as unknown as Record<string, unknown>\n\t\t\ttarget['status'] = response.status\n\t\t\ttarget['statusText'] = response.statusText\n\t\t\ttarget['readyState'] = 4\n\t\t\ttarget['responseURL'] = xhr._cmcdUrl ?? ''\n\t\t\ttarget['response'] = text\n\t\t\ttarget['responseText'] = text\n\t\t\tif (typeof xhr.onload === 'function') {\n\t\t\t\txhr.onload.call(xhr as unknown as XMLHttpRequest, new ProgressEventCtor('load') as ProgressEvent<EventTarget>)\n\t\t\t}\n\t\t\tif (typeof xhr.onloadend === 'function') {\n\t\t\t\txhr.onloadend.call(xhr as unknown as XMLHttpRequest, new ProgressEventCtor('loadend') as ProgressEvent<EventTarget>)\n\t\t\t}\n\t\t}\n\t})\n}\n\n/**\n * Create a transport adapter for `CmcdReportRecorder` that patches\n * `XMLHttpRequest.prototype` to capture requests with CMCD data.\n *\n * @public\n */\nexport function createXhrTransport(): CmcdTransportAdapter {\n\treturn {\n\t\tattach(deliver: CmcdRequestDeliver): () => void {\n\t\t\tconst Xhr = globalThis.XMLHttpRequest\n\t\t\tif (!Xhr) {\n\t\t\t\treturn () => { /* no XHR to detach */ }\n\t\t\t}\n\t\t\tconst origOpen = Xhr.prototype.open\n\t\t\tconst origSetRequestHeader = Xhr.prototype.setRequestHeader\n\t\t\tconst origSend = Xhr.prototype.send\n\n\t\t\tXhr.prototype.open = function (this: XhrInstance, method: string, url: string | URL): void {\n\t\t\t\tthis._cmcdMethod = method\n\t\t\t\tthis._cmcdUrl = typeof url === 'string' ? url : url.toString()\n\t\t\t\tthis._cmcdHeaders = {}\n\t\t\t\t// eslint-disable-next-line prefer-rest-params\n\t\t\t\treturn origOpen.apply(this, arguments as unknown as Parameters<typeof origOpen>)\n\t\t\t}\n\n\t\t\tXhr.prototype.setRequestHeader = function (this: XhrInstance, name: string, value: string): void {\n\t\t\t\tif (this._cmcdHeaders) {\n\t\t\t\t\tthis._cmcdHeaders[name.toLowerCase()] = value\n\t\t\t\t}\n\t\t\t\treturn origSetRequestHeader.apply(this, [name, value])\n\t\t\t}\n\n\t\t\tXhr.prototype.send = function (this: XhrInstance, body?: Document | XMLHttpRequestBodyInit | null): void {\n\t\t\t\tconst httpRequest: HttpRequest = {\n\t\t\t\t\turl: this._cmcdUrl ?? '',\n\t\t\t\t\tmethod: (this._cmcdMethod ?? 'GET').toUpperCase(),\n\t\t\t\t\theaders: this._cmcdHeaders ?? {},\n\t\t\t\t\tbody: (typeof Document !== 'undefined' && body instanceof Document ? undefined : body as BodyInit | null | undefined) ?? undefined,\n\t\t\t\t}\n\n\t\t\t\tconst synthetic = deliver(httpRequest)\n\n\t\t\t\tif (synthetic) {\n\t\t\t\t\tcompleteXhrWith(this, synthetic)\n\t\t\t\t\treturn\n\t\t\t\t}\n\n\t\t\t\treturn origSend.apply(this, [body])\n\t\t\t}\n\n\t\t\treturn () => {\n\t\t\t\tXhr.prototype.open = origOpen\n\t\t\t\tXhr.prototype.setRequestHeader = origSetRequestHeader\n\t\t\t\tXhr.prototype.send = origSend\n\t\t\t}\n\t\t},\n\t}\n}\n","import type { HttpRequest } from '@svta/cml-utils'\nimport { CMCD_PARAM } from './CMCD_PARAM.ts'\nimport type { CmcdRecordedReport } from './CmcdRecordedReport.ts'\nimport type { CmcdRecordedReportMode } from './CmcdRecordedReportMode.ts'\nimport type { CmcdReportRecorderOptions } from './CmcdReportRecorderOptions.ts'\nimport type { CmcdReportRecorderWaitOptions } from './CmcdReportRecorderWaitOptions.ts'\nimport { CmcdRecordedRequestType } from './CmcdRecordedRequestType.ts'\nimport { createFetchTransport } from './createFetchTransport.ts'\nimport { createXhrTransport } from './createXhrTransport.ts'\n\nconst MANIFEST_EXTENSIONS = /\\.(m3u8|mpd)(\\?|$|\\/)/i\nconst SEGMENT_EXTENSIONS = /\\.(m4s|m4v|m4a|mp4|ts|aac)(\\?|$|\\/)/i\n\nfunction classifyUrl(url: string, isEventTarget: boolean): CmcdRecordedRequestType {\n\tif (isEventTarget) {\n\t\treturn CmcdRecordedRequestType.EVENT\n\t}\n\tif (MANIFEST_EXTENSIONS.test(url)) {\n\t\treturn CmcdRecordedRequestType.MANIFEST\n\t}\n\tif (SEGMENT_EXTENSIONS.test(url)) {\n\t\treturn CmcdRecordedRequestType.SEGMENT\n\t}\n\treturn CmcdRecordedRequestType.UNKNOWN\n}\n\nfunction hasCmcdHeader(headers: Record<string, string> | undefined): boolean {\n\tif (!headers) {\n\t\treturn false\n\t}\n\tfor (const name in headers) {\n\t\tif (name.toLowerCase().startsWith('cmcd-')) {\n\t\t\treturn true\n\t\t}\n\t}\n\treturn false\n}\n\nfunction detectReportingMode(\n\turl: string,\n\theaders: Record<string, string> | undefined,\n\tisEventTarget: boolean,\n): CmcdRecordedReportMode | null {\n\tif (isEventTarget) {\n\t\treturn 'event'\n\t}\n\tif (hasCmcdHeader(headers)) {\n\t\treturn 'header'\n\t}\n\treturn url.includes(`${CMCD_PARAM}=`) ? 'query' : null\n}\n\ntype CmcdReportWaiter = {\n\ttype: CmcdRecordedRequestType | undefined\n\tcount: number\n\tresolve: (r: CmcdRecordedReport[]) => void\n\treject: (e: Error) => void\n}\n\n/**\n * Test helper that records CMCD reports from the XHR and fetch\n * transports for assertions in e2e tests. The recorder normalizes each\n * captured request to {@link @svta/cml-utils!HttpRequest | HttpRequest},\n * so tests are identical regardless of which transport the player uses.\n *\n * @example\n * {@includeCode ../test/CmcdReportRecorder.test.ts#example}\n *\n * @public\n */\nexport class CmcdReportRecorder {\n\t#reports: CmcdRecordedReport[] = []\n\t#detachers: (() => void)[] = []\n\t#attached = false\n\t#eventTargetUrls: readonly string[] = []\n\t#waiters = new Map<ReturnType<typeof setTimeout>, CmcdReportWaiter>()\n\t#onReport: ((report: CmcdRecordedReport) => void) | undefined\n\t#waitTimeout = 15000\n\n\treadonly #deliver = (request: HttpRequest): Response | undefined => {\n\t\tconst url = request.url\n\t\tconst method = (request.method ?? 'GET').toUpperCase()\n\t\tconst isEventTarget = method === 'POST' && this.#eventTargetUrls.some((t) => url.startsWith(t))\n\n\t\tconst reportingMode = detectReportingMode(url, request.headers, isEventTarget)\n\t\tif (reportingMode === null) {\n\t\t\treturn undefined\n\t\t}\n\n\t\tconst captured: CmcdRecordedReport = {\n\t\t\trequest,\n\t\t\ttype: classifyUrl(url, isEventTarget),\n\t\t\treportingMode,\n\t\t\ttimestamp: Date.now(),\n\t\t}\n\t\tthis.#reports.push(captured)\n\t\tif (this.#onReport) {\n\t\t\ttry {\n\t\t\t\tthis.#onReport(captured)\n\t\t\t} catch (err) {\n\t\t\t\tconsole.error('CmcdReportRecorder onReport listener threw:', err)\n\t\t\t}\n\t\t}\n\t\tthis.#notifyWaiters()\n\n\t\treturn isEventTarget ? new Response(null, { status: 204 }) : undefined\n\t}\n\n\t#getMatching(type: CmcdRecordedRequestType | undefined): CmcdRecordedReport[] {\n\t\treturn type === undefined\n\t\t\t? [...this.#reports]\n\t\t\t: this.#reports.filter((r) => r.type === type)\n\t}\n\n\t#notifyWaiters(): void {\n\t\tfor (const [timer, waiter] of this.#waiters) {\n\t\t\tconst matching = this.#getMatching(waiter.type)\n\t\t\tif (matching.length >= waiter.count) {\n\t\t\t\tclearTimeout(timer)\n\t\t\t\tthis.#waiters.delete(timer)\n\t\t\t\twaiter.resolve(matching)\n\t\t\t}\n\t\t}\n\t}\n\n\t#waitFor(\n\t\ttype: CmcdRecordedRequestType | undefined,\n\t\toptions: CmcdReportRecorderWaitOptions,\n\t): Promise<CmcdRecordedReport[]> {\n\t\tconst count = options.count ?? 1\n\t\tconst timeout = options.timeout ?? this.#waitTimeout\n\n\t\tconst matching = this.#getMatching(type)\n\t\tif (matching.length >= count) {\n\t\t\treturn Promise.resolve(matching)\n\t\t}\n\n\t\treturn new Promise<CmcdRecordedReport[]>((resolve, reject) => {\n\t\t\tconst timer = setTimeout(() => {\n\t\t\t\tthis.#waiters.delete(timer)\n\t\t\t\tconst current = this.#getMatching(type)\n\t\t\t\treject(new Error(\n\t\t\t\t\t`Timeout waiting for ${count} ${type ?? 'any'} CMCD report(s). Got ${current.length}. Total recorded: ${this.#reports.length}.`,\n\t\t\t\t))\n\t\t\t}, timeout)\n\n\t\t\tthis.#waiters.set(timer, { type, count, resolve, reject })\n\t\t})\n\t}\n\n\t/**\n\t * Install transport patches and start recording CMCD reports.\n\t * If the recorder is already attached, this call does nothing. The\n\t * recorder keeps the previous options and silently ignores the new\n\t * `options` argument. To re-attach with different options, call\n\t * `detach()` first.\n\t *\n\t * @public\n\t */\n\tattach(options: CmcdReportRecorderOptions = {}): void {\n\t\tif (this.#attached) {\n\t\t\treturn\n\t\t}\n\t\tthis.#attached = true\n\t\tthis.#eventTargetUrls = options.eventTargetUrls ?? []\n\t\tthis.#onReport = options.onReport\n\t\tthis.#waitTimeout = options.waitTimeout ?? 15000\n\n\t\tconst transports = options.transports ?? [createXhrTransport(), createFetchTransport()]\n\t\tfor (const transport of transports) {\n\t\t\tthis.#detachers.push(transport.attach(this.#deliver))\n\t\t}\n\t}\n\n\t/**\n\t * Remove transport patches and stop recording. Rejects any pending\n\t * wait promises with `Error('Recorder detached while waiting')`.\n\t *\n\t * @public\n\t */\n\tdetach(): void {\n\t\tif (!this.#attached) {\n\t\t\treturn\n\t\t}\n\t\tfor (const detacher of this.#detachers) {\n\t\t\tdetacher()\n\t\t}\n\t\tthis.#detachers = []\n\t\tthis.#attached = false\n\t\tthis.#eventTargetUrls = []\n\t\tthis.#onReport = undefined\n\n\t\tfor (const [timer, waiter] of this.#waiters) {\n\t\t\tclearTimeout(timer)\n\t\t\twaiter.reject(new Error('Recorder detached while waiting'))\n\t\t}\n\t\tthis.#waiters.clear()\n\t}\n\n\t/**\n\t * Discard all recorded reports. Does not affect the attached state.\n\t *\n\t * @public\n\t */\n\tclear(): void {\n\t\tthis.#reports = []\n\t}\n\n\t/**\n\t * Return a copy of all recorded reports.\n\t *\n\t * @public\n\t */\n\tgetReports(): CmcdRecordedReport[] {\n\t\treturn [...this.#reports]\n\t}\n\n\t/**\n\t * Wait until at least `count` reports of any type are recorded.\n\t * Resolves with all matching reports. Rejects with a diagnostic error\n\t * on timeout. `count` defaults to 1. `timeout` defaults to the\n\t * recorder's `waitTimeout` option (default 15000 ms).\n\t *\n\t * @public\n\t */\n\twaitForReports(options: CmcdReportRecorderWaitOptions = {}): Promise<CmcdRecordedReport[]> {\n\t\treturn this.#waitFor(undefined, options)\n\t}\n\n\t/**\n\t * Wait until at least `count` manifest reports are recorded.\n\t * Resolves with all matching reports. Rejects with a diagnostic error\n\t * on timeout. `count` defaults to 1. `timeout` defaults to the\n\t * recorder's `waitTimeout` option (default 15000 ms).\n\t *\n\t * @public\n\t */\n\twaitForManifest(options: CmcdReportRecorderWaitOptions = {}): Promise<CmcdRecordedReport[]> {\n\t\treturn this.#waitFor(CmcdRecordedRequestType.MANIFEST, options)\n\t}\n\n\t/**\n\t * Wait until at least `count` segment reports are recorded.\n\t * Resolves with all matching reports. Rejects with a diagnostic error\n\t * on timeout. `count` defaults to 1. `timeout` defaults to the\n\t * recorder's `waitTimeout` option (default 15000 ms).\n\t *\n\t * @public\n\t */\n\twaitForSegments(options: CmcdReportRecorderWaitOptions = {}): Promise<CmcdRecordedReport[]> {\n\t\treturn this.#waitFor(CmcdRecordedRequestType.SEGMENT, options)\n\t}\n\n\t/**\n\t * Wait until at least `count` event-mode reports are recorded.\n\t * Resolves with all matching reports. Rejects with a diagnostic error\n\t * on timeout. `count` defaults to 1. `timeout` defaults to the\n\t * recorder's `waitTimeout` option (default 15000 ms).\n\t *\n\t * @public\n\t */\n\twaitForEvents(options: CmcdReportRecorderWaitOptions = {}): Promise<CmcdRecordedReport[]> {\n\t\treturn this.#waitFor(CmcdRecordedRequestType.EVENT, options)\n\t}\n}\n","import {\n\tCMCD_EVENT_BACKGROUNDED_MODE,\n\tCMCD_EVENT_BITRATE_CHANGE,\n\tCMCD_EVENT_CONTENT_ID,\n\tCMCD_EVENT_PLAY_STATE,\n\tCMCD_EVENT_PLAYBACK_RATE,\n\ttype CmcdEventType,\n} from './CmcdEventType.ts'\nimport type { CmcdKey } from './CmcdKey.ts'\n\n/**\n * Maps each state-change event type to the persistent field whose value\n * the event signals.\n *\n * The key table (`CMCD_KEY_SPECS`) marks the field as always sent on its\n * event, so the key filter of `prepareCmcdData` does not remove it.\n * `CmcdReporter` deduplicates events against the field value. It drops an\n * event whose field has no value and restores the field if a transform\n * removes it.\n *\n * Sending the field with each state-change event is a library choice.\n * The exception is the exit from backgrounded mode, which CTA-5004-B\n * defines as a `b` event without `bg`. CTA-5004-B requires the field only\n * on the `ps` event, which MUST carry `sta`. CTA-5004-B states no such rule\n * for `pr`, `c`, or `bc`. `validateCmcdStructure` follows CTA-5004-B and\n * does not read this map.\n *\n * Iteration order matters: `CmcdReporter.update()` records state-change\n * events in map order when several tracked fields change in one call.\n * Do not reorder entries without auditing reporter behavior.\n *\n * @internal\n */\nexport const CMCD_STATE_EVENT_FIELDS: ReadonlyMap<CmcdEventType, CmcdKey> = /* @__PURE__ */ new Map([\n\t[CMCD_EVENT_PLAY_STATE, 'sta'],\n\t[CMCD_EVENT_PLAYBACK_RATE, 'pr'],\n\t[CMCD_EVENT_CONTENT_ID, 'cid'],\n\t[CMCD_EVENT_BACKGROUNDED_MODE, 'bg'],\n\t[CMCD_EVENT_BITRATE_CHANGE, 'br'],\n])\n","import type { ValueOf } from '@svta/cml-utils'\n\n/**\n * CMCD `query` transmission mode.\n *\n * @public\n */\nexport const CMCD_QUERY = 'query' as const\n\n/**\n * CMCD `headers` transmission mode.\n *\n * @public\n */\nexport const CMCD_HEADERS = 'headers' as const\n\n/**\n * CMCD `json` transmission mode.\n *\n * @public\n *\n * @deprecated JSON transmission mode is deprecated and will be removed in future versions.\n */\nexport const CMCD_JSON = 'json' as const\n\n/**\n * CMCD transmission modes.\n *\n * @enum\n *\n * @public\n */\nexport const CmcdTransmissionMode = {\n\t/**\n\t * JSON\n\t *\n\t * @deprecated JSON transmission mode is deprecated and will be removed in future versions.\n\t */\n\tJSON: CMCD_JSON as typeof CMCD_JSON,\n\n\t/**\n\t * Query string\n\t */\n\tQUERY: CMCD_QUERY as typeof CMCD_QUERY,\n\n\t/**\n\t * Request headers\n\t */\n\tHEADERS: CMCD_HEADERS as typeof CMCD_HEADERS,\n\n} as const\n\n/**\n * @public\n */\nexport type CmcdTransmissionMode = ValueOf<typeof CmcdTransmissionMode>;\n","import { CMCD_INNER_LIST_KEYS } from './CMCD_INNER_LIST_KEYS.ts'\nimport { CMCD_V2 } from './CMCD_V2.ts'\nimport { toBareValue } from './toBareValue.ts'\n\n/**\n * Up-convert version 1 CMCD data to version 2.\n *\n * - Wraps scalar values in arrays for inner-list keys.\n * - Wraps `nor` string in an array.\n *\n * The function returns version 2 data (has `v: 2`) unchanged. An inner list\n * with parameters, which `decodeCmcd` returns as an `SfItem` that wraps the\n * list, also stays unchanged.\n *\n * @internal\n */\nexport function upConvertToV2(obj: Record<string, any>): Record<string, any> {\n\tif (toBareValue(obj['v']) === CMCD_V2) {\n\t\treturn obj\n\t}\n\n\tconst result: Record<string, any> = {}\n\n\tfor (const [key, value] of Object.entries(obj)) {\n\t\tif (value == null) {\n\t\t\tresult[key] = value\n\t\t\tcontinue\n\t\t}\n\n\t\tif (CMCD_INNER_LIST_KEYS.has(key) && !Array.isArray(toBareValue(value))) {\n\t\t\tresult[key] = [value]\n\t\t}\n\t\telse if (key === 'nor' && typeof value === 'string') {\n\t\t\tresult[key] = [value]\n\t\t}\n\t\telse {\n\t\t\tresult[key] = value\n\t\t}\n\t}\n\n\treturn result\n}\n","import type { SfBareItem } from '@svta/cml-structured-field-values'\nimport { decodeSfDict, SfItem, symbolToStr } from '@svta/cml-structured-field-values'\nimport type { Cmcd } from './Cmcd.ts'\nimport type { CmcdData } from './CmcdData.ts'\nimport type { CmcdDecodeOptions } from './CmcdDecodeOptions.ts'\nimport type { CmcdValue } from './CmcdValue.ts'\nimport { upConvertToV2 } from './upConvertToV2.ts'\n\n// Define the input type for reduceValue\ntype ReduceValueInput = SfBareItem | SfItem | ReduceValueInput[];\n\n// Define the output type for reduceValue - matches what CMCD values can be, including arrays\ntype ReduceValueOutput = CmcdValue | ReduceValueOutput[];\n\nfunction reduceValue(value: ReduceValueInput, useSymbol: boolean | undefined): ReduceValueOutput {\n\tif (Array.isArray(value)) {\n\t\treturn value.map(item => reduceValue(item, useSymbol))\n\t}\n\n\t// Tokens reduce to plain strings unless the caller opted into\n\t// preservation, where the parser's own representation passes through:\n\t// a registry symbol, or an SfToken when `useSymbol` is `false`. Both\n\t// re-encode as bare tokens, so preserved output round-trips.\n\tif (typeof value === 'symbol') {\n\t\treturn useSymbol === undefined ? symbolToStr(value) : (value as unknown as ReduceValueOutput)\n\t}\n\n\tif (value instanceof SfItem) {\n\t\t// Params are data: an item that carries them stays an SfItem, with\n\t\t// its value reduced the same way a bare member's would be. Only\n\t\t// param-less wrappers unwrap.\n\t\treturn value.params\n\t\t\t? new SfItem(reduceValue(value.value, useSymbol), value.params)\n\t\t\t: reduceValue(value.value, useSymbol)\n\t}\n\n\treturn value as ReduceValueOutput\n};\n\n/**\n * Decode a CMCD string to an object.\n *\n * @param cmcd - The CMCD string to decode.\n * @param options - Options for decoding.\n *\n * @returns The decoded CMCD object.\n *\n * @see {@link https://cta-wave.github.io/Resources/common-media-client-data--cta-5004-b.html#payload-definition-for-headers-and-query-argument-transmission | CTA-5004-B Payload Definition}\n *\n * @public\n *\n * @example\n * {@includeCode ../test/decodeCmcd.test.ts#example}\n */\nexport function decodeCmcd(cmcd: string, options: CmcdDecodeOptions & { convertToLatest: true }): Cmcd\nexport function decodeCmcd<T extends CmcdData = CmcdData>(cmcd: string, options?: CmcdDecodeOptions): T\nexport function decodeCmcd(cmcd: string, options?: CmcdDecodeOptions): CmcdData | Cmcd {\n\tif (!cmcd) {\n\t\treturn {} as CmcdData\n\t}\n\n\tconst sfDict = decodeSfDict(cmcd, options)\n\n\t// Each dictionary member is reduced whole, not via `item.value`, so\n\t// member-level and inner-list-level params survive decoding.\n\tconst result: Record<string, unknown> = {}\n\tfor (const [key, item] of Object.entries(sfDict as Record<string, SfItem>)) {\n\t\tresult[key] = reduceValue(item, options?.useSymbol)\n\t}\n\n\tif (options?.convertToLatest) {\n\t\treturn upConvertToV2(result) as Cmcd\n\t}\n\n\treturn result as CmcdData\n}\n","import type { HttpRequest, HttpResponse } from '@svta/cml-utils'\nimport { uuid } from '@svta/cml-utils'\nimport { CMCD_DEFAULT_TIME_INTERVAL } from './CMCD_DEFAULT_TIME_INTERVAL.ts'\nimport { CMCD_MIME_TYPE } from './CMCD_MIME_TYPE.ts'\nimport { CMCD_REQUEST_PROVENANCE } from './CMCD_REQUEST_PROVENANCE.ts'\nimport { CMCD_V2 } from './CMCD_V2.ts'\nimport type { Cmcd } from './Cmcd.ts'\nimport type { CmcdEncodeOptions } from './CmcdEncodeOptions.ts'\nimport type { CmcdEventReportConfig } from './CmcdEventReportConfig.ts'\nimport { CMCD_EVENT_BACKGROUNDED_MODE, CMCD_EVENT_CUSTOM_EVENT, CMCD_EVENT_ERROR, CMCD_EVENT_RESPONSE_RECEIVED, CMCD_EVENT_TIME_INTERVAL, CmcdEventType } from './CmcdEventType.ts'\nimport { CMCD_STATE_EVENT_FIELDS } from './CMCD_STATE_EVENT_FIELDS.ts'\nimport type { CmcdKey } from './CmcdKey.ts'\nimport type { CmcdObjectTypeList } from './CmcdObjectTypeList.ts'\nimport type { CmcdReportConfig } from './CmcdReportConfig.ts'\nimport type { CmcdReporterConfig } from './CmcdReporterConfig.ts'\nimport type { CmcdReporterCustomData } from './CmcdReporterCustomData.ts'\nimport type { CmcdRequestProvenance } from './CmcdRequestProvenance.ts'\nimport type { CmcdRequestReportConfig } from './CmcdRequestReportConfig.ts'\nimport type { CmcdReportingMode } from './CmcdReportingMode.ts'\nimport { CMCD_EVENT_MODE, CMCD_REQUEST_MODE } from './CmcdReportingMode.ts'\nimport type { CmcdRequestReport } from './CmcdRequestReport.ts'\nimport type { CmcdTransformRequest } from './CmcdTransformRequest.ts'\nimport { CMCD_HEADERS, CMCD_QUERY } from './CmcdTransmissionMode.ts'\nimport type { CmcdVersion } from './CmcdVersion.ts'\nimport { decodeCmcd } from './decodeCmcd.ts'\nimport { encodeCmcd } from './encodeCmcd.ts'\nimport { encodePreparedCmcd } from './encodePreparedCmcd.ts'\nimport { isValid } from './isValid.ts'\nimport { prepareCmcdData } from './prepareCmcdData.ts'\nimport { replaceCmcdParam } from './replaceCmcdParam.ts'\nimport { toBareValue } from './toBareValue.ts'\nimport { toPreparedCmcdHeaders } from './toPreparedCmcdHeaders.ts'\n\ntype CmcdReportConfigNormalized = CmcdReportConfig & {\n\tversion: CmcdVersion;\n}\n\ntype CmcdEventReportConfigNormalized<C> = CmcdEventReportConfig<C> & CmcdReportConfigNormalized & {\n\tevents: CmcdEventType[];\n\tinterval: number;\n\tbatchSize: number;\n}\n\ntype CmcdReporterConfigNormalized<C> = CmcdReporterConfig<C> & CmcdReportConfigNormalized & {\n\tsid: string;\n\teventTargets: CmcdEventReportConfigNormalized<C>[];\n\tsessionRetention: number;\n}\n\nfunction createEncodingOptions(reportingMode: CmcdReportingMode, config: CmcdReportConfig & Pick<CmcdRequestReportConfig, 'customHeaderMap'>, baseUrl?: string): CmcdEncodeOptions {\n\tconst enabledKeySet = new Set(config.enabledKeys ?? [])\n\n\treturn {\n\t\tversion: config.version || CMCD_V2,\n\t\treportingMode,\n\t\tfilter: (key: CmcdKey) => enabledKeySet.has(key),\n\t\tbaseUrl,\n\t\tcustomHeaderMap: config.customHeaderMap,\n\t}\n}\n\n/**\n * Tracked state field for deduplication and auto-fired events.\n */\ntype StateField = 'sta' | 'pr' | 'cid' | 'bg' | 'br'\n\n/**\n * One row in the STATE_FIELDS dispatch table.\n *\n * `snapshot` returns the value stored in `lastEmitted` for deduplication\n * comparisons. Reference types must clone. Otherwise the baseline would\n * share a reference with the caller's input, and in-place mutation would\n * silently corrupt the baseline.\n */\ntype StateFieldEntry = {\n\tfield: StateField\n\tevent: CmcdEventType\n\tequal: (a: unknown, b: unknown) => boolean\n\tsnapshot: (v: unknown) => unknown\n}\n\n/**\n * Deep equality for CmcdObjectTypeList (used for `br` deduplication).\n *\n * Arrays with the same elements in different positions count as different.\n * Players that construct `br` consistently get correct deduplication.\n * Reordered arrays produce extra events, which is the safer failure.\n */\nfunction cmcdObjectTypeListEqual(a: CmcdObjectTypeList, b: CmcdObjectTypeList): boolean {\n\tif (a === b) return true\n\tif (a.length !== b.length) return false\n\n\tfor (let i = 0; i < a.length; i++) {\n\t\tconst ai = a[i]\n\t\tconst bi = b[i]\n\t\tif (ai === bi) continue\n\t\tif ((typeof ai === 'number' ? ai : ai.value) !== (typeof bi === 'number' ? bi : bi.value)) return false\n\n\t\t// ExclusiveRecord: params (when defined) has exactly one key\n\t\tconst ap = typeof ai === 'number' ? undefined : ai.params\n\t\tconst bp = typeof bi === 'number' ? undefined : bi.params\n\t\tconst ak = ap && Object.keys(ap)[0]\n\t\tconst bk = bp && Object.keys(bp)[0]\n\t\tif (ak !== bk) return false\n\t\tif (ak !== undefined && bk !== undefined && ap && bp && ap[ak as keyof typeof ap] !== bp[bk as keyof typeof bp]) return false\n\t}\n\n\treturn true\n}\n\n/**\n * Equality for `br` deduplication. A `br` value can be an `SfItem` that\n * wraps the list, as `decodeCmcd` returns for an inner list with\n * parameters. Two values are equal when their lists are equal. The\n * parameters of the list are not compared.\n */\nfunction brEqual(a: unknown, b: unknown): boolean {\n\tconst listA = toBareValue(a)\n\tconst listB = toBareValue(b)\n\n\tif (!Array.isArray(listA) || !Array.isArray(listB)) {\n\t\treturn Object.is(a, b)\n\t}\n\n\treturn cmcdObjectTypeListEqual(listA, listB)\n}\n\nconst equal = Object.is\nconst identity = <T>(v: T): T => v\n\n/**\n * Maps each tracked state field to its event type and equality function.\n * Order matters: `update()` fires events in this order for multi-field updates.\n */\nconst STATE_FIELDS: readonly StateFieldEntry[] = /* @__PURE__ */ Array.from(\n\tCMCD_STATE_EVENT_FIELDS,\n\t([event, field]): StateFieldEntry => {\n\t\tif (field === 'br') {\n\t\t\treturn {\n\t\t\t\tevent,\n\t\t\t\tfield,\n\t\t\t\tequal: brEqual,\n\t\t\t\tsnapshot: (v) => Array.isArray(v) ? v.slice() : copyItemValue(v),\n\t\t\t}\n\t\t}\n\t\treturn { event, field: field as StateField, equal, snapshot: identity }\n\t},\n)\n\nconst STATE_FIELDS_BY_EVENT: ReadonlyMap<CmcdEventType, StateFieldEntry> = /* @__PURE__ */ new Map(\n\t/* @__PURE__ */ STATE_FIELDS.map(e => [e.event, e]),\n)\n\nfunction buildRequiredEventKeys(): ReadonlyMap<CmcdEventType, CmcdKey> {\n\treturn new Map([\n\t\t...CMCD_STATE_EVENT_FIELDS,\n\t\t[CMCD_EVENT_CUSTOM_EVENT, 'cen'] as const,\n\t\t[CMCD_EVENT_ERROR, 'ec'] as const,\n\t\t[CMCD_EVENT_RESPONSE_RECEIVED, 'url'] as const,\n\t])\n}\n\n/**\n * Maps each event type to the key that a report of that type must keep,\n * beyond `e` and `ts`. Built from the state-change table plus the three\n * event types whose required key is event data, not player state.\n */\nconst CMCD_REQUIRED_EVENT_KEYS: ReadonlyMap<CmcdEventType, CmcdKey> = /* @__PURE__ */ buildRequiredEventKeys()\n\n/**\n * Copies a value with the `SfItem` structure, including its `params` record\n * and the list of an `SfItem` that wraps a list.\n *\n * The copy keeps the prototype because `prepareCmcdData`, the formatter map,\n * validation, and the structured-field encoder all branch on\n * `instanceof SfItem`. A plain spread (and `structuredClone`) would return a\n * prototype-less object and silently change the encoded output.\n */\nfunction copyItemValue(value: unknown): unknown {\n\tif (value === null || typeof value !== 'object') {\n\t\treturn value\n\t}\n\n\tconst copy = Object.assign(Object.create(Object.getPrototypeOf(value)), value) as { params?: unknown; value?: unknown; }\n\n\tif (copy.params !== null && typeof copy.params === 'object') {\n\t\tcopy.params = { ...copy.params }\n\t}\n\n\tif (Array.isArray(copy.value)) {\n\t\tcopy.value = copy.value.map(copyItemValue)\n\t}\n\n\treturn copy\n}\n\n/**\n * Copies the nested values of a report in place. A transform cannot mutate\n * the reporter's data store, or another target's report for the same event,\n * through an array or an `SfItem` it received.\n *\n * The copy is complete for the CMCD value space. `CmcdValue` and\n * `CmcdCustomValue` admit only primitives, `SfItem<primitive>`, and arrays of\n * those. `decodeCmcd` also returns an `SfItem` that wraps a list, and the\n * copy includes that list. `SfItem.params` is a flat record. The reporter calls this function\n * where a transform is configured, at session end on the ended session's\n * store, and on the request's stored player-facing view. The session-end\n * copy detaches the frozen snapshot from caller-held references.\n */\nfunction copyReportValues(data: Cmcd): Cmcd {\n\tconst record = data as Record<string, unknown>\n\n\tfor (const key in record) {\n\t\tconst value = record[key]\n\n\t\tif (Array.isArray(value)) {\n\t\t\tconst copy = new Array(value.length)\n\n\t\t\tfor (let i = 0; i < value.length; i++) {\n\t\t\t\tcopy[i] = copyItemValue(value[i])\n\t\t\t}\n\n\t\t\trecord[key] = copy\n\t\t}\n\t\telse if (value !== null && typeof value === 'object') {\n\t\t\trecord[key] = copyItemValue(value)\n\t\t}\n\t}\n\n\treturn data\n}\n\n/**\n * Decodes the per-call data snapshot of a provenance record into new,\n * encodable report data. Tokens decode as `SfToken` and items with params\n * as `SfItem` (`useSymbol: false`), so every value re-encodes with its\n * original type. Only `recordResponseReceived()` calls this function.\n * Returns an empty object when the record is absent, has no snapshot, or\n * the snapshot does not parse (a value this reporter did not write). The\n * response then reports its derived keys over the session's data alone.\n */\nfunction decodeSnapshot(provenance: unknown): Cmcd {\n\tconst encoded = (provenance !== null && typeof provenance === 'object')\n\t\t? (provenance as { data?: unknown; }).data\n\t\t: undefined\n\n\tif (typeof encoded !== 'string' || !encoded) {\n\t\treturn {}\n\t}\n\n\ttry {\n\t\treturn decodeCmcd(encoded, { useSymbol: false }) as Cmcd\n\t}\n\tcatch {\n\t\treturn {}\n\t}\n}\n\n/**\n * Creates a session's frozen base provenance record: the issuing `sid`, and\n * the `cid` that is current at creation time. `update()` creates a new record\n * on every `cid` change. Requests issued before a mid-session content change\n * keep their original `cid`, while later requests get the new one.\n */\nfunction mintProvenance(sid: string, cid: string | undefined): CmcdRequestProvenance {\n\treturn Object.freeze(typeof cid === 'string' && cid ? { sid, cid } : { sid })\n}\n\nfunction defaultRequester(request: HttpRequest): Promise<{ status: number; }> {\n\tconst { url, ...init } = request\n\treturn fetch(url, init)\n}\n\nfunction createCmcdReporterConfig<C>(config: Partial<CmcdReporterConfig<C>>): CmcdReporterConfigNormalized<C> {\n\t// Apply top-level config defaults\n\tconst {\n\t\tversion = CMCD_V2,\n\t\teventTargets = [],\n\t\tsid = uuid(),\n\t\ttransmissionMode = CMCD_QUERY,\n\t\t...rest\n\t} = config\n\n\t// Type-checked, never type-coerced: a numeric string or boolean falls\n\t// back to the default instead of converting, and a Symbol must not\n\t// throw under Math.floor's ToNumber.\n\tconst retention = config.sessionRetention\n\tconst sessionRetention = typeof retention === 'number' ? Math.floor(retention) : NaN\n\n\treturn {\n\t\t...rest,\n\t\tversion,\n\t\ttransmissionMode,\n\t\tsid,\n\t\tsessionRetention: sessionRetention >= 0 ? sessionRetention : 2,\n\t\t// Apply target config defaults\n\t\teventTargets: eventTargets.reduce((acc, target) => {\n\t\t\tif (target?.url && target.events?.length) {\n\t\t\t\tacc.push({\n\t\t\t\t\tversion: target.version || CMCD_V2,\n\t\t\t\t\tenabledKeys: target.enabledKeys?.slice() || [],\n\t\t\t\t\turl: target.url,\n\t\t\t\t\tevents: target.events.slice(),\n\t\t\t\t\tinterval: target.interval ?? CMCD_DEFAULT_TIME_INTERVAL,\n\t\t\t\t\tbatchSize: target.batchSize || 1,\n\t\t\t\t\ttransform: target.transform,\n\t\t\t\t})\n\t\t\t}\n\t\t\treturn acc\n\t\t}, [] as CmcdEventReportConfigNormalized<C>[]),\n\t}\n}\n\ntype CmcdTarget = {\n\tsn: number;\n\tmsdSent: boolean;\n}\n\ntype CmcdEventTarget = CmcdTarget & {\n\t/**\n\t * Complete, encoded report lines not yet sent. Encoding happens at queue\n\t * time, so a value that cannot serialize throws inside the recording call.\n\t * Later mutation of the source values cannot change a queued line.\n\t */\n\tqueue: string[];\n\tdisposed: boolean;\n}\n\n/**\n * The state owned by one session (one `sid`). This state stores everything\n * CTA-5004-B scopes to the session. A report can belong to an ended session:\n * a response that completes after a `sid` change, or a re-queued batch. Such\n * a report uses its own session's data and counters, not the current\n * session's.\n */\ntype CmcdSession<C> = {\n\tsid: string;\n\t/**\n\t * Frozen base provenance record for this session: its `sid` and the\n\t * `cid` current at creation time. The reporter writes the record under\n\t * {@link CMCD_REQUEST_PROVENANCE} on every request it returns. A request\n\t * created with per-call data gets a per-request record: the base record\n\t * plus that data encoded. `update()` creates a new record on every `cid`\n\t * change, so a record describes the state at request time. Already-issued\n\t * requests keep their record. Attribution reads the record's `sid` (see\n\t * `resolveSession()`).\n\t */\n\tprovenance: CmcdRequestProvenance;\n\tdata: Cmcd;\n\tmsd: number;\n\tlastEmitted: Partial<Pick<Cmcd, StateField>>;\n\teventTargets: Map<CmcdEventReportConfigNormalized<C>, CmcdEventTarget>;\n\trequestTarget: CmcdTarget;\n}\n\n/**\n * The CMCD reporter.\n *\n * `C` describes the player's own `customData`, which the reporter passes to\n * each configured `transform`. TypeScript infers `C` from the configuration,\n * so an annotation on one `transform` types the request in every other\n * `transform`. The default leaves `customData` values `unknown`.\n *\n * @typeParam C - The type of the player's `customData`. Defaults to\n * `Record<string, unknown>`.\n *\n * @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}\n *\n * @public\n */\nexport class CmcdReporter<C = Record<string, unknown>> {\n\tprivate timeOrigin = performance.timeOrigin || performance.timing?.fetchStart || Date.now() - performance.now()\n\tprivate config: CmcdReporterConfigNormalized<C>\n\n\t/**\n\t * Retained sessions keyed by `sid`, in insertion order: oldest first,\n\t * current session last. `config.sessionRetention` limits the ended-session\n\t * count. CTA-5004-B expects a `sid` to be unique per playback session. A\n\t * reused `sid` replaces the earlier session with that `sid` at the newest\n\t * position (see `startSession()`).\n\t */\n\tprivate sessions = new Map<string, CmcdSession<C>>()\n\tprivate session: CmcdSession<C>\n\n\t/**\n\t * Active time-interval timers by target config. Timers continue across\n\t * session changes (their callbacks report into whichever session is\n\t * current when they fire), so the reporter owns them, not the session.\n\t */\n\tprivate intervals = new Map<CmcdEventReportConfigNormalized<C>, ReturnType<typeof setInterval>>()\n\tprivate started = false\n\n\tprivate requester: (request: HttpRequest) => Promise<{ status: number; }>\n\n\t/**\n\t * Creates a new CMCD reporter.\n\t *\n\t * @param config - The configuration for the CMCD reporter.\n\t * @param requester - The function that sends the request.\n\t * The default is a simple wrapper around the\n\t * native `fetch` API.\n\t */\n\tconstructor(config: Partial<CmcdReporterConfig<C>>, requester: (request: HttpRequest) => Promise<{ status: number; }> = defaultRequester) {\n\t\tthis.config = createCmcdReporterConfig(config)\n\t\tthis.session = this.createSession(this.config.sid, {\n\t\t\tcid: this.config.cid,\n\t\t\tv: this.config.version,\n\t\t})\n\t\tthis.sessions.set(this.session.sid, this.session)\n\t\tthis.requester = requester\n\t}\n\n\t/**\n\t * Creates the state for a new session: initial counters, flags, queues, and\n\t * deduplication baseline for every configured target.\n\t */\n\tprivate createSession(sid: string, data: Cmcd): CmcdSession<C> {\n\t\tconst eventTargets = new Map<CmcdEventReportConfigNormalized<C>, CmcdEventTarget>()\n\n\t\tfor (const target of this.config.eventTargets) {\n\t\t\teventTargets.set(target, {\n\t\t\t\tsn: 0,\n\t\t\t\tmsdSent: false,\n\t\t\t\tqueue: [],\n\t\t\t\tdisposed: false,\n\t\t\t})\n\t\t}\n\n\t\treturn {\n\t\t\tsid,\n\t\t\t// Frozen because it is handed out on every returned request; the\n\t\t\t// sid value, not the record's identity, is what attributes.\n\t\t\tprovenance: mintProvenance(sid, data.cid),\n\t\t\tdata,\n\t\t\tmsd: NaN,\n\t\t\t// A session that does not start backgrounded has no exit to report.\n\t\t\t// CTA-5004-B defines a `b` event without `bg` as the exit.\n\t\t\tlastEmitted: toBareValue(data.bg) === true ? {} : { bg: false },\n\t\t\teventTargets,\n\t\t\trequestTarget: {\n\t\t\t\tsn: 0,\n\t\t\t\tmsdSent: false,\n\t\t\t},\n\t\t}\n\t}\n\n\t/**\n\t * Starts the CMCD reporter. The player calls this method when it enables the\n\t * reporter.\n\t *\n\t * This method fires an initial time-interval event immediately (synchronously),\n\t * before the first interval elapses. Populate the CMCD data (sid, cid, and\n\t * others) before calling start().\n\t */\n\tstart(): void {\n\t\tthis.started = true\n\n\t\t// The initial time-interval event is fired synchronously per target, so a\n\t\t// throwing transform must not abort the loop: later targets would never\n\t\t// have their intervals armed and would report nothing for the session,\n\t\t// and a retried start() would fail on the same target again. Same\n\t\t// continue-then-rethrow contract as `emitEvent()`.\n\t\tlet failure: { error: unknown; } | undefined\n\n\t\t// The fan-out is pinned to the session that was current when start()\n\t\t// was called: a transform can synchronously rotate the session, and\n\t\t// pairing the new session with the old session's targets would let a\n\t\t// report consume another session's sequence numbers.\n\t\tconst session = this.session\n\n\t\tsession.eventTargets.forEach((target, config) => {\n\t\t\t// Disarm any existing timer so repeated start() calls do not leak intervals.\n\t\t\tthis.disarmInterval(config)\n\n\t\t\t// A target disposed via HTTP 410 stays silent for the rest of the\n\t\t\t// session. Armed before the initial event so a throwing transform\n\t\t\t// leaves the timer in the same state a successful start() would,\n\t\t\t// rather than silently disabling the target.\n\t\t\tif (target.disposed || !this.armInterval(config)) {\n\t\t\t\treturn\n\t\t\t}\n\n\t\t\ttry {\n\t\t\t\tthis.recordTargetEvent(session, target, config, CMCD_EVENT_TIME_INTERVAL)\n\t\t\t\tthis.processEventTargets()\n\t\t\t}\n\t\t\tcatch (error) {\n\t\t\t\tfailure ??= { error }\n\t\t\t}\n\t\t})\n\n\t\tif (failure) {\n\t\t\tthrow failure.error\n\t\t}\n\t}\n\n\t/**\n\t * Starts the time-interval timer for an event target when its config\n\t * requires one. Returns whether a timer started. The callback reports into\n\t * whichever session is current when the timer fires.\n\t */\n\tprivate armInterval(config: CmcdEventReportConfigNormalized<C>): boolean {\n\t\t// If the interval is 0 or the TIME_INTERVAL event is not enabled, do not start the interval.\n\t\tif (config.interval === 0 || !config.events.includes(CMCD_EVENT_TIME_INTERVAL)) {\n\t\t\treturn false\n\t\t}\n\n\t\tthis.intervals.set(config, setInterval(() => {\n\t\t\tconst session = this.session\n\t\t\tconst target = session.eventTargets.get(config)\n\n\t\t\tif (target) {\n\t\t\t\tthis.recordTargetEvent(session, target, config, CMCD_EVENT_TIME_INTERVAL)\n\t\t\t\tthis.processEventTargets()\n\t\t\t}\n\t\t}, config.interval * 1000))\n\n\t\treturn true\n\t}\n\n\t/**\n\t * Stops the CMCD reporter. The player calls this method when it disables the\n\t * reporter.\n\t *\n\t * @param flush - Whether to flush the event targets.\n\t */\n\tstop(flush: boolean = false): void {\n\t\tthis.started = false\n\n\t\tif (flush) {\n\t\t\tthis.flush()\n\t\t}\n\n\t\tfor (const config of this.config.eventTargets) {\n\t\t\tthis.disarmInterval(config)\n\t\t}\n\t}\n\n\t/**\n\t * Sends all outstanding event reports, regardless of the batch size or\n\t * interval. Use this method when the player is destroyed or a playback\n\t * session ends.\n\t */\n\tflush(): void {\n\t\tthis.processEventTargets(true)\n\t}\n\n\t/**\n\t * Updates the CMCD data.\n\t *\n\t * The player calls this method when data changes. The tracked state fields\n\t * are `sta`, `pr`, `cid`, `bg`, and `br`. If a new value for one of them\n\t * differs from the last reported value for that field, the reporter fires\n\t * the matching state-change event. The comparison uses the last reported\n\t * value, not the previous persisted value. The first state-change event in\n\t * a new session therefore always fires, even when the persisted value did\n\t * not change across the `sid` boundary.\n\t *\n\t * The `bg` field is an exception. A session that does not start with\n\t * `bg: true` begins with `false` as its last reported `bg` value.\n\t * `bg: false` therefore fires `BACKGROUNDED_MODE` only if the session\n\t * started with `bg: true` or reported `bg: true`. CTA-5004-B defines a\n\t * `b` event without `bg` as the exit from backgrounded mode, so the exit\n\t * report does not carry `bg`. A target transform can add `bg: false` to\n\t * the exit report. The encoder writes that value as `?0`.\n\t *\n\t * Multi-field updates fire the events in this order: `sta`, `pr`, `cid`,\n\t * `bg`, `br`. The order of keys in the input object does not affect the\n\t * firing order.\n\t *\n\t * A state-change event can include context fields, for example `bl`, `mtp`,\n\t * `pt`, `ltc`. Those fields must be in the data store before the state field\n\t * changes. Either pass them with the state field in the same `update()`\n\t * call, or persist them with earlier `update()` calls. An auto-fired event\n\t * reports the current content of the data store. `TIME_INTERVAL` events also\n\t * read the data store, and the caller cannot add per-call data to them. The\n\t * player must therefore update the fields it wants in periodic reports with\n\t * this method.\n\t *\n\t * A `sid` change resets the deduplication baseline.\n\t *\n\t * `sid` and `msd` are session-owned. The reporter tracks them itself and\n\t * writes them into every outgoing report, so this method is the only way\n\t * to change them. A per-call value on {@link CmcdReporter.recordEvent},\n\t * {@link CmcdReporter.createRequestReport}, or\n\t * {@link CmcdReporter.recordResponseReceived} has no effect.\n\t * `msd` must be a finite number of milliseconds between `0` and\n\t * `999_999_999_999_999` (the RFC 8941 integer maximum). The reporter\n\t * rounds `msd` to the nearest integer and ignores invalid values.\n\t *\n\t * @param data - The data to update.\n\t */\n\tupdate(data: Partial<Cmcd>): void {\n\t\tif (data.sid && data.sid !== this.session.sid) {\n\t\t\tthis.startSession(data.sid)\n\t\t}\n\n\t\tconst session = this.session\n\t\tconst { msd } = data\n\n\t\t// CTA-5004-B defines msd as integer milliseconds, sent once per session.\n\t\t// 0 is a valid instant-start value; anything non-finite or negative is\n\t\t// ignored so it can neither reach the wire nor consume the send gate.\n\t\t// The rounded value must also fit an RFC 8941 structured-field integer\n\t\t// (at most 999_999_999_999_999), or serialization throws after the\n\t\t// gate is already consumed.\n\t\tif (typeof msd === 'number' && Number.isFinite(msd) && msd >= 0) {\n\t\t\tconst rounded = Math.round(msd)\n\n\t\t\tif (rounded <= 999_999_999_999_999) {\n\t\t\t\tsession.msd = rounded\n\t\t\t}\n\t\t}\n\n\t\t// sid and msd are session-owned: tracked in their own fields, stripped\n\t\t// from the persistent store, and stamped onto each report at queue time.\n\t\tsession.data = { ...session.data, ...data, sid: undefined, msd: undefined }\n\n\t\t// A cid change re-mints the session's base provenance record, so a\n\t\t// request issued from here on carries the new cid while requests\n\t\t// already in flight keep the one they were issued under. Their late\n\t\t// responses then report the content the request was actually about.\n\t\tif (session.data.cid !== session.provenance.cid) {\n\t\t\tsession.provenance = mintProvenance(session.sid, session.data.cid)\n\t\t}\n\n\t\t// Auto-trigger state-change events for any tracked field whose value\n\t\t// differs from the last wire-emitted value. Comparing against lastEmitted\n\t\t// (not the pre-merge value) ensures correctness after a session change,\n\t\t// and unifies the comparison basis with recordEvent's internal dedup.\n\t\tfor (const entry of STATE_FIELDS) {\n\t\t\tif (entry.field in data && !entry.equal(session.data[entry.field], session.lastEmitted[entry.field])) {\n\t\t\t\tthis.recordEvent(entry.event)\n\t\t\t}\n\t\t}\n\t}\n\n\t/**\n\t * Starts a new session. The reporter retains the current session for late\n\t * responses and creates a new current session. It then sends the ended\n\t * sessions' queued reports and removes the oldest sessions beyond the\n\t * configured retention.\n\t *\n\t * The ended session's snapshot is frozen: the reporter detaches its value\n\t * graph, so nested values from earlier `update()` calls cannot mutate the\n\t * snapshot. The new session starts from a shallow copy of that graph, which\n\t * preserves the data store. All fields, including `cid`, `br`, and custom\n\t * keys, survive a `sid` change as before. CTA-5004-B expects a `sid` to be\n\t * unique per playback session, so a reused `sid` replaces the retained\n\t * session with that `sid`. The replaced session's remaining state is lost,\n\t * as if removed, and the reporter attributes its late responses to the\n\t * replacement.\n\t */\n\tprivate startSession(sid: string): void {\n\t\tthis.session.data = copyReportValues({ ...this.session.data })\n\t\tthis.session = this.createSession(sid, { ...this.session.data })\n\n\t\t// Map.set keeps an existing key's insertion position, so a reused\n\t\t// sid must be deleted first: re-inserting at the newest position\n\t\t// keeps oldest-first eviction from ever reaching the current\n\t\t// session, and ages out genuinely older sessions ahead of it.\n\t\tthis.sessions.delete(sid)\n\t\tthis.sessions.set(sid, this.session)\n\n\t\t// Drain ended sessions before eviction can destroy their queues: a\n\t\t// partial batch the ended session could never fill again leaves now.\n\t\tthis.processEventTargets()\n\n\t\t// An evicted session's unsent queues die with it, and its stale\n\t\t// responses drop, because its sid no longer names a retained\n\t\t// session. The current session was inserted last, so oldest-first\n\t\t// eviction never reaches it, and `Infinity` retention never evicts.\n\t\tfor (const key of this.sessions.keys()) {\n\t\t\tif (this.sessions.size <= this.config.sessionRetention + 1) {\n\t\t\t\tbreak\n\t\t\t}\n\n\t\t\tthis.sessions.delete(key)\n\t\t}\n\n\t\t// Timers keep ticking across session changes. Configs whose timer was\n\t\t// disarmed by a 410 in the previous session re-arm here, because the\n\t\t// new session's targets are fresh; the immediate report start() fires\n\t\t// is not repeated.\n\t\tif (this.started) {\n\t\t\tfor (const config of this.config.eventTargets) {\n\t\t\t\tif (!this.intervals.has(config)) {\n\t\t\t\t\tthis.armInterval(config)\n\t\t\t\t}\n\t\t\t}\n\t\t}\n\t}\n\n\t/**\n\t * Records an event. The player calls this method when an event occurs.\n\t *\n\t * For state-change events (`PLAY_STATE`, `PLAYBACK_RATE`, `CONTENT_ID`,\n\t * `BACKGROUNDED_MODE`, `BITRATE_CHANGE`), this method:\n\t * 1. Writes the state field from `data` (if present) into the reporter's\n\t * data store, as `update()` would.\n\t * 2. Discards the event if the state field has no value after that write\n\t * (never set, or cleared with `update({ field: undefined })`).\n\t * 3. Suppresses the event if the field's current value equals the\n\t * last reported value (no state transition). {@link CmcdReporter.update}\n\t * describes the `bg` value that a new session starts with.\n\t *\n\t * The reporter always records all other event types.\n\t *\n\t * For state-change events, prefer {@link CmcdReporter.update}, also for\n\t * context fields in a combined call like\n\t * `update({ sta: 'p', bl: [3000], mtp: [8500] })`. After `update()`\n\t * auto-fires a state-change event, deduplication suppresses a\n\t * `recordEvent()` call for the same event, and that call's `data` is\n\t * silently lost.\n\t *\n\t * Call `recordEvent()` directly for events whose data comes with the event\n\t * call. Examples: `CUSTOM_EVENT` with `cen`, `ERROR` with `ec`, ad lifecycle\n\t * events, `MUTE`/`UNMUTE`, `PLAYER_EXPAND`/`PLAYER_COLLAPSE`, `SKIP`. For\n\t * `RESPONSE_RECEIVED`, prefer {@link CmcdReporter.recordResponseReceived},\n\t * which derives the per-response fields automatically.\n\t *\n\t * @param type - The type of event to record.\n\t * @param data - Additional data to record with the event. This data applies\n\t * only to this event report. The exception is the state field\n\t * of a state-change event, which the reporter also writes into\n\t * its data store. The reporter ignores session-owned keys\n\t * (`sid`, `msd`) supplied here and writes its own values.\n\t */\n\trecordEvent(type: CmcdEventType, data: Partial<Cmcd> = {}): void {\n\t\tthis.emitEvent(this.session, type, data)\n\t}\n\n\t/**\n\t * Records an event for every configured target of a session. State-change\n\t * deduplication runs once, before the per-target loop.\n\t *\n\t * @param session - The session the event belongs to. Everything the event\n\t * touches (data store, deduplication baseline, counters,\n\t * queues) is that session's. Only `recordResponseReceived()`\n\t * ever passes an ended session.\n\t * @param type - The type of event to record.\n\t * @param data - Additional data to record with the event.\n\t * @param request - The media request that triggered the event, when\n\t * one exists. Only `recordResponseReceived()` sets this\n\t * parameter, which the reporter passes to each target's\n\t * `transform`.\n\t */\n\tprivate emitEvent(session: CmcdSession<C>, type: CmcdEventType, data: Partial<Cmcd>, request?: HttpRequest): void {\n\t\tconst entry = STATE_FIELDS_BY_EVENT.get(type)\n\t\tif (entry) {\n\t\t\tconst field = entry.field\n\t\t\tconst incoming = data[field]\n\n\t\t\tif (incoming !== undefined) {\n\t\t\t\tObject.assign(session.data, { [field]: incoming })\n\t\t\t}\n\n\t\t\tconst current = session.data[field]\n\n\t\t\t// Never emit a state-change event whose state field has no value.\n\t\t\t// Catches both \"no value ever set\" and \"previous value was cleared to\n\t\t\t// undefined\".\n\t\t\tif (current === undefined) {\n\t\t\t\treturn\n\t\t\t}\n\n\t\t\tif (entry.equal(current, session.lastEmitted[field])) {\n\t\t\t\treturn\n\t\t\t}\n\n\t\t\tObject.assign(session.lastEmitted, { [field]: entry.snapshot(current) })\n\t\t}\n\n\t\t// A throwing transform must not abort the fan-out. The dedup baseline\n\t\t// above is already committed and is never rolled back, so aborting here\n\t\t// would strand the transition: targets after the throwing one would\n\t\t// never receive it, and the caller's retry would be deduped away.\n\t\tlet failure: { error: unknown; } | undefined\n\n\t\tsession.eventTargets.forEach((target, config) => {\n\t\t\ttry {\n\t\t\t\tthis.recordTargetEvent(session, target, config, type, data, request)\n\t\t\t}\n\t\t\tcatch (error) {\n\t\t\t\tfailure ??= { error }\n\t\t\t}\n\t\t})\n\n\t\tthis.processEventTargets()\n\n\t\t// Surfaced only once every target has had its turn and the queues have\n\t\t// been processed. Transforms must not throw; this makes the violation\n\t\t// visible without letting it starve unrelated targets.\n\t\tif (failure) {\n\t\t\tthrow failure.error\n\t\t}\n\t}\n\n\t/**\n\t * Records an event for a target. The reporter calls this method when an\n\t * event occurs.\n\t *\n\t * @param target - The target to record the event for.\n\t * @param config - The configuration for the target.\n\t * @param type - The type of event to record.\n\t * @param data - Additional data to record with the event. This data\n\t * only applies to this event report. Use `update()` for\n\t * persistent data.\n\t * @param request - The media request that triggered the event, when\n\t * one exists. The target's `transform` receives it.\n\t */\n\tprivate recordTargetEvent(session: CmcdSession<C>, target: CmcdEventTarget, config: CmcdEventReportConfigNormalized<C>, type: CmcdEventType, data: Partial<Cmcd> = {}, request?: HttpRequest): void {\n\t\tif (target.disposed || !config.events.includes(type)) {\n\t\t\treturn\n\t\t}\n\n\t\t// The session's sid is stamped over any per-call value here so a\n\t\t// transform sees the session identity the report will carry.\n\t\tconst item: Cmcd = {\n\t\t\t...session.data,\n\t\t\t...data,\n\t\t\tsid: session.sid,\n\t\t\te: type,\n\t\t\tts: data.ts ?? Date.now(),\n\t\t}\n\n\t\t// CTA-5004-B defines a `b` event without `bg` as the exit from\n\t\t// backgrounded mode. A transform can add `bg: false`, which the encoder\n\t\t// writes as `?0`.\n\t\tif (type === CMCD_EVENT_BACKGROUNDED_MODE && toBareValue(item.bg) === false) {\n\t\t\tdelete item.bg\n\t\t}\n\n\t\tconst { transform } = config\n\n\t\tif (!transform) {\n\t\t\tthis.queueTargetEvent(session, target, config, item, type)\n\t\t\treturn\n\t\t}\n\n\t\t// The spread above is shallow, so nested values are still shared with\n\t\t// the persistent store and with sibling targets' inputs; a transform\n\t\t// gets its own detached copy so in-place mutation reaches neither.\n\t\tcopyReportValues(item)\n\n\t\t// Captured so a transform cannot strip a key the event requires.\n\t\t// `CmcdKey` spans custom keys too, so index through a record view.\n\t\tconst requiredKey = CMCD_REQUIRED_EVENT_KEYS.get(type)\n\t\tconst requiredValue = requiredKey ? (item as Record<string, unknown>)[requiredKey] : undefined\n\t\tconst ts = item.ts\n\n\t\tconst report = transform(item, request)\n\n\t\t// A cancelled report consumes neither a sequence number nor msd.\n\t\tif (report == null) {\n\t\t\treturn\n\t\t}\n\n\t\t// Restore, never fabricate: a required key that was already absent (or\n\t\t// already unusable) before the transform ran is not restored. The\n\t\t// restore covers removal and substitution with any value that `isValid`\n\t\t// rejects, `false` included.\n\t\tif (!isValid(report.ts)) {\n\t\t\treport.ts = ts\n\t\t}\n\n\t\tif (requiredKey && isValid(requiredValue) && !isValid((report as Record<string, unknown>)[requiredKey])) {\n\t\t\tObject.assign(report, { [requiredKey]: requiredValue })\n\t\t}\n\n\t\tthis.queueTargetEvent(session, target, config, report, type)\n\t}\n\n\t/**\n\t * Writes the reporter-owned fields into a finished event report, encodes\n\t * the report, and pushes the encoded line to the target's queue.\n\t *\n\t * This method runs after any transform. A transform cannot bypass the\n\t * target's `events` filter through `e`, break `sn` continuity, or replace\n\t * the session identity in `sid` and `msd`. Encoding here makes a report\n\t * that cannot serialize throw inside the recording call, instead of failing\n\t * the batch send and re-queueing forever.\n\t *\n\t * @param target - The target to queue the report for.\n\t * @param config - The configuration for the target.\n\t * @param report - The finished report data.\n\t * @param type - The type of event being reported.\n\t */\n\tprivate queueTargetEvent(session: CmcdSession<C>, target: CmcdEventTarget, config: CmcdEventReportConfigNormalized<C>, report: Cmcd, type: CmcdEventType): void {\n\t\treport.e = type\n\t\treport.sn = target.sn++\n\t\treport.sid = session.sid\n\n\t\t// msd may only ride a report through the once-per-target gate, and only\n\t\t// when the target's key filter will retain it (msd is never force-added\n\t\t// at encode time): consuming the gate for a report that filters msd out\n\t\t// would silently drop it for the session. A value smuggled in via\n\t\t// per-call data or a transform is stripped, so the gate stays the\n\t\t// single source of once-per-session semantics.\n\t\tif (!isNaN(session.msd) && !target.msdSent && config.enabledKeys?.includes('msd')) {\n\t\t\treport.msd = session.msd\n\t\t\ttarget.msdSent = true\n\t\t}\n\t\telse {\n\t\t\tdelete report.msd\n\t\t}\n\n\t\ttarget.queue.push(encodeCmcd(report, createEncodingOptions(CMCD_EVENT_MODE, config)))\n\t}\n\n\t/**\n\t * Records a response-received event. The player calls this method when a\n\t * media request response has fully arrived.\n\t *\n\t * This method derives these `rr` event keys automatically:\n\t *\n\t * - `url` - the original requested URL (before any redirects)\n\t * - `rc` - the HTTP response status code\n\t * - `ts` - the request initiation time (from `resourceTiming.startTime`)\n\t * - `ttfb` - time to first byte (from `resourceTiming.responseStart`)\n\t * - `ttlb` - time to last byte (from `resourceTiming.duration`)\n\t *\n\t * If the player has additional keys like `ttfbb`, `cmsdd`, `cmsds`, and\n\t * `smrt`, pass them in the `data` parameter.\n\t *\n\t * The request's `customData` is generic, so a player can pass a request with\n\t * its own keys (for example `{ requestType: 'segment' }`) without a cast. The\n\t * reporter reads only the provenance record that\n\t * {@link CmcdReporter.createRequestReport} writes there. Every other key\n\t * stays unchanged and visible to an event target's `transform` through its\n\t * `request` argument.\n\t *\n\t * A reporter with a concrete `C` requires the request to satisfy that type.\n\t * TypeScript therefore rejects a call whose request the configured\n\t * transforms could not read. See {@link CmcdReporterCustomData}.\n\t *\n\t * The provenance record that {@link CmcdReporter.createRequestReport}\n\t * stored on the request's `customData` (under\n\t * {@link CMCD_REQUEST_PROVENANCE}) selects the session by `sid`. A record\n\t * that names no retained session drops the response (see\n\t * `CmcdReporterConfig.sessionRetention`). A request without a record reports\n\t * under the current session, as in version 2.4.0. The request-time data then\n\t * comes from `customData.cmcd`. A per-call `data.sid` cannot substitute. The\n\t * reporter accepts any record whose `sid` names a retained session. The\n\t * record may come from another reporter with the same session attributes,\n\t * or be hand-built. If the request has a record, a response that completes\n\t * after a `sid` change reports under its own retained session, with that\n\t * session's data snapshot and sequence numbers.\n\t *\n\t * With a record, request-time report keys come from the record's encoded\n\t * per-call `data` snapshot, which the reporter decodes for each response.\n\t * The record's `cid` replaces the session's current `cid` in the report. A\n\t * response that completes after a mid-session content change therefore\n\t * reports its request-time values.\n\t *\n\t * @typeParam RD - The `customData` of this request. Defaults to the\n\t * reporter's own `C`.\n\t *\n\t * @param response - The HTTP response received.\n\t * @param data - Additional CMCD data to include with the event.\n\t * Values provided here override the derived values.\n\t * The reporter ignores session-owned keys (`sid`, `msd`)\n\t * supplied here.\n\t */\n\trecordResponseReceived<RD extends CmcdReporterCustomData<C> = C>(response: HttpResponse<HttpRequest<RD & { cmcd?: Cmcd; [CMCD_REQUEST_PROVENANCE]?: CmcdRequestProvenance }>>, data: Partial<Cmcd> = {}): void {\n\t\tconst { request } = response\n\n\t\tconst url = data.url ?? request?.url\n\n\t\tif (!url) {\n\t\t\treturn\n\t\t}\n\n\t\tconst provenance = request.customData?.[CMCD_REQUEST_PROVENANCE]\n\t\tconst session = provenance === undefined ? this.session : this.resolveSession(provenance)\n\n\t\tif (!session) {\n\t\t\treturn\n\t\t}\n\n\t\tconst cmcd = provenance === undefined ? { ...request.customData?.cmcd } : decodeSnapshot(provenance)\n\n\t\t// The record's cid is the content the request was issued under. It\n\t\t// overrides the session store's current value so a response landing\n\t\t// after a mid-session content change keeps its meaning, and it\n\t\t// yields to the decoded snapshot and per-call data above it.\n\t\tconst { cid } = (provenance ?? {}) as { cid?: unknown; }\n\n\t\tconst derived: Partial<Cmcd> = {\n\t\t\turl: replaceCmcdParam(url),\n\t\t\trc: response.status,\n\t\t}\n\n\t\tconst timing = response.resourceTiming\n\n\t\tif (timing) {\n\t\t\tif (timing.startTime != null) {\n\t\t\t\tderived.ts = Math.round(this.timeOrigin + timing.startTime)\n\n\t\t\t\tif (timing.responseStart != null) {\n\t\t\t\t\tderived.ttfb = Math.round(timing.responseStart - timing.startTime)\n\t\t\t\t}\n\t\t\t}\n\n\t\t\tif (timing.duration != null) {\n\t\t\t\tderived.ttlb = Math.round(timing.duration)\n\t\t\t}\n\t\t}\n\n\t\tthis.emitEvent(session, CMCD_EVENT_RESPONSE_RECEIVED, {\n\t\t\t...(typeof cid === 'string' && cid ? { cid } : undefined),\n\t\t\t...cmcd,\n\t\t\t...derived,\n\t\t\t...data,\n\t\t}, request)\n\t}\n\n\t/**\n\t * Resolves the session that a provenance record names. The record's `sid`\n\t * must name one of this reporter's retained sessions, or the reporter\n\t * discards the response. A record that names a removed or unknown `sid`\n\t * resolves nothing. Any other attribution would be wrong. The reporter reads\n\t * the `sid` as a plain property. A record\n\t * copied through JSON therefore resolves the same session, and a hand-built\n\t * record that names a retained session is accepted.\n\t */\n\tprivate resolveSession(provenance: unknown): CmcdSession<C> | undefined {\n\t\tif (provenance === null || typeof provenance !== 'object') {\n\t\t\treturn undefined\n\t\t}\n\n\t\tconst { sid } = provenance as { sid?: unknown; }\n\n\t\treturn typeof sid === 'string' ? this.sessions.get(sid) : undefined\n\t}\n\n\t/**\n\t * Applies the CMCD request report data to the request. The player calls this\n\t * method before sending the request.\n\t *\n\t * @param req - The request to apply the CMCD request report to.\n\t * @returns The request with the CMCD request report applied.\n\t *\n\t * @deprecated Use {@link CmcdReporter.createRequestReport} instead.\n\t */\n\tapplyRequestReport(req: HttpRequest): HttpRequest {\n\t\treturn this.createRequestReport(req) ?? req\n\t}\n\n\t/**\n\t * Checks whether request reporting is enabled.\n\t *\n\t * @returns `true` if request reporting is enabled, `false` otherwise.\n\t */\n\tisRequestReportingEnabled(): boolean {\n\t\treturn !!this.config.enabledKeys?.length\n\t}\n\n\t/**\n\t * The provenance record to write on a returned request. It is the session's\n\t * frozen base record, extended with the caller's per-call data encoded as a\n\t * CMCD string when there is any. Requests without per-call data share the\n\t * base record, so the reporter writes only one property. The snapshot never\n\t * contains reporter-written fields. A value that cannot encode contributes\n\t * no snapshot and does not fail the request. The response still attributes\n\t * and reports derived keys over session data, matching the tolerance of\n\t * `decodeSnapshot()` when reading.\n\t */\n\tprivate createRequestProvenance(data: Partial<Cmcd> | undefined, baseUrl: string | undefined): CmcdRequestProvenance {\n\t\tconst base = this.session.provenance\n\n\t\tif (!data) {\n\t\t\treturn base\n\t\t}\n\n\t\ttry {\n\t\t\tconst encoded = encodeCmcd(data as Cmcd, {\n\t\t\t\tversion: this.config.version,\n\t\t\t\treportingMode: CMCD_REQUEST_MODE,\n\t\t\t\tbaseUrl,\n\t\t\t})\n\n\t\t\treturn encoded ? Object.freeze({ ...base, data: encoded }) : base\n\t\t}\n\t\tcatch {\n\t\t\treturn base\n\t\t}\n\t}\n\n\t/**\n\t * Creates a new request with the CMCD request report data applied. The\n\t * player calls this method before sending the request.\n\t *\n\t * A reporter with a concrete `C` requires the request's `customData` to\n\t * satisfy that type. TypeScript therefore rejects a call whose request the\n\t * configured transform could not read. See\n\t * {@link CmcdReporterCustomData}.\n\t *\n\t * @typeParam R - The type of the request. Its `customData` must satisfy\n\t * the reporter's `C`.\n\t *\n\t * @param request - The request to apply the CMCD request report to.\n\t * @param data - The data to apply to the request. This data only\n\t * applies to this request report. Use `update()` for\n\t * persistent data.\n\t * @returns The request with the CMCD request report applied.\n\t */\n\tcreateRequestReport<R extends HttpRequest<CmcdReporterCustomData<C>> = HttpRequest<C>>(request: R, data?: Partial<Cmcd>): R & CmcdRequestReport<R['customData']> {\n\t\tconst { customData = {}, headers = {}, ...rest } = request\n\t\tconst report = {\n\t\t\t...rest,\n\t\t\theaders: {\n\t\t\t\t...headers,\n\t\t\t},\n\t\t\tcustomData: {\n\t\t\t\t...customData,\n\t\t\t\tcmcd: {},\n\t\t\t\t// Session provenance rides every returned request, including\n\t\t\t\t// ones this method does not decorate (request reporting\n\t\t\t\t// disabled, or a transform cancels below): the request was\n\t\t\t\t// still issued by this session, and its response still needs\n\t\t\t\t// attribution. The per-call data is captured on the record\n\t\t\t\t// here, before any early return, key filter, or transform\n\t\t\t\t// can lose it, so a late response reports the caller's own\n\t\t\t\t// request-time inputs.\n\t\t\t\t[CMCD_REQUEST_PROVENANCE]: this.createRequestProvenance(data, request.url),\n\t\t\t},\n\t\t} as R & CmcdRequestReport<R['customData']>\n\n\t\tif (!this.config.enabledKeys?.length || !report.url) {\n\t\t\treturn report\n\t\t}\n\n\t\t// Request reports are always current-session. The session's sid is\n\t\t// stamped over any per-call value here so a transform sees the\n\t\t// session identity the report will carry.\n\t\tconst session = this.session\n\t\tconst merged: Cmcd = { ...session.data, ...data, sid: session.sid }\n\t\tconst { transform } = this.config\n\t\tlet cmcdData: Cmcd | null = merged\n\n\t\tif (transform) {\n\t\t\t// The spread above is shallow, so nested values are still shared\n\t\t\t// with the persistent store.\n\t\t\tcopyReportValues(merged)\n\n\t\t\t// The caller's request is passed, not the internal clone, so a\n\t\t\t// transform cannot alter the outgoing report through it.\n\t\t\tcmcdData = transform(merged, request as CmcdTransformRequest<C>)\n\n\t\t\t// A cancelled report consumes neither a sequence number nor msd.\n\t\t\tif (cmcdData == null) {\n\t\t\t\treturn report\n\t\t\t}\n\t\t}\n\n\t\t// Reporter-owned fields are stamped after the transform runs.\n\t\tcmcdData.sn = session.requestTarget.sn++\n\t\tcmcdData.sid = session.sid\n\n\t\t// msd may only ride a report through the once-per-session gate; a value\n\t\t// smuggled in via per-call data or the transform is stripped, so the\n\t\t// gate stays the single source of once-per-session semantics. The gate\n\t\t// is consumed after preparation, and only if the key filter retained\n\t\t// msd, so a filtered-out msd is not silently dropped for the session.\n\t\tconst sendMsd = !isNaN(session.msd) && !session.requestTarget.msdSent\n\n\t\tif (sendMsd) {\n\t\t\tcmcdData.msd = session.msd\n\t\t}\n\t\telse {\n\t\t\tdelete cmcdData.msd\n\t\t}\n\n\t\tconst options = createEncodingOptions(CMCD_REQUEST_MODE, this.config, report.url)\n\n\t\t// The player-facing view is detached from the persistent store:\n\t\t// prepareCmcdData builds a fresh object but copies values by\n\t\t// reference, and players read this object to identify requests, so a\n\t\t// shared array would leak mutation into the store. The reporter never\n\t\t// reads it back; the response path works from the encoded snapshot on\n\t\t// the provenance record.\n\t\tconst cmcd = report.customData.cmcd = copyReportValues(prepareCmcdData(cmcdData, options))\n\n\t\tif (sendMsd && cmcd.msd !== undefined) {\n\t\t\tsession.requestTarget.msdSent = true\n\t\t}\n\n\t\tconst encoded = encodePreparedCmcd(cmcd)\n\n\t\tswitch (this.config.transmissionMode) {\n\t\t\tcase CMCD_QUERY:\n\t\t\t\tif (encoded) {\n\t\t\t\t\treport.url = replaceCmcdParam(report.url, encoded)\n\t\t\t\t}\n\t\t\t\tbreak\n\n\t\t\tcase CMCD_HEADERS:\n\t\t\t\tObject.assign(report.headers, toPreparedCmcdHeaders(cmcd, options.customHeaderMap))\n\t\t\t\tbreak\n\t\t}\n\n\t\treturn report\n\t}\n\n\t/**\n\t * Processes the event targets. The reporter calls this method when an event\n\t * occurs.\n\t *\n\t * @param flush - Whether to flush the event targets.\n\t */\n\tprivate processEventTargets(flush: boolean = false): void {\n\t\tlet reprocess = false\n\n\t\t// Oldest session first, so an archived session's late reports leave\n\t\t// ahead of current traffic.\n\t\tthis.sessions.forEach((session) => {\n\t\t\t// An archived session receives no further regular events, so its\n\t\t\t// queues could never fill a batch again; its remainders are always\n\t\t\t// drain-eligible, preserving the pre-existing behavior of unsent\n\t\t\t// old-sid events draining after a session change.\n\t\t\tconst drain = flush || session !== this.session\n\n\t\t\tsession.eventTargets.forEach((target, config) => {\n\t\t\t\tconst { queue } = target\n\n\t\t\t\t// A disposed target's queue can be non-empty again if a failed\n\t\t\t\t// batch was re-queued after disposal; it must stay unsent.\n\t\t\t\tif (target.disposed || !queue.length) {\n\t\t\t\t\treturn\n\t\t\t\t}\n\n\t\t\t\tif (queue.length < config.batchSize && !drain) {\n\t\t\t\t\treturn\n\t\t\t\t}\n\n\t\t\t\tconst deleteCount = drain ? queue.length : config.batchSize\n\t\t\t\tconst events = queue.splice(0, deleteCount)\n\t\t\t\tthis.sendEventReport(session, config, events).catch(() => {\n\t\t\t\t\t// Re-queue events that failed to send. The target belongs\n\t\t\t\t\t// to the batch's own session, so a failure after a session\n\t\t\t\t\t// change re-queues there, never into the current session.\n\t\t\t\t\ttarget.queue.unshift(...events)\n\t\t\t\t})\n\n\t\t\t\treprocess ||= queue.length > 0\n\t\t\t})\n\t\t})\n\n\t\tif (reprocess) {\n\t\t\tthis.processEventTargets()\n\t\t}\n\t}\n\n\t/**\n\t * Sends an event report. The reporter calls this method when a batch is\n\t * ready.\n\t *\n\t * @param config - The target config to send the event report to.\n\t * @param data - The encoded report lines to send in the event report.\n\t */\n\tprivate async sendEventReport(session: CmcdSession<C>, config: CmcdEventReportConfigNormalized<C>, data: string[]): Promise<void> {\n\t\tconst response = await this.requester({\n\t\t\turl: config.url,\n\t\t\tmethod: 'POST',\n\t\t\theaders: {\n\t\t\t\t'Content-Type': CMCD_MIME_TYPE,\n\t\t\t},\n\t\t\tbody: data.join('\\n'),\n\t\t})\n\n\t\tconst { status } = response\n\n\t\tif (status === 410) {\n\t\t\t// CTA-5004-B scopes 410 suppression to \"the remainder of the\n\t\t\t// current session\". The batch's own session is disposed, so a\n\t\t\t// delayed 410 that lands after a session change silences the\n\t\t\t// session that sent it, never the one that replaced it.\n\t\t\tthis.disposeEventTarget(session, config)\n\t\t} else if (status === 429 || (status > 499 && status < 600)) {\n\t\t\tthrow new Error(`Event report failed with status ${status}`)\n\t\t}\n\t}\n\n\t/**\n\t * Cancels the time-interval timer for an event target config and clears the\n\t * stored id. Safe to call when no timer is active (clearInterval(undefined)\n\t * does nothing).\n\t */\n\tprivate disarmInterval(config: CmcdEventReportConfigNormalized<C>): void {\n\t\tclearInterval(this.intervals.get(config))\n\t\tthis.intervals.delete(config)\n\t}\n\n\t/**\n\t * Silences an event target URL for the remainder of its session after the\n\t * collector signals that the target is gone (HTTP 410). The method clears\n\t * the queues and blocks further enqueues for every config in the session\n\t * that reports to the URL (the CTA-5004-B suppression scope). For the\n\t * current session, the method also cancels those configs' timers. A session\n\t * started after the disposal gets new target state and is unaffected.\n\t */\n\tprivate disposeEventTarget(session: CmcdSession<C>, config: CmcdEventReportConfigNormalized<C>): void {\n\t\tsession.eventTargets.forEach((target, sibling) => {\n\t\t\tif (sibling.url !== config.url || target.disposed) {\n\t\t\t\treturn\n\t\t\t}\n\n\t\t\ttarget.disposed = true\n\t\t\ttarget.queue.length = 0\n\n\t\t\t// The timer belongs to the live session only; an archived session's\n\t\t\t// disposal is bookkeeping and must not silence current reporting.\n\t\t\tif (session === this.session) {\n\t\t\t\tthis.disarmInterval(sibling)\n\t\t\t}\n\t\t})\n\t}\n}\n","import type { ValueOf } from '@svta/cml-utils'\n\n/**\n * Common Media Client Data Streaming Format\n *\n * @enum\n *\n * @see {@link https://cta-wave.github.io/Resources/common-media-client-data--cta-5004-b.html#streaming-format | CTA-5004-B Streaming Format}\n *\n * @public\n */\nexport const CmcdStreamingFormat = {\n\t/**\n\t * MPEG DASH\n\t */\n\tDASH: 'd',\n\n\t/**\n\t * HTTP Live Streaming (HLS)\n\t */\n\tHLS: 'h',\n\n\t/**\n\t * Smooth Streaming\n\t */\n\tSMOOTH: 's',\n\n\t/**\n\t * Other\n\t */\n\tOTHER: 'o',\n} as const\n\n/**\n * @public\n */\nexport type CmcdStreamingFormat = ValueOf<typeof CmcdStreamingFormat>;\n","import type { ValueOf } from '@svta/cml-utils'\n\n/**\n * Common Media Client Data Stream Type\n *\n * @enum\n *\n * @see {@link https://cta-wave.github.io/Resources/common-media-client-data--cta-5004-b.html#stream-type | CTA-5004-B Stream Type}\n *\n * @public\n */\nexport const CmcdStreamType = {\n\t/**\n\t * All segments are available, for example VOD\n\t */\n\tVOD: 'v',\n\n\t/**\n\t * Segments become available over time, for example LIVE\n\t */\n\tLIVE: 'l',\n\n\t/**\n\t * Low latency stream\n\t */\n\tLOW_LATENCY: 'll',\n} as const\n\n/**\n * @public\n */\nexport type CmcdStreamType = ValueOf<typeof CmcdStreamType>;\n","import type { ValueOf } from '@svta/cml-utils'\n\n/**\n * CMCD validation severity level: error.\n *\n * @public\n */\nexport const CMCD_VALIDATION_SEVERITY_ERROR = 'error' as const\n\n/**\n * CMCD validation severity level: warning.\n *\n * @public\n */\nexport const CMCD_VALIDATION_SEVERITY_WARNING = 'warning' as const\n\n/**\n * CMCD validation severity level.\n *\n * @public\n */\nexport const CmcdValidationSeverity = {\n\tERROR: CMCD_VALIDATION_SEVERITY_ERROR as typeof CMCD_VALIDATION_SEVERITY_ERROR,\n\tWARNING: CMCD_VALIDATION_SEVERITY_WARNING as typeof CMCD_VALIDATION_SEVERITY_WARNING,\n} as const\n\n/**\n * CMCD validation severity level.\n *\n * @public\n */\nexport type CmcdValidationSeverity = ValueOf<typeof CmcdValidationSeverity>;\n","/**\n * Converts a record of header fields to a `Headers` instance if necessary.\n *\n * @param headers - A `Headers` instance or a plain record of header fields.\n * @returns A `Headers` instance.\n *\n * @internal\n */\nexport function ensureHeaders(headers: Record<string, string> | Headers): Headers {\n\treturn headers instanceof Headers ? headers : new Headers(headers)\n}\n","import type { Cmcd } from './Cmcd.ts'\nimport type { CmcdData } from './CmcdData.ts'\nimport type { CmcdDecodeOptions } from './CmcdDecodeOptions.ts'\nimport { CMCD_HEADER_FIELDS } from './CmcdHeaderField.ts'\nimport { decodeCmcd } from './decodeCmcd.ts'\nimport { ensureHeaders } from './ensureHeaders.ts'\nimport { upConvertToV2 } from './upConvertToV2.ts'\n\n/**\n * Decode CMCD data from request headers.\n *\n * @param headers - The request headers to decode.\n * @param options - Options for decoding.\n *\n * @returns The decoded CMCD data.\n *\n * @see {@link https://cta-wave.github.io/Resources/common-media-client-data--cta-5004-b.html#header-field-definition | CTA-5004-B Header Field Definition}\n *\n * @public\n *\n * @example\n * {@includeCode ../test/fromCmcdHeaders.test.ts#example}\n */\nexport function fromCmcdHeaders(headers: Record<string, string> | Headers, options: CmcdDecodeOptions & { convertToLatest: true }): Cmcd\nexport function fromCmcdHeaders(headers: Record<string, string> | Headers, options?: CmcdDecodeOptions): CmcdData\nexport function fromCmcdHeaders(headers: Record<string, string> | Headers, options?: CmcdDecodeOptions): CmcdData | Cmcd {\n\tconst h = ensureHeaders(headers)\n\n\tconst result: Record<string, unknown> = {}\n\tfor (const field of CMCD_HEADER_FIELDS) {\n\t\tconst value = h.get(field)\n\t\tif (value) {\n\t\t\tObject.assign(result, decodeCmcd(value))\n\t\t}\n\t}\n\n\tif (options?.convertToLatest) {\n\t\treturn upConvertToV2(result) as Cmcd\n\t}\n\n\treturn result as CmcdData\n}\n","import { CMCD_PARAM } from './CMCD_PARAM.ts'\nimport type { Cmcd } from './Cmcd.ts'\nimport type { CmcdData } from './CmcdData.ts'\nimport type { CmcdDecodeOptions } from './CmcdDecodeOptions.ts'\nimport { decodeCmcd } from './decodeCmcd.ts'\n\n/**\n * Decode CMCD data from a query string.\n *\n * @param query - The query string to decode.\n * @param options - Options for decoding.\n *\n * @returns The decoded CMCD data.\n *\n * @see {@link https://cta-wave.github.io/Resources/common-media-client-data--cta-5004-b.html#query-argument-definition | CTA-5004-B Query Argument Definition}\n *\n * @public\n *\n * @example\n * {@includeCode ../test/fromCmcdQuery.test.ts#example}\n */\nexport function fromCmcdQuery(query: string | URLSearchParams, options: CmcdDecodeOptions & { convertToLatest: true }): Cmcd\nexport function fromCmcdQuery(query: string | URLSearchParams, options?: CmcdDecodeOptions): CmcdData\nexport function fromCmcdQuery(query: string | URLSearchParams, options?: CmcdDecodeOptions): CmcdData | Cmcd {\n\tif (typeof query === 'string') {\n\t\tquery = new URLSearchParams(query)\n\t}\n\n\tconst value = query.get(CMCD_PARAM)\n\n\treturn decodeCmcd(value ?? '', options as CmcdDecodeOptions)\n}\n","import type { Cmcd } from './Cmcd.ts'\nimport type { CmcdData } from './CmcdData.ts'\nimport type { CmcdDecodeOptions } from './CmcdDecodeOptions.ts'\nimport { decodeCmcd } from './decodeCmcd.ts'\n\n/**\n * Decode CMCD data from a URL encoded string.\n *\n * A `+` decodes as a space, as in `application/x-www-form-urlencoded`.\n * A `%2B` decodes as a `+`.\n *\n * @param url - The URL encoded string to decode.\n * @param options - Options for decoding.\n *\n * @returns The decoded CMCD data.\n *\n * @see {@link https://cta-wave.github.io/Resources/common-media-client-data--cta-5004-b.html#query-argument-definition | CTA-5004-B Query Argument Definition}\n *\n * @public\n *\n * @example\n * {@includeCode ../test/fromCmcdUrl.test.ts#example}\n */\nexport function fromCmcdUrl(url: string, options: CmcdDecodeOptions & { convertToLatest: true }): Cmcd\nexport function fromCmcdUrl(url: string, options?: CmcdDecodeOptions): CmcdData\nexport function fromCmcdUrl(url: string, options?: CmcdDecodeOptions): CmcdData | Cmcd {\n\treturn decodeCmcd(decodeURIComponent(url.replace(/^CMCD=/, '').replace(/\\+/g, ' ')), options as CmcdDecodeOptions)\n}\n","import { CMCD_REQUEST_KEYS } from './CMCD_REQUEST_KEYS.ts'\nimport type { Cmcd } from './Cmcd.ts'\nimport type { CmcdKey } from './CmcdKey.ts'\nimport { isCmcdCustomKey } from './isCmcdCustomKey.ts'\n\nconst CMCD_REQUEST_KEY_SET: ReadonlySet<string> = /* @__PURE__ */ new Set(CMCD_REQUEST_KEYS)\n\n/**\n * Check if a key is a valid CMCD request key.\n *\n * @param key - The key to check.\n *\n * @returns `true` if the key is a valid CMCD request key, `false` otherwise.\n *\n * @public\n *\n * @example\n * {@includeCode ../test/isCmcdRequestKey.test.ts#example}\n */\nexport function isCmcdRequestKey(key: string): key is keyof Cmcd {\n\treturn CMCD_REQUEST_KEY_SET.has(key) ||\n\t\tisCmcdCustomKey(key as CmcdKey)\n}\n","import { CMCD_RESPONSE_KEYS } from './CMCD_RESPONSE_KEYS.ts'\nimport type { Cmcd } from './Cmcd.ts'\n\nconst CMCD_RESPONSE_KEY_SET: ReadonlySet<string> = /* @__PURE__ */ new Set(CMCD_RESPONSE_KEYS)\n\n/**\n * Check if a key is a valid CMCD response key.\n *\n * @param key - The key to check.\n *\n * @returns `true` if the key is a valid CMCD response key, `false` otherwise.\n *\n * @public\n *\n * @example\n * {@includeCode ../test/isCmcdResponseReceivedKey.test.ts#example}\n */\nexport function isCmcdResponseReceivedKey(key: string): key is keyof Cmcd {\n\treturn CMCD_RESPONSE_KEY_SET.has(key)\n}\n","import { CMCD_EVENT_KEYS } from './CMCD_EVENT_KEYS.ts'\nimport type { Cmcd } from './Cmcd.ts'\nimport { isCmcdRequestKey } from './isCmcdRequestKey.ts'\nimport { isCmcdResponseReceivedKey } from './isCmcdResponseReceivedKey.ts'\n\nconst CMCD_EVENT_KEY_SET: ReadonlySet<string> = /* @__PURE__ */ new Set(CMCD_EVENT_KEYS)\n\n/**\n * Check if a key is a valid CMCD event key.\n *\n * @param key - The key to check.\n *\n * @returns `true` if the key is a valid CMCD event key, `false` otherwise.\n *\n * @public\n *\n * @example\n * {@includeCode ../test/isCmcdEventKey.test.ts#example}\n */\nexport function isCmcdEventKey(key: string): key is keyof Cmcd {\n\treturn isCmcdRequestKey(key) ||\n\t\tisCmcdResponseReceivedKey(key) ||\n\t\tCMCD_EVENT_KEY_SET.has(key)\n}\n","import { CMCD_V2 } from './CMCD_V2.ts'\nimport type { CmcdData } from './CmcdData.ts'\nimport type { CmcdV1Data } from './CmcdData.ts'\n\n/**\n * Check if a CMCD data object is version 1.\n *\n * @param data - The CMCD data object to check.\n *\n * @returns `true` if the data is version 1, `false` otherwise.\n *\n * @public\n *\n * @example\n * {@includeCode ../test/isCmcdV1Data.test.ts#example}\n */\nexport function isCmcdV1Data(data: CmcdData): data is CmcdV1Data {\n\treturn data.v !== CMCD_V2\n}\n","import { CMCD_V1_KEYS } from './CMCD_V1_KEYS.ts'\nimport type { CmcdKey } from './CmcdKey.ts'\nimport { isCmcdCustomKey } from './isCmcdCustomKey.ts'\n\nconst CMCD_V1_KEY_SET: ReadonlySet<string> = /* @__PURE__ */ new Set(CMCD_V1_KEYS)\n\n/**\n * Filter for CMCD version 1 keys.\n *\n * @param key - The CMCD key to filter.\n *\n * @returns `true` if the key should be included, `false` otherwise.\n *\n * @public\n *\n * @example\n * {@includeCode ../test/isCmcdV1Key.test.ts#example}\n */\nexport function isCmcdV1Key(key: string): key is CmcdKey {\n\treturn CMCD_V1_KEY_SET.has(key) || isCmcdCustomKey(key as CmcdKey)\n}\n","import { CMCD_V2 } from './CMCD_V2.ts'\nimport type { CmcdData } from './CmcdData.ts'\nimport type { CmcdV2Data } from './CmcdData.ts'\n\n/**\n * Check if a CMCD data object is version 2.\n *\n * @param data - The CMCD data object to check.\n *\n * @returns `true` if the data is version 2, `false` otherwise.\n *\n * @public\n *\n * @example\n * {@includeCode ../test/isCmcdV2Data.test.ts#example}\n */\nexport function isCmcdV2Data(data: CmcdData): data is CmcdV2Data {\n\treturn data.v === CMCD_V2\n}\n","import type { Cmcd } from './Cmcd.ts'\nimport type { CmcdEncodeOptions } from './CmcdEncodeOptions.ts'\nimport { encodeCmcd } from './encodeCmcd.ts'\nimport { percentEncode } from './percentEncode.ts'\n\n/**\n * Convert a CMCD object to a URL encoded string.\n *\n * Only letters, digits, `-`, `.`, `_`, and `~` stay unencoded, as in the\n * query examples of CTA-5004-B.\n *\n * @param cmcd - The CMCD object to convert.\n * @param options - Options for encoding.\n *\n * @returns The URL encoded CMCD data.\n *\n * @see {@link https://cta-wave.github.io/Resources/common-media-client-data--cta-5004-b.html#query-argument-definition | CTA-5004-B Query Argument Definition}\n *\n * @public\n */\nexport function toCmcdUrl(cmcd: Cmcd, options: CmcdEncodeOptions = {}): string {\n\tif (!cmcd) {\n\t\treturn ''\n\t}\n\n\tconst params = encodeCmcd(cmcd, options)\n\n\treturn percentEncode(params)\n}\n","import { CMCD_PARAM } from './CMCD_PARAM.ts'\nimport type { Cmcd } from './Cmcd.ts'\nimport type { CmcdEncodeOptions } from './CmcdEncodeOptions.ts'\nimport { toCmcdUrl } from './toCmcdUrl.ts'\n\n/**\n * Convert a CMCD object to a query arg.\n *\n * @param cmcd - The CMCD object to convert.\n * @param options - Options for encoding.\n *\n * @returns The CMCD query arg.\n *\n * @see {@link https://cta-wave.github.io/Resources/common-media-client-data--cta-5004-b.html#query-argument-definition | CTA-5004-B Query Argument Definition}\n *\n * @public\n *\n * @example\n * {@includeCode ../test/toCmcdQuery.test.ts#example}\n */\nexport function toCmcdQuery(cmcd: Cmcd, options: CmcdEncodeOptions = {}): string {\n\tif (!cmcd) {\n\t\treturn ''\n\t}\n\n\tconst value = toCmcdUrl(cmcd, options)\n\n\treturn `${CMCD_PARAM}=${value}`\n}\n","import { type SfBareItem, SfItem } from '@svta/cml-structured-field-values'\n\n/**\n * Convert a value to a CMCD value.\n *\n * @param value - The value to convert to a CMCD value.\n * @param params - The parameters of the CMCD value.\n * @returns The CMCD value.\n *\n * @public\n */\nexport function toCmcdValue<V extends SfBareItem, P>(value: V, params?: P): SfItem<V, P> {\n\treturn new SfItem(value, params)\n}\n","import type { CmcdValidationResult } from './CmcdValidationResult.ts'\nimport { CMCD_VALIDATION_SEVERITY_ERROR } from './CmcdValidationSeverity.ts'\n\n/**\n * Merges multiple validation results into a single result.\n *\n * @internal\n */\nexport function mergeValidationResults(...results: CmcdValidationResult[]): CmcdValidationResult {\n\tconst issues = results.flatMap(r => r.issues)\n\treturn {\n\t\tvalid: issues.every(i => i.severity !== CMCD_VALIDATION_SEVERITY_ERROR),\n\t\tissues,\n\t}\n}\n","import { CMCD_V1 } from './CMCD_V1.ts'\nimport type { CmcdValidationOptions } from './CmcdValidationOptions.ts'\nimport { toBareValue } from './toBareValue.ts'\n\n/**\n * Resolves the CMCD version from options, the payload's `v` key, or the default (version 1).\n *\n * @internal\n */\nexport function resolveVersion(data: Record<string, unknown>, options?: CmcdValidationOptions): number {\n\tif (options?.version === 1 || options?.version === 2) {\n\t\treturn options.version\n\t}\n\n\tconst payloadVersion = toBareValue(data['v'])\n\tif (payloadVersion === 1 || payloadVersion === 2) {\n\t\treturn payloadVersion\n\t}\n\n\treturn CMCD_V1\n}\n","import { CMCD_KEYS } from './CMCD_KEYS.ts'\nimport { CMCD_V1 } from './CMCD_V1.ts'\nimport { CMCD_V1_KEYS } from './CMCD_V1_KEYS.ts'\nimport type { CmcdKey } from './CmcdKey.ts'\nimport type { CmcdValidationOptions } from './CmcdValidationOptions.ts'\nimport type { CmcdValidationResult } from './CmcdValidationResult.ts'\nimport { CMCD_VALIDATION_SEVERITY_ERROR } from './CmcdValidationSeverity.ts'\nimport { isCmcdCustomKey } from './isCmcdCustomKey.ts'\nimport { resolveVersion } from './resolveVersion.ts'\n\nconst CMCD_V1_KEY_SET: ReadonlySet<string> = /* @__PURE__ */ new Set(CMCD_V1_KEYS)\nconst CMCD_KEY_SET: ReadonlySet<string> = /* @__PURE__ */ new Set(CMCD_KEYS)\n\n/**\n * Validates that all keys in a CMCD payload are recognized spec keys or valid custom keys.\n *\n * @example\n * {@includeCode ../test/validateCmcdKeys.test.ts#example}\n *\n * @param data - The CMCD payload to validate.\n * @param options - Validation options.\n * @returns The validation result.\n *\n * @see {@link https://cta-wave.github.io/Resources/common-media-client-data--cta-5004-b.html#reserved-keys | CTA-5004-B Reserved Keys}\n *\n * @public\n */\nexport function validateCmcdKeys(data: Record<string, unknown>, options?: CmcdValidationOptions): CmcdValidationResult {\n\tconst version = resolveVersion(data, options)\n\tconst validKeySet = version === CMCD_V1 ? CMCD_V1_KEY_SET : CMCD_KEY_SET\n\tconst issues: CmcdValidationResult['issues'] = []\n\n\tfor (const key of Object.keys(data)) {\n\t\tif (isCmcdCustomKey(key as CmcdKey)) {\n\t\t\tcontinue\n\t\t}\n\n\t\tif (!validKeySet.has(key)) {\n\t\t\tissues.push({\n\t\t\t\tkey,\n\t\t\t\tmessage: `Unknown CMCD key \"${key}\" for version ${version}.`,\n\t\t\t\tseverity: CMCD_VALIDATION_SEVERITY_ERROR,\n\t\t\t})\n\t\t}\n\t}\n\n\treturn {\n\t\tvalid: issues.length === 0,\n\t\tissues,\n\t}\n}\n","import type { CmcdKey } from './CmcdKey.ts'\n\n/**\n * Maps each aggregate bitrate key to the exact bitrate key that supersedes it.\n *\n * Per CTA-5004-B, `ab` MUST NOT be sent when the encoded bitrate `br` is\n * known. `lab` and `tab` follow the same rule for the lowest bitrate `lb`\n * and the top bitrate `tb`.\n *\n * @internal\n */\nexport const CMCD_AGGREGATE_BITRATE_KEYS: Record<string, CmcdKey> = {\n\tab: 'br',\n\tlab: 'lb',\n\ttab: 'tb',\n}\n","/**\n * Maps a key to the object types (`ot`) for which CTA-5004-B allows the key.\n *\n * A key that is absent from this map is allowed for every object type.\n * `d` (Object duration) and `tpb` (Top playable bitrate) MUST NOT be sent for\n * other object types.\n *\n * @internal\n */\nexport const CMCD_KEY_OBJECT_TYPES: Record<string, readonly string[]> = {\n\td: ['a', 'v', 'av', 'tt', 'c', 'o'] as const,\n\ttpb: ['a', 'v', 'av', 'c'] as const,\n}\n","import { CMCD_AGGREGATE_BITRATE_KEYS } from './CMCD_AGGREGATE_BITRATE_KEYS.ts'\nimport { CMCD_EVENT_KEYS } from './CMCD_EVENT_KEYS.ts'\nimport { CMCD_KEY_OBJECT_TYPES } from './CMCD_KEY_OBJECT_TYPES.ts'\nimport { CMCD_RESPONSE_KEYS } from './CMCD_RESPONSE_KEYS.ts'\nimport { CMCD_V1 } from './CMCD_V1.ts'\nimport { CMCD_EVENT_CUSTOM_EVENT, CMCD_EVENT_ERROR, CMCD_EVENT_PLAY_STATE, CMCD_EVENT_RESPONSE_RECEIVED } from './CmcdEventType.ts'\nimport { CMCD_EVENT_MODE, CMCD_REQUEST_MODE } from './CmcdReportingMode.ts'\nimport type { CmcdValidationIssue } from './CmcdValidationIssue.ts'\nimport type { CmcdValidationOptions } from './CmcdValidationOptions.ts'\nimport type { CmcdValidationResult } from './CmcdValidationResult.ts'\nimport { CMCD_VALIDATION_SEVERITY_ERROR, CMCD_VALIDATION_SEVERITY_WARNING } from './CmcdValidationSeverity.ts'\nimport { resolveVersion } from './resolveVersion.ts'\nimport { toBareValue } from './toBareValue.ts'\nimport { toTokenString } from './toTokenString.ts'\n\n/**\n * Validates the structural rules of a CMCD payload.\n *\n * @example\n * {@includeCode ../test/validateCmcdStructure.test.ts#example}\n *\n * @param data - The CMCD payload to validate.\n * @param options - Validation options.\n * @returns The validation result.\n *\n * @see {@link https://cta-wave.github.io/Resources/common-media-client-data--cta-5004-b.html#data-payload-definition-what-data-to-send | CTA-5004-B Data Payload Definition}\n *\n * @public\n */\nexport function validateCmcdStructure(data: Record<string, unknown>, options?: CmcdValidationOptions): CmcdValidationResult {\n\tconst version = resolveVersion(data, options)\n\tconst issues: CmcdValidationIssue[] = []\n\n\t// Request mode checks\n\tif (options?.reportingMode === CMCD_REQUEST_MODE) {\n\t\tfor (const key of CMCD_EVENT_KEYS) {\n\t\t\tif (key in data) {\n\t\t\t\tissues.push({\n\t\t\t\t\tkey,\n\t\t\t\t\tmessage: `Event key \"${key}\" must not be present in request mode.`,\n\t\t\t\t\tseverity: CMCD_VALIDATION_SEVERITY_ERROR\n\t\t\t\t})\n\t\t\t}\n\t\t}\n\t\tfor (const key of CMCD_RESPONSE_KEYS) {\n\t\t\tif (key in data) {\n\t\t\t\tissues.push({\n\t\t\t\t\tkey,\n\t\t\t\t\tmessage: `Response key \"${key}\" must not be present in request mode.`,\n\t\t\t\t\tseverity: CMCD_VALIDATION_SEVERITY_ERROR\n\t\t\t\t})\n\t\t\t}\n\t\t}\n\t}\n\n\t// Event mode checks\n\tif (options?.reportingMode === CMCD_EVENT_MODE) {\n\t\tif (!('e' in data)) {\n\t\t\tissues.push({\n\t\t\t\tkey: 'e',\n\t\t\t\tmessage: 'Event mode requires the \"e\" key to be present.',\n\t\t\t\tseverity: CMCD_VALIDATION_SEVERITY_ERROR\n\t\t\t})\n\t\t}\n\t\tif (!('ts' in data)) {\n\t\t\tissues.push({\n\t\t\t\tkey: 'ts',\n\t\t\t\tmessage: 'Event mode requires the \"ts\" key to be present.',\n\t\t\t\tseverity: CMCD_VALIDATION_SEVERITY_ERROR\n\t\t\t})\n\t\t}\n\t}\n\n\t// Custom event checks\n\tif ('e' in data) {\n\t\tconst eventType = toTokenString(data['e'])\n\n\t\tif (eventType === CMCD_EVENT_CUSTOM_EVENT) {\n\t\t\tif (!('cen' in data)) {\n\t\t\t\tissues.push({\n\t\t\t\t\tkey: 'cen',\n\t\t\t\t\tmessage: 'Custom event (e=\"ce\") requires the \"cen\" key to be present.',\n\t\t\t\t\tseverity: CMCD_VALIDATION_SEVERITY_ERROR\n\t\t\t\t})\n\t\t\t}\n\t\t}\n\t\telse {\n\t\t\tif ('cen' in data) {\n\t\t\t\tissues.push({\n\t\t\t\t\tkey: 'cen',\n\t\t\t\t\tmessage: 'The \"cen\" key must only be present when e=\"ce\".',\n\t\t\t\t\tseverity: CMCD_VALIDATION_SEVERITY_ERROR\n\t\t\t\t})\n\t\t\t}\n\t\t}\n\n\t\t// Response-received key restriction and required url\n\t\tif (eventType === CMCD_EVENT_RESPONSE_RECEIVED) {\n\t\t\tif (!('url' in data)) {\n\t\t\t\tissues.push({\n\t\t\t\t\tkey: 'url',\n\t\t\t\t\tmessage: 'Response received event (e=\"rr\") requires the \"url\" key to be present.',\n\t\t\t\t\tseverity: CMCD_VALIDATION_SEVERITY_ERROR\n\t\t\t\t})\n\t\t\t}\n\t\t}\n\t\telse {\n\t\t\tfor (const key of CMCD_RESPONSE_KEYS) {\n\t\t\t\tif (key in data) {\n\t\t\t\t\tissues.push({\n\t\t\t\t\t\tkey,\n\t\t\t\t\t\tmessage: `Response key \"${key}\" must only be present when e=\"rr\".`,\n\t\t\t\t\t\tseverity: CMCD_VALIDATION_SEVERITY_ERROR\n\t\t\t\t\t})\n\t\t\t\t}\n\t\t\t}\n\t\t}\n\n\t\t// Play state change event requires sta\n\t\tif (eventType === CMCD_EVENT_PLAY_STATE && !('sta' in data)) {\n\t\t\tissues.push({\n\t\t\t\tkey: 'sta',\n\t\t\t\tmessage: 'Play state change event (e=\"ps\") requires the \"sta\" key to be present.',\n\t\t\t\tseverity: CMCD_VALIDATION_SEVERITY_ERROR\n\t\t\t})\n\t\t}\n\n\t\t// Error event requires ec\n\t\tif (eventType === CMCD_EVENT_ERROR && !('ec' in data)) {\n\t\t\tissues.push({\n\t\t\t\tkey: 'ec',\n\t\t\t\tmessage: 'Error event (e=\"e\") requires the \"ec\" key to be present.',\n\t\t\t\tseverity: CMCD_VALIDATION_SEVERITY_ERROR\n\t\t\t})\n\t\t}\n\t}\n\n\t// Object type checks\n\tconst ot = version > 1 ? toTokenString(data['ot']) : undefined\n\tif (ot !== undefined) {\n\t\tfor (const key in CMCD_KEY_OBJECT_TYPES) {\n\t\t\tconst objectTypes = CMCD_KEY_OBJECT_TYPES[key]\n\t\t\tif (key in data && !objectTypes.includes(ot)) {\n\t\t\t\tissues.push({\n\t\t\t\t\tkey,\n\t\t\t\t\tmessage: `Key \"${key}\" must not be present when \"ot\" is \"${ot}\". Expected \"ot\" to be one of: ${objectTypes.join(', ')}.`,\n\t\t\t\t\tseverity: CMCD_VALIDATION_SEVERITY_ERROR\n\t\t\t\t})\n\t\t\t}\n\t\t}\n\t}\n\n\t// Aggregate bitrate checks\n\tif (version > 1) {\n\t\tfor (const key in CMCD_AGGREGATE_BITRATE_KEYS) {\n\t\t\tconst exactKey = CMCD_AGGREGATE_BITRATE_KEYS[key]\n\t\t\tif (key in data && exactKey in data) {\n\t\t\t\tissues.push({\n\t\t\t\t\tkey,\n\t\t\t\t\tmessage: `Key \"${key}\" must not be present when \"${exactKey}\" is present.`,\n\t\t\t\t\tseverity: CMCD_VALIDATION_SEVERITY_ERROR\n\t\t\t\t})\n\t\t\t}\n\t\t}\n\t}\n\n\t// Version key checks\n\tconst v = toBareValue(data['v'])\n\tif ('v' in data && v !== 1 && v !== 2) {\n\t\tissues.push({\n\t\t\tkey: 'v',\n\t\t\tmessage: `Unsupported CMCD version \"${String(v)}\". Expected 1 or 2.`,\n\t\t\tseverity: CMCD_VALIDATION_SEVERITY_ERROR\n\t\t})\n\t}\n\telse if (version > 1 && !('v' in data)) {\n\t\tissues.push({\n\t\t\tkey: 'v',\n\t\t\tmessage: 'Version 2 payloads require the \"v\" key to be present.',\n\t\t\tseverity: CMCD_VALIDATION_SEVERITY_ERROR\n\t\t})\n\t}\n\telse if (version === CMCD_V1 && 'v' in data) {\n\t\tissues.push({\n\t\t\tkey: 'v',\n\t\t\tmessage: 'Version 1 payloads should omit the \"v\" key (v1 is the default).',\n\t\t\tseverity: CMCD_VALIDATION_SEVERITY_WARNING\n\t\t})\n\t}\n\n\treturn {\n\t\tvalid: issues.every(i => i.severity !== CMCD_VALIDATION_SEVERITY_ERROR),\n\t\tissues,\n\t}\n}\n","/**\n * CMCD key value type: inner list of integers with token identifiers.\n *\n * @internal\n */\nexport const CMCD_KEY_TYPE_NUMBER_LIST = 'number[]' as const\n\n/**\n * CMCD key value type: inner list of strings.\n *\n * @internal\n */\nexport const CMCD_KEY_TYPE_STRING_LIST = 'string[]' as const\n\n/**\n * CMCD key value type: integer.\n *\n * @internal\n */\nexport const CMCD_KEY_TYPE_INTEGER = 'integer' as const\n\n/**\n * CMCD key value type: number (decimal).\n *\n * @internal\n */\nexport const CMCD_KEY_TYPE_NUMBER = 'number' as const\n\n/**\n * CMCD key value type: boolean.\n *\n * @internal\n */\nexport const CMCD_KEY_TYPE_BOOLEAN = 'boolean' as const\n\n/**\n * CMCD key value type: string.\n *\n * @internal\n */\nexport const CMCD_KEY_TYPE_STRING = 'string' as const\n\n/**\n * CMCD key value type: token.\n *\n * @internal\n */\nexport const CMCD_KEY_TYPE_TOKEN = 'token' as const\n\n/**\n * Maps each CMCD key to its value type for version 2.\n * CMCD_V1_KEY_TYPE_OVERRIDES handles the keys that differ between version 1 and version 2.\n *\n * @internal\n */\nexport const CMCD_KEY_TYPES: Record<string, string> = {\n\t// List keys (inner list of integers with token identifiers)\n\tab: CMCD_KEY_TYPE_NUMBER_LIST,\n\tbl: CMCD_KEY_TYPE_NUMBER_LIST,\n\tbr: CMCD_KEY_TYPE_NUMBER_LIST,\n\tbsa: CMCD_KEY_TYPE_NUMBER_LIST,\n\tbsd: CMCD_KEY_TYPE_NUMBER_LIST,\n\tbsda: CMCD_KEY_TYPE_NUMBER_LIST,\n\tlab: CMCD_KEY_TYPE_NUMBER_LIST,\n\tlb: CMCD_KEY_TYPE_NUMBER_LIST,\n\tmtp: CMCD_KEY_TYPE_NUMBER_LIST,\n\tpb: CMCD_KEY_TYPE_NUMBER_LIST,\n\ttab: CMCD_KEY_TYPE_NUMBER_LIST,\n\ttb: CMCD_KEY_TYPE_NUMBER_LIST,\n\ttbl: CMCD_KEY_TYPE_NUMBER_LIST,\n\ttpb: CMCD_KEY_TYPE_NUMBER_LIST,\n\n\t// String array keys (inner list of strings)\n\tec: CMCD_KEY_TYPE_STRING_LIST,\n\tnor: CMCD_KEY_TYPE_STRING_LIST,\n\n\t// Integer keys\n\td: CMCD_KEY_TYPE_INTEGER,\n\tdfa: CMCD_KEY_TYPE_INTEGER,\n\tdl: CMCD_KEY_TYPE_INTEGER,\n\tltc: CMCD_KEY_TYPE_INTEGER,\n\tmsd: CMCD_KEY_TYPE_INTEGER,\n\tpt: CMCD_KEY_TYPE_INTEGER,\n\trc: CMCD_KEY_TYPE_INTEGER,\n\trtp: CMCD_KEY_TYPE_INTEGER,\n\tsn: CMCD_KEY_TYPE_INTEGER,\n\tts: CMCD_KEY_TYPE_INTEGER,\n\tttfb: CMCD_KEY_TYPE_INTEGER,\n\tttfbb: CMCD_KEY_TYPE_INTEGER,\n\tttlb: CMCD_KEY_TYPE_INTEGER,\n\tv: CMCD_KEY_TYPE_INTEGER,\n\n\t// Number keys\n\tpr: CMCD_KEY_TYPE_NUMBER,\n\n\t// Boolean keys\n\tbg: CMCD_KEY_TYPE_BOOLEAN,\n\tbs: CMCD_KEY_TYPE_BOOLEAN,\n\tnr: CMCD_KEY_TYPE_BOOLEAN,\n\tsu: CMCD_KEY_TYPE_BOOLEAN,\n\n\t// String keys\n\tcdn: CMCD_KEY_TYPE_STRING,\n\tcen: CMCD_KEY_TYPE_STRING,\n\tcid: CMCD_KEY_TYPE_STRING,\n\tcmsdd: CMCD_KEY_TYPE_STRING,\n\tcmsds: CMCD_KEY_TYPE_STRING,\n\tcs: CMCD_KEY_TYPE_STRING,\n\th: CMCD_KEY_TYPE_STRING,\n\tnrr: CMCD_KEY_TYPE_STRING,\n\tsid: CMCD_KEY_TYPE_STRING,\n\tsmrt: CMCD_KEY_TYPE_STRING,\n\turl: CMCD_KEY_TYPE_STRING,\n\n\t// Token keys\n\te: CMCD_KEY_TYPE_TOKEN,\n\tot: CMCD_KEY_TYPE_TOKEN,\n\tsf: CMCD_KEY_TYPE_TOKEN,\n\tst: CMCD_KEY_TYPE_TOKEN,\n\tsta: CMCD_KEY_TYPE_TOKEN,\n}\n\n/**\n * Version 1 types of the keys that differ from version 2.\n *\n * @internal\n */\nexport const CMCD_V1_KEY_TYPE_OVERRIDES: Record<string, string> = {\n\tbl: CMCD_KEY_TYPE_INTEGER,\n\tbr: CMCD_KEY_TYPE_INTEGER,\n\tmtp: CMCD_KEY_TYPE_INTEGER,\n\ttb: CMCD_KEY_TYPE_INTEGER,\n\tnor: CMCD_KEY_TYPE_STRING,\n}\n","/**\n * Maps CMCD keys to their maximum string length.\n *\n * @internal\n */\nexport const CMCD_STRING_LENGTH_LIMITS: Record<string, number> = {\n\tsid: 64,\n\tcid: 128,\n\tcdn: 128,\n\th: 128,\n\tcen: 64,\n}\n\n/**\n * Maximum length for custom key values.\n *\n * @internal\n */\nexport const CMCD_CUSTOM_KEY_VALUE_MAX_LENGTH = 64\n","/**\n * Maps token keys to their valid values.\n *\n * @internal\n */\nexport const CMCD_TOKEN_VALUES: Record<string, readonly string[]> = {\n\te: ['bc', 'ps', 'pr', 'e', 't', 'c', 'b', 'm', 'um', 'pe', 'pc', 'rr', 'as', 'ae', 'abs', 'abe', 'sk', 'ce'] as const,\n\tot: ['m', 'a', 'v', 'av', 'i', 'c', 'tt', 'k', 'o'] as const,\n\tsf: ['d', 'h', 's', 'o'] as const,\n\tst: ['v', 'l', 'll'] as const,\n\tsta: ['s', 'p', 'k', 'r', 'a', 'w', 'e', 'f', 'q', 'd'] as const,\n}\n","import { CMCD_KEY_TYPE_BOOLEAN, CMCD_KEY_TYPE_INTEGER, CMCD_KEY_TYPE_NUMBER, CMCD_KEY_TYPE_NUMBER_LIST, CMCD_KEY_TYPE_STRING, CMCD_KEY_TYPE_STRING_LIST, CMCD_KEY_TYPE_TOKEN, CMCD_KEY_TYPES, CMCD_V1_KEY_TYPE_OVERRIDES } from './CMCD_KEY_TYPES.ts'\nimport { CMCD_CUSTOM_KEY_VALUE_MAX_LENGTH, CMCD_STRING_LENGTH_LIMITS } from './CMCD_STRING_LENGTH_LIMITS.ts'\nimport { CMCD_TOKEN_VALUES } from './CMCD_TOKEN_VALUES.ts'\nimport { CMCD_V1 } from './CMCD_V1.ts'\nimport type { CmcdKey } from './CmcdKey.ts'\nimport type { CmcdValidationIssue } from './CmcdValidationIssue.ts'\nimport type { CmcdValidationOptions } from './CmcdValidationOptions.ts'\nimport type { CmcdValidationResult } from './CmcdValidationResult.ts'\nimport { CMCD_VALIDATION_SEVERITY_ERROR, CMCD_VALIDATION_SEVERITY_WARNING } from './CmcdValidationSeverity.ts'\nimport { isCmcdCustomKey } from './isCmcdCustomKey.ts'\nimport { resolveVersion } from './resolveVersion.ts'\nimport { toBareValue } from './toBareValue.ts'\nimport { toTokenString } from './toTokenString.ts'\n\nconst HUNDRED_ROUNDING_UNITS: Record<string, string> = {\n\tbl: 'ms',\n\tdl: 'ms',\n\tmtp: 'kbps',\n\trtp: 'kbps',\n\ttbl: 'ms',\n}\n\nfunction isFiniteNumber(value: unknown): value is number {\n\treturn typeof value === 'number' && Number.isFinite(value)\n}\n\nfunction isInteger(value: unknown): value is number {\n\treturn Number.isInteger(value)\n}\n\n// CTA-5004 Table 1 states every rounding rule with MUST. CTA-5004-B Table 1 uses SHOULD for bl and tbl.\nfunction validateRounding(key: string, value: number, version: number, issues: CmcdValidationIssue[], index?: number): void {\n\tconst unit = HUNDRED_ROUNDING_UNITS[key]\n\tif (!unit || value % 100 === 0) {\n\t\treturn\n\t}\n\tconst should = key === 'tbl' || (key === 'bl' && version !== CMCD_V1)\n\tconst target = index === undefined ? `Key \"${key}\"` : `Key \"${key}\" array element [${index}]`\n\tissues.push({\n\t\tkey,\n\t\tmessage: `${target} ${should ? 'should' : 'must'} be rounded to the nearest 100 ${unit}. Received ${value}.`,\n\t\tseverity: should ? CMCD_VALIDATION_SEVERITY_WARNING : CMCD_VALIDATION_SEVERITY_ERROR\n\t})\n}\n\nfunction validateListValue(key: string, value: unknown, version: number, issues: CmcdValidationIssue[]): void {\n\tif (!Array.isArray(value)) {\n\t\tissues.push({\n\t\t\tkey,\n\t\t\tmessage: `Key \"${key}\" must be an array.`,\n\t\t\tseverity: CMCD_VALIDATION_SEVERITY_ERROR\n\t\t})\n\t\treturn\n\t}\n\tfor (let i = 0; i < value.length; i++) {\n\t\tconst element = toBareValue(value[i])\n\t\tif (!isInteger(element)) {\n\t\t\tissues.push({\n\t\t\t\tkey,\n\t\t\t\tmessage: `Key \"${key}\" array element [${i}] must be a finite integer.`,\n\t\t\t\tseverity: CMCD_VALIDATION_SEVERITY_ERROR\n\t\t\t})\n\t\t}\n\t\telse {\n\t\t\tvalidateRounding(key, element, version, issues, i)\n\t\t}\n\t}\n}\n\nfunction validateStringArrayValue(key: string, value: unknown, issues: CmcdValidationIssue[]): void {\n\tif (!Array.isArray(value)) {\n\t\tissues.push({\n\t\t\tkey,\n\t\t\tmessage: `Key \"${key}\" must be an array.`,\n\t\t\tseverity: CMCD_VALIDATION_SEVERITY_ERROR\n\t\t})\n\t\treturn\n\t}\n\tfor (let i = 0; i < value.length; i++) {\n\t\tif (typeof toBareValue(value[i]) !== 'string') {\n\t\t\tissues.push({\n\t\t\t\tkey,\n\t\t\t\tmessage: `Key \"${key}\" array element [${i}] must be a string.`,\n\t\t\t\tseverity: CMCD_VALIDATION_SEVERITY_ERROR\n\t\t\t})\n\t\t}\n\t}\n}\n\n/**\n * Validates that all values in a CMCD payload conform to the expected types and constraints.\n *\n * @example\n * {@includeCode ../test/validateCmcdValues.test.ts#example}\n *\n * @param data - The CMCD payload to validate.\n * @param options - Validation options.\n * @returns The validation result.\n *\n * @see {@link https://cta-wave.github.io/Resources/common-media-client-data--cta-5004-b.html#reserved-keys | CTA-5004-B Reserved Keys}\n *\n * @public\n */\nexport function validateCmcdValues(data: Record<string, unknown>, options?: CmcdValidationOptions): CmcdValidationResult {\n\tconst version = resolveVersion(data, options)\n\tconst issues: CmcdValidationIssue[] = []\n\n\tfor (const [key, entry] of Object.entries(data)) {\n\t\tconst value = toBareValue(entry)\n\t\tif (isCmcdCustomKey(key as CmcdKey)) {\n\t\t\t// Custom key values must be string or token, max 64 chars\n\t\t\tif (typeof value !== 'string') {\n\t\t\t\tissues.push({\n\t\t\t\t\tkey,\n\t\t\t\t\tmessage: `Custom key \"${key}\" value must be a string or token.`,\n\t\t\t\t\tseverity: CMCD_VALIDATION_SEVERITY_ERROR\n\t\t\t\t})\n\t\t\t}\n\t\t\telse if (value.length > CMCD_CUSTOM_KEY_VALUE_MAX_LENGTH) {\n\t\t\t\tissues.push({\n\t\t\t\t\tkey,\n\t\t\t\t\tmessage: `Custom key \"${key}\" value exceeds maximum length of ${CMCD_CUSTOM_KEY_VALUE_MAX_LENGTH}.`,\n\t\t\t\t\tseverity: CMCD_VALIDATION_SEVERITY_ERROR\n\t\t\t\t})\n\t\t\t}\n\t\t\tcontinue\n\t\t}\n\n\t\t// Version value check\n\t\tif (key === 'v') {\n\t\t\tif (value !== 1 && value !== 2) {\n\t\t\t\tissues.push({\n\t\t\t\t\tkey,\n\t\t\t\t\tmessage: `Key \"v\" must be 1 or 2.`,\n\t\t\t\t\tseverity: CMCD_VALIDATION_SEVERITY_ERROR\n\t\t\t\t})\n\t\t\t}\n\t\t\tcontinue\n\t\t}\n\n\t\t// Determine expected type\n\t\tlet expectedType = CMCD_KEY_TYPES[key]\n\t\tif (!expectedType) {\n\t\t\tcontinue\n\t\t}\n\n\t\tif (version === CMCD_V1 && key in CMCD_V1_KEY_TYPE_OVERRIDES) {\n\t\t\texpectedType = CMCD_V1_KEY_TYPE_OVERRIDES[key]\n\t\t}\n\n\t\tswitch (expectedType) {\n\t\t\tcase CMCD_KEY_TYPE_INTEGER:\n\t\t\t\tif (!isInteger(value)) {\n\t\t\t\t\tissues.push({\n\t\t\t\t\t\tkey,\n\t\t\t\t\t\tmessage: `Key \"${key}\" must be a finite integer.`,\n\t\t\t\t\t\tseverity: CMCD_VALIDATION_SEVERITY_ERROR\n\t\t\t\t\t})\n\t\t\t\t}\n\t\t\t\telse {\n\t\t\t\t\tvalidateRounding(key, value, version, issues)\n\t\t\t\t}\n\t\t\t\tbreak\n\n\t\t\tcase CMCD_KEY_TYPE_NUMBER:\n\t\t\t\tif (!isFiniteNumber(value)) {\n\t\t\t\t\tissues.push({\n\t\t\t\t\t\tkey,\n\t\t\t\t\t\tmessage: `Key \"${key}\" must be a finite number.`,\n\t\t\t\t\t\tseverity: CMCD_VALIDATION_SEVERITY_ERROR\n\t\t\t\t\t})\n\t\t\t\t}\n\t\t\t\tbreak\n\n\t\t\tcase CMCD_KEY_TYPE_BOOLEAN:\n\t\t\t\tif (typeof value !== 'boolean') {\n\t\t\t\t\tissues.push({\n\t\t\t\t\t\tkey,\n\t\t\t\t\t\tmessage: `Key \"${key}\" must be a boolean.`,\n\t\t\t\t\t\tseverity: CMCD_VALIDATION_SEVERITY_ERROR\n\t\t\t\t\t})\n\t\t\t\t}\n\t\t\t\tbreak\n\n\t\t\tcase CMCD_KEY_TYPE_STRING:\n\t\t\t\tif (typeof value !== 'string') {\n\t\t\t\t\tissues.push({\n\t\t\t\t\t\tkey,\n\t\t\t\t\t\tmessage: `Key \"${key}\" must be a string.`,\n\t\t\t\t\t\tseverity: CMCD_VALIDATION_SEVERITY_ERROR\n\t\t\t\t\t})\n\t\t\t\t}\n\t\t\t\telse if (key in CMCD_STRING_LENGTH_LIMITS && value.length > CMCD_STRING_LENGTH_LIMITS[key]) {\n\t\t\t\t\tissues.push({\n\t\t\t\t\t\tkey,\n\t\t\t\t\t\tmessage: `Key \"${key}\" exceeds maximum length of ${CMCD_STRING_LENGTH_LIMITS[key]}.`,\n\t\t\t\t\t\tseverity: CMCD_VALIDATION_SEVERITY_ERROR\n\t\t\t\t\t})\n\t\t\t\t}\n\t\t\t\tbreak\n\n\t\t\tcase CMCD_KEY_TYPE_TOKEN: {\n\t\t\t\tconst validValues = CMCD_TOKEN_VALUES[key]\n\t\t\t\tconst token = toTokenString(value)\n\t\t\t\tif (validValues && (token === undefined || !validValues.includes(token))) {\n\t\t\t\t\tissues.push({\n\t\t\t\t\t\tkey,\n\t\t\t\t\t\tmessage: `Key \"${key}\" has invalid token value \"${token ?? String(value)}\". Expected one of: ${validValues.join(', ')}.`,\n\t\t\t\t\t\tseverity: CMCD_VALIDATION_SEVERITY_ERROR\n\t\t\t\t\t})\n\t\t\t\t}\n\t\t\t\tbreak\n\t\t\t}\n\n\t\t\tcase CMCD_KEY_TYPE_NUMBER_LIST:\n\t\t\t\tvalidateListValue(key, value, version, issues)\n\t\t\t\tbreak\n\n\t\t\tcase CMCD_KEY_TYPE_STRING_LIST:\n\t\t\t\tvalidateStringArrayValue(key, value, issues)\n\t\t\t\tbreak\n\t\t}\n\t}\n\n\treturn {\n\t\tvalid: issues.every(i => i.severity !== CMCD_VALIDATION_SEVERITY_ERROR),\n\t\tissues,\n\t}\n}\n","import type { CmcdValidationOptions } from './CmcdValidationOptions.ts'\nimport type { CmcdValidationResult } from './CmcdValidationResult.ts'\nimport { mergeValidationResults } from './mergeValidationResults.ts'\nimport { validateCmcdKeys } from './validateCmcdKeys.ts'\nimport { validateCmcdStructure } from './validateCmcdStructure.ts'\nimport { validateCmcdValues } from './validateCmcdValues.ts'\n\n/**\n * Validates a CMCD payload by checking keys, values, and structure.\n *\n * @example\n * {@includeCode ../test/validateCmcd.test.ts#example}\n *\n * @param data - The CMCD payload to validate.\n * @param options - Validation options.\n * @returns The validation result.\n *\n * @see {@link https://cta-wave.github.io/Resources/common-media-client-data--cta-5004-b.html#data-payload-definition-what-data-to-send | CTA-5004-B Data Payload Definition}\n *\n * @public\n */\nexport function validateCmcd(data: Record<string, unknown>, options?: CmcdValidationOptions): CmcdValidationResult {\n\treturn mergeValidationResults(\n\t\tvalidateCmcdKeys(data, options),\n\t\tvalidateCmcdValues(data, options),\n\t\tvalidateCmcdStructure(data, options),\n\t)\n}\n","import type { CmcdData } from './CmcdData.ts'\nimport type { CmcdEventsValidationResult } from './CmcdEventsValidationResult.ts'\nimport { CMCD_EVENT_MODE } from './CmcdReportingMode.ts'\nimport type { CmcdValidationOptions } from './CmcdValidationOptions.ts'\nimport type { CmcdValidationResult } from './CmcdValidationResult.ts'\nimport type { CmcdValidationIssue } from './CmcdValidationIssue.ts'\nimport { CMCD_VALIDATION_SEVERITY_ERROR } from './CmcdValidationSeverity.ts'\nimport { decodeCmcd } from './decodeCmcd.ts'\nimport { mergeValidationResults } from './mergeValidationResults.ts'\nimport { validateCmcd } from './validateCmcd.ts'\n\n/**\n * Validates a raw CMCD string as an event-mode payload.\n *\n * This function decodes the string internally and validates it with\n * `reportingMode` set to `'event'`. The input may contain multiple\n * newline-separated events, for example an `application/cmcd` POST body.\n * The function validates each line independently and merges the results.\n *\n * @param cmcd - The raw CMCD-encoded string to validate. May contain\n * multiple newline-separated event lines.\n * @param options - Validation options (excluding `reportingMode`).\n * @returns The validation result including decoded data per event line.\n *\n * @example\n * {@includeCode ../test/validateCmcdEvents.test.ts#example}\n *\n * @see {@link https://cta-wave.github.io/Resources/common-media-client-data--cta-5004-b.html#body-definition | CTA-5004-B Body Definition}\n *\n * @public\n */\nexport function validateCmcdEvents(cmcd: string, options?: Omit<CmcdValidationOptions, 'reportingMode'>): CmcdEventsValidationResult {\n\tconst opts = { ...options, reportingMode: CMCD_EVENT_MODE } as const\n\tconst lines = cmcd.split(/\\r?\\n/).filter(line => line.length > 0)\n\n\tif (lines.length === 0) {\n\t\treturn {\n\t\t\tvalid: false,\n\t\t\tissues: [{\n\t\t\t\tmessage: 'Empty event mode payload. At least one event line is required.',\n\t\t\t\tseverity: CMCD_VALIDATION_SEVERITY_ERROR,\n\t\t\t}],\n\t\t\tdata: [],\n\t\t}\n\t}\n\n\tconst bodyIssues: CmcdValidationIssue[] = []\n\tif (cmcd.endsWith('\\n')) {\n\t\tbodyIssues.push({\n\t\t\tmessage: 'Event report body must not end with a line feed.',\n\t\t\tseverity: CMCD_VALIDATION_SEVERITY_ERROR,\n\t\t})\n\t}\n\n\tconst decodedLines: CmcdData[] = []\n\tconst lineResults: CmcdValidationResult[] = []\n\n\tfor (let i = 0; i < lines.length; i++) {\n\t\ttry {\n\t\t\tconst data = decodeCmcd(lines[i])\n\t\t\tdecodedLines.push(data)\n\t\t\tlineResults.push(validateCmcd(data, opts))\n\t\t} catch {\n\t\t\tdecodedLines.push({} as CmcdData)\n\t\t\tlineResults.push({\n\t\t\t\tvalid: false,\n\t\t\t\tissues: [{\n\t\t\t\t\tmessage: `Failed to decode event line ${i + 1}: invalid structured field syntax.`,\n\t\t\t\t\tseverity: CMCD_VALIDATION_SEVERITY_ERROR,\n\t\t\t\t}],\n\t\t\t})\n\t\t}\n\t}\n\n\tconst result = mergeValidationResults({ valid: true, issues: bodyIssues }, ...lineResults)\n\treturn { ...result, data: decodedLines }\n}\n","import type { HttpRequest } from '@svta/cml-utils'\nimport { CMCD_MIME_TYPE } from './CMCD_MIME_TYPE.ts'\nimport type { CmcdEventsValidationResult } from './CmcdEventsValidationResult.ts'\nimport type { CmcdValidationOptions } from './CmcdValidationOptions.ts'\nimport { CMCD_VALIDATION_SEVERITY_ERROR } from './CmcdValidationSeverity.ts'\nimport { ensureHeaders } from './ensureHeaders.ts'\nimport { validateCmcdEvents } from './validateCmcdEvents.ts'\n\n/**\n * Validates a full HTTP request as an event-mode payload.\n *\n * Accepts an {@link @svta/cml-utils!HttpRequest | HttpRequest} object.\n *\n * This function validates that the request uses the POST method and has\n * the correct `Content-Type` header (`application/cmcd`). It also\n * validates the body content with {@link validateCmcdEvents}.\n *\n * @param request - An `HttpRequest` to validate.\n * @param options - Validation options (excluding `reportingMode`).\n * @returns The validation result including decoded data per event line.\n *\n * @example {@includeCode ../test/validateCmcdEventReport.test.ts#example}\n *\n * @see {@link https://cta-wave.github.io/Resources/common-media-client-data--cta-5004-b.html#event-mode | CTA-5004-B Event Mode}\n *\n * @public\n */\nexport function validateCmcdEventReport(request: HttpRequest, options?: Omit<CmcdValidationOptions, 'reportingMode'>): CmcdEventsValidationResult {\n\tconst issues: CmcdEventsValidationResult['issues'] = []\n\n\tif (request.method !== 'POST') {\n\t\tissues.push({\n\t\t\tmessage: `Invalid HTTP method '${request.method ?? 'GET'}'. Event reports must use POST.`,\n\t\t\tseverity: CMCD_VALIDATION_SEVERITY_ERROR,\n\t\t})\n\t}\n\n\tconst contentType = request.headers ? ensureHeaders(request.headers).get('Content-Type') : undefined\n\n\tif (!contentType) {\n\t\tissues.push({\n\t\t\tmessage: `Missing Content-Type header. Event reports must use '${CMCD_MIME_TYPE}'.`,\n\t\t\tseverity: CMCD_VALIDATION_SEVERITY_ERROR,\n\t\t})\n\t} else {\n\t\tconst mediaType = contentType.split(';')[0].trim().toLowerCase()\n\t\tif (mediaType !== CMCD_MIME_TYPE) {\n\t\t\tissues.push({\n\t\t\t\tmessage: `Invalid Content-Type '${mediaType}'. Event reports must use '${CMCD_MIME_TYPE}'.`,\n\t\t\t\tseverity: CMCD_VALIDATION_SEVERITY_ERROR,\n\t\t\t})\n\t\t}\n\t}\n\n\tconst body = request.body\n\tif (body === undefined || body === null) {\n\t\tissues.push({\n\t\t\tmessage: 'Missing request body. Event reports must include a body.',\n\t\t\tseverity: CMCD_VALIDATION_SEVERITY_ERROR,\n\t\t})\n\t\treturn {\n\t\t\tvalid: false,\n\t\t\tissues,\n\t\t\tdata: [],\n\t\t}\n\t}\n\n\tif (typeof body !== 'string') {\n\t\tissues.push({\n\t\t\tmessage: 'Request body must be a string.',\n\t\t\tseverity: CMCD_VALIDATION_SEVERITY_ERROR,\n\t\t})\n\t\treturn {\n\t\t\tvalid: false,\n\t\t\tissues,\n\t\t\tdata: [],\n\t\t}\n\t}\n\n\tconst bodyResult = validateCmcdEvents(body, options)\n\n\treturn {\n\t\tvalid: issues.length === 0 && bodyResult.valid,\n\t\tissues: [...issues, ...bodyResult.issues],\n\t\tdata: bodyResult.data,\n\t}\n}\n","import { CMCD_HEADER_MAP } from './CMCD_HEADER_MAP.ts'\nimport type { CmcdData } from './CmcdData.ts'\nimport type { CmcdDataValidationResult } from './CmcdDataValidationResult.ts'\nimport { type CmcdHeaderField, CMCD_HEADER_FIELDS } from './CmcdHeaderField.ts'\nimport type { CmcdKey } from './CmcdKey.ts'\nimport { CMCD_REQUEST_MODE } from './CmcdReportingMode.ts'\nimport type { CmcdValidationOptions } from './CmcdValidationOptions.ts'\nimport type { CmcdValidationResult } from './CmcdValidationResult.ts'\nimport { CMCD_VALIDATION_SEVERITY_ERROR } from './CmcdValidationSeverity.ts'\nimport { decodeCmcd } from './decodeCmcd.ts'\nimport { ensureHeaders } from './ensureHeaders.ts'\nimport { isCmcdCustomKey } from './isCmcdCustomKey.ts'\nimport { mergeValidationResults } from './mergeValidationResults.ts'\nimport { validateCmcd } from './validateCmcd.ts'\n\n/**\n * Validates CMCD HTTP headers by checking shard placement and payload validity.\n *\n * This function accepts raw CMCD header strings and decodes each shard\n * internally. It verifies that each key is in its correct header shard.\n * The function then merges all shards and runs payload validation (keys,\n * values, and structure) on the merged data.\n *\n * @example\n * {@includeCode ../test/validateCmcdHeaders.test.ts#example}\n *\n * @param headers - A `Headers` instance or a record of CMCD header fields to raw encoded strings.\n * @param options - Validation options (excluding `reportingMode`).\n * @returns The validation result including decoded data.\n *\n * @see {@link https://cta-wave.github.io/Resources/common-media-client-data--cta-5004-b.html#header-field-definition | CTA-5004-B Header Field Definition}\n *\n * @public\n */\nexport function validateCmcdHeaders(headers: Record<string, string> | Headers, options?: Omit<CmcdValidationOptions, 'reportingMode'>): CmcdDataValidationResult {\n\tconst h = ensureHeaders(headers)\n\tconst issues: CmcdValidationResult['issues'] = []\n\tconst decoded: Partial<Record<CmcdHeaderField, Record<string, unknown>>> = {}\n\n\tfor (const headerField of CMCD_HEADER_FIELDS) {\n\t\tconst raw = h.get(headerField)\n\t\tif (!raw) {\n\t\t\tcontinue\n\t\t}\n\n\t\tlet shard: Record<string, unknown>\n\t\ttry {\n\t\t\tshard = decodeCmcd(raw)\n\t\t} catch {\n\t\t\tissues.push({\n\t\t\t\tkey: headerField,\n\t\t\t\tmessage: `Failed to decode \"${headerField}\" header: invalid structured field syntax.`,\n\t\t\t\tseverity: CMCD_VALIDATION_SEVERITY_ERROR,\n\t\t\t})\n\t\t\tcontinue\n\t\t}\n\t\tdecoded[headerField] = shard\n\n\t\tfor (const key of Object.keys(shard)) {\n\t\t\tif (isCmcdCustomKey(key as CmcdKey)) {\n\t\t\t\tcontinue\n\t\t\t}\n\n\t\t\tconst expectedHeader = CMCD_HEADER_MAP[key as keyof typeof CMCD_HEADER_MAP]\n\t\t\tif (expectedHeader && expectedHeader !== headerField) {\n\t\t\t\tissues.push({\n\t\t\t\t\tkey,\n\t\t\t\t\tmessage: `Key \"${key}\" is in \"${headerField}\" but should be in \"${expectedHeader}\".`,\n\t\t\t\t\tseverity: CMCD_VALIDATION_SEVERITY_ERROR,\n\t\t\t\t})\n\t\t\t}\n\t\t}\n\t}\n\n\tconst shardResult: CmcdValidationResult = {\n\t\tvalid: issues.length === 0,\n\t\tissues,\n\t}\n\n\tconst merged: Record<string, unknown> = Object.assign({}, ...CMCD_HEADER_FIELDS.map(f => decoded[f]).filter(Boolean))\n\tconst payloadResult = validateCmcd(merged, { ...options, reportingMode: CMCD_REQUEST_MODE })\n\n\tconst result = mergeValidationResults(shardResult, payloadResult)\n\treturn { ...result, data: merged as CmcdData }\n}\n","import type { HttpRequest } from '@svta/cml-utils'\nimport { CMCD_PARAM } from './CMCD_PARAM.ts'\nimport type { CmcdData } from './CmcdData.ts'\nimport type { CmcdDataValidationResult } from './CmcdDataValidationResult.ts'\nimport { type CmcdHeaderField, CMCD_HEADER_FIELDS } from './CmcdHeaderField.ts'\nimport { CMCD_REQUEST_MODE } from './CmcdReportingMode.ts'\nimport type { CmcdValidationOptions } from './CmcdValidationOptions.ts'\nimport type { CmcdValidationResult } from './CmcdValidationResult.ts'\nimport { CMCD_VALIDATION_SEVERITY_ERROR } from './CmcdValidationSeverity.ts'\nimport { decodeCmcd } from './decodeCmcd.ts'\nimport { ensureHeaders } from './ensureHeaders.ts'\nimport { mergeValidationResults } from './mergeValidationResults.ts'\nimport { validateCmcd } from './validateCmcd.ts'\nimport { validateCmcdHeaders } from './validateCmcdHeaders.ts'\n\n/**\n * Validates CMCD data from a request as a request-mode payload.\n *\n * Accepts a\n * {@link https://developer.mozilla.org/en-US/docs/Web/API/Request | Request}\n * object or an {@link @svta/cml-utils!HttpRequest | HttpRequest} object.\n *\n * The function checks the HTTP headers for CMCD data first. If the\n * request has CMCD headers, {@link validateCmcdHeaders} validates them,\n * including shard placement. Otherwise, the function validates the CMCD\n * query parameter of the URL. A request with CMCD data in both the\n * headers and the `CMCD` query parameter is an error. The function still\n * validates the headers and returns their data.\n *\n * @param request - A `Request` or `HttpRequest` to validate.\n * @param options - Validation options (excluding `reportingMode`).\n * @returns The validation result including decoded data.\n *\n * @example\n * {@includeCode ../test/validateCmcdRequest.test.ts#example}\n *\n * @see {@link https://cta-wave.github.io/Resources/common-media-client-data--cta-5004-b.html#request-mode | CTA-5004-B Request Mode}\n *\n * @public\n */\nexport function validateCmcdRequest(request: Request | HttpRequest, options?: Omit<CmcdValidationOptions, 'reportingMode'>): CmcdDataValidationResult {\n\tconst headers = extractHeaderRecord(request.headers)\n\tconst param = getCmcdQueryParam(request.url)\n\n\tif (headers) {\n\t\tconst result = validateCmcdHeaders(headers, options)\n\n\t\tif (!param) {\n\t\t\treturn result\n\t\t}\n\n\t\tconst conflict: CmcdValidationResult = {\n\t\t\tvalid: false,\n\t\t\tissues: [{\n\t\t\t\tmessage: 'CMCD data found in both request headers and the \"CMCD\" query parameter. A request must use only one transmission mode.',\n\t\t\t\tseverity: CMCD_VALIDATION_SEVERITY_ERROR,\n\t\t\t}],\n\t\t}\n\n\t\treturn { ...mergeValidationResults(conflict, result), data: result.data }\n\t}\n\n\tif (!param) {\n\t\treturn {\n\t\t\tvalid: false,\n\t\t\tissues: [{\n\t\t\t\tmessage: hasCmcdInFragment(request.url)\n\t\t\t\t\t? 'No CMCD data found in request headers or query parameters. The URL fragment contains a \"CMCD\" parameter. A server never receives the fragment.'\n\t\t\t\t\t: 'No CMCD data found in request headers or query parameters.',\n\t\t\t\tseverity: CMCD_VALIDATION_SEVERITY_ERROR,\n\t\t\t}],\n\t\t\tdata: {} as CmcdData,\n\t\t}\n\t}\n\n\tlet data: CmcdData\n\ttry {\n\t\tdata = decodeCmcd(param)\n\t} catch {\n\t\treturn {\n\t\t\tvalid: false,\n\t\t\tissues: [{\n\t\t\t\tmessage: 'Failed to decode CMCD query parameter: invalid structured field syntax.',\n\t\t\t\tseverity: CMCD_VALIDATION_SEVERITY_ERROR,\n\t\t\t}],\n\t\t\tdata: {} as CmcdData,\n\t\t}\n\t}\n\n\tconst result = validateCmcd(data, { ...options, reportingMode: CMCD_REQUEST_MODE })\n\treturn { ...result, data }\n}\n\nconst CMCD_IN_FRAGMENT = /(?:^|[?&])CMCD=/\n\nfunction getCmcdQueryParam(url: string): string | null {\n\tconst hash = url.indexOf('#')\n\tconst path = hash < 0 ? url : url.slice(0, hash)\n\tconst start = path.indexOf('?')\n\n\tif (start < 0) {\n\t\treturn null\n\t}\n\n\treturn new URLSearchParams(path.slice(start + 1)).get(CMCD_PARAM)\n}\n\nfunction hasCmcdInFragment(url: string): boolean {\n\tconst hash = url.indexOf('#')\n\n\treturn hash >= 0 && CMCD_IN_FRAGMENT.test(url.slice(hash + 1))\n}\n\nfunction extractHeaderRecord(headers: Headers | Record<string, string> | undefined): Partial<Record<CmcdHeaderField, string>> | undefined {\n\tif (!headers) {\n\t\treturn undefined\n\t}\n\n\tconst h = ensureHeaders(headers)\n\tconst result: Partial<Record<CmcdHeaderField, string>> = {}\n\tlet found = false\n\n\tfor (const field of CMCD_HEADER_FIELDS) {\n\t\tconst value = h.get(field)\n\n\t\tif (value) {\n\t\t\tresult[field] = value\n\t\t\tfound = true\n\t\t}\n\t}\n\n\treturn found ? result : undefined\n}\n"],"mappings":";;;;;;;;;;;AAOA,MAAaA,uBAAoC,IAAI,IAAY;CAChE;CAAM;CAAM;CAAM;CAAO;CAAO;CAAQ;CAAO;CAAM;CAAO;CAAM;CAAO;CAAM;CAAO;CACtF,CAAC;;;;ACPF,MAAM,QAAQ;CAAC;CAAK;CAAK;CAAM;CAAM;CAAK;CAAI;;;;;;AAO9C,MAAaC,iBAAwD;CACpE,IAAI;EAAE,MAAM;EAAW,OAAO;EAAG,cAAc;EAAM,SAAS;EAAG;CACjE,IAAI;EAAE,MAAM;EAAW,aAAa;EAAO,YAAY;EAAK,SAAS;EAAG;CACxE,IAAI;EAAE,MAAM;EAAW,OAAO;EAAK;CACnC,IAAI;EAAE,MAAM;EAAW,OAAO;EAAG,YAAY;EAAM;CACnD,IAAI;EAAE,MAAM;EAAW,aAAa;EAAO;CAC3C,KAAK;EAAE,MAAM;EAAW,OAAO;EAAG,SAAS;EAAG;CAC9C,KAAK;EAAE,MAAM;EAAW,OAAO;EAAG,SAAS;EAAG;CAC9C,MAAM;EAAE,MAAM;EAAW,OAAO;EAAG,SAAS;EAAG;CAC/C,KAAK;EAAE,MAAM;EAAU,KAAK;EAAK,SAAS;EAAG;CAC7C,KAAK;EAAE,MAAM;EAAU,KAAK;EAAI,MAAM;EAAS,QAAQ;EAAM,YAAY;EAAM,SAAS;EAAG;CAC3F,KAAK;EAAE,MAAM;EAAU,KAAK;EAAK,OAAO;EAAI,YAAY;EAAK;CAC7D,OAAO;EAAE,MAAM;EAAU,MAAM;EAAS,QAAQ;EAAM,SAAS;EAAG;CAClE,OAAO;EAAE,MAAM;EAAU,MAAM;EAAS,QAAQ;EAAM,SAAS;EAAG;CAClE,IAAI;EAAE,MAAM;EAAU,SAAS;EAAG;CAClC,GAAG;EAAE,MAAM;EAAW,OAAO;EAAG,IAAI;EAAO;CAC3C,KAAK;EAAE,MAAM;EAAW,OAAO;EAAG,SAAS;EAAG;CAC9C,IAAI;EAAE,MAAM;EAAW,OAAO;EAAK;CACnC,GAAG;EAAE,MAAM;EAAS,MAAM;EAAS,YAAY;EAAU,SAAS;EAAG;CACrE,IAAI;EAAE,MAAM;EAAe,YAAY;EAAK,SAAS;EAAG;CACxD,GAAG;EAAE,MAAM;EAAU,KAAK;EAAK,MAAM;EAAS,YAAY;EAAK,SAAS;EAAG;CAC3E,KAAK;EAAE,MAAM;EAAW,OAAO;EAAG,cAAc;EAAM,SAAS;EAAG;CAClE,IAAI;EAAE,MAAM;EAAW,OAAO;EAAG,SAAS;EAAG;CAC7C,KAAK;EAAE,MAAM;EAAW,OAAO;EAAG,SAAS;EAAG;CAC9C,KAAK;EAAE,MAAM;EAAW,OAAO;EAAG,SAAS;EAAG;CAC9C,KAAK;EAAE,MAAM;EAAW,OAAO;EAAK;CACpC,KAAK,EAAE,MAAM,OAAO;CACpB,IAAI;EAAE,MAAM;EAAW,aAAa;EAAO,SAAS;EAAG;CACvD,KAAK;EAAE,MAAM;EAAU,SAAS;EAAG;CACnC,IAAI,EAAE,MAAM,SAAS;CACrB,IAAI;EAAE,MAAM;EAAW,OAAO;EAAG,SAAS;EAAG;CAC7C,IAAI;EAAE,MAAM;EAAW,aAAa;EAAG,YAAY;EAAM;CACzD,IAAI;EAAE,MAAM;EAAW,OAAO;EAAG,SAAS;EAAG;CAC7C,IAAI;EAAE,MAAM;EAAW,OAAO;EAAG,MAAM;EAAS,QAAQ;EAAM,SAAS;EAAG;CAC1E,KAAK;EAAE,MAAM;EAAW,OAAO;EAAK;CACpC,IAAI;EAAE,MAAM;EAAS,OAAO,EAAE,GAAG,KAAK;EAAE;CACxC,KAAK;EAAE,MAAM;EAAU,KAAK;EAAI;CAChC,MAAM;EAAE,MAAM;EAAU,MAAM;EAAS,QAAQ;EAAM,SAAS;EAAG;CACjE,IAAI;EAAE,MAAM;EAAW,OAAO;EAAG,SAAS;EAAG;CAC7C,IAAI;EAAE,MAAM;EAAS,OAAO,EAAE,IAAI,KAAK;EAAE;CACzC,KAAK;EAAE,MAAM;EAAS,YAAY;EAAM,SAAS;EAAG;CACpD,IAAI;EAAE,MAAM;EAAW,aAAa;EAAO;CAC3C,KAAK;EAAE,MAAM;EAAW,OAAO;EAAG,cAAc;EAAM,SAAS;EAAG;CAClE,IAAI;EAAE,MAAM;EAAW,OAAO;EAAG;CACjC,KAAK;EAAE,MAAM;EAAW,OAAO;EAAK,SAAS;EAAG;CAChD,KAAK;EAAE,MAAM;EAAW,OAAO;EAAG,IAAI;GAAC;GAAK;GAAK;GAAM;GAAI;EAAE,SAAS;EAAG;CACzE,IAAI;EAAE,MAAM;EAAW,OAAO;EAAG,MAAM;EAAS,YAAY;EAAU,SAAS;EAAG;CAClF,MAAM;EAAE,MAAM;EAAW,OAAO;EAAG,MAAM;EAAS,QAAQ;EAAM,SAAS;EAAG;CAC5E,OAAO;EAAE,MAAM;EAAW,OAAO;EAAG,MAAM;EAAS,QAAQ;EAAM,SAAS;EAAG;CAC7E,MAAM;EAAE,MAAM;EAAW,OAAO;EAAG,MAAM;EAAS,QAAQ;EAAM,SAAS;EAAG;CAC5E,KAAK;EAAE,MAAM;EAAU,MAAM;EAAS,QAAQ;EAAM,YAAY;EAAM,SAAS;EAAG;CAClF,GAAG;EAAE,MAAM;EAAW,OAAO;EAAG,YAAY;EAAU,SAAS;EAAG;CAClE;;;;;;;;;ACxDD,MAAa,UAAU;;;;;;;;;ACEvB,MAAa,kBAAkB;;;;;;AAO/B,MAAa,oBAAoB;;;;;;;;AASjC,MAAa,oBAAoB;CAIhC,SAAS;CAKT,OAAO;CACP;;;;AC9BD,SAAS,UAAU,QAAqC;AACvD,MAAK,MAAM,KAAK,OACf,QAAO;AAGR,QAAO;;;;;;;;;AAUR,SAAS,YAAY,OAAgB,IAAiC;AACrE,KAAI,iBAAiB,OACpB,SAAQ,MAAM;AAGf,KAAI,CAAC,MAAM,QAAQ,MAAM,CACxB,QAAO;CAGR,IAAIC;AAEJ,MAAK,MAAM,QAAQ,OAAO;AACzB,MAAI,EAAE,gBAAgB,SAAS;AAC9B,OAAI,aAAa,OAChB,YAAW;AAEZ;;AAGD,MAAI,MAAM,KAAK,SAAS,QAAQ,KAC/B,QAAO,KAAK;AAGb,MAAI,aAAa,UAAa,CAAC,UAAU,KAAK,OAAO,CACpD,YAAW,KAAK;;AAIlB,QAAO;;;;;;;;;;AAWR,SAAgB,gBAAgB,KAA0B,IAA6C;CACtG,MAAMC,SAA8B,EAAE;AAEtC,MAAK,MAAM,CAAC,KAAK,UAAU,OAAO,QAAQ,IAAI,EAAE;AAC/C,MAAI,SAAS,MAAM;AAClB,UAAO,OAAO;AACd;;AAGD,MAAI,QAAQ,OAAO;GAClB,MAAM,OAAO,iBAAiB,UAAU,MAAM,QAAQ,MAAM,MAAM,GAAG,MAAM,QAAQ;GACnF,MAAM,QAAQ,MAAM,QAAQ,KAAK,GAAG,KAAK,KAAK;AAE9C,OAAI,iBAAiB,QAAQ;AAC5B,WAAO,SAAS,MAAM;AACtB,QAAI,MAAM,QAAQ,EACjB,QAAO,SAAS,MAAM,OAAO;SAI9B,QAAO,SAAS;aAGT,qBAAqB,IAAI,IAAI,CACrC,QAAO,OAAO,YAAY,OAAO,GAAG;MAGpC,QAAO,OAAO;;AAIhB,QAAO;;;;;ACpFR,MAAM,mBAAmB;;;;;;;;;;;;;;;;AAiBzB,SAAgB,gBAAgB,KAAuB;CAEtD,MAAM,YAAY,IAAI,QAAQ,KAAK,EAAE;AACrC,QAAO,YAAY,KAAK,YAAY,IAAI,SAAS,KAAK,iBAAiB,KAAK,IAAI;;;;;ACnBjF,MAAMC,kBAA+B;CAAE,MAAM;CAAU,aAAa;CAAO,KAAK;CAAI,OAAO;CAAU;;;;;;;;;;AAWrG,SAAgB,WAAW,KAAsC;AAChE,KAAI,OAAO,UAAU,eAAe,KAAK,gBAAgB,IAAI,CAC5D,QAAO,eAAe;AAGvB,QAAO,gBAAgB,IAAe,GAAG,kBAAkB;;;;;;;;;;;;;;;;;;ACR5D,SAAgB,QAAQ,OAAyB;AAChD,KAAI,OAAO,UAAU,SACpB,QAAO,OAAO,SAAS,MAAM;AAG9B,KAAI,MAAM,QAAQ,MAAM,CACvB,QAAO,MAAM,SAAS;AAGvB,QAAO,SAAS,QAAQ,UAAU,MAAM,UAAU;;;;;ACfnD,SAAS,OAAO,SAAiD;AAChE,KAAI,CAAC,QACJ;AAGD,KAAI;AACH,SAAO,IAAI,IAAI,WAAW,QAAQ,CAAC,CAAC;SAE/B;AACL;;;AAIF,SAAS,WAAW,MAAe,MAA0B,SAA0C;AACtG,KAAI,OAAO,SAAS,YAAY,SAAS,GACxC;CAGD,MAAM,WAAW,OAAO,kBAAkB,MAAM,KAAK,GAAG;AAExD,QAAO,YAAY,IAAI,mBAAmB,SAAS,GAAG;;AAGvD,SAAS,YAAY,OAAgB,MAA0B,SAAgD;AAC9G,KAAI,iBAAiB,QAAQ;EAC5B,MAAM,OAAO,WAAW,MAAM,OAAO,MAAM,QAAQ;AAEnD,SAAO,SAAS,SAAY,SAAY,IAAI,OAAO,MAAM,MAAM,OAAO;;AAGvE,QAAO,WAAW,OAAO,MAAM,QAAQ;;AAGxC,SAAS,cAAc,SAAoB,MAA0B,SAAkD;CACtH,MAAMC,OAAuB,EAAE;AAE/B,MAAK,MAAM,SAAS,SAAS;EAC5B,MAAM,YAAY,YAAY,OAAO,MAAM,QAAQ;AAEnD,MAAI,cAAc,OACjB,MAAK,KAAK,UAAU;;AAItB,QAAO,KAAK,SAAS,IAAI,OAAO;;;;;;;;;;;;;;AAejC,SAAgB,UAAU,OAAgB,SAAoG;CAC7I,MAAM,OAAO,OAAO,QAAQ,QAAQ;CACpC,MAAM,UAAU,QAAQ;AAExB,KAAI,MAAM,QAAQ,MAAM,CACvB,QAAO,cAAc,OAAO,MAAM,QAAQ;AAG3C,KAAI,iBAAiB,UAAU,MAAM,QAAQ,MAAM,MAAM,EAAE;EAC1D,MAAM,OAAO,cAAc,MAAM,OAAO,MAAM,QAAQ;AAEtD,SAAO,QAAQ,IAAI,OAAO,MAAM,MAAM,OAAO;;CAG9C,MAAM,QAAQ,YAAY,OAAO,MAAM,QAAQ;AAE/C,QAAO,YAAY,KAAK,UAAU,SAAY,QAAQ,CAAC,MAAM;;;;;;;;;;;;;;;;;ACpE9D,SAAgB,cAAc,OAAoC;AACjE,KAAI,iBAAiB,OACpB,QAAO,cAAc,MAAM,MAAM;AAGlC,KAAI,OAAO,UAAU,SACpB,QAAO;AAGR,KAAI,OAAO,UAAU,YAAY,iBAAiB,QACjD,QAAO,YAAY,MAAM;;;;;ACf3B,SAAS,OAAO,OAAgB,MAAyB,SAA0C;CAClG,MAAM,OAAO,YAAY,IAAI,KAAK,QAAQ,WAAc,KAAK,OAAO;AAEpE,QAAO,OAAO,UAAU,YAAY,UAAU,MAAM,MAAM,UAAU,MAAM,QAAQ;;AAGnF,SAAS,cAAc,OAAgB,MAAmB,SAA+B;AACxF,SAAQ,KAAK,MAAb;EACC,KAAK,UACJ,QAAO,OAAO,UAAU,YAAY,QAAQ;EAE7C,KAAK;EACL,KAAK,UACJ,QAAO,OAAO,UAAU,YAAY,OAAO,SAAS,MAAM,GAAG,KAAK,MAAM,QAAQ,KAAK,MAAM,GAAG,KAAK,QAAQ;EAE5G,KAAK,UACJ,QAAO,OAAO,UAAU,YAAY,OAAO,SAAS,MAAM,GAAG,QAAQ;EAEtE,KAAK,SACJ,QAAO,OAAO,OAAO,MAAM,QAAQ;EAEpC,KAAK,cACJ,QAAO,OAAO,UAAU,YAAY,UAAU,KAAK,QAAQ;EAE5D,KAAK,SAAS;GACb,MAAM,OAAO,cAAc,MAAM;GACjC,MAAM,QAAQ,YAAY,IAAI,KAAK,QAAQ;GAC3C,MAAM,QAAQ,SAAS,UAAa,UAAU,UAAa,OAAO,UAAU,eAAe,KAAK,OAAO,KAAK,GAAG,MAAM,QAAQ;AAE7H,UAAO,QAAQ,IAAI,QAAQ,MAAM,GAAG;;EAGrC,KAAK;AACJ,OAAI,OAAO,UAAU,SACpB,QAAO,OAAO,OAAO,MAAM,QAAQ;AAGpC,OAAI,OAAO,UAAU,SACpB,QAAO,OAAO,SAAS,MAAM,GAAG,QAAQ;AAGzC,OAAI,MAAM,QAAQ,MAAM,CACvB,QAAO,MAAM,SAAS,IAAI,QAAQ;AAGnC,UAAO,OAAO,UAAU,aAAa,OAAO,UAAU,YAAY,iBAAiB,UAAU,QAAQ;EAEtG,QACC;;;AAIH,SAAS,cAAc,OAAgB,MAAmB,SAA+B;AACxF,KAAI,iBAAiB,QAAQ;EAC5B,MAAM,OAAO,cAAc,MAAM,OAAO,MAAM,QAAQ;AAEtD,SAAO,SAAS,SAAY,SAAY,IAAI,OAAO,MAAM,MAAM,OAAO;;AAGvE,QAAO,cAAc,OAAO,MAAM,QAAQ;;AAG3C,SAAS,cAAc,OAAgB,MAAmB,SAA+B;CACxF,MAAM,UAAU,iBAAiB,UAAU,MAAM,QAAQ,MAAM,MAAM,GAAG,QAAQ;CAChF,MAAM,QAAQ,UAAU,QAAQ,QAAgC,MAAM,QAAQ,MAAM,GAAG,QAAQ,CAAC,MAAM;CACtG,MAAMC,OAAkB,EAAE;AAE1B,MAAK,MAAM,QAAQ,OAAO;EACzB,MAAM,aAAa,cAAc,MAAM,MAAM,QAAQ;AAErD,MAAI,eAAe,OAClB,MAAK,KAAK,WAAW;;AAIvB,KAAI,KAAK,WAAW,EACnB;AAGD,QAAO,UAAU,IAAI,OAAO,MAAM,QAAQ,OAAO,GAAG;;;;;;;;;;;;;;;;;AAkBrD,SAAgB,eAAe,OAAgB,MAAmB,SAAwC;AACzG,KAAI,KAAK,SAAS,MACjB,QAAO,UAAU,OAAO,QAAQ;AAGjC,KAAI,KAAK,SAAS,iBAAkB,KAAK,SAAS,aAAa,QAAQ,YAAY,EAClF,QAAO,cAAc,OAAO,MAAM,QAAQ,QAAQ;AAGnD,QAAO,cAAc,OAAO,MAAM,QAAQ,QAAQ;;;;;;;;;;;;;;;;ACtGnD,SAAgB,YAAY,OAAyB;AACpD,QAAO,iBAAiB,SAAS,MAAM,QAAQ;;;;;ACKhD,SAAS,OAAO,MAAmB,eAAkC,MAAwB;AAC5F,SAAQ,KAAK,SAAS,UAAa,KAAK,SAAS,mBAC5C,KAAK,YAAY,UAAc,KAAK,YAAY,MAAO;;AAG7D,SAAS,WAAW,MAAmB,OAAoC;AAC1E,QAAO,KAAK,eAAe,YAAa,UAAU,UAAa,KAAK,eAAe;;AAGpF,SAAS,eAAe,MAA4B;AACnD,SAAQ,KAAK,SAAS,aAAa,KAAK,SAAS,cAAc,KAAK,OAAO;;AAG5E,SAAS,kBAAkB,KAA0B,QAA8C;AAClG,KAAI,OAAO,WAAW,cAAc,OAAO,KAAK,CAC/C,QAAO;AAGR,MAAK,MAAM,OAAO,qBACjB,KAAI,MAAM,QAAQ,YAAY,IAAI,KAAK,CAAC,IAAI,OAAO,IAAe,CACjE,QAAO;AAIT,QAAO;;AAGR,SAAS,iBAAiB,MAAmB,YAAyC;AACrF,KAAI,eAAe,UAAc,KAAK,SAAS,aAAa,KAAK,SAAS,aAAc,KAAK,OAAO,OACnG,QAAO;AAGR,QAAO,KAAK,GAAG,SAAS,WAAW;;AAGpC,SAAS,eAAe,MAAmB,OAAyB;AACnE,QAAO,iBAAiB,QAAQ,YAAY,MAAM,KAAK,KAAK;;AAG7D,SAAS,UAAU,MAAgB,OAAsB,KAAmB;CAC3E,IAAI,QAAQ;AAEZ,QAAO,QAAQ,KAAK,UAAU,KAAK,SAAS,IAC3C;AAGD,MAAK,OAAO,OAAO,GAAG,IAAI;AAC1B,OAAM,OAAO,OAAO,GAAG,eAAe,KAAK;;AAG5C,SAAS,aAAa,KAAa,OAAgB,MAAmB,SAA4B,kBAAiD;CAClJ,MAAM,YAAY,QAAQ,aAAa;AAEvC,KAAI,OAAO,cAAc,WACxB,QAAO,SAAS,OAAO,SAAY,eAAe,OAAO,MAAM,iBAAiB;CAGjF,MAAMC,YAAqB,QAAQ,MAAM,GAAG,UAAU,OAAoB,iBAAiB,GAAG;AAE9F,KAAI,CAAC,QAAQ,UAAU,IAAI,EAAE,cAAc,SAAS,KAAK,SAAS,WACjE;AAGD,KAAI,KAAK,SAAS,SAAS;AAC1B,MAAI,OAAO,cAAc,SACxB,QAAO,IAAI,QAAQ,UAAU;AAG9B,MAAI,qBAAqB,UAAU,OAAO,UAAU,UAAU,SAC7D,QAAO,IAAI,OAAO,IAAI,QAAQ,UAAU,MAAM,EAAE,UAAU,OAAO;;AAInE,QAAO;;;;;;;;;;;;;AAcR,SAAgB,gBAAgB,KAA0B,UAA6B,EAAE,EAAQ;CAChG,MAAMC,UAAmC,EAAE;AAE3C,KAAI,OAAO,QAAQ,OAAO,QAAQ,SACjC,QAAO;CAGR,MAAM,UAAU,QAAQ,WAAW,YAAY,IAAI,KAAK,IAAmB;CAC3E,MAAM,gBAAgB,QAAQ,iBAAiB;CAC/C,MAAM,OAAO,YAAY;CACzB,MAAM,gBAAgB,CAAC,QAAQ,kBAAkB;CACjD,MAAMC,mBAAyC;EAAE;EAAS;EAAe,SAAS,QAAQ;EAAS;CACnG,MAAM,SAAS,QAAQ;CAEvB,IAAIC;CACJ,IAAIC;AAEJ,KAAI,QAAQ,kBAAkB,KAAK,OAAO,EAAE;AAC3C,oBAAkB,aAAa,MAAM,IAAI,OAAO,eAAe,OAAO,SAAS,iBAAiB;AAChG,eAAa,cAAc,gBAAgB;;CAG5C,MAAM,OAAO,OAAO,gBAAgB,KAAK,WAAW,GAAG;CACvD,MAAM,aAAa,gBAAgB,aAAa,KAAK,KAAK,MAAM,eAAe,MAAM,SAAS,iBAAiB,GAAG;CAClH,MAAM,QAAQ,cAAc,WAAW;CACvC,MAAMC,OAAiB,EAAE;CACzB,MAAMC,QAAuB,EAAE;CAC/B,IAAI,SAAS;CACb,IAAI,kBAAkB;AAEtB,MAAK,MAAM,OAAO,OAAO,KAAK,KAAK,CAAC,MAAM,EAAE;EAC3C,MAAM,OAAO,WAAW,IAAI;AAE5B,MAAI,SAAS,UAAa,CAAC,OAAO,MAAM,eAAe,KAAK,CAC3D;AAGD,MAAI,OAAO,WAAW,cAAc,OAAO,IAAe,CACzD,UAAS;WAED,CAAC,WAAW,MAAM,MAAM,CAChC;AAGD,MAAI,KAAK,WAAW,UAAa,KAAK,WAAW,MAChD;AAGD,MAAI,QAAQ,QAAQ,eAAe,KAAK,CACvC,mBAAkB;AAGnB,OAAK,KAAK,IAAI;AACd,QAAM,KAAK,KAAK;;AAGjB,KAAI,CAAC,UAAU,CAAC,cACf,QAAO;AAGR,KAAI,mBAAmB,CAAC,MAAM;AAC7B,oBAAkB,aAAa,MAAM,KAAK,OAAO,eAAe,OAAO,SAAS,iBAAiB;AACjG,eAAa,cAAc,gBAAgB;;AAG5C,KAAI,iBAAiB,CAAC,KAAK,SAAS,KAAK,CACxC,WAAU,MAAM,OAAO,KAAK;AAG7B,KAAI,CAAC,QAAQ,CAAC,KAAK,SAAS,IAAI,CAC/B,WAAU,MAAM,OAAO,IAAI;CAG5B,MAAMC,SAAoB,IAAI,MAAM,KAAK,OAAO;AAEhD,MAAK,IAAI,IAAI,KAAK,SAAS,GAAG,KAAK,GAAG,KAAK;EAC1C,MAAM,MAAM,KAAK;EACjB,MAAM,OAAO,MAAM;AAEnB,MAAI,KAAK,SAAS,aAAa,KAAK,iBAAiB,QAAW;GAC/D,MAAM,QAAQ,KAAK,QAAQ,KAAK,cAAc,IAAI,EAAE;AAEpD,OAAI,UAAU,MAAM,OAAO,WAAW,OACrC;;AAIF,MAAI,QAAQ,IACX,QAAO,KAAK;WAEJ,QAAQ,KAChB,QAAO,KAAK;WAEJ,QAAQ,IAChB,QAAO,KAAK;WAEJ,QAAQ,iBAAiB,MAAM,WAAW,CAClD,QAAO,KAAK,aAAa,KAAK,KAAK,MAAM,MAAM,SAAS,iBAAiB;AAG1E,MAAI,QAAQ,MAAM;GACjB,MAAM,YAAY,YAAY,OAAO,GAAG;AAExC,OAAI,OAAO,cAAc,YAAY,CAAC,OAAO,SAAS,UAAU,CAC/D,QAAO,KAAK,KAAK,KAAK;;;AAKzB,MAAK,IAAI,IAAI,GAAG,IAAI,KAAK,QAAQ,KAAK;EACrC,MAAM,QAAQ,OAAO;AAErB,MAAI,UAAU,WAAc,CAAC,eAAe,MAAM,IAAI,MAAM,IAAI,WAAW,MAAM,IAAI,MAAM,EAC1F,SAAQ,KAAK,MAAM;;AAIrB,QAAO;;;;;;;;;;ACxNR,MAAa,cAAc;;;;;;AAO3B,MAAa,eAAe;;;;;;AAO5B,MAAa,eAAe;;;;;;AAO5B,MAAa,cAAc;;;;;;;;;AAU3B,MAAa,kBAAkB;CAI9B,QAAQ;CAKR,SAAS;CAKT,SAAS;CAKT,QAAQ;CACR;;;;;;AAYD,MAAaC,qBAAiD;CAAC;CAAa;CAAc;CAAc;CAAY;;;;;;;;;;;;;AC1DpH,MAAaC,kBAAmE;CAE/E,IAAI;CACJ,IAAI;CACJ,GAAG;CACH,KAAK;CACL,IAAI;CACJ,IAAI;CACJ,KAAK;CACL,IAAI;CACJ,KAAK;CAGL,IAAI;CACJ,IAAI;CACJ,KAAK;CACL,IAAI;CACJ,KAAK;CACL,KAAK;CACL,KAAK;CACL,KAAK;CACL,IAAI;CACJ,IAAI;CACJ,KAAK;CACL,IAAI;CACJ,KAAK;CAGL,KAAK;CACL,KAAK;CACL,IAAI;CACJ,KAAK;CACL,IAAI;CACJ,GAAG;CAGH,IAAI;CACJ,IAAI;CACJ,KAAK;CACL,KAAK;CACL,MAAM;CACN,KAAK;CACL,IAAI;CACJ,IAAI;CACJ,IAAI;CACJ,IAAI;CACJ,KAAK;CACL;;;;ACnDD,SAAS,gBAAgB,WAA2E;AACnG,QAAO,OAAO,KAAK,UAAU,CAC3B,QAAQ,KAAK,UAAU;AACvB,YAAU,QAA2B,SAAQ,QAAO,IAAI,OAAO,MAAyB;AACxF,SAAO;IACL,EAAE,CAAqC;;;;;;;;;;;;;;AAe5C,SAAgB,iBAAiB,MAAY,iBAAoF;CAChI,MAAM,SAAS,EAAE;AAEjB,KAAI,CAAC,KACJ,QAAO;CAGR,MAAM,OAAO,OAAO,KAAK,KAAK;CAC9B,MAAMC,SAA0D,kBAAkB,gBAAgB,gBAAgB,GAAG,EAAE;AAEvH,MAAK,MAAM,OAAO,MAAM;EACvB,MAAM,QAAQ,gBAAgB,QAAQ,OAAO,QAAQ,gBAAgB;EACrE,MAAM,OAAO,OAAO,WAAW,EAAE;AACjC,EAAC,KAAiC,OAAQ,KAAiC;;AAG5E,QAAO;;;;;;;;;;;;;;AC5BR,SAAgB,sBAAsB,MAAY,iBAA2E;CAC5H,MAAM,SAAS,EAAE;CACjB,MAAM,SAAS,iBAAiB,MAAM,gBAAgB;AAEtD,MAAK,MAAM,CAAC,OAAO,UAAU,OAAO,QAAQ,OAAO,EAAE;EACpD,MAAM,QAAQ,aAAa,OAA0B,EAAE,YAAY,OAAO,CAAC;AAC3E,MAAI,MACH,QAAO,SAA4B;;AAIrC,QAAO;;;;;;;;;;;;;;;;;;;;ACNR,SAAgB,cAAc,MAAY,UAA6B,EAAE,EAAmC;AAC3G,KAAI,CAAC,KACJ,QAAO,EAAE;AAGV,QAAO,sBAAsB,gBAAgB,MAAM,QAAQ,EAAE,SAAS,gBAAgB;;;;;;;;;;;;;;;;;;;;;ACNvF,SAAgB,kBAAkB,SAAiC,MAAY,SAAqD;AACnI,QAAO,OAAO,OAAO,SAAS,cAAc,MAAM,QAAQ,CAAC;;;;;;;;;;;;;ACV5D,SAAgB,mBAAmB,MAAoB;AACtD,QAAO,aAAa,MAAM,EAAE,YAAY,OAAO,CAAC;;;;;;;;;;;;;;;;;;;;ACQjD,SAAgB,WAAW,MAAY,UAA6B,EAAE,EAAU;AAC/E,KAAI,CAAC,KACJ,QAAO;AAGR,QAAO,mBAAmB,gBAAgB,MAAM,QAAQ,CAAC;;;;;;;;;;ACpB1D,MAAa,aAAa;;;;ACJ1B,MAAM,mBAAmB;AACzB,MAAM,kBAAkB;AAExB,SAAS,eAAe,MAAsB;AAC7C,QAAO,IAAI,KAAK,WAAW,EAAE,CAAC,SAAS,GAAG,CAAC,aAAa;;AAGzD,SAAS,gBAAgB,OAAuB;AAC/C,QAAO,MAAM,WAAW,IAAI,QAAQ;;;;;;;;;;;;;;AAerC,SAAgB,cAAc,OAAuB;CACpD,IAAIC;AAEJ,KAAI;AACH,YAAU,mBAAmB,MAAM;SAE9B;AACL,YAAU,mBAAmB,MAAM,QAAQ,iBAAiB,gBAAgB,CAAC;;AAG9E,QAAO,QAAQ,QAAQ,kBAAkB,eAAe;;;;;AC/BzD,SAAS,YAAY,OAAwB;AAC5C,QAAO,UAAU,cAAc,MAAM,WAAW,GAAG,WAAW,GAAG;;;;;;;;;;;;;;;;;AAkBlE,SAAgB,iBAAiB,KAAa,OAAwB;CACrE,MAAM,YAAY,IAAI,QAAQ,IAAI;CAClC,MAAM,MAAM,cAAc,KAAK,IAAI,SAAS;CAC5C,MAAM,aAAa,IAAI,QAAQ,IAAI;CACnC,MAAM,QAAQ,eAAe,MAAM,aAAa,MAAM,MAAM;CAC5D,MAAMC,SAAmB,EAAE;CAC3B,IAAI,QAAQ,QAAQ,GAAG,WAAW,GAAG,cAAc,MAAM,KAAK;CAC9D,IAAI,QAAQ;AAEZ,MAAK,MAAM,QAAQ,QAAQ,MAAM,IAAI,MAAM,QAAQ,GAAG,IAAI,CAAC,MAAM,IAAI,GAAG,EAAE,CACzE,KAAI,CAAC,YAAY,KAAK,CACrB,QAAO,KAAK,KAAK;MAEb;AACJ,UAAQ;AAER,MAAI,OAAO;AACV,UAAO,KAAK,MAAM;AAClB,WAAQ;;;AAKX,KAAI,OAAO;AACV,MAAI,OAAO,OAAO,SAAS,OAAO,GACjC,QAAO,KAAK;AAGb,SAAO,KAAK,MAAM;YAEV,CAAC,MACT,QAAO;CAGR,MAAM,QAAQ,OAAO,KAAK,IAAI;AAE9B,QAAO,GAAG,IAAI,MAAM,GAAG,MAAM,GAAG,QAAQ,IAAI,UAAU,KAAK,IAAI,MAAM,IAAI;;;;;;;;;;;;;;;;;;;;;;;;;ACjC1E,SAAgB,gBAAgB,KAAa,MAAY,SAAqC;CAC7F,MAAM,QAAQ,OAAO,WAAW,MAAM,QAAQ,GAAG;AAEjD,QAAO,QAAQ,iBAAiB,KAAK,MAAM,GAAG;;;;;;;;;;ACvB/C,MAAa,6BAA6B;;;;;;;;;ACA1C,MAAa,kBAAkB;CAC9B;CACA;CACA;CACA;CACA;;;;ACFD,MAAM,iBAAiB,OAAkB,WAA6E;AACrH,KAAI,MAAM,QAAQ,MAAM,EAAE;EACzB,MAAMC,OAAoC,EAAE;AAE5C,OAAK,MAAM,QAAQ,OAAO;GACzB,MAAM,YAAY,cAAc,MAAM,OAAO;AAE7C,OAAI,OAAO,SAAS,qBAAqB,SAAS,UAAU,QAAQ,UAAU,CAC7E,MAAK,KAAK,UAAU;;AAItB,SAAO;;AAGR,KAAI,iBAAiB,QAAQ;EAC5B,MAAM,YAAY,cAAc,MAAM,OAAoB,OAAO;AACjE,SAAO,QAAQ,UAAU,GAAG,IAAI,OAAO,WAAW,MAAM,OAAO,GAAG;;AAGnE,QAAO,OAAO,UAAU,WAAW,OAAO,MAAM,GAAG;;AAGpD,MAAM,aAAa,UAAqB,cAAc,OAAO,KAAK,MAAM;AAExE,MAAM,YAAY,UAAqB,cAAc,OAAO,OAAO;AAEnE,MAAM,kBAAkB,UAA0B,KAAK,MAAM,QAAQ,IAAI,GAAG;AAE5E,MAAM,aAAa,UAAqB,cAAc,OAAO,eAAe;;;;;;;;;;AAW5E,MAAaC,qBAAoD;CAIhE,IAAI;CAKJ,GAAG;CAKH,IAAI;CAKJ,IAAI;CAKJ,KAAK;CAKL,MAAM,OAAkB,YAAkC,UAAU,OAAO,QAAQ,IAAI;CAKvF,KAAK;CAKL,IAAI;CAKJ,KAAK;CAKL,IAAI;CAKJ,KAAK;CAKL,KAAK;CAKL,MAAM;CAKN,KAAK;CAKL,KAAK;CAKL,IAAI;CAKJ,KAAK;CAKL,KAAK;CAKL,IAAI;CAKJ,IAAI;CAKJ,IAAI;CAKJ,IAAI;CAKJ,IAAI;CAKJ,KAAK;CAKL,KAAK;CAKL,IAAI;CAKJ,MAAM;CAKN,OAAO;CAKP,MAAM;CACN;;;;;;;;;AC5LD,MAAa,oBAAoB;CAChC;CACA;CACA;CACA;CACA;CACA;CACA;CACA;CACA;CACA;CACA;CACA;CACA;CACA;CACA;CACA;CACA;CACA;CACA;CACA;CACA;CACA;CACA;CACA;CACA;CACA;CACA;CACA;CACA;CACA;CACA;CACA;CACA;CACA;CACA;CACA;CACA;CACA;CACA;;;;;;;;;ACvCD,MAAa,qBAAqB;CACjC;CACA;CACA;CACA;CACA;CACA;CACA;CACA;CACA;;;;;;;;;ACTD,MAAa,eAAe;CAC3B;CACA;CACA;CACA;CACA;CACA;CACA;CACA;CACA;CACA;CACA;CACA;CACA;CACA;CACA;CACA;CACA;CACA;CACA;;;;;;;;;ACbD,MAAaC,YAAuC;CACnD,GAAG;CACH,GAAG;CACH,GAAG;CACH,GAAG;CACH,CAAC,QAAQ,KAAK,OAAO,QAAQ,IAAI,QAAQ,IAAI,KAAK,MAAM;;;;;;;;;ACXzD,MAAa,iBAAiB;;;;;;;;;;;;;;;;;;;;;;;;;;;;ACmB9B,MAAaC,0BAAyD,uBAAO,IAAI,oCAAoC;;;;;;;;;ACnBrH,MAAa,UAAU;;;;;;;;;ACEvB,MAAa,4BAA4B;;;;;;AAOzC,MAAa,wBAAwB;;;;;;AAOrC,MAAa,2BAA2B;;;;;;AAOxC,MAAa,mBAAmB;;;;;;AAOhC,MAAa,2BAA2B;;;;;;AAOxC,MAAa,wBAAwB;;;;;;AAOrC,MAAa,+BAA+B;;;;;;AAO5C,MAAa,kBAAkB;;;;;;AAO/B,MAAa,oBAAoB;;;;;;AAOjC,MAAa,2BAA2B;;;;;;AAOxC,MAAa,6BAA6B;;;;;;AAO1C,MAAa,+BAA+B;;;;;;AAO5C,MAAa,sBAAsB;;;;;;AAOnC,MAAa,oBAAoB;;;;;;AAOjC,MAAa,4BAA4B;;;;;;AAOzC,MAAa,0BAA0B;;;;;;AAOvC,MAAa,kBAAkB;;;;;;AAO/B,MAAa,0BAA0B;;;;;;;;;;AAWvC,MAAa,gBAAgB;CAI5B,gBAAgB;CAKhB,YAAY;CAKZ,eAAe;CAKf,OAAO;CAKP,eAAe;CAKf,YAAY;CAKZ,mBAAmB;CAKnB,MAAM;CAKN,QAAQ;CAKR,eAAe;CAKf,iBAAiB;CAKjB,mBAAmB;CAKnB,UAAU;CAKV,QAAQ;CAKR,gBAAgB;CAKhB,cAAc;CAKd,MAAM;CAKN,cAAc;CACd;;;;;;;;;;;;;ACxND,MAAa,iBAAiB;CAI7B,UAAU;CAKV,OAAO;CAKP,OAAO;CAKP,OAAO;CAKP,MAAM;CAKN,SAAS;CAKT,YAAY;CAKZ,KAAK;CAKL,OAAO;CACP;;;;;;;;;;;;;;AC5CD,MAAa,kBAAkB;CAI9B,UAAU;CAKV,SAAS;CAKT,SAAS;CAKT,aAAa;CAKb,QAAQ;CAKR,SAAS;CAKT,OAAO;CAKP,aAAa;CAKb,MAAM;CAKN,YAAY;CACZ;;;;;;;;;;ACtDD,MAAa,kCAAkC;;;;;;;AAQ/C,MAAa,mCAAmC;;;;;;;AAQhD,MAAa,kCAAkC;;;;;;;;;AAU/C,MAAa,yBAAyB;CACrC,OAAO;CACP,QAAQ;CACR,OAAO;CACP;;;;;;;;;AC/BD,MAAa,sCAAsC;;;;;;AAOnD,MAAa,qCAAqC;;;;;;;AAQlD,MAAa,mCAAmC;;;;;;;AAQhD,MAAa,qCAAqC;;;;;;;;;AAUlD,MAAa,0BAA0B;CACtC,UAAU;CACV,SAAS;CACT,OAAO;CACP,SAAS;CACT;;;;AC1CD,eAAe,cAAc,SAAwC;CACpE,MAAMC,UAAkC,EAAE;AAC1C,SAAQ,QAAQ,SAAS,OAAO,SAAS;AACxC,UAAQ,KAAK,aAAa,IAAI;GAC7B;CAEF,IAAIC;AACJ,KAAI,QAAQ,KACX,KAAI;AACH,SAAO,MAAM,QAAQ,MAAM;SACpB;AACP,SAAO;;AAIT,QAAO;EACN,KAAK,QAAQ;EACb,QAAQ,QAAQ;EAChB;EACA;EACA;;;;;;;;;;;;;;;;;;AAmBF,SAAgB,uBAA6C;AAC5D,QAAO,EACN,OAAO,SAAyC;EAC/C,MAAM,YAAY,WAAW;AAE7B,aAAW,QAAQ,OAClB,OACA,SACuB;GAKvB,MAAM,YAAY,QADE,MAAM,cAHV,iBAAiB,UAC9B,MAAM,OAAO,GACb,IAAI,QAAQ,OAAO,KAAK,CACqB,CACV;AACtC,OAAI,UACH,QAAO;AAER,UAAO,UAAU,KAAK,YAAY,OAAsB,KAAK;;AAG9D,eAAa;AACZ,cAAW,QAAQ;;IAGrB;;;;;ACzDF,eAAe,gBAAgB,KAAkB,UAAmC;CACnF,MAAM,OAAO,MAAM,SAAS,OAAO,CAAC,MAAM,CAAC,YAAY,GAAG;CAC1D,MAAMC,oBACL,OAAO,kBAAkB,cAAc,gBAAgB;AAExD,sBAAqB;AACpB,MAAI;AACH,UAAO,eAAe,KAAK,UAAU;IAAE,OAAO,SAAS;IAAQ,cAAc;IAAM,CAAC;AACpF,UAAO,eAAe,KAAK,cAAc;IAAE,OAAO,SAAS;IAAY,cAAc;IAAM,CAAC;AAC5F,UAAO,eAAe,KAAK,cAAc;IAAE,OAAO;IAAG,cAAc;IAAM,CAAC;AAC1E,UAAO,eAAe,KAAK,eAAe;IAAE,OAAO,IAAI,YAAY;IAAI,cAAc;IAAM,CAAC;AAC5F,UAAO,eAAe,KAAK,YAAY;IAAE,OAAO;IAAM,cAAc;IAAM,CAAC;AAC3E,UAAO,eAAe,KAAK,gBAAgB;IAAE,OAAO;IAAM,cAAc;IAAM,CAAC;AAE/E,OAAI,OAAO,IAAI,WAAW,WACzB,KAAI,OAAO,KAAK,KAAK,IAAI,kBAAkB,OAAO,CAA+B;AAElF,OAAI,OAAO,IAAI,cAAc,WAC5B,KAAI,UAAU,KAAK,KAAK,IAAI,kBAAkB,UAAU,CAA+B;UAEjF;GAGP,MAAM,SAAS;AACf,UAAO,YAAY,SAAS;AAC5B,UAAO,gBAAgB,SAAS;AAChC,UAAO,gBAAgB;AACvB,UAAO,iBAAiB,IAAI,YAAY;AACxC,UAAO,cAAc;AACrB,UAAO,kBAAkB;AACzB,OAAI,OAAO,IAAI,WAAW,WACzB,KAAI,OAAO,KAAK,KAAkC,IAAI,kBAAkB,OAAO,CAA+B;AAE/G,OAAI,OAAO,IAAI,cAAc,WAC5B,KAAI,UAAU,KAAK,KAAkC,IAAI,kBAAkB,UAAU,CAA+B;;GAGrH;;;;;;;;AASH,SAAgB,qBAA2C;AAC1D,QAAO,EACN,OAAO,SAAyC;EAC/C,MAAM,MAAM,WAAW;AACvB,MAAI,CAAC,IACJ,cAAa;EAEd,MAAM,WAAW,IAAI,UAAU;EAC/B,MAAM,uBAAuB,IAAI,UAAU;EAC3C,MAAM,WAAW,IAAI,UAAU;AAE/B,MAAI,UAAU,OAAO,SAA6B,QAAgB,KAAyB;AAC1F,QAAK,cAAc;AACnB,QAAK,WAAW,OAAO,QAAQ,WAAW,MAAM,IAAI,UAAU;AAC9D,QAAK,eAAe,EAAE;AAEtB,UAAO,SAAS,MAAM,MAAM,UAAoD;;AAGjF,MAAI,UAAU,mBAAmB,SAA6B,MAAc,OAAqB;AAChG,OAAI,KAAK,aACR,MAAK,aAAa,KAAK,aAAa,IAAI;AAEzC,UAAO,qBAAqB,MAAM,MAAM,CAAC,MAAM,MAAM,CAAC;;AAGvD,MAAI,UAAU,OAAO,SAA6B,MAAuD;GAQxG,MAAM,YAAY,QAPe;IAChC,KAAK,KAAK,YAAY;IACtB,SAAS,KAAK,eAAe,OAAO,aAAa;IACjD,SAAS,KAAK,gBAAgB,EAAE;IAChC,OAAO,OAAO,aAAa,eAAe,gBAAgB,WAAW,SAAY,SAAwC;IACzH,CAEqC;AAEtC,OAAI,WAAW;AACd,oBAAgB,MAAM,UAAU;AAChC;;AAGD,UAAO,SAAS,MAAM,MAAM,CAAC,KAAK,CAAC;;AAGpC,eAAa;AACZ,OAAI,UAAU,OAAO;AACrB,OAAI,UAAU,mBAAmB;AACjC,OAAI,UAAU,OAAO;;IAGvB;;;;;AC/FF,MAAM,sBAAsB;AAC5B,MAAM,qBAAqB;AAE3B,SAAS,YAAY,KAAa,eAAiD;AAClF,KAAI,cACH,QAAO,wBAAwB;AAEhC,KAAI,oBAAoB,KAAK,IAAI,CAChC,QAAO,wBAAwB;AAEhC,KAAI,mBAAmB,KAAK,IAAI,CAC/B,QAAO,wBAAwB;AAEhC,QAAO,wBAAwB;;AAGhC,SAAS,cAAc,SAAsD;AAC5E,KAAI,CAAC,QACJ,QAAO;AAER,MAAK,MAAM,QAAQ,QAClB,KAAI,KAAK,aAAa,CAAC,WAAW,QAAQ,CACzC,QAAO;AAGT,QAAO;;AAGR,SAAS,oBACR,KACA,SACA,eACgC;AAChC,KAAI,cACH,QAAO;AAER,KAAI,cAAc,QAAQ,CACzB,QAAO;AAER,QAAO,IAAI,SAAS,GAAG,WAAW,GAAG,GAAG,UAAU;;;;;;;;;;;;;AAqBnD,IAAa,qBAAb,MAAgC;CAC/B,WAAiC,EAAE;CACnC,aAA6B,EAAE;CAC/B,YAAY;CACZ,mBAAsC,EAAE;CACxC,2BAAW,IAAI,KAAsD;CACrE;CACA,eAAe;CAEf,CAASC,WAAY,YAA+C;EACnE,MAAM,MAAM,QAAQ;EAEpB,MAAM,iBADU,QAAQ,UAAU,OAAO,aAAa,KACrB,UAAU,MAAKC,gBAAiB,MAAM,MAAM,IAAI,WAAW,EAAE,CAAC;EAE/F,MAAM,gBAAgB,oBAAoB,KAAK,QAAQ,SAAS,cAAc;AAC9E,MAAI,kBAAkB,KACrB;EAGD,MAAMC,WAA+B;GACpC;GACA,MAAM,YAAY,KAAK,cAAc;GACrC;GACA,WAAW,KAAK,KAAK;GACrB;AACD,QAAKC,QAAS,KAAK,SAAS;AAC5B,MAAI,MAAKC,SACR,KAAI;AACH,SAAKA,SAAU,SAAS;WAChB,KAAK;AACb,WAAQ,MAAM,+CAA+C,IAAI;;AAGnE,QAAKC,eAAgB;AAErB,SAAO,gBAAgB,IAAI,SAAS,MAAM,EAAE,QAAQ,KAAK,CAAC,GAAG;;CAG9D,aAAa,MAAiE;AAC7E,SAAO,SAAS,SACb,CAAC,GAAG,MAAKF,QAAS,GAClB,MAAKA,QAAS,QAAQ,MAAM,EAAE,SAAS,KAAK;;CAGhD,iBAAuB;AACtB,OAAK,MAAM,CAAC,OAAO,WAAW,MAAKG,SAAU;GAC5C,MAAM,WAAW,MAAKC,YAAa,OAAO,KAAK;AAC/C,OAAI,SAAS,UAAU,OAAO,OAAO;AACpC,iBAAa,MAAM;AACnB,UAAKD,QAAS,OAAO,MAAM;AAC3B,WAAO,QAAQ,SAAS;;;;CAK3B,SACC,MACA,SACgC;EAChC,MAAM,QAAQ,QAAQ,SAAS;EAC/B,MAAM,UAAU,QAAQ,WAAW,MAAKE;EAExC,MAAM,WAAW,MAAKD,YAAa,KAAK;AACxC,MAAI,SAAS,UAAU,MACtB,QAAO,QAAQ,QAAQ,SAAS;AAGjC,SAAO,IAAI,SAA+B,SAAS,WAAW;GAC7D,MAAM,QAAQ,iBAAiB;AAC9B,UAAKD,QAAS,OAAO,MAAM;IAC3B,MAAM,UAAU,MAAKC,YAAa,KAAK;AACvC,2BAAO,IAAI,MACV,uBAAuB,MAAM,GAAG,QAAQ,MAAM,uBAAuB,QAAQ,OAAO,oBAAoB,MAAKJ,QAAS,OAAO,GAC7H,CAAC;MACA,QAAQ;AAEX,SAAKG,QAAS,IAAI,OAAO;IAAE;IAAM;IAAO;IAAS;IAAQ,CAAC;IACzD;;;;;;;;;;;CAYH,OAAO,UAAqC,EAAE,EAAQ;AACrD,MAAI,MAAKG,SACR;AAED,QAAKA,WAAY;AACjB,QAAKR,kBAAmB,QAAQ,mBAAmB,EAAE;AACrD,QAAKG,WAAY,QAAQ;AACzB,QAAKI,cAAe,QAAQ,eAAe;EAE3C,MAAM,aAAa,QAAQ,cAAc,CAAC,oBAAoB,EAAE,sBAAsB,CAAC;AACvF,OAAK,MAAM,aAAa,WACvB,OAAKE,UAAW,KAAK,UAAU,OAAO,MAAKV,QAAS,CAAC;;;;;;;;CAUvD,SAAe;AACd,MAAI,CAAC,MAAKS,SACT;AAED,OAAK,MAAM,YAAY,MAAKC,UAC3B,WAAU;AAEX,QAAKA,YAAa,EAAE;AACpB,QAAKD,WAAY;AACjB,QAAKR,kBAAmB,EAAE;AAC1B,QAAKG,WAAY;AAEjB,OAAK,MAAM,CAAC,OAAO,WAAW,MAAKE,SAAU;AAC5C,gBAAa,MAAM;AACnB,UAAO,uBAAO,IAAI,MAAM,kCAAkC,CAAC;;AAE5D,QAAKA,QAAS,OAAO;;;;;;;CAQtB,QAAc;AACb,QAAKH,UAAW,EAAE;;;;;;;CAQnB,aAAmC;AAClC,SAAO,CAAC,GAAG,MAAKA,QAAS;;;;;;;;;;CAW1B,eAAe,UAAyC,EAAE,EAAiC;AAC1F,SAAO,MAAKQ,QAAS,QAAW,QAAQ;;;;;;;;;;CAWzC,gBAAgB,UAAyC,EAAE,EAAiC;AAC3F,SAAO,MAAKA,QAAS,wBAAwB,UAAU,QAAQ;;;;;;;;;;CAWhE,gBAAgB,UAAyC,EAAE,EAAiC;AAC3F,SAAO,MAAKA,QAAS,wBAAwB,SAAS,QAAQ;;;;;;;;;;CAW/D,cAAc,UAAyC,EAAE,EAAiC;AACzF,SAAO,MAAKA,QAAS,wBAAwB,OAAO,QAAQ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;ACrO9D,MAAaC,0CAA+E,IAAI,IAAI;CACnG,CAAC,uBAAuB,MAAM;CAC9B,CAAC,0BAA0B,KAAK;CAChC,CAAC,uBAAuB,MAAM;CAC9B,CAAC,8BAA8B,KAAK;CACpC,CAAC,2BAA2B,KAAK;CACjC,CAAC;;;;;;;;;AChCF,MAAa,aAAa;;;;;;AAO1B,MAAa,eAAe;;;;;;;;AAS5B,MAAa,YAAY;;;;;;;;AASzB,MAAa,uBAAuB;CAMnC,MAAM;CAKN,OAAO;CAKP,SAAS;CAET;;;;;;;;;;;;;;;;AClCD,SAAgB,cAAc,KAA+C;AAC5E,KAAI,YAAY,IAAI,KAAK,KAAK,QAC7B,QAAO;CAGR,MAAMC,SAA8B,EAAE;AAEtC,MAAK,MAAM,CAAC,KAAK,UAAU,OAAO,QAAQ,IAAI,EAAE;AAC/C,MAAI,SAAS,MAAM;AAClB,UAAO,OAAO;AACd;;AAGD,MAAI,qBAAqB,IAAI,IAAI,IAAI,CAAC,MAAM,QAAQ,YAAY,MAAM,CAAC,CACtE,QAAO,OAAO,CAAC,MAAM;WAEb,QAAQ,SAAS,OAAO,UAAU,SAC1C,QAAO,OAAO,CAAC,MAAM;MAGrB,QAAO,OAAO;;AAIhB,QAAO;;;;;AC1BR,SAAS,YAAY,OAAyB,WAAmD;AAChG,KAAI,MAAM,QAAQ,MAAM,CACvB,QAAO,MAAM,KAAI,SAAQ,YAAY,MAAM,UAAU,CAAC;AAOvD,KAAI,OAAO,UAAU,SACpB,QAAO,cAAc,SAAY,YAAY,MAAM,GAAI;AAGxD,KAAI,iBAAiB,OAIpB,QAAO,MAAM,SACV,IAAI,OAAO,YAAY,MAAM,OAAO,UAAU,EAAE,MAAM,OAAO,GAC7D,YAAY,MAAM,OAAO,UAAU;AAGvC,QAAO;;AAoBR,SAAgB,WAAW,MAAc,SAA8C;AACtF,KAAI,CAAC,KACJ,QAAO,EAAE;CAGV,MAAM,SAAS,aAAa,MAAM,QAAQ;CAI1C,MAAMC,SAAkC,EAAE;AAC1C,MAAK,MAAM,CAAC,KAAK,SAAS,OAAO,QAAQ,OAAiC,CACzE,QAAO,OAAO,YAAY,MAAM,SAAS,UAAU;AAGpD,KAAI,SAAS,gBACZ,QAAO,cAAc,OAAO;AAG7B,QAAO;;;;;ACzBR,SAAS,sBAAsB,eAAkC,QAA6E,SAAqC;CAClL,MAAM,gBAAgB,IAAI,IAAI,OAAO,eAAe,EAAE,CAAC;AAEvD,QAAO;EACN,SAAS,OAAO,WAAW;EAC3B;EACA,SAAS,QAAiB,cAAc,IAAI,IAAI;EAChD;EACA,iBAAiB,OAAO;EACxB;;;;;;;;;AA8BF,SAAS,wBAAwB,GAAuB,GAAgC;AACvF,KAAI,MAAM,EAAG,QAAO;AACpB,KAAI,EAAE,WAAW,EAAE,OAAQ,QAAO;AAElC,MAAK,IAAI,IAAI,GAAG,IAAI,EAAE,QAAQ,KAAK;EAClC,MAAM,KAAK,EAAE;EACb,MAAM,KAAK,EAAE;AACb,MAAI,OAAO,GAAI;AACf,OAAK,OAAO,OAAO,WAAW,KAAK,GAAG,YAAY,OAAO,OAAO,WAAW,KAAK,GAAG,OAAQ,QAAO;EAGlG,MAAM,KAAK,OAAO,OAAO,WAAW,SAAY,GAAG;EACnD,MAAM,KAAK,OAAO,OAAO,WAAW,SAAY,GAAG;EACnD,MAAM,KAAK,MAAM,OAAO,KAAK,GAAG,CAAC;EACjC,MAAM,KAAK,MAAM,OAAO,KAAK,GAAG,CAAC;AACjC,MAAI,OAAO,GAAI,QAAO;AACtB,MAAI,OAAO,UAAa,OAAO,UAAa,MAAM,MAAM,GAAG,QAA2B,GAAG,IAAwB,QAAO;;AAGzH,QAAO;;;;;;;;AASR,SAAS,QAAQ,GAAY,GAAqB;CACjD,MAAM,QAAQ,YAAY,EAAE;CAC5B,MAAM,QAAQ,YAAY,EAAE;AAE5B,KAAI,CAAC,MAAM,QAAQ,MAAM,IAAI,CAAC,MAAM,QAAQ,MAAM,CACjD,QAAO,OAAO,GAAG,GAAG,EAAE;AAGvB,QAAO,wBAAwB,OAAO,MAAM;;AAG7C,MAAM,QAAQ,OAAO;AACrB,MAAM,YAAe,MAAY;;;;;AAMjC,MAAMC,eAA2D,sBAAM,KACtE,0BACC,CAAC,OAAO,WAA4B;AACpC,KAAI,UAAU,KACb,QAAO;EACN;EACA;EACA,OAAO;EACP,WAAW,MAAM,MAAM,QAAQ,EAAE,GAAG,EAAE,OAAO,GAAG,cAAc,EAAE;EAChE;AAEF,QAAO;EAAE;EAAc;EAAqB;EAAO,UAAU;EAAU;EAExE;AAED,MAAMC,wCAAqF,IAAI,IAC9E,6BAAa,KAAI,MAAK,CAAC,EAAE,OAAO,EAAE,CAAC,CACnD;AAED,SAAS,yBAA8D;AACtE,QAAO,IAAI,IAAI;EACd,GAAG;EACH,CAAC,yBAAyB,MAAM;EAChC,CAAC,kBAAkB,KAAK;EACxB,CAAC,8BAA8B,MAAM;EACrC,CAAC;;;;;;;AAQH,MAAMC,2BAAgF,wCAAwB;;;;;;;;;;AAW9G,SAAS,cAAc,OAAyB;AAC/C,KAAI,UAAU,QAAQ,OAAO,UAAU,SACtC,QAAO;CAGR,MAAM,OAAO,OAAO,OAAO,OAAO,OAAO,OAAO,eAAe,MAAM,CAAC,EAAE,MAAM;AAE9E,KAAI,KAAK,WAAW,QAAQ,OAAO,KAAK,WAAW,SAClD,MAAK,SAAS,EAAE,GAAG,KAAK,QAAQ;AAGjC,KAAI,MAAM,QAAQ,KAAK,MAAM,CAC5B,MAAK,QAAQ,KAAK,MAAM,IAAI,cAAc;AAG3C,QAAO;;;;;;;;;;;;;;;AAgBR,SAAS,iBAAiB,MAAkB;CAC3C,MAAM,SAAS;AAEf,MAAK,MAAM,OAAO,QAAQ;EACzB,MAAM,QAAQ,OAAO;AAErB,MAAI,MAAM,QAAQ,MAAM,EAAE;GACzB,MAAM,OAAO,IAAI,MAAM,MAAM,OAAO;AAEpC,QAAK,IAAI,IAAI,GAAG,IAAI,MAAM,QAAQ,IACjC,MAAK,KAAK,cAAc,MAAM,GAAG;AAGlC,UAAO,OAAO;aAEN,UAAU,QAAQ,OAAO,UAAU,SAC3C,QAAO,OAAO,cAAc,MAAM;;AAIpC,QAAO;;;;;;;;;;;AAYR,SAAS,eAAe,YAA2B;CAClD,MAAM,UAAW,eAAe,QAAQ,OAAO,eAAe,WAC1D,WAAmC,OACpC;AAEH,KAAI,OAAO,YAAY,YAAY,CAAC,QACnC,QAAO,EAAE;AAGV,KAAI;AACH,SAAO,WAAW,SAAS,EAAE,WAAW,OAAO,CAAC;SAE3C;AACL,SAAO,EAAE;;;;;;;;;AAUX,SAAS,eAAe,KAAa,KAAgD;AACpF,QAAO,OAAO,OAAO,OAAO,QAAQ,YAAY,MAAM;EAAE;EAAK;EAAK,GAAG,EAAE,KAAK,CAAC;;AAG9E,SAAS,iBAAiB,SAAoD;CAC7E,MAAM,EAAE,IAAK,GAAG,SAAS;AACzB,QAAO,MAAM,KAAK,KAAK;;AAGxB,SAAS,yBAA4B,QAAyE;CAE7G,MAAM,EACL,UAAU,SACV,eAAe,EAAE,EACjB,MAAM,MAAM,EACZ,mBAAmB,WACnB,GAAG,SACA;CAKJ,MAAM,YAAY,OAAO;CACzB,MAAM,mBAAmB,OAAO,cAAc,WAAW,KAAK,MAAM,UAAU,GAAG;AAEjF,QAAO;EACN,GAAG;EACH;EACA;EACA;EACA,kBAAkB,oBAAoB,IAAI,mBAAmB;EAE7D,cAAc,aAAa,QAAQ,KAAK,WAAW;AAClD,OAAI,QAAQ,OAAO,OAAO,QAAQ,OACjC,KAAI,KAAK;IACR,SAAS,OAAO,WAAW;IAC3B,aAAa,OAAO,aAAa,OAAO,IAAI,EAAE;IAC9C,KAAK,OAAO;IACZ,QAAQ,OAAO,OAAO,OAAO;IAC7B,UAAU,OAAO,YAAY;IAC7B,WAAW,OAAO,aAAa;IAC/B,WAAW,OAAO;IAClB,CAAC;AAEH,UAAO;KACL,EAAE,CAAyC;EAC9C;;;;;;;;;;;;;;;;;AA4DF,IAAa,eAAb,MAAuD;;;;;;;;;CAgCtD,YAAY,QAAwC,YAAoE,kBAAkB;oBA/BrH,YAAY,cAAc,YAAY,QAAQ,cAAc,KAAK,KAAK,GAAG,YAAY,KAAK;kCAU5F,IAAI,KAA6B;mCAQhC,IAAI,KAAyE;iBAC/E;AAajB,OAAK,SAAS,yBAAyB,OAAO;AAC9C,OAAK,UAAU,KAAK,cAAc,KAAK,OAAO,KAAK;GAClD,KAAK,KAAK,OAAO;GACjB,GAAG,KAAK,OAAO;GACf,CAAC;AACF,OAAK,SAAS,IAAI,KAAK,QAAQ,KAAK,KAAK,QAAQ;AACjD,OAAK,YAAY;;;;;;CAOlB,AAAQ,cAAc,KAAa,MAA4B;EAC9D,MAAM,+BAAe,IAAI,KAA0D;AAEnF,OAAK,MAAM,UAAU,KAAK,OAAO,aAChC,cAAa,IAAI,QAAQ;GACxB,IAAI;GACJ,SAAS;GACT,OAAO,EAAE;GACT,UAAU;GACV,CAAC;AAGH,SAAO;GACN;GAGA,YAAY,eAAe,KAAK,KAAK,IAAI;GACzC;GACA,KAAK;GAGL,aAAa,YAAY,KAAK,GAAG,KAAK,OAAO,EAAE,GAAG,EAAE,IAAI,OAAO;GAC/D;GACA,eAAe;IACd,IAAI;IACJ,SAAS;IACT;GACD;;;;;;;;;;CAWF,QAAc;AACb,OAAK,UAAU;EAOf,IAAIC;EAMJ,MAAM,UAAU,KAAK;AAErB,UAAQ,aAAa,SAAS,QAAQ,WAAW;AAEhD,QAAK,eAAe,OAAO;AAM3B,OAAI,OAAO,YAAY,CAAC,KAAK,YAAY,OAAO,CAC/C;AAGD,OAAI;AACH,SAAK,kBAAkB,SAAS,QAAQ,QAAQ,yBAAyB;AACzE,SAAK,qBAAqB;YAEpB,OAAO;AACb,gBAAY,EAAE,OAAO;;IAErB;AAEF,MAAI,QACH,OAAM,QAAQ;;;;;;;CAShB,AAAQ,YAAY,QAAqD;AAExE,MAAI,OAAO,aAAa,KAAK,CAAC,OAAO,OAAO,SAAS,yBAAyB,CAC7E,QAAO;AAGR,OAAK,UAAU,IAAI,QAAQ,kBAAkB;GAC5C,MAAM,UAAU,KAAK;GACrB,MAAM,SAAS,QAAQ,aAAa,IAAI,OAAO;AAE/C,OAAI,QAAQ;AACX,SAAK,kBAAkB,SAAS,QAAQ,QAAQ,yBAAyB;AACzE,SAAK,qBAAqB;;KAEzB,OAAO,WAAW,IAAK,CAAC;AAE3B,SAAO;;;;;;;;CASR,KAAK,QAAiB,OAAa;AAClC,OAAK,UAAU;AAEf,MAAI,MACH,MAAK,OAAO;AAGb,OAAK,MAAM,UAAU,KAAK,OAAO,aAChC,MAAK,eAAe,OAAO;;;;;;;CAS7B,QAAc;AACb,OAAK,oBAAoB,KAAK;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;CAgD/B,OAAO,MAA2B;AACjC,MAAI,KAAK,OAAO,KAAK,QAAQ,KAAK,QAAQ,IACzC,MAAK,aAAa,KAAK,IAAI;EAG5B,MAAM,UAAU,KAAK;EACrB,MAAM,EAAE,QAAQ;AAQhB,MAAI,OAAO,QAAQ,YAAY,OAAO,SAAS,IAAI,IAAI,OAAO,GAAG;GAChE,MAAM,UAAU,KAAK,MAAM,IAAI;AAE/B,OAAI,WAAW,gBACd,SAAQ,MAAM;;AAMhB,UAAQ,OAAO;GAAE,GAAG,QAAQ;GAAM,GAAG;GAAM,KAAK;GAAW,KAAK;GAAW;AAM3E,MAAI,QAAQ,KAAK,QAAQ,QAAQ,WAAW,IAC3C,SAAQ,aAAa,eAAe,QAAQ,KAAK,QAAQ,KAAK,IAAI;AAOnE,OAAK,MAAM,SAAS,aACnB,KAAI,MAAM,SAAS,QAAQ,CAAC,MAAM,MAAM,QAAQ,KAAK,MAAM,QAAQ,QAAQ,YAAY,MAAM,OAAO,CACnG,MAAK,YAAY,MAAM,MAAM;;;;;;;;;;;;;;;;;;CAqBhC,AAAQ,aAAa,KAAmB;AACvC,OAAK,QAAQ,OAAO,iBAAiB,EAAE,GAAG,KAAK,QAAQ,MAAM,CAAC;AAC9D,OAAK,UAAU,KAAK,cAAc,KAAK,EAAE,GAAG,KAAK,QAAQ,MAAM,CAAC;AAMhE,OAAK,SAAS,OAAO,IAAI;AACzB,OAAK,SAAS,IAAI,KAAK,KAAK,QAAQ;AAIpC,OAAK,qBAAqB;AAM1B,OAAK,MAAM,OAAO,KAAK,SAAS,MAAM,EAAE;AACvC,OAAI,KAAK,SAAS,QAAQ,KAAK,OAAO,mBAAmB,EACxD;AAGD,QAAK,SAAS,OAAO,IAAI;;AAO1B,MAAI,KAAK,SACR;QAAK,MAAM,UAAU,KAAK,OAAO,aAChC,KAAI,CAAC,KAAK,UAAU,IAAI,OAAO,CAC9B,MAAK,YAAY,OAAO;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;CAyC5B,YAAY,MAAqB,OAAsB,EAAE,EAAQ;AAChE,OAAK,UAAU,KAAK,SAAS,MAAM,KAAK;;;;;;;;;;;;;;;;;CAkBzC,AAAQ,UAAU,SAAyB,MAAqB,MAAqB,SAA6B;EACjH,MAAM,QAAQ,sBAAsB,IAAI,KAAK;AAC7C,MAAI,OAAO;GACV,MAAM,QAAQ,MAAM;GACpB,MAAM,WAAW,KAAK;AAEtB,OAAI,aAAa,OAChB,QAAO,OAAO,QAAQ,MAAM,GAAG,QAAQ,UAAU,CAAC;GAGnD,MAAM,UAAU,QAAQ,KAAK;AAK7B,OAAI,YAAY,OACf;AAGD,OAAI,MAAM,MAAM,SAAS,QAAQ,YAAY,OAAO,CACnD;AAGD,UAAO,OAAO,QAAQ,aAAa,GAAG,QAAQ,MAAM,SAAS,QAAQ,EAAE,CAAC;;EAOzE,IAAIA;AAEJ,UAAQ,aAAa,SAAS,QAAQ,WAAW;AAChD,OAAI;AACH,SAAK,kBAAkB,SAAS,QAAQ,QAAQ,MAAM,MAAM,QAAQ;YAE9D,OAAO;AACb,gBAAY,EAAE,OAAO;;IAErB;AAEF,OAAK,qBAAqB;AAK1B,MAAI,QACH,OAAM,QAAQ;;;;;;;;;;;;;;;CAiBhB,AAAQ,kBAAkB,SAAyB,QAAyB,QAA4C,MAAqB,OAAsB,EAAE,EAAE,SAA6B;AACnM,MAAI,OAAO,YAAY,CAAC,OAAO,OAAO,SAAS,KAAK,CACnD;EAKD,MAAMC,OAAa;GAClB,GAAG,QAAQ;GACX,GAAG;GACH,KAAK,QAAQ;GACb,GAAG;GACH,IAAI,KAAK,MAAM,KAAK,KAAK;GACzB;AAKD,MAAI,SAAS,gCAAgC,YAAY,KAAK,GAAG,KAAK,MACrE,QAAO,KAAK;EAGb,MAAM,EAAE,cAAc;AAEtB,MAAI,CAAC,WAAW;AACf,QAAK,iBAAiB,SAAS,QAAQ,QAAQ,MAAM,KAAK;AAC1D;;AAMD,mBAAiB,KAAK;EAItB,MAAM,cAAc,yBAAyB,IAAI,KAAK;EACtD,MAAM,gBAAgB,cAAe,KAAiC,eAAe;EACrF,MAAM,KAAK,KAAK;EAEhB,MAAM,SAAS,UAAU,MAAM,QAAQ;AAGvC,MAAI,UAAU,KACb;AAOD,MAAI,CAAC,QAAQ,OAAO,GAAG,CACtB,QAAO,KAAK;AAGb,MAAI,eAAe,QAAQ,cAAc,IAAI,CAAC,QAAS,OAAmC,aAAa,CACtG,QAAO,OAAO,QAAQ,GAAG,cAAc,eAAe,CAAC;AAGxD,OAAK,iBAAiB,SAAS,QAAQ,QAAQ,QAAQ,KAAK;;;;;;;;;;;;;;;;;CAkB7D,AAAQ,iBAAiB,SAAyB,QAAyB,QAA4C,QAAc,MAA2B;AAC/J,SAAO,IAAI;AACX,SAAO,KAAK,OAAO;AACnB,SAAO,MAAM,QAAQ;AAQrB,MAAI,CAAC,MAAM,QAAQ,IAAI,IAAI,CAAC,OAAO,WAAW,OAAO,aAAa,SAAS,MAAM,EAAE;AAClF,UAAO,MAAM,QAAQ;AACrB,UAAO,UAAU;QAGjB,QAAO,OAAO;AAGf,SAAO,MAAM,KAAK,WAAW,QAAQ,sBAAsB,iBAAiB,OAAO,CAAC,CAAC;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;CAyDtF,uBAAiE,UAA8G,OAAsB,EAAE,EAAQ;EAC9M,MAAM,EAAE,YAAY;EAEpB,MAAM,MAAM,KAAK,OAAO,SAAS;AAEjC,MAAI,CAAC,IACJ;EAGD,MAAM,aAAa,QAAQ,aAAa;EACxC,MAAM,UAAU,eAAe,SAAY,KAAK,UAAU,KAAK,eAAe,WAAW;AAEzF,MAAI,CAAC,QACJ;EAGD,MAAM,OAAO,eAAe,SAAY,EAAE,GAAG,QAAQ,YAAY,MAAM,GAAG,eAAe,WAAW;EAMpG,MAAM,EAAE,QAAS,cAAc,EAAE;EAEjC,MAAMC,UAAyB;GAC9B,KAAK,iBAAiB,IAAI;GAC1B,IAAI,SAAS;GACb;EAED,MAAM,SAAS,SAAS;AAExB,MAAI,QAAQ;AACX,OAAI,OAAO,aAAa,MAAM;AAC7B,YAAQ,KAAK,KAAK,MAAM,KAAK,aAAa,OAAO,UAAU;AAE3D,QAAI,OAAO,iBAAiB,KAC3B,SAAQ,OAAO,KAAK,MAAM,OAAO,gBAAgB,OAAO,UAAU;;AAIpE,OAAI,OAAO,YAAY,KACtB,SAAQ,OAAO,KAAK,MAAM,OAAO,SAAS;;AAI5C,OAAK,UAAU,SAAS,8BAA8B;GACrD,GAAI,OAAO,QAAQ,YAAY,MAAM,EAAE,KAAK,GAAG;GAC/C,GAAG;GACH,GAAG;GACH,GAAG;GACH,EAAE,QAAQ;;;;;;;;;;;CAYZ,AAAQ,eAAe,YAAiD;AACvE,MAAI,eAAe,QAAQ,OAAO,eAAe,SAChD;EAGD,MAAM,EAAE,QAAQ;AAEhB,SAAO,OAAO,QAAQ,WAAW,KAAK,SAAS,IAAI,IAAI,GAAG;;;;;;;;;;;CAY3D,mBAAmB,KAA+B;AACjD,SAAO,KAAK,oBAAoB,IAAI,IAAI;;;;;;;CAQzC,4BAAqC;AACpC,SAAO,CAAC,CAAC,KAAK,OAAO,aAAa;;;;;;;;;;;;CAanC,AAAQ,wBAAwB,MAAiC,SAAoD;EACpH,MAAM,OAAO,KAAK,QAAQ;AAE1B,MAAI,CAAC,KACJ,QAAO;AAGR,MAAI;GACH,MAAM,UAAU,WAAW,MAAc;IACxC,SAAS,KAAK,OAAO;IACrB,eAAe;IACf;IACA,CAAC;AAEF,UAAO,UAAU,OAAO,OAAO;IAAE,GAAG;IAAM,MAAM;IAAS,CAAC,GAAG;UAExD;AACL,UAAO;;;;;;;;;;;;;;;;;;;;;CAsBT,oBAAuF,SAAY,MAA8D;EAChK,MAAM,EAAE,aAAa,EAAE,EAAE,UAAU,EAAE,CAAE,GAAG,SAAS;EACnD,MAAM,SAAS;GACd,GAAG;GACH,SAAS,EACR,GAAG,SACH;GACD,YAAY;IACX,GAAG;IACH,MAAM,EAAE;KASP,0BAA0B,KAAK,wBAAwB,MAAM,QAAQ,IAAI;IAC1E;GACD;AAED,MAAI,CAAC,KAAK,OAAO,aAAa,UAAU,CAAC,OAAO,IAC/C,QAAO;EAMR,MAAM,UAAU,KAAK;EACrB,MAAMC,SAAe;GAAE,GAAG,QAAQ;GAAM,GAAG;GAAM,KAAK,QAAQ;GAAK;EACnE,MAAM,EAAE,cAAc,KAAK;EAC3B,IAAIC,WAAwB;AAE5B,MAAI,WAAW;AAGd,oBAAiB,OAAO;AAIxB,cAAW,UAAU,QAAQ,QAAmC;AAGhE,OAAI,YAAY,KACf,QAAO;;AAKT,WAAS,KAAK,QAAQ,cAAc;AACpC,WAAS,MAAM,QAAQ;EAOvB,MAAM,UAAU,CAAC,MAAM,QAAQ,IAAI,IAAI,CAAC,QAAQ,cAAc;AAE9D,MAAI,QACH,UAAS,MAAM,QAAQ;MAGvB,QAAO,SAAS;EAGjB,MAAM,UAAU,sBAAsB,mBAAmB,KAAK,QAAQ,OAAO,IAAI;EAQjF,MAAM,OAAO,OAAO,WAAW,OAAO,iBAAiB,gBAAgB,UAAU,QAAQ,CAAC;AAE1F,MAAI,WAAW,KAAK,QAAQ,OAC3B,SAAQ,cAAc,UAAU;EAGjC,MAAM,UAAU,mBAAmB,KAAK;AAExC,UAAQ,KAAK,OAAO,kBAApB;GACC,KAAK;AACJ,QAAI,QACH,QAAO,MAAM,iBAAiB,OAAO,KAAK,QAAQ;AAEnD;GAED,KAAK;AACJ,WAAO,OAAO,OAAO,SAAS,sBAAsB,MAAM,QAAQ,gBAAgB,CAAC;AACnF;;AAGF,SAAO;;;;;;;;CASR,AAAQ,oBAAoB,QAAiB,OAAa;EACzD,IAAI,YAAY;AAIhB,OAAK,SAAS,SAAS,YAAY;GAKlC,MAAM,QAAQ,SAAS,YAAY,KAAK;AAExC,WAAQ,aAAa,SAAS,QAAQ,WAAW;IAChD,MAAM,EAAE,UAAU;AAIlB,QAAI,OAAO,YAAY,CAAC,MAAM,OAC7B;AAGD,QAAI,MAAM,SAAS,OAAO,aAAa,CAAC,MACvC;IAGD,MAAM,cAAc,QAAQ,MAAM,SAAS,OAAO;IAClD,MAAM,SAAS,MAAM,OAAO,GAAG,YAAY;AAC3C,SAAK,gBAAgB,SAAS,QAAQ,OAAO,CAAC,YAAY;AAIzD,YAAO,MAAM,QAAQ,GAAG,OAAO;MAC9B;AAEF,kBAAc,MAAM,SAAS;KAC5B;IACD;AAEF,MAAI,UACH,MAAK,qBAAqB;;;;;;;;;CAW5B,MAAc,gBAAgB,SAAyB,QAA4C,MAA+B;EAUjI,MAAM,EAAE,WATS,MAAM,KAAK,UAAU;GACrC,KAAK,OAAO;GACZ,QAAQ;GACR,SAAS,EACR,gBAAgB,gBAChB;GACD,MAAM,KAAK,KAAK,KAAK;GACrB,CAAC;AAIF,MAAI,WAAW,IAKd,MAAK,mBAAmB,SAAS,OAAO;WAC9B,WAAW,OAAQ,SAAS,OAAO,SAAS,IACtD,OAAM,IAAI,MAAM,mCAAmC,SAAS;;;;;;;CAS9D,AAAQ,eAAe,QAAkD;AACxE,gBAAc,KAAK,UAAU,IAAI,OAAO,CAAC;AACzC,OAAK,UAAU,OAAO,OAAO;;;;;;;;;;CAW9B,AAAQ,mBAAmB,SAAyB,QAAkD;AACrG,UAAQ,aAAa,SAAS,QAAQ,YAAY;AACjD,OAAI,QAAQ,QAAQ,OAAO,OAAO,OAAO,SACxC;AAGD,UAAO,WAAW;AAClB,UAAO,MAAM,SAAS;AAItB,OAAI,YAAY,KAAK,QACpB,MAAK,eAAe,QAAQ;IAE5B;;;;;;;;;;;;;;;ACzxCJ,MAAa,sBAAsB;CAIlC,MAAM;CAKN,KAAK;CAKL,QAAQ;CAKR,OAAO;CACP;;;;;;;;;;;;;ACpBD,MAAa,iBAAiB;CAI7B,KAAK;CAKL,MAAM;CAKN,aAAa;CACb;;;;;;;;;ACnBD,MAAa,iCAAiC;;;;;;AAO9C,MAAa,mCAAmC;;;;;;AAOhD,MAAa,yBAAyB;CACrC,OAAO;CACP,SAAS;CACT;;;;;;;;;;;;AChBD,SAAgB,cAAc,SAAoD;AACjF,QAAO,mBAAmB,UAAU,UAAU,IAAI,QAAQ,QAAQ;;;;;ACgBnE,SAAgB,gBAAgB,SAA2C,SAA8C;CACxH,MAAM,IAAI,cAAc,QAAQ;CAEhC,MAAMC,SAAkC,EAAE;AAC1C,MAAK,MAAM,SAAS,oBAAoB;EACvC,MAAM,QAAQ,EAAE,IAAI,MAAM;AAC1B,MAAI,MACH,QAAO,OAAO,QAAQ,WAAW,MAAM,CAAC;;AAI1C,KAAI,SAAS,gBACZ,QAAO,cAAc,OAAO;AAG7B,QAAO;;;;;ACjBR,SAAgB,cAAc,OAAiC,SAA8C;AAC5G,KAAI,OAAO,UAAU,SACpB,SAAQ,IAAI,gBAAgB,MAAM;AAKnC,QAAO,WAFO,MAAM,IAAI,WAAW,IAER,IAAI,QAA6B;;;;;ACL7D,SAAgB,YAAY,KAAa,SAA8C;AACtF,QAAO,WAAW,mBAAmB,IAAI,QAAQ,UAAU,GAAG,CAAC,QAAQ,OAAO,IAAI,CAAC,EAAE,QAA6B;;;;;ACrBnH,MAAMC,uCAA4D,IAAI,IAAI,kBAAkB;;;;;;;;;;;;;AAc5F,SAAgB,iBAAiB,KAAgC;AAChE,QAAO,qBAAqB,IAAI,IAAI,IACnC,gBAAgB,IAAe;;;;;AClBjC,MAAMC,wCAA6D,IAAI,IAAI,mBAAmB;;;;;;;;;;;;;AAc9F,SAAgB,0BAA0B,KAAgC;AACzE,QAAO,sBAAsB,IAAI,IAAI;;;;;ACbtC,MAAMC,qCAA0D,IAAI,IAAI,gBAAgB;;;;;;;;;;;;;AAcxF,SAAgB,eAAe,KAAgC;AAC9D,QAAO,iBAAiB,IAAI,IAC3B,0BAA0B,IAAI,IAC9B,mBAAmB,IAAI,IAAI;;;;;;;;;;;;;;;;;ACN7B,SAAgB,aAAa,MAAoC;AAChE,QAAO,KAAK,MAAM;;;;;ACbnB,MAAMC,oCAAuD,IAAI,IAAI,aAAa;;;;;;;;;;;;;AAclF,SAAgB,YAAY,KAA6B;AACxD,QAAOC,kBAAgB,IAAI,IAAI,IAAI,gBAAgB,IAAe;;;;;;;;;;;;;;;;;ACHnE,SAAgB,aAAa,MAAoC;AAChE,QAAO,KAAK,MAAM;;;;;;;;;;;;;;;;;;;;ACGnB,SAAgB,UAAU,MAAY,UAA6B,EAAE,EAAU;AAC9E,KAAI,CAAC,KACJ,QAAO;AAKR,QAAO,cAFQ,WAAW,MAAM,QAAQ,CAEZ;;;;;;;;;;;;;;;;;;;;ACP7B,SAAgB,YAAY,MAAY,UAA6B,EAAE,EAAU;AAChF,KAAI,CAAC,KACJ,QAAO;AAKR,QAAO,GAAG,WAAW,GAFP,UAAU,MAAM,QAAQ;;;;;;;;;;;;;;ACdvC,SAAgB,YAAqC,OAAU,QAA0B;AACxF,QAAO,IAAI,OAAO,OAAO,OAAO;;;;;;;;;;ACJjC,SAAgB,uBAAuB,GAAG,SAAuD;CAChG,MAAM,SAAS,QAAQ,SAAQ,MAAK,EAAE,OAAO;AAC7C,QAAO;EACN,OAAO,OAAO,OAAM,MAAK,EAAE,aAAa,+BAA+B;EACvE;EACA;;;;;;;;;;ACJF,SAAgB,eAAe,MAA+B,SAAyC;AACtG,KAAI,SAAS,YAAY,KAAK,SAAS,YAAY,EAClD,QAAO,QAAQ;CAGhB,MAAM,iBAAiB,YAAY,KAAK,KAAK;AAC7C,KAAI,mBAAmB,KAAK,mBAAmB,EAC9C,QAAO;AAGR,QAAO;;;;;ACTR,MAAMC,kCAAuD,IAAI,IAAI,aAAa;AAClF,MAAMC,+BAAoD,IAAI,IAAI,UAAU;;;;;;;;;;;;;;;AAgB5E,SAAgB,iBAAiB,MAA+B,SAAuD;CACtH,MAAM,UAAU,eAAe,MAAM,QAAQ;CAC7C,MAAM,cAAc,YAAY,UAAU,kBAAkB;CAC5D,MAAMC,SAAyC,EAAE;AAEjD,MAAK,MAAM,OAAO,OAAO,KAAK,KAAK,EAAE;AACpC,MAAI,gBAAgB,IAAe,CAClC;AAGD,MAAI,CAAC,YAAY,IAAI,IAAI,CACxB,QAAO,KAAK;GACX;GACA,SAAS,qBAAqB,IAAI,gBAAgB,QAAQ;GAC1D,UAAU;GACV,CAAC;;AAIJ,QAAO;EACN,OAAO,OAAO,WAAW;EACzB;EACA;;;;;;;;;;;;;;ACtCF,MAAaC,8BAAuD;CACnE,IAAI;CACJ,KAAK;CACL,KAAK;CACL;;;;;;;;;;;;;ACND,MAAaC,wBAA2D;CACvE,GAAG;EAAC;EAAK;EAAK;EAAM;EAAM;EAAK;EAAI;CACnC,KAAK;EAAC;EAAK;EAAK;EAAM;EAAI;CAC1B;;;;;;;;;;;;;;;;;;ACiBD,SAAgB,sBAAsB,MAA+B,SAAuD;CAC3H,MAAM,UAAU,eAAe,MAAM,QAAQ;CAC7C,MAAMC,SAAgC,EAAE;AAGxC,KAAI,SAAS,kBAAkB,mBAAmB;AACjD,OAAK,MAAM,OAAO,gBACjB,KAAI,OAAO,KACV,QAAO,KAAK;GACX;GACA,SAAS,cAAc,IAAI;GAC3B,UAAU;GACV,CAAC;AAGJ,OAAK,MAAM,OAAO,mBACjB,KAAI,OAAO,KACV,QAAO,KAAK;GACX;GACA,SAAS,iBAAiB,IAAI;GAC9B,UAAU;GACV,CAAC;;AAML,KAAI,SAAS,kBAAkB,iBAAiB;AAC/C,MAAI,EAAE,OAAO,MACZ,QAAO,KAAK;GACX,KAAK;GACL,SAAS;GACT,UAAU;GACV,CAAC;AAEH,MAAI,EAAE,QAAQ,MACb,QAAO,KAAK;GACX,KAAK;GACL,SAAS;GACT,UAAU;GACV,CAAC;;AAKJ,KAAI,OAAO,MAAM;EAChB,MAAM,YAAY,cAAc,KAAK,KAAK;AAE1C,MAAI,cAAc,yBACjB;OAAI,EAAE,SAAS,MACd,QAAO,KAAK;IACX,KAAK;IACL,SAAS;IACT,UAAU;IACV,CAAC;aAIC,SAAS,KACZ,QAAO,KAAK;GACX,KAAK;GACL,SAAS;GACT,UAAU;GACV,CAAC;AAKJ,MAAI,cAAc,8BACjB;OAAI,EAAE,SAAS,MACd,QAAO,KAAK;IACX,KAAK;IACL,SAAS;IACT,UAAU;IACV,CAAC;QAIH,MAAK,MAAM,OAAO,mBACjB,KAAI,OAAO,KACV,QAAO,KAAK;GACX;GACA,SAAS,iBAAiB,IAAI;GAC9B,UAAU;GACV,CAAC;AAML,MAAI,cAAc,yBAAyB,EAAE,SAAS,MACrD,QAAO,KAAK;GACX,KAAK;GACL,SAAS;GACT,UAAU;GACV,CAAC;AAIH,MAAI,cAAc,oBAAoB,EAAE,QAAQ,MAC/C,QAAO,KAAK;GACX,KAAK;GACL,SAAS;GACT,UAAU;GACV,CAAC;;CAKJ,MAAM,KAAK,UAAU,IAAI,cAAc,KAAK,MAAM,GAAG;AACrD,KAAI,OAAO,OACV,MAAK,MAAM,OAAO,uBAAuB;EACxC,MAAM,cAAc,sBAAsB;AAC1C,MAAI,OAAO,QAAQ,CAAC,YAAY,SAAS,GAAG,CAC3C,QAAO,KAAK;GACX;GACA,SAAS,QAAQ,IAAI,sCAAsC,GAAG,iCAAiC,YAAY,KAAK,KAAK,CAAC;GACtH,UAAU;GACV,CAAC;;AAML,KAAI,UAAU,EACb,MAAK,MAAM,OAAO,6BAA6B;EAC9C,MAAM,WAAW,4BAA4B;AAC7C,MAAI,OAAO,QAAQ,YAAY,KAC9B,QAAO,KAAK;GACX;GACA,SAAS,QAAQ,IAAI,8BAA8B,SAAS;GAC5D,UAAU;GACV,CAAC;;CAML,MAAM,IAAI,YAAY,KAAK,KAAK;AAChC,KAAI,OAAO,QAAQ,MAAM,KAAK,MAAM,EACnC,QAAO,KAAK;EACX,KAAK;EACL,SAAS,6BAA6B,OAAO,EAAE,CAAC;EAChD,UAAU;EACV,CAAC;UAEM,UAAU,KAAK,EAAE,OAAO,MAChC,QAAO,KAAK;EACX,KAAK;EACL,SAAS;EACT,UAAU;EACV,CAAC;UAEM,YAAY,WAAW,OAAO,KACtC,QAAO,KAAK;EACX,KAAK;EACL,SAAS;EACT,UAAU;EACV,CAAC;AAGH,QAAO;EACN,OAAO,OAAO,OAAM,MAAK,EAAE,aAAa,+BAA+B;EACvE;EACA;;;;;;;;;;AC5LF,MAAa,4BAA4B;;;;;;AAOzC,MAAa,4BAA4B;;;;;;AAOzC,MAAa,wBAAwB;;;;;;AAOrC,MAAa,uBAAuB;;;;;;AAOpC,MAAa,wBAAwB;;;;;;AAOrC,MAAa,uBAAuB;;;;;;AAOpC,MAAa,sBAAsB;;;;;;;AAQnC,MAAaC,iBAAyC;CAErD,IAAI;CACJ,IAAI;CACJ,IAAI;CACJ,KAAK;CACL,KAAK;CACL,MAAM;CACN,KAAK;CACL,IAAI;CACJ,KAAK;CACL,IAAI;CACJ,KAAK;CACL,IAAI;CACJ,KAAK;CACL,KAAK;CAGL,IAAI;CACJ,KAAK;CAGL,GAAG;CACH,KAAK;CACL,IAAI;CACJ,KAAK;CACL,KAAK;CACL,IAAI;CACJ,IAAI;CACJ,KAAK;CACL,IAAI;CACJ,IAAI;CACJ,MAAM;CACN,OAAO;CACP,MAAM;CACN,GAAG;CAGH,IAAI;CAGJ,IAAI;CACJ,IAAI;CACJ,IAAI;CACJ,IAAI;CAGJ,KAAK;CACL,KAAK;CACL,KAAK;CACL,OAAO;CACP,OAAO;CACP,IAAI;CACJ,GAAG;CACH,KAAK;CACL,KAAK;CACL,MAAM;CACN,KAAK;CAGL,GAAG;CACH,IAAI;CACJ,IAAI;CACJ,IAAI;CACJ,KAAK;CACL;;;;;;AAOD,MAAaC,6BAAqD;CACjE,IAAI;CACJ,IAAI;CACJ,KAAK;CACL,IAAI;CACJ,KAAK;CACL;;;;;;;;;AChID,MAAaC,4BAAoD;CAChE,KAAK;CACL,KAAK;CACL,KAAK;CACL,GAAG;CACH,KAAK;CACL;;;;;;AAOD,MAAa,mCAAmC;;;;;;;;;ACbhD,MAAaC,oBAAuD;CACnE,GAAG;EAAC;EAAM;EAAM;EAAM;EAAK;EAAK;EAAK;EAAK;EAAK;EAAM;EAAM;EAAM;EAAM;EAAM;EAAM;EAAO;EAAO;EAAM;EAAK;CAC5G,IAAI;EAAC;EAAK;EAAK;EAAK;EAAM;EAAK;EAAK;EAAM;EAAK;EAAI;CACnD,IAAI;EAAC;EAAK;EAAK;EAAK;EAAI;CACxB,IAAI;EAAC;EAAK;EAAK;EAAK;CACpB,KAAK;EAAC;EAAK;EAAK;EAAK;EAAK;EAAK;EAAK;EAAK;EAAK;EAAK;EAAI;CACvD;;;;ACGD,MAAMC,yBAAiD;CACtD,IAAI;CACJ,IAAI;CACJ,KAAK;CACL,KAAK;CACL,KAAK;CACL;AAED,SAAS,eAAe,OAAiC;AACxD,QAAO,OAAO,UAAU,YAAY,OAAO,SAAS,MAAM;;AAG3D,SAAS,UAAU,OAAiC;AACnD,QAAO,OAAO,UAAU,MAAM;;AAI/B,SAAS,iBAAiB,KAAa,OAAe,SAAiB,QAA+B,OAAsB;CAC3H,MAAM,OAAO,uBAAuB;AACpC,KAAI,CAAC,QAAQ,QAAQ,QAAQ,EAC5B;CAED,MAAM,SAAS,QAAQ,SAAU,QAAQ,QAAQ,YAAY;CAC7D,MAAM,SAAS,UAAU,SAAY,QAAQ,IAAI,KAAK,QAAQ,IAAI,mBAAmB,MAAM;AAC3F,QAAO,KAAK;EACX;EACA,SAAS,GAAG,OAAO,GAAG,SAAS,WAAW,OAAO,iCAAiC,KAAK,aAAa,MAAM;EAC1G,UAAU,SAAS,mCAAmC;EACtD,CAAC;;AAGH,SAAS,kBAAkB,KAAa,OAAgB,SAAiB,QAAqC;AAC7G,KAAI,CAAC,MAAM,QAAQ,MAAM,EAAE;AAC1B,SAAO,KAAK;GACX;GACA,SAAS,QAAQ,IAAI;GACrB,UAAU;GACV,CAAC;AACF;;AAED,MAAK,IAAI,IAAI,GAAG,IAAI,MAAM,QAAQ,KAAK;EACtC,MAAM,UAAU,YAAY,MAAM,GAAG;AACrC,MAAI,CAAC,UAAU,QAAQ,CACtB,QAAO,KAAK;GACX;GACA,SAAS,QAAQ,IAAI,mBAAmB,EAAE;GAC1C,UAAU;GACV,CAAC;MAGF,kBAAiB,KAAK,SAAS,SAAS,QAAQ,EAAE;;;AAKrD,SAAS,yBAAyB,KAAa,OAAgB,QAAqC;AACnG,KAAI,CAAC,MAAM,QAAQ,MAAM,EAAE;AAC1B,SAAO,KAAK;GACX;GACA,SAAS,QAAQ,IAAI;GACrB,UAAU;GACV,CAAC;AACF;;AAED,MAAK,IAAI,IAAI,GAAG,IAAI,MAAM,QAAQ,IACjC,KAAI,OAAO,YAAY,MAAM,GAAG,KAAK,SACpC,QAAO,KAAK;EACX;EACA,SAAS,QAAQ,IAAI,mBAAmB,EAAE;EAC1C,UAAU;EACV,CAAC;;;;;;;;;;;;;;;;AAmBL,SAAgB,mBAAmB,MAA+B,SAAuD;CACxH,MAAM,UAAU,eAAe,MAAM,QAAQ;CAC7C,MAAMC,SAAgC,EAAE;AAExC,MAAK,MAAM,CAAC,KAAK,UAAU,OAAO,QAAQ,KAAK,EAAE;EAChD,MAAM,QAAQ,YAAY,MAAM;AAChC,MAAI,gBAAgB,IAAe,EAAE;AAEpC,OAAI,OAAO,UAAU,SACpB,QAAO,KAAK;IACX;IACA,SAAS,eAAe,IAAI;IAC5B,UAAU;IACV,CAAC;YAEM,MAAM,SAAS,iCACvB,QAAO,KAAK;IACX;IACA,SAAS,eAAe,IAAI,oCAAoC,iCAAiC;IACjG,UAAU;IACV,CAAC;AAEH;;AAID,MAAI,QAAQ,KAAK;AAChB,OAAI,UAAU,KAAK,UAAU,EAC5B,QAAO,KAAK;IACX;IACA,SAAS;IACT,UAAU;IACV,CAAC;AAEH;;EAID,IAAI,eAAe,eAAe;AAClC,MAAI,CAAC,aACJ;AAGD,MAAI,YAAY,WAAW,OAAO,2BACjC,gBAAe,2BAA2B;AAG3C,UAAQ,cAAR;GACC,KAAK;AACJ,QAAI,CAAC,UAAU,MAAM,CACpB,QAAO,KAAK;KACX;KACA,SAAS,QAAQ,IAAI;KACrB,UAAU;KACV,CAAC;QAGF,kBAAiB,KAAK,OAAO,SAAS,OAAO;AAE9C;GAED,KAAK;AACJ,QAAI,CAAC,eAAe,MAAM,CACzB,QAAO,KAAK;KACX;KACA,SAAS,QAAQ,IAAI;KACrB,UAAU;KACV,CAAC;AAEH;GAED,KAAK;AACJ,QAAI,OAAO,UAAU,UACpB,QAAO,KAAK;KACX;KACA,SAAS,QAAQ,IAAI;KACrB,UAAU;KACV,CAAC;AAEH;GAED,KAAK;AACJ,QAAI,OAAO,UAAU,SACpB,QAAO,KAAK;KACX;KACA,SAAS,QAAQ,IAAI;KACrB,UAAU;KACV,CAAC;aAEM,OAAO,6BAA6B,MAAM,SAAS,0BAA0B,KACrF,QAAO,KAAK;KACX;KACA,SAAS,QAAQ,IAAI,8BAA8B,0BAA0B,KAAK;KAClF,UAAU;KACV,CAAC;AAEH;GAED,KAAK,qBAAqB;IACzB,MAAM,cAAc,kBAAkB;IACtC,MAAM,QAAQ,cAAc,MAAM;AAClC,QAAI,gBAAgB,UAAU,UAAa,CAAC,YAAY,SAAS,MAAM,EACtE,QAAO,KAAK;KACX;KACA,SAAS,QAAQ,IAAI,6BAA6B,SAAS,OAAO,MAAM,CAAC,sBAAsB,YAAY,KAAK,KAAK,CAAC;KACtH,UAAU;KACV,CAAC;AAEH;;GAGD,KAAK;AACJ,sBAAkB,KAAK,OAAO,SAAS,OAAO;AAC9C;GAED,KAAK;AACJ,6BAAyB,KAAK,OAAO,OAAO;AAC5C;;;AAIH,QAAO;EACN,OAAO,OAAO,OAAM,MAAK,EAAE,aAAa,+BAA+B;EACvE;EACA;;;;;;;;;;;;;;;;;;;AC9MF,SAAgB,aAAa,MAA+B,SAAuD;AAClH,QAAO,uBACN,iBAAiB,MAAM,QAAQ,EAC/B,mBAAmB,MAAM,QAAQ,EACjC,sBAAsB,MAAM,QAAQ,CACpC;;;;;;;;;;;;;;;;;;;;;;;;;ACKF,SAAgB,mBAAmB,MAAc,SAAoF;CACpI,MAAM,OAAO;EAAE,GAAG;EAAS,eAAe;EAAiB;CAC3D,MAAM,QAAQ,KAAK,MAAM,QAAQ,CAAC,QAAO,SAAQ,KAAK,SAAS,EAAE;AAEjE,KAAI,MAAM,WAAW,EACpB,QAAO;EACN,OAAO;EACP,QAAQ,CAAC;GACR,SAAS;GACT,UAAU;GACV,CAAC;EACF,MAAM,EAAE;EACR;CAGF,MAAMC,aAAoC,EAAE;AAC5C,KAAI,KAAK,SAAS,KAAK,CACtB,YAAW,KAAK;EACf,SAAS;EACT,UAAU;EACV,CAAC;CAGH,MAAMC,eAA2B,EAAE;CACnC,MAAMC,cAAsC,EAAE;AAE9C,MAAK,IAAI,IAAI,GAAG,IAAI,MAAM,QAAQ,IACjC,KAAI;EACH,MAAM,OAAO,WAAW,MAAM,GAAG;AACjC,eAAa,KAAK,KAAK;AACvB,cAAY,KAAK,aAAa,MAAM,KAAK,CAAC;SACnC;AACP,eAAa,KAAK,EAAE,CAAa;AACjC,cAAY,KAAK;GAChB,OAAO;GACP,QAAQ,CAAC;IACR,SAAS,+BAA+B,IAAI,EAAE;IAC9C,UAAU;IACV,CAAC;GACF,CAAC;;AAKJ,QAAO;EAAE,GADM,uBAAuB;GAAE,OAAO;GAAM,QAAQ;GAAY,EAAE,GAAG,YAAY;EACtE,MAAM;EAAc;;;;;;;;;;;;;;;;;;;;;;;;AChDzC,SAAgB,wBAAwB,SAAsB,SAAoF;CACjJ,MAAMC,SAA+C,EAAE;AAEvD,KAAI,QAAQ,WAAW,OACtB,QAAO,KAAK;EACX,SAAS,wBAAwB,QAAQ,UAAU,MAAM;EACzD,UAAU;EACV,CAAC;CAGH,MAAM,cAAc,QAAQ,UAAU,cAAc,QAAQ,QAAQ,CAAC,IAAI,eAAe,GAAG;AAE3F,KAAI,CAAC,YACJ,QAAO,KAAK;EACX,SAAS,wDAAwD,eAAe;EAChF,UAAU;EACV,CAAC;MACI;EACN,MAAM,YAAY,YAAY,MAAM,IAAI,CAAC,GAAG,MAAM,CAAC,aAAa;AAChE,MAAI,cAAc,eACjB,QAAO,KAAK;GACX,SAAS,yBAAyB,UAAU,6BAA6B,eAAe;GACxF,UAAU;GACV,CAAC;;CAIJ,MAAM,OAAO,QAAQ;AACrB,KAAI,SAAS,UAAa,SAAS,MAAM;AACxC,SAAO,KAAK;GACX,SAAS;GACT,UAAU;GACV,CAAC;AACF,SAAO;GACN,OAAO;GACP;GACA,MAAM,EAAE;GACR;;AAGF,KAAI,OAAO,SAAS,UAAU;AAC7B,SAAO,KAAK;GACX,SAAS;GACT,UAAU;GACV,CAAC;AACF,SAAO;GACN,OAAO;GACP;GACA,MAAM,EAAE;GACR;;CAGF,MAAM,aAAa,mBAAmB,MAAM,QAAQ;AAEpD,QAAO;EACN,OAAO,OAAO,WAAW,KAAK,WAAW;EACzC,QAAQ,CAAC,GAAG,QAAQ,GAAG,WAAW,OAAO;EACzC,MAAM,WAAW;EACjB;;;;;;;;;;;;;;;;;;;;;;;;ACnDF,SAAgB,oBAAoB,SAA2C,SAAkF;CAChK,MAAM,IAAI,cAAc,QAAQ;CAChC,MAAMC,SAAyC,EAAE;CACjD,MAAMC,UAAqE,EAAE;AAE7E,MAAK,MAAM,eAAe,oBAAoB;EAC7C,MAAM,MAAM,EAAE,IAAI,YAAY;AAC9B,MAAI,CAAC,IACJ;EAGD,IAAIC;AACJ,MAAI;AACH,WAAQ,WAAW,IAAI;UAChB;AACP,UAAO,KAAK;IACX,KAAK;IACL,SAAS,qBAAqB,YAAY;IAC1C,UAAU;IACV,CAAC;AACF;;AAED,UAAQ,eAAe;AAEvB,OAAK,MAAM,OAAO,OAAO,KAAK,MAAM,EAAE;AACrC,OAAI,gBAAgB,IAAe,CAClC;GAGD,MAAM,iBAAiB,gBAAgB;AACvC,OAAI,kBAAkB,mBAAmB,YACxC,QAAO,KAAK;IACX;IACA,SAAS,QAAQ,IAAI,WAAW,YAAY,sBAAsB,eAAe;IACjF,UAAU;IACV,CAAC;;;CAKL,MAAMC,cAAoC;EACzC,OAAO,OAAO,WAAW;EACzB;EACA;CAED,MAAMC,SAAkC,OAAO,OAAO,EAAE,EAAE,GAAG,mBAAmB,KAAI,MAAK,QAAQ,GAAG,CAAC,OAAO,QAAQ,CAAC;AAIrH,QAAO;EAAE,GADM,uBAAuB,aAFhB,aAAa,QAAQ;GAAE,GAAG;GAAS,eAAe;GAAmB,CAAC,CAE3B;EAC7C,MAAM;EAAoB;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;AC3C/C,SAAgB,oBAAoB,SAAgC,SAAkF;CACrJ,MAAM,UAAU,oBAAoB,QAAQ,QAAQ;CACpD,MAAM,QAAQ,kBAAkB,QAAQ,IAAI;AAE5C,KAAI,SAAS;EACZ,MAAM,SAAS,oBAAoB,SAAS,QAAQ;AAEpD,MAAI,CAAC,MACJ,QAAO;AAWR,SAAO;GAAE,GAAG,uBAR2B;IACtC,OAAO;IACP,QAAQ,CAAC;KACR,SAAS;KACT,UAAU;KACV,CAAC;IACF,EAE4C,OAAO;GAAE,MAAM,OAAO;GAAM;;AAG1E,KAAI,CAAC,MACJ,QAAO;EACN,OAAO;EACP,QAAQ,CAAC;GACR,SAAS,kBAAkB,QAAQ,IAAI,GACpC,qJACA;GACH,UAAU;GACV,CAAC;EACF,MAAM,EAAE;EACR;CAGF,IAAIC;AACJ,KAAI;AACH,SAAO,WAAW,MAAM;SACjB;AACP,SAAO;GACN,OAAO;GACP,QAAQ,CAAC;IACR,SAAS;IACT,UAAU;IACV,CAAC;GACF,MAAM,EAAE;GACR;;AAIF,QAAO;EAAE,GADM,aAAa,MAAM;GAAE,GAAG;GAAS,eAAe;GAAmB,CAAC;EAC/D;EAAM;;AAG3B,MAAM,mBAAmB;AAEzB,SAAS,kBAAkB,KAA4B;CACtD,MAAM,OAAO,IAAI,QAAQ,IAAI;CAC7B,MAAM,OAAO,OAAO,IAAI,MAAM,IAAI,MAAM,GAAG,KAAK;CAChD,MAAM,QAAQ,KAAK,QAAQ,IAAI;AAE/B,KAAI,QAAQ,EACX,QAAO;AAGR,QAAO,IAAI,gBAAgB,KAAK,MAAM,QAAQ,EAAE,CAAC,CAAC,IAAI,WAAW;;AAGlE,SAAS,kBAAkB,KAAsB;CAChD,MAAM,OAAO,IAAI,QAAQ,IAAI;AAE7B,QAAO,QAAQ,KAAK,iBAAiB,KAAK,IAAI,MAAM,OAAO,EAAE,CAAC;;AAG/D,SAAS,oBAAoB,SAA6G;AACzI,KAAI,CAAC,QACJ;CAGD,MAAM,IAAI,cAAc,QAAQ;CAChC,MAAMC,SAAmD,EAAE;CAC3D,IAAI,QAAQ;AAEZ,MAAK,MAAM,SAAS,oBAAoB;EACvC,MAAM,QAAQ,EAAE,IAAI,MAAM;AAE1B,MAAI,OAAO;AACV,UAAO,SAAS;AAChB,WAAQ;;;AAIV,QAAO,QAAQ,SAAS"}
|
|
1
|
+
{"version":3,"file":"index.js","names":["CMCD_V1_KEY_SET"],"sources":["../src/CMCD_INNER_LIST_KEYS.ts","../src/CMCD_KEY_SPECS.ts","../src/CMCD_V2.ts","../src/CmcdReportingMode.ts","../src/downConvertToV1.ts","../src/isCmcdCustomKey.ts","../src/getKeySpec.ts","../src/isValid.ts","../src/formatNor.ts","../src/toTokenString.ts","../src/normalizeValue.ts","../src/toBareValue.ts","../src/prepareCmcdData.ts","../src/CmcdHeaderField.ts","../src/CMCD_HEADER_MAP.ts","../src/groupCmcdHeaders.ts","../src/toPreparedCmcdHeaders.ts","../src/toCmcdHeaders.ts","../src/appendCmcdHeaders.ts","../src/encodePreparedCmcd.ts","../src/encodeCmcd.ts","../src/CMCD_PARAM.ts","../src/percentEncode.ts","../src/replaceCmcdParam.ts","../src/appendCmcdQuery.ts","../src/CMCD_DEFAULT_TIME_INTERVAL.ts","../src/CMCD_EVENT_KEYS.ts","../src/CMCD_FORMATTER_MAP.ts","../src/CMCD_REQUEST_KEYS.ts","../src/CMCD_RESPONSE_KEYS.ts","../src/CMCD_V1_KEYS.ts","../src/CMCD_KEYS.ts","../src/CMCD_MIME_TYPE.ts","../src/CMCD_REQUEST_PROVENANCE.ts","../src/CMCD_V1.ts","../src/CmcdEventType.ts","../src/CmcdObjectType.ts","../src/CmcdPlayerState.ts","../src/CmcdRecordedReportMode.ts","../src/CmcdRecordedRequestType.ts","../src/createFetchTransport.ts","../src/createXhrTransport.ts","../src/CmcdReportRecorder.ts","../src/CMCD_STATE_EVENT_FIELDS.ts","../src/CmcdTransmissionMode.ts","../src/upConvertToV2.ts","../src/decodeCmcd.ts","../src/CmcdReporter.ts","../src/CmcdStreamingFormat.ts","../src/CmcdStreamType.ts","../src/CmcdValidationSeverity.ts","../src/ensureHeaders.ts","../src/fromCmcdHeaders.ts","../src/fromCmcdQuery.ts","../src/fromCmcdUrl.ts","../src/isCmcdRequestKey.ts","../src/isCmcdResponseReceivedKey.ts","../src/isCmcdEventKey.ts","../src/isCmcdV1Data.ts","../src/isCmcdV1Key.ts","../src/isCmcdV2Data.ts","../src/toCmcdUrl.ts","../src/toCmcdQuery.ts","../src/toCmcdValue.ts","../src/mergeValidationResults.ts","../src/resolveVersion.ts","../src/validateCmcdKeys.ts","../src/CMCD_AGGREGATE_BITRATE_KEYS.ts","../src/CMCD_KEY_OBJECT_TYPES.ts","../src/validateCmcdStructure.ts","../src/CMCD_KEY_TYPES.ts","../src/CMCD_STRING_LENGTH_LIMITS.ts","../src/CMCD_TOKEN_VALUES.ts","../src/validateCmcdValues.ts","../src/validateCmcd.ts","../src/validateCmcdEvents.ts","../src/validateCmcdEventReport.ts","../src/validateCmcdHeaders.ts","../src/validateCmcdRequest.ts"],"sourcesContent":["/**\n * Inner-list keys in version 2 that are scalars in version 1.\n *\n * Used by both encoding (down-conversion) and decoding (up-conversion).\n *\n * @internal\n */\nexport const CMCD_INNER_LIST_KEYS: Set<string> = /* @__PURE__ */ new Set<string>([\n\t'ab', 'bl', 'br', 'bsa', 'bsd', 'bsda', 'lab', 'lb', 'mtp', 'pb', 'tab', 'tb', 'tbl', 'tpb',\n])\n","import type { CmcdKeySpec } from './CmcdKeySpec.ts'\n\nconst MEDIA = ['a', 'v', 'av', 'tt', 'c', 'o']\n\n/**\n * The encoder rules of each key. The table has one row for each key of CTA-5004-B Table 1, plus `nrr` of CTA-5004 and `cdn`.\n *\n * @internal\n */\nexport const CMCD_KEY_SPECS: Readonly<Record<string, CmcdKeySpec>> = {\n\tab: { type: 'ot-list', round: 1, supersededBy: 'br', version: 2 },\n\tbg: { type: 'boolean', omitDefault: false, requiredOn: 'b', version: 2 },\n\tbl: { type: 'ot-list', round: 100 },\n\tbr: { type: 'ot-list', round: 1, requiredOn: 'bc' },\n\tbs: { type: 'boolean', omitDefault: false },\n\tbsa: { type: 'ot-list', round: 1, version: 2 },\n\tbsd: { type: 'ot-list', round: 1, version: 2 },\n\tbsda: { type: 'ot-list', round: 1, version: 2 },\n\tcdn: { type: 'string', max: 128, version: 2 },\n\tcen: { type: 'string', max: 64, mode: 'event', onlyOn: 'ce', requiredOn: 'ce', version: 2 },\n\tcid: { type: 'string', max: 128, v1Max: 64, requiredOn: 'c' },\n\tcmsdd: { type: 'string', mode: 'event', onlyOn: 'rr', version: 2 },\n\tcmsds: { type: 'string', mode: 'event', onlyOn: 'rr', version: 2 },\n\tcs: { type: 'string', version: 2 },\n\td: { type: 'integer', round: 1, ot: MEDIA },\n\tdfa: { type: 'integer', round: 1, version: 2 },\n\tdl: { type: 'integer', round: 100 },\n\te: { type: 'token', mode: 'event', requiredOn: 'always', version: 2 },\n\tec: { type: 'string-list', requiredOn: 'e', version: 2 },\n\th: { type: 'string', max: 128, mode: 'event', requiredOn: 'h', version: 2 },\n\tlab: { type: 'ot-list', round: 1, supersededBy: 'lb', version: 2 },\n\tlb: { type: 'ot-list', round: 1, version: 2 },\n\tltc: { type: 'integer', round: 1, version: 2 },\n\tmsd: { type: 'integer', round: 1, version: 2 },\n\tmtp: { type: 'ot-list', round: 100 },\n\tnor: { type: 'nor' },\n\tnr: { type: 'boolean', omitDefault: false, version: 2 },\n\tnrr: { type: 'string', version: 1 },\n\tot: { type: 'token' },\n\tpb: { type: 'ot-list', round: 1, version: 2 },\n\tpr: { type: 'decimal', omitDefault: 1, requiredOn: 'pr' },\n\tpt: { type: 'integer', round: 1, version: 2 },\n\trc: { type: 'integer', round: 1, mode: 'event', onlyOn: 'rr', version: 2 },\n\trtp: { type: 'integer', round: 100 },\n\tsf: { type: 'token', v1Map: { e: 'o' } },\n\tsid: { type: 'string', max: 64 },\n\tsmrt: { type: 'string', mode: 'event', onlyOn: 'rr', version: 2 },\n\tsn: { type: 'integer', round: 1, version: 2 },\n\tst: { type: 'token', v1Map: { ll: 'l' } },\n\tsta: { type: 'token', requiredOn: 'ps', version: 2 },\n\tsu: { type: 'boolean', omitDefault: false },\n\ttab: { type: 'ot-list', round: 1, supersededBy: 'tb', version: 2 },\n\ttb: { type: 'ot-list', round: 1 },\n\ttbl: { type: 'ot-list', round: 100, version: 2 },\n\ttpb: { type: 'ot-list', round: 1, ot: ['a', 'v', 'av', 'c'], version: 2 },\n\tts: { type: 'integer', round: 1, mode: 'event', requiredOn: 'always', version: 2 },\n\tttfb: { type: 'integer', round: 1, mode: 'event', onlyOn: 'rr', version: 2 },\n\tttfbb: { type: 'integer', round: 1, mode: 'event', onlyOn: 'rr', version: 2 },\n\tttlb: { type: 'integer', round: 1, mode: 'event', onlyOn: 'rr', version: 2 },\n\turl: { type: 'string', mode: 'event', onlyOn: 'rr', requiredOn: 'rr', version: 2 },\n\tv: { type: 'integer', round: 1, requiredOn: 'always', version: 2 },\n}\n","/**\n * CMCD Version 2\n *\n * @public\n */\nexport const CMCD_V2 = 2 as const\n","import type { ValueOf } from '@svta/cml-utils'\n\n/**\n * CMCD event mode variable name.\n *\n * @public\n */\nexport const CMCD_EVENT_MODE = 'event' as const\n\n/**\n * CMCD request mode variable name.\n *\n * @public\n */\nexport const CMCD_REQUEST_MODE = 'request' as const\n\n/**\n * CMCD reporting mode types.\n *\n * @enum\n *\n * @public\n */\nexport const CmcdReportingMode = {\n\t/**\n\t * Request mode\n\t */\n\tREQUEST: CMCD_REQUEST_MODE as typeof CMCD_REQUEST_MODE,\n\n\t/**\n\t * Event mode\n\t */\n\tEVENT: CMCD_EVENT_MODE as typeof CMCD_EVENT_MODE,\n} as const\n\n/**\n * @public\n */\nexport type CmcdReportingMode = ValueOf<typeof CmcdReportingMode>;\n","import { SfItem } from '@svta/cml-structured-field-values'\nimport { CMCD_INNER_LIST_KEYS } from './CMCD_INNER_LIST_KEYS.ts'\n\nfunction hasParams(params: object | undefined): boolean {\n\tfor (const _ in params) {\n\t\treturn true\n\t}\n\n\treturn false\n}\n\n/**\n * Unwrap an inner list or SfItem value to a scalar.\n *\n * The scalar is the value of the item with the object type flag of `ot`\n * (CTA-5004-B section 4.1, item 14). Without that item, it is the value\n * of the first item without parameters. Otherwise it is `undefined`.\n */\nfunction unwrapValue(value: unknown, ot: string | undefined): unknown {\n\tif (value instanceof SfItem) {\n\t\tvalue = value.value\n\t}\n\n\tif (!Array.isArray(value)) {\n\t\treturn value\n\t}\n\n\tlet fallback: unknown\n\n\tfor (const item of value) {\n\t\tif (!(item instanceof SfItem)) {\n\t\t\tif (fallback === undefined) {\n\t\t\t\tfallback = item\n\t\t\t}\n\t\t\tcontinue\n\t\t}\n\n\t\tif (ot && item.params?.[ot] === true) {\n\t\t\treturn item.value\n\t\t}\n\n\t\tif (fallback === undefined && !hasParams(item.params)) {\n\t\t\tfallback = item.value\n\t\t}\n\t}\n\n\treturn fallback\n}\n\n/**\n * Down-convert version 2 CMCD data to version 1.\n *\n * - Extracts `nrr` from the `nor` SfItem's `r` parameter.\n * - Unwraps inner-list values to scalars for the object type `ot`.\n *\n * @internal\n */\nexport function downConvertToV1(obj: Record<string, any>, ot: string | undefined): Record<string, any> {\n\tconst result: Record<string, any> = {}\n\n\tfor (const [key, value] of Object.entries(obj)) {\n\t\tif (value == null) {\n\t\t\tresult[key] = value\n\t\t\tcontinue\n\t\t}\n\n\t\tif (key === 'nor') {\n\t\t\tconst list = value instanceof SfItem && Array.isArray(value.value) ? value.value : value\n\t\t\tconst first = Array.isArray(list) ? list[0] : list\n\n\t\t\tif (first instanceof SfItem) {\n\t\t\t\tresult['nor'] = first.value\n\t\t\t\tif (first.params?.r) {\n\t\t\t\t\tresult['nrr'] = first.params.r\n\t\t\t\t}\n\t\t\t}\n\t\t\telse {\n\t\t\t\tresult['nor'] = first\n\t\t\t}\n\t\t}\n\t\telse if (CMCD_INNER_LIST_KEYS.has(key)) {\n\t\t\tresult[key] = unwrapValue(value, ot)\n\t\t}\n\t\telse {\n\t\t\tresult[key] = value\n\t\t}\n\t}\n\n\treturn result\n}\n","import type { CmcdKey } from './CmcdKey.ts'\n\n// The CMCD custom-key charset restricted to RFC 8941 key serialization\n// (serializeKey): a lowercase first letter, then `a-z 0-9 . -`.\nconst CUSTOM_KEY_REGEX = /^[a-z][a-z0-9.-]*$/\n\n/**\n * Check if a key is a valid custom key: a lowercase first letter, then\n * characters from `a-z 0-9 . -`. The key needs a hyphen, not at the start\n * or end. This check applies the CTA-5004-B custom-key rules, restricted\n * to names that RFC 8941 key serialization accepts.\n *\n * @param key - The key to check.\n *\n * @returns `true` if the key is a custom key, `false` otherwise.\n *\n * @public\n *\n * @example\n * {@includeCode ../test/isCmcdCustomKey.test.ts#example}\n */\nexport function isCmcdCustomKey(key: CmcdKey): boolean {\n\t// The separator is checked outside the regex to keep matching linear (CodeQL js/polynomial-redos).\n\tconst separator = key.indexOf('-', 1)\n\treturn separator > 0 && separator < key.length - 1 && CUSTOM_KEY_REGEX.test(key)\n}\n","import { CMCD_KEY_SPECS } from './CMCD_KEY_SPECS.ts'\nimport type { CmcdKey } from './CmcdKey.ts'\nimport type { CmcdKeySpec } from './CmcdKeySpec.ts'\nimport { isCmcdCustomKey } from './isCmcdCustomKey.ts'\n\nconst CUSTOM_KEY_SPEC: CmcdKeySpec = { type: 'custom', omitDefault: false, max: 64, v1Max: Infinity }\n\n/**\n * Returns the row of a key in the key table.\n *\n * @param key - The key to look up.\n *\n * @returns The row of a reserved key, the custom row for a valid custom key, or `undefined`.\n *\n * @internal\n */\nexport function getKeySpec(key: string): CmcdKeySpec | undefined {\n\tif (Object.prototype.hasOwnProperty.call(CMCD_KEY_SPECS, key)) {\n\t\treturn CMCD_KEY_SPECS[key]\n\t}\n\n\treturn isCmcdCustomKey(key as CmcdKey) ? CUSTOM_KEY_SPEC : undefined\n}\n","/**\n * Checks if the given value is valid to send as a CMCD value.\n *\n * `undefined`, `null`, an empty string, `false`, an empty array, and a\n * number that is not finite are not valid. CTA-5004-B requires omitting\n * the key when its value is unknown.\n *\n * @param value - The value to check.\n *\n * @returns `true` if the value is valid.\n *\n * @internal\n */\nexport function isValid(value: unknown): boolean {\n\tif (typeof value === 'number') {\n\t\treturn Number.isFinite(value)\n\t}\n\n\tif (Array.isArray(value)) {\n\t\treturn value.length > 0\n\t}\n\n\treturn value != null && value !== '' && value !== false\n}\n","import { SfItem } from '@svta/cml-structured-field-values'\nimport { getBaseUrl, urlToRelativePath, type ValueOrArray } from '@svta/cml-utils'\nimport type { CmcdFormatterOptions } from './CmcdFormatterOptions.ts'\nimport type { CmcdVersion } from './CmcdVersion.ts'\n\ntype CmcdNorEntry = string | SfItem<string>\n\nfunction toBase(baseUrl: string | undefined): string | undefined {\n\tif (!baseUrl) {\n\t\treturn undefined\n\t}\n\n\ttry {\n\t\treturn new URL(getBaseUrl(baseUrl)).href\n\t}\n\tcatch {\n\t\treturn undefined\n\t}\n}\n\nfunction formatPath(path: unknown, base: string | undefined, version: CmcdVersion): string | undefined {\n\tif (typeof path !== 'string' || path === '') {\n\t\treturn undefined\n\t}\n\n\tconst relative = base ? urlToRelativePath(path, base) : path\n\n\treturn version === 1 ? encodeURIComponent(relative) : relative\n}\n\nfunction formatEntry(entry: unknown, base: string | undefined, version: CmcdVersion): CmcdNorEntry | undefined {\n\tif (entry instanceof SfItem) {\n\t\tconst path = formatPath(entry.value, base, version)\n\n\t\treturn path === undefined ? undefined : new SfItem(path, entry.params)\n\t}\n\n\treturn formatPath(entry, base, version)\n}\n\nfunction formatEntries(entries: unknown[], base: string | undefined, version: CmcdVersion): CmcdNorEntry[] | undefined {\n\tconst list: CmcdNorEntry[] = []\n\n\tfor (const entry of entries) {\n\t\tconst formatted = formatEntry(entry, base, version)\n\n\t\tif (formatted !== undefined) {\n\t\t\tlist.push(formatted)\n\t\t}\n\t}\n\n\treturn list.length > 0 ? list : undefined\n}\n\n/**\n * Formats a `nor` value. Each path becomes relative to `baseUrl` when `baseUrl` is a valid URL.\n * Version 1 encodes the path with `encodeURIComponent`. Version 2 wraps one path in a list.\n * The parameters of an entry and of an inner list stay on the value.\n *\n * @param value - A path, an `SfItem` of a path, or a list of them. An `SfItem` can also wrap the list.\n * @param options - The version and `baseUrl` of the report.\n *\n * @returns The formatted value, or `undefined` when no entry is a non-empty string.\n *\n * @internal\n */\nexport function formatNor(value: unknown, options: Pick<CmcdFormatterOptions, 'version' | 'baseUrl'>): ValueOrArray<CmcdNorEntry> | undefined {\n\tconst base = toBase(options.baseUrl)\n\tconst version = options.version\n\n\tif (Array.isArray(value)) {\n\t\treturn formatEntries(value, base, version)\n\t}\n\n\tif (value instanceof SfItem && Array.isArray(value.value)) {\n\t\tconst list = formatEntries(value.value, base, version)\n\n\t\treturn list && new SfItem(list, value.params)\n\t}\n\n\tconst entry = formatEntry(value, base, version)\n\n\treturn version === 1 || entry === undefined ? entry : [entry]\n}\n","import { SfItem, SfToken, symbolToStr } from '@svta/cml-structured-field-values'\n\n/**\n * Resolve the text of a token value.\n *\n * A token may be a plain string, a registry `Symbol`, an `SfToken`, or an\n * `SfItem` that wraps such a value.\n *\n * @param value - The value to resolve.\n *\n * @returns The token text, or `undefined` when the value is not a token.\n *\n * @internal\n */\nexport function toTokenString(value: unknown): string | undefined {\n\tif (value instanceof SfItem) {\n\t\treturn toTokenString(value.value)\n\t}\n\n\tif (typeof value === 'string') {\n\t\treturn value\n\t}\n\n\tif (typeof value === 'symbol' || value instanceof SfToken) {\n\t\treturn symbolToStr(value)\n\t}\n\n\treturn undefined\n}\n","import { SfItem, SfToken } from '@svta/cml-structured-field-values'\nimport type { CmcdFormatterOptions } from './CmcdFormatterOptions.ts'\nimport type { CmcdKeySpec } from './CmcdKeySpec.ts'\nimport type { CmcdVersion } from './CmcdVersion.ts'\nimport { formatNor } from './formatNor.ts'\nimport { toTokenString } from './toTokenString.ts'\n\ntype CmcdStringKeySpec = Extract<CmcdKeySpec, { type: 'string' | 'custom' }>\n\nfunction toText(value: unknown, spec: CmcdStringKeySpec, version: CmcdVersion): string | undefined {\n\tconst max = (version === 1 ? spec.v1Max : undefined) ?? spec.max ?? Infinity\n\n\treturn typeof value === 'string' && value !== '' && value.length <= max ? value : undefined\n}\n\nfunction normalizeBare(value: unknown, spec: CmcdKeySpec, version: CmcdVersion): unknown {\n\tswitch (spec.type) {\n\t\tcase 'boolean':\n\t\t\treturn typeof value === 'boolean' ? value : undefined\n\n\t\tcase 'integer':\n\t\tcase 'ot-list':\n\t\t\treturn typeof value === 'number' && Number.isFinite(value) ? Math.round(value / spec.round) * spec.round : undefined\n\n\t\tcase 'decimal':\n\t\t\treturn typeof value === 'number' && Number.isFinite(value) ? value : undefined\n\n\t\tcase 'string':\n\t\t\treturn toText(value, spec, version)\n\n\t\tcase 'string-list':\n\t\t\treturn typeof value === 'string' && value !== '' ? value : undefined\n\n\t\tcase 'token': {\n\t\t\tconst text = toTokenString(value)\n\t\t\tconst v1Map = version === 1 ? spec.v1Map : undefined\n\t\t\tconst token = text !== undefined && v1Map !== undefined && Object.prototype.hasOwnProperty.call(v1Map, text) ? v1Map[text] : text\n\n\t\t\treturn token ? new SfToken(token) : undefined\n\t\t}\n\n\t\tcase 'custom':\n\t\t\tif (typeof value === 'string') {\n\t\t\t\treturn toText(value, spec, version)\n\t\t\t}\n\n\t\t\tif (typeof value === 'number') {\n\t\t\t\treturn Number.isFinite(value) ? value : undefined\n\t\t\t}\n\n\t\t\tif (Array.isArray(value)) {\n\t\t\t\treturn value.length > 0 ? value : undefined\n\t\t\t}\n\n\t\t\treturn typeof value === 'boolean' || typeof value === 'symbol' || value instanceof SfToken ? value : undefined\n\n\t\tdefault:\n\t\t\treturn undefined\n\t}\n}\n\nfunction normalizeItem(value: unknown, spec: CmcdKeySpec, version: CmcdVersion): unknown {\n\tif (value instanceof SfItem) {\n\t\tconst bare = normalizeBare(value.value, spec, version)\n\n\t\treturn bare === undefined ? undefined : new SfItem(bare, value.params)\n\t}\n\n\treturn normalizeBare(value, spec, version)\n}\n\nfunction normalizeList(value: unknown, spec: CmcdKeySpec, version: CmcdVersion): unknown {\n\tconst wrapper = value instanceof SfItem && Array.isArray(value.value) ? value : undefined\n\tconst items = wrapper ? wrapper.value as unknown as unknown[] : Array.isArray(value) ? value : [value]\n\tconst list: unknown[] = []\n\n\tfor (const item of items) {\n\t\tconst normalized = normalizeItem(item, spec, version)\n\n\t\tif (normalized !== undefined) {\n\t\t\tlist.push(normalized)\n\t\t}\n\t}\n\n\tif (list.length === 0) {\n\t\treturn undefined\n\t}\n\n\treturn wrapper ? new SfItem(list, wrapper.params) : list\n}\n\n/**\n * Applies the value rule of a key type from the key table.\n *\n * An `SfItem` keeps its parameters, and the rule applies to the value inside it.\n * In version 2, a list key wraps one value in a list.\n * The rules do not check the limits of RFC 8941, such as the integer range.\n *\n * @param value - The value to prepare.\n * @param spec - The row of the key in the key table.\n * @param options - The version and `baseUrl` of the report.\n *\n * @returns The value to send, or `undefined` when the value fails the rule.\n *\n * @internal\n */\nexport function normalizeValue(value: unknown, spec: CmcdKeySpec, options: CmcdFormatterOptions): unknown {\n\tif (spec.type === 'nor') {\n\t\treturn formatNor(value, options)\n\t}\n\n\tif (spec.type === 'string-list' || (spec.type === 'ot-list' && options.version !== 1)) {\n\t\treturn normalizeList(value, spec, options.version)\n\t}\n\n\treturn normalizeItem(value, spec, options.version)\n}\n","import { SfItem } from '@svta/cml-structured-field-values'\n\n/**\n * Returns the value inside an `SfItem`, or the value itself.\n *\n * `decodeCmcd` returns a member with parameters as an `SfItem`. For an\n * inner list with parameters, the value of the `SfItem` is the list.\n *\n * @param value - The value to read.\n * @returns The value without its parameters.\n *\n * @internal\n */\nexport function toBareValue(value: unknown): unknown {\n\treturn value instanceof SfItem ? value.value : value\n}\n","import { SfItem, SfToken } from '@svta/cml-structured-field-values'\nimport { CMCD_INNER_LIST_KEYS } from './CMCD_INNER_LIST_KEYS.ts'\nimport { CMCD_KEY_SPECS } from './CMCD_KEY_SPECS.ts'\nimport { CMCD_V2 } from './CMCD_V2.ts'\nimport type { Cmcd } from './Cmcd.ts'\nimport type { CmcdEncodeOptions } from './CmcdEncodeOptions.ts'\nimport type { CmcdFormatterOptions } from './CmcdFormatterOptions.ts'\nimport type { CmcdKey } from './CmcdKey.ts'\nimport type { CmcdKeySpec } from './CmcdKeySpec.ts'\nimport { CMCD_EVENT_MODE, CMCD_REQUEST_MODE, type CmcdReportingMode } from './CmcdReportingMode.ts'\nimport type { CmcdValue } from './CmcdValue.ts'\nimport type { CmcdVersion } from './CmcdVersion.ts'\nimport { downConvertToV1 } from './downConvertToV1.ts'\nimport { getKeySpec } from './getKeySpec.ts'\nimport { isValid } from './isValid.ts'\nimport { normalizeValue } from './normalizeValue.ts'\nimport { toBareValue } from './toBareValue.ts'\nimport { toTokenString } from './toTokenString.ts'\n\nfunction hasKey(spec: CmcdKeySpec, reportingMode: CmcdReportingMode, isV1: boolean): boolean {\n\treturn (spec.mode === undefined || spec.mode === reportingMode)\n\t\t&& (spec.version === undefined || (spec.version === 1) === isV1)\n}\n\nfunction isRequired(spec: CmcdKeySpec, event: string | undefined): boolean {\n\treturn spec.requiredOn === 'always' || (event !== undefined && spec.requiredOn === event)\n}\n\nfunction hasObjectTypes(spec: CmcdKeySpec): boolean {\n\treturn (spec.type === 'integer' || spec.type === 'ot-list') && spec.ot !== undefined\n}\n\nfunction needsV1ObjectType(obj: Record<string, any>, filter: CmcdEncodeOptions['filter']): boolean {\n\tif (typeof filter !== 'function' || filter('ot')) {\n\t\treturn true\n\t}\n\n\tfor (const key of CMCD_INNER_LIST_KEYS) {\n\t\tif (Array.isArray(toBareValue(obj[key])) && filter(key as CmcdKey)) {\n\t\t\treturn true\n\t\t}\n\t}\n\n\treturn false\n}\n\nfunction allowsObjectType(spec: CmcdKeySpec, objectType: string | undefined): boolean {\n\tif (objectType === undefined || (spec.type !== 'integer' && spec.type !== 'ot-list') || spec.ot === undefined) {\n\t\treturn true\n\t}\n\n\treturn spec.ot.includes(objectType)\n}\n\nfunction isDefaultValue(spec: CmcdKeySpec, value: unknown): boolean {\n\treturn 'omitDefault' in spec && toBareValue(value) === spec.omitDefault\n}\n\nfunction insertKey(keys: string[], specs: CmcdKeySpec[], key: string): void {\n\tlet index = 0\n\n\twhile (index < keys.length && keys[index] < key) {\n\t\tindex++\n\t}\n\n\tkeys.splice(index, 0, key)\n\tspecs.splice(index, 0, CMCD_KEY_SPECS[key])\n}\n\nfunction prepareValue(key: string, value: unknown, spec: CmcdKeySpec, options: CmcdEncodeOptions, formatterOptions: CmcdFormatterOptions): unknown {\n\tconst formatter = options.formatters?.[key as CmcdKey]\n\n\tif (typeof formatter !== 'function') {\n\t\treturn value == null ? undefined : normalizeValue(value, spec, formatterOptions)\n\t}\n\n\tconst formatted: unknown = isValid(value) ? formatter(value as CmcdValue, formatterOptions) : value\n\n\tif (!isValid(formatted) && !(formatted === false && spec.type === 'boolean')) {\n\t\treturn undefined\n\t}\n\n\tif (spec.type === 'token') {\n\t\tif (typeof formatted === 'string') {\n\t\t\treturn new SfToken(formatted)\n\t\t}\n\n\t\tif (formatted instanceof SfItem && typeof formatted.value === 'string') {\n\t\t\treturn new SfItem(new SfToken(formatted.value), formatted.params)\n\t\t}\n\t}\n\n\treturn formatted\n}\n\n/**\n * Convert a generic object to CMCD data.\n *\n * @param obj - The CMCD object to process.\n * @param options - Options for encoding.\n *\n * @public\n *\n * @example\n * {@includeCode ../test/prepareCmcdData.test.ts#example}\n */\nexport function prepareCmcdData(obj: Record<string, any>, options: CmcdEncodeOptions = {}): Cmcd {\n\tconst results: Record<string, unknown> = {}\n\n\tif (obj == null || typeof obj !== 'object') {\n\t\treturn results as Cmcd\n\t}\n\n\tconst version = options.version || toBareValue(obj['v']) as CmcdVersion || CMCD_V2\n\tconst reportingMode = options.reportingMode || CMCD_REQUEST_MODE\n\tconst isV1 = version === 1\n\tconst isEventReport = !isV1 && reportingMode === CMCD_EVENT_MODE\n\tconst formatterOptions: CmcdFormatterOptions = { version, reportingMode, baseUrl: options.baseUrl }\n\tconst filter = options.filter\n\n\tlet objectTypeValue: unknown\n\tlet objectType: string | undefined\n\n\tif (isV1 && needsV1ObjectType(obj, filter)) {\n\t\tobjectTypeValue = prepareValue('ot', obj['ot'], CMCD_KEY_SPECS['ot'], options, formatterOptions)\n\t\tobjectType = toTokenString(objectTypeValue)\n\t}\n\n\tconst data = isV1 ? downConvertToV1(obj, objectType) : obj\n\tconst eventValue = isEventReport ? prepareValue('e', data['e'], CMCD_KEY_SPECS['e'], options, formatterOptions) : undefined\n\tconst event = toTokenString(eventValue)\n\tconst keys: string[] = []\n\tconst specs: CmcdKeySpec[] = []\n\tlet passed = false\n\tlet needsObjectType = false\n\n\tfor (const key of Object.keys(data).sort()) {\n\t\tconst spec = getKeySpec(key)\n\n\t\tif (spec === undefined || !hasKey(spec, reportingMode, isV1)) {\n\t\t\tcontinue\n\t\t}\n\n\t\tif (typeof filter !== 'function' || filter(key as CmcdKey)) {\n\t\t\tpassed = true\n\t\t}\n\t\telse if (!isRequired(spec, event)) {\n\t\t\tcontinue\n\t\t}\n\n\t\tif (spec.onlyOn !== undefined && spec.onlyOn !== event) {\n\t\t\tcontinue\n\t\t}\n\n\t\tif (key === 'ot' || hasObjectTypes(spec)) {\n\t\t\tneedsObjectType = true\n\t\t}\n\n\t\tkeys.push(key)\n\t\tspecs.push(spec)\n\t}\n\n\tif (!passed && !isEventReport) {\n\t\treturn results as Cmcd\n\t}\n\n\tif (needsObjectType && !isV1) {\n\t\tobjectTypeValue = prepareValue('ot', data['ot'], CMCD_KEY_SPECS['ot'], options, formatterOptions)\n\t\tobjectType = toTokenString(objectTypeValue)\n\t}\n\n\tif (isEventReport && !keys.includes('ts')) {\n\t\tinsertKey(keys, specs, 'ts')\n\t}\n\n\tif (!isV1 && !keys.includes('v')) {\n\t\tinsertKey(keys, specs, 'v')\n\t}\n\n\tconst values: unknown[] = new Array(keys.length)\n\n\tfor (let i = keys.length - 1; i >= 0; i--) {\n\t\tconst key = keys[i]\n\t\tconst spec = specs[i]\n\n\t\tif (spec.type === 'ot-list' && spec.supersededBy !== undefined) {\n\t\t\tconst exact = keys.indexOf(spec.supersededBy, i + 1)\n\n\t\t\tif (exact !== -1 && values[exact] !== undefined) {\n\t\t\t\tcontinue\n\t\t\t}\n\t\t}\n\n\t\tif (key === 'v') {\n\t\t\tvalues[i] = version\n\t\t}\n\t\telse if (key === 'ot') {\n\t\t\tvalues[i] = objectTypeValue\n\t\t}\n\t\telse if (key === 'e') {\n\t\t\tvalues[i] = eventValue\n\t\t}\n\t\telse if (isV1 || allowsObjectType(spec, objectType)) {\n\t\t\tvalues[i] = prepareValue(key, data[key], spec, options, formatterOptions)\n\t\t}\n\n\t\tif (key === 'ts') {\n\t\t\tconst timestamp = toBareValue(values[i])\n\n\t\t\tif (typeof timestamp !== 'number' || !Number.isFinite(timestamp)) {\n\t\t\t\tvalues[i] = Date.now()\n\t\t\t}\n\t\t}\n\t}\n\n\tfor (let i = 0; i < keys.length; i++) {\n\t\tconst value = values[i]\n\n\t\tif (value !== undefined && (!isDefaultValue(specs[i], value) || isRequired(specs[i], event))) {\n\t\t\tresults[keys[i]] = value\n\t\t}\n\t}\n\n\treturn results as Cmcd\n}\n","import type { ValueOf } from '@svta/cml-utils'\n\n/**\n * CMCD object header name.\n *\n * @public\n */\nexport const CMCD_OBJECT = 'CMCD-Object' as const\n\n/**\n * CMCD request header name.\n *\n * @public\n */\nexport const CMCD_REQUEST = 'CMCD-Request' as const\n\n/**\n * CMCD session header name.\n *\n * @public\n */\nexport const CMCD_SESSION = 'CMCD-Session' as const\n\n/**\n * CMCD status header name.\n *\n * @public\n */\nexport const CMCD_STATUS = 'CMCD-Status' as const\n\n/**\n * CMCD header fields.\n *\n *\n * @enum\n *\n * @public\n */\nexport const CmcdHeaderField = {\n\t/**\n\t * keys whose values vary with the object being requested.\n\t */\n\tOBJECT: CMCD_OBJECT as typeof CMCD_OBJECT,\n\n\t/**\n\t * keys whose values vary with each request.\n\t */\n\tREQUEST: CMCD_REQUEST as typeof CMCD_REQUEST,\n\n\t/**\n\t * keys whose values are expected to be invariant over the life of the session.\n\t */\n\tSESSION: CMCD_SESSION as typeof CMCD_SESSION,\n\n\t/**\n\t * keys whose values do not vary with every request or object.\n\t */\n\tSTATUS: CMCD_STATUS as typeof CMCD_STATUS,\n} as const\n\n/**\n * @public\n */\nexport type CmcdHeaderField = ValueOf<typeof CmcdHeaderField>;\n\n/**\n * All CMCD header fields as an array.\n *\n * @public\n */\nexport const CMCD_HEADER_FIELDS: readonly CmcdHeaderField[] = [CMCD_OBJECT, CMCD_REQUEST, CMCD_SESSION, CMCD_STATUS]\n","import { type CmcdHeaderField, CMCD_OBJECT, CMCD_REQUEST, CMCD_SESSION, CMCD_STATUS } from './CmcdHeaderField.ts'\nimport type { CmcdRequestKey } from './CmcdRequestKey.ts'\n\n/**\n * The map of CMCD keys to their appropriate header shard.\n *\n * Event-only keys (e, ts, cen, h) and response-received keys (rc, ttfb,\n * ttlb, url, and others) are intentionally absent. They are transmitted\n * in the event-mode POST body, not HTTP headers.\n *\n * @public\n */\nexport const CMCD_HEADER_MAP: Record<CmcdRequestKey | 'nrr', CmcdHeaderField> = {\n\t// Object\n\tab: CMCD_OBJECT,\n\tbr: CMCD_OBJECT,\n\td: CMCD_OBJECT,\n\tlab: CMCD_OBJECT,\n\tlb: CMCD_OBJECT,\n\tot: CMCD_OBJECT,\n\ttab: CMCD_OBJECT,\n\ttb: CMCD_OBJECT,\n\ttpb: CMCD_OBJECT,\n\n\t// Request\n\tbl: CMCD_REQUEST,\n\tcs: CMCD_REQUEST,\n\tdfa: CMCD_REQUEST,\n\tdl: CMCD_REQUEST,\n\tltc: CMCD_REQUEST,\n\tmtp: CMCD_REQUEST,\n\tnor: CMCD_REQUEST,\n\tnrr: CMCD_REQUEST,\n\tpb: CMCD_REQUEST,\n\tsn: CMCD_REQUEST,\n\tsta: CMCD_REQUEST,\n\tsu: CMCD_REQUEST,\n\ttbl: CMCD_REQUEST,\n\n\t// Session\n\tcid: CMCD_SESSION,\n\tmsd: CMCD_SESSION,\n\tsf: CMCD_SESSION,\n\tsid: CMCD_SESSION,\n\tst: CMCD_SESSION,\n\tv: CMCD_SESSION,\n\n\t// Status\n\tbg: CMCD_STATUS,\n\tbs: CMCD_STATUS,\n\tbsa: CMCD_STATUS,\n\tbsd: CMCD_STATUS,\n\tbsda: CMCD_STATUS,\n\tcdn: CMCD_STATUS,\n\tec: CMCD_STATUS,\n\tnr: CMCD_STATUS,\n\tpr: CMCD_STATUS,\n\tpt: CMCD_STATUS,\n\trtp: CMCD_STATUS,\n}\n","import type { Cmcd } from './Cmcd.ts'\nimport { CMCD_HEADER_MAP } from './CMCD_HEADER_MAP.ts'\nimport { CmcdHeaderField } from './CmcdHeaderField.ts'\nimport type { CmcdHeaderKey } from './CmcdHeaderKey.ts'\nimport type { CmcdHeaderMap } from './CmcdHeaderMap.ts'\nimport type { CmcdHeaderValue } from './CmcdHeaderValue.ts'\nimport type { CmcdKey } from './CmcdKey.ts'\n\nfunction createHeaderMap(headerMap: Partial<CmcdHeaderMap>): Record<CmcdHeaderKey, CmcdHeaderField> {\n\treturn Object.keys(headerMap)\n\t\t.reduce((acc, field) => {\n\t\t\theaderMap[field as CmcdHeaderField]?.forEach(key => acc[key] = field as CmcdHeaderField)\n\t\t\treturn acc\n\t\t}, {} as Record<CmcdKey, CmcdHeaderField>)\n}\n\n/**\n * Group a CMCD object into header shards\n *\n * @param cmcd - The CMCD object to convert.\n * @param customHeaderMap - A map of CMCD header fields to custom CMCD keys.\n *\n * @returns The CMCD header shards.\n *\n * @see {@link https://cta-wave.github.io/Resources/common-media-client-data--cta-5004-b.html#header-field-definition | CTA-5004-B Header Field Definition}\n *\n * @public\n */\nexport function groupCmcdHeaders(cmcd: Cmcd, customHeaderMap?: Partial<CmcdHeaderMap>): Record<CmcdHeaderField, CmcdHeaderValue> {\n\tconst result = {} as Record<CmcdHeaderField, CmcdHeaderValue>\n\n\tif (!cmcd) {\n\t\treturn result\n\t}\n\n\tconst keys = Object.keys(cmcd) as CmcdHeaderKey[]\n\tconst custom: Partial<Record<CmcdHeaderKey, CmcdHeaderField>> = customHeaderMap ? createHeaderMap(customHeaderMap) : {}\n\n\tfor (const key of keys) {\n\t\tconst field = CMCD_HEADER_MAP[key] || custom[key] || CmcdHeaderField.REQUEST\n\t\tconst data = result[field] ??= {};\n\t\t(data as Record<string, unknown>)[key] = (cmcd as Record<string, unknown>)[key]\n\t}\n\n\treturn result\n}\n","import { encodeSfDict } from '@svta/cml-structured-field-values'\nimport type { Cmcd } from './Cmcd.ts'\nimport type { CmcdHeaderField } from './CmcdHeaderField.ts'\nimport type { CmcdHeaderMap } from './CmcdHeaderMap.ts'\nimport type { CmcdHeaderValue } from './CmcdHeaderValue.ts'\nimport { groupCmcdHeaders } from './groupCmcdHeaders.ts'\n\n/**\n * Encode already-prepared CMCD data to CMCD header shards.\n *\n * @param data - The prepared CMCD data to encode.\n * @param customHeaderMap - A map of CMCD header fields to custom CMCD keys.\n * @returns The CMCD header shards.\n *\n * @internal\n */\nexport function toPreparedCmcdHeaders(data: Cmcd, customHeaderMap?: Partial<CmcdHeaderMap>): Record<CmcdHeaderField, string> {\n\tconst result = {} as Record<CmcdHeaderField, string>\n\tconst shards = groupCmcdHeaders(data, customHeaderMap)\n\n\tfor (const [field, value] of Object.entries(shards)) {\n\t\tconst shard = encodeSfDict(value as CmcdHeaderValue, { whitespace: false })\n\t\tif (shard) {\n\t\t\tresult[field as CmcdHeaderField] = shard\n\t\t}\n\t}\n\n\treturn result\n}\n","import type { Cmcd } from './Cmcd.ts'\nimport type { CmcdEncodeOptions } from './CmcdEncodeOptions.ts'\nimport type { CmcdHeaderField } from './CmcdHeaderField.ts'\nimport { prepareCmcdData } from './prepareCmcdData.ts'\nimport { toPreparedCmcdHeaders } from './toPreparedCmcdHeaders.ts'\n\n/**\n * Convert a CMCD object to request headers\n *\n * @param cmcd - The CMCD object to convert.\n * @param options - Options for encoding.\n *\n * @returns The CMCD header shards.\n *\n * @see {@link https://cta-wave.github.io/Resources/common-media-client-data--cta-5004-b.html#header-field-definition | CTA-5004-B Header Field Definition}\n *\n * @public\n *\n * @example\n * {@includeCode ../test/toCmcdHeaders.test.ts#example}\n */\nexport function toCmcdHeaders(cmcd: Cmcd, options: CmcdEncodeOptions = {}): Record<CmcdHeaderField, string> {\n\tif (!cmcd) {\n\t\treturn {} as Record<CmcdHeaderField, string>\n\t}\n\n\treturn toPreparedCmcdHeaders(prepareCmcdData(cmcd, options), options?.customHeaderMap)\n}\n","import type { Cmcd } from './Cmcd.ts'\nimport type { CmcdEncodeOptions } from './CmcdEncodeOptions.ts'\nimport { toCmcdHeaders } from './toCmcdHeaders.ts'\n\n/**\n * Append CMCD header shards to a header object.\n *\n * @param headers - The headers to append to.\n * @param cmcd - The CMCD object to append.\n * @param options - Options for encoding.\n *\n * @returns The headers with CMCD header shards appended.\n *\n * @public\n *\n * @example\n * {@includeCode ../test/appendCmcdHeaders.test.ts#example}\n *\n * @see {@link https://cta-wave.github.io/Resources/common-media-client-data--cta-5004-b.html#header-field-definition | CTA-5004-B Header Field Definition}\n */\nexport function appendCmcdHeaders(headers: Record<string, string>, cmcd: Cmcd, options?: CmcdEncodeOptions): Record<string, string> {\n\treturn Object.assign(headers, toCmcdHeaders(cmcd, options))\n}\n","import { encodeSfDict } from '@svta/cml-structured-field-values'\nimport type { Cmcd } from './Cmcd.ts'\n\n/**\n * Encode already-prepared CMCD data to a structured field dictionary string.\n *\n * @param data - The prepared CMCD data to encode.\n * @returns The encoded CMCD string.\n *\n * @internal\n */\nexport function encodePreparedCmcd(data: Cmcd): string {\n\treturn encodeSfDict(data, { whitespace: false })\n}\n","import type { Cmcd } from './Cmcd.ts'\nimport type { CmcdEncodeOptions } from './CmcdEncodeOptions.ts'\nimport { encodePreparedCmcd } from './encodePreparedCmcd.ts'\nimport { prepareCmcdData } from './prepareCmcdData.ts'\n\n/**\n * Encode a CMCD object to a string.\n *\n * @param cmcd - The CMCD object to encode.\n * @param options - Options for encoding.\n *\n * @returns The encoded CMCD string.\n *\n * @see {@link https://cta-wave.github.io/Resources/common-media-client-data--cta-5004-b.html#payload-definition-for-headers-and-query-argument-transmission | CTA-5004-B Payload Definition}\n *\n * @public\n *\n * @example\n * {@includeCode ../test/encodeCmcd.test.ts#example}\n */\nexport function encodeCmcd(cmcd: Cmcd, options: CmcdEncodeOptions = {}): string {\n\tif (!cmcd) {\n\t\treturn ''\n\t}\n\n\treturn encodePreparedCmcd(prepareCmcdData(cmcd, options))\n}\n","/**\n * CMCD parameter name.\n *\n * @public\n */\nexport const CMCD_PARAM = 'CMCD'\n","// The sub-delims of RFC 3986 that `encodeURIComponent` does not encode.\nconst SUB_DELIMS_REGEX = /[!'()*]/g\nconst SURROGATE_REGEX = /[\\uD800-\\uDBFF][\\uDC00-\\uDFFF]|[\\uD800-\\uDFFF]/g\n\nfunction encodeSubDelim(char: string): string {\n\treturn `%${char.charCodeAt(0).toString(16).toUpperCase()}`\n}\n\nfunction replaceUnpaired(match: string): string {\n\treturn match.length === 2 ? match : '�'\n}\n\n/**\n * Percent-encode a string for the `CMCD` query parameter.\n *\n * Only the unreserved characters of RFC 3986 stay unencoded: letters, digits,\n * `-`, `.`, `_`, and `~`. The query examples of CTA-5004-B use this encoding.\n * An unpaired surrogate becomes U+FFFD.\n *\n * @param value - The string to encode.\n * @returns The encoded string.\n *\n * @internal\n */\nexport function percentEncode(value: string): string {\n\tlet encoded: string\n\n\ttry {\n\t\tencoded = encodeURIComponent(value)\n\t}\n\tcatch {\n\t\tencoded = encodeURIComponent(value.replace(SURROGATE_REGEX, replaceUnpaired))\n\t}\n\n\treturn encoded.replace(SUB_DELIMS_REGEX, encodeSubDelim)\n}\n","import { CMCD_PARAM } from './CMCD_PARAM.ts'\nimport { percentEncode } from './percentEncode.ts'\n\nfunction isCmcdParam(param: string): boolean {\n\treturn param === CMCD_PARAM || param.startsWith(`${CMCD_PARAM}=`)\n}\n\n/**\n * Replace the `CMCD` query parameter of a URL.\n *\n * The first `CMCD` parameter takes the new value in place. The function\n * removes the other `CMCD` parameters. If the URL has no `CMCD` parameter,\n * the new parameter goes at the end of the query. An empty `value` only\n * removes the parameters. The function does not change the rest of the URL.\n * The URL can be relative.\n *\n * @param url - The URL.\n * @param value - The encoded CMCD data, before percent-encoding.\n * @returns The URL with at most one `CMCD` parameter.\n *\n * @internal\n */\nexport function replaceCmcdParam(url: string, value?: string): string {\n\tconst hashIndex = url.indexOf('#')\n\tconst end = hashIndex === -1 ? url.length : hashIndex\n\tconst queryIndex = url.indexOf('?')\n\tconst start = queryIndex === -1 || queryIndex > end ? end : queryIndex\n\tconst params: string[] = []\n\tlet param = value ? `${CMCD_PARAM}=${percentEncode(value)}` : ''\n\tlet found = false\n\n\tfor (const item of start < end ? url.slice(start + 1, end).split('&') : []) {\n\t\tif (!isCmcdParam(item)) {\n\t\t\tparams.push(item)\n\t\t}\n\t\telse {\n\t\t\tfound = true\n\n\t\t\tif (param) {\n\t\t\t\tparams.push(param)\n\t\t\t\tparam = ''\n\t\t\t}\n\t\t}\n\t}\n\n\tif (param) {\n\t\tif (params[params.length - 1] === '') {\n\t\t\tparams.pop()\n\t\t}\n\n\t\tparams.push(param)\n\t}\n\telse if (!found) {\n\t\treturn url\n\t}\n\n\tconst query = params.join('&')\n\n\treturn `${url.slice(0, start)}${query ? `?${query}` : ''}${url.slice(end)}`\n}\n","import type { Cmcd } from './Cmcd.ts'\nimport type { CmcdEncodeOptions } from './CmcdEncodeOptions.ts'\nimport { encodeCmcd } from './encodeCmcd.ts'\nimport { replaceCmcdParam } from './replaceCmcdParam.ts'\n\n/**\n * Append CMCD query args to a URL.\n *\n * If the URL has a `CMCD` parameter, the new value replaces it in place. The\n * other parameters and the fragment stay as they are. If the data has no keys\n * to send, the function returns the URL unchanged.\n *\n * @param url - The URL to append to.\n * @param cmcd - The CMCD object to append.\n * @param options - Options for encoding.\n *\n * @returns The URL with the CMCD query args appended.\n *\n * @public\n *\n * @example\n * {@includeCode ../test/appendCmcdQuery.test.ts#example}\n *\n * @see {@link https://cta-wave.github.io/Resources/common-media-client-data--cta-5004-b.html#query-argument-definition | CTA-5004-B Query Argument Definition}\n */\nexport function appendCmcdQuery(url: string, cmcd: Cmcd, options?: CmcdEncodeOptions): string {\n\tconst value = cmcd ? encodeCmcd(cmcd, options) : ''\n\n\treturn value ? replaceCmcdParam(url, value) : url\n}\n","/**\n * The default time interval in seconds when using event mode\n *\n * @public\n */\nexport const CMCD_DEFAULT_TIME_INTERVAL = 30\n","/**\n * Defines the event-specific keys for CMCD (Common Media Client Data) version 2.\n *\n * @public\n */\nexport const CMCD_EVENT_KEYS = [\n\t'cen',\n\t'e',\n\t'h',\n\t'ts',\n] as const\n","import { SfItem } from '@svta/cml-structured-field-values'\nimport type { ValueOrArray } from '@svta/cml-utils'\nimport type { CmcdFormatter } from './CmcdFormatter.ts'\nimport type { CmcdFormatterOptions } from './CmcdFormatterOptions.ts'\nimport type { CmcdValue } from './CmcdValue.ts'\nimport { formatNor } from './formatNor.ts'\nimport { isValid } from './isValid.ts'\n\nconst formatNumbers = (value: CmcdValue, format: (value: number) => number): ValueOrArray<number | SfItem<number>> => {\n\tif (Array.isArray(value)) {\n\t\tconst list: (number | SfItem<number>)[] = []\n\n\t\tfor (const item of value) {\n\t\t\tconst formatted = formatNumbers(item, format) as number | SfItem<number>\n\n\t\t\tif (Number.isFinite(formatted instanceof SfItem ? formatted.value : formatted)) {\n\t\t\t\tlist.push(formatted)\n\t\t\t}\n\t\t}\n\n\t\treturn list\n\t}\n\n\tif (value instanceof SfItem) {\n\t\tconst formatted = formatNumbers(value.value as CmcdValue, format)\n\t\treturn isValid(formatted) ? new SfItem(formatted, value.params) : NaN\n\t}\n\n\treturn typeof value === 'number' ? format(value) : NaN\n}\n\nconst toRounded = (value: CmcdValue) => formatNumbers(value, Math.round)\n\nconst toNumber = (value: CmcdValue) => formatNumbers(value, Number)\n\nconst roundToHundred = (value: number): number => Math.round(value / 100) * 100\n\nconst toHundred = (value: CmcdValue) => formatNumbers(value, roundToHundred)\n\n/**\n * Formatters for CMCD values.\n *\n * The encoder applies the same rounding through its key table, and `nor` is the `nor` rule of the encoder.\n * Use an entry to build a custom formatter for `CmcdEncodeOptions.formatters`.\n * The formatter of a numeric key drops a value or a list element that is not a finite number.\n *\n * @public\n */\nexport const CMCD_FORMATTER_MAP: Record<string, CmcdFormatter> = {\n\t/**\n\t * Bitrate (kbps) rounded integer\n\t */\n\tbr: toRounded,\n\n\t/**\n\t * Duration (milliseconds) rounded integer\n\t */\n\td: toRounded,\n\n\t/**\n\t * Buffer Length (milliseconds) rounded nearest 100ms\n\t */\n\tbl: toHundred,\n\n\t/**\n\t * Deadline (milliseconds) rounded nearest 100ms\n\t */\n\tdl: toHundred,\n\n\t/**\n\t * Measured Throughput (kbps) rounded nearest 100kbps\n\t */\n\tmtp: toHundred,\n\n\t/**\n\t * Next Object Request URL encoded\n\t */\n\tnor: (value: CmcdValue, options: CmcdFormatterOptions) => formatNor(value, options) ?? '',\n\n\t/**\n\t * Requested maximum throughput (kbps) rounded nearest 100kbps\n\t */\n\trtp: toHundred,\n\n\t/**\n\t * Top Bitrate (kbps) rounded integer\n\t */\n\ttb: toRounded,\n\n\t/**\n\t * Target Buffer Length (milliseconds) rounded nearest 100ms\n\t */\n\ttbl: toHundred,\n\n\t/**\n\t * Aggregate Encoded Bitrate (kbps) rounded integer\n\t */\n\tab: toRounded,\n\n\t/**\n\t * Buffer Starvation Absolute (count) rounded integer\n\t */\n\tbsa: toRounded,\n\n\t/**\n\t * Buffer Starvation Duration (milliseconds) rounded integer\n\t */\n\tbsd: toRounded,\n\n\t/**\n\t * Buffer Starvation Duration Absolute (milliseconds) rounded integer\n\t */\n\tbsda: toRounded,\n\n\t/**\n\t * Dropped Frames Absolute (count) rounded integer\n\t */\n\tdfa: toRounded,\n\n\t/**\n\t * Lowest Aggregated Encoded Bitrate (kbps) rounded integer\n\t */\n\tlab: toRounded,\n\n\t/**\n\t * Lowest Encoded Bitrate (kbps) rounded integer\n\t */\n\tlb: toRounded,\n\n\t/**\n\t * Live Stream Latency (milliseconds) rounded integer\n\t */\n\tltc: toRounded,\n\n\t/**\n\t * Media Start Delay (milliseconds) rounded integer\n\t */\n\tmsd: toRounded,\n\n\t/**\n\t * Playhead Bitrate (kbps) rounded integer\n\t */\n\tpb: toRounded,\n\n\t/**\n\t * Playback Rate decimal, not rounded\n\t */\n\tpr: toNumber,\n\n\t/**\n\t * Playhead Time (milliseconds) rounded integer\n\t */\n\tpt: toRounded,\n\n\t/**\n\t * Response Code rounded integer\n\t */\n\trc: toRounded,\n\n\t/**\n\t * Sequence Number rounded integer\n\t */\n\tsn: toRounded,\n\n\t/**\n\t * Top Aggregated Encoded Bitrate (kbps) rounded integer\n\t */\n\ttab: toRounded,\n\n\t/**\n\t * Top Playable Bitrate (kbps) rounded integer\n\t */\n\ttpb: toRounded,\n\n\t/**\n\t * Timestamp (milliseconds) rounded integer\n\t */\n\tts: toRounded,\n\n\t/**\n\t * Time To First Byte (milliseconds) rounded integer\n\t */\n\tttfb: toRounded,\n\n\t/**\n\t * Time To First Body Byte (milliseconds) rounded integer\n\t */\n\tttfbb: toRounded,\n\n\t/**\n\t * Time To Last Byte (milliseconds) rounded integer\n\t */\n\tttlb: toRounded,\n} as const\n","/**\n * Defines the request-specific keys for CMCD (Common Media Client Data) version 2.\n *\n * @public\n */\nexport const CMCD_REQUEST_KEYS = [\n\t'ab',\n\t'bg',\n\t'bl',\n\t'br',\n\t'bs',\n\t'bsa',\n\t'bsd',\n\t'bsda',\n\t'cdn',\n\t'cid',\n\t'cs',\n\t'd',\n\t'dfa',\n\t'dl',\n\t'ec',\n\t'lab',\n\t'lb',\n\t'ltc',\n\t'msd',\n\t'mtp',\n\t'nor',\n\t'nr',\n\t'ot',\n\t'pb',\n\t'pr',\n\t'pt',\n\t'rtp',\n\t'sf',\n\t'sid',\n\t'sn',\n\t'st',\n\t'sta',\n\t'su',\n\t'tab',\n\t'tb',\n\t'tbl',\n\t'tpb',\n\t'v',\n] as const\n","/**\n * Response-only and timing keys for version 2.\n *\n * @public\n */\nexport const CMCD_RESPONSE_KEYS = [\n\t'cmsdd',\n\t'cmsds',\n\t'rc',\n\t'smrt',\n\t'ttfb',\n\t'ttfbb',\n\t'ttlb',\n\t'url',\n] as const\n","/**\n * Defines the keys for CMCD (Common Media Client Data) version 1.\n *\n * @public\n */\nexport const CMCD_V1_KEYS = [\n\t'bl',\n\t'br',\n\t'bs',\n\t'cid',\n\t'd',\n\t'dl',\n\t'mtp',\n\t'nor',\n\t'nrr',\n\t'ot',\n\t'pr',\n\t'rtp',\n\t'sf',\n\t'sid',\n\t'st',\n\t'su',\n\t'tb',\n\t'v',\n] as const\n","import { CMCD_EVENT_KEYS } from './CMCD_EVENT_KEYS.ts'\nimport { CMCD_REQUEST_KEYS } from './CMCD_REQUEST_KEYS.ts'\nimport { CMCD_RESPONSE_KEYS } from './CMCD_RESPONSE_KEYS.ts'\nimport { CMCD_V1_KEYS } from './CMCD_V1_KEYS.ts'\nimport type { CmcdKey } from './CmcdKey.ts'\n\n/**\n * A list of all CMCD keys.\n *\n * @public\n */\nexport const CMCD_KEYS: CmcdKey[] = /* @__PURE__ */ [\n\t...CMCD_V1_KEYS,\n\t...CMCD_REQUEST_KEYS,\n\t...CMCD_RESPONSE_KEYS,\n\t...CMCD_EVENT_KEYS,\n].filter((key, index, arr) => arr.indexOf(key) === index)\n","/**\n * CMCD MIME type for event report payloads.\n *\n * @public\n */\nexport const CMCD_MIME_TYPE = 'application/cmcd'\n","/**\n * The `customData` property where `CmcdReporter.createRequestReport()`\n * writes session provenance on every request it returns.\n *\n * The value is a frozen `CmcdRequestProvenance` record. `sid` names the\n * session that issued the request. `cid` is the content id at the time the\n * request was issued. `data` is the request's per-call data as an encoded\n * CMCD string. `CmcdReporter.recordResponseReceived()` reads the record to\n * attribute a late response to its session and to rebuild the request-time\n * report keys.\n * Spread and `Object.assign` copy the record into ordinary request clones.\n * `JSON.stringify` and structured clone drop symbol-keyed properties. Before\n * either operation, read the value and restore it afterward. JSON preserves\n * the record's fields. Attribution uses the `sid` value rather than object\n * identity, so a parsed plain-object copy attributes correctly. For a record\n * naming a `sid` the reporter does not retain, the reporter drops the\n * response rather than reattributing it.\n *\n * The symbol registry provides the symbol, so duplicated copies of this\n * library in one bundle interoperate. The registry key is stable across\n * versions.\n *\n * @public\n */\nexport const CMCD_REQUEST_PROVENANCE: unique symbol = /* @__PURE__ */ Symbol.for('@svta/cml-cmcd/request-provenance')\n","/**\n * CMCD Version 1\n *\n * @public\n */\nexport const CMCD_V1 = 1 as const\n","import type { ValueOf } from '@svta/cml-utils'\n\n/**\n * CMCD event type 'bc' (bitrate change).\n *\n * @public\n */\nexport const CMCD_EVENT_BITRATE_CHANGE = 'bc' as const\n\n/**\n * CMCD event type 'ps' (play state change).\n *\n * @public\n */\nexport const CMCD_EVENT_PLAY_STATE = 'ps' as const\n\n/**\n * CMCD event type 'pr' (playback rate change).\n *\n * @public\n */\nexport const CMCD_EVENT_PLAYBACK_RATE = 'pr' as const\n\n/**\n * CMCD event type 'e' (error).\n *\n * @public\n */\nexport const CMCD_EVENT_ERROR = 'e' as const\n\n/**\n * CMCD event type 't' (time interval).\n *\n * @public\n */\nexport const CMCD_EVENT_TIME_INTERVAL = 't' as const\n\n/**\n * CMCD event type 'c' (content ID).\n *\n * @public\n */\nexport const CMCD_EVENT_CONTENT_ID = 'c' as const\n\n/**\n * CMCD event type 'b' (backgrounded mode).\n *\n * @public\n */\nexport const CMCD_EVENT_BACKGROUNDED_MODE = 'b' as const\n\n/**\n * CMCD event type 'm' (mute).\n *\n * @public\n */\nexport const CMCD_EVENT_MUTE = 'm' as const\n\n/**\n * CMCD event type 'um' (unmute).\n *\n * @public\n */\nexport const CMCD_EVENT_UNMUTE = 'um' as const\n\n/**\n * CMCD event type 'pe' (player expand).\n *\n * @public\n */\nexport const CMCD_EVENT_PLAYER_EXPAND = 'pe' as const\n\n/**\n * CMCD event type 'pc' (player collapse).\n *\n * @public\n */\nexport const CMCD_EVENT_PLAYER_COLLAPSE = 'pc' as const\n\n/**\n * CMCD event type 'rr' (response received).\n *\n * @public\n */\nexport const CMCD_EVENT_RESPONSE_RECEIVED = 'rr' as const\n\n/**\n * CMCD event type 'as' (ad start).\n *\n * @public\n */\nexport const CMCD_EVENT_AD_START = 'as' as const\n\n/**\n * CMCD event type 'ae' (ad end).\n *\n * @public\n */\nexport const CMCD_EVENT_AD_END = 'ae' as const\n\n/**\n * CMCD event type 'abs' (ad break start).\n *\n * @public\n */\nexport const CMCD_EVENT_AD_BREAK_START = 'abs' as const\n\n/**\n * CMCD event type 'abe' (ad break end).\n *\n * @public\n */\nexport const CMCD_EVENT_AD_BREAK_END = 'abe' as const\n\n/**\n * CMCD event type 'sk' (skip).\n *\n * @public\n */\nexport const CMCD_EVENT_SKIP = 'sk' as const\n\n/**\n * CMCD event type 'ce' (custom event).\n *\n * @public\n */\nexport const CMCD_EVENT_CUSTOM_EVENT = 'ce' as const\n\n/**\n * CMCD event types for the 'e' key (event mode).\n *\n * @enum\n *\n * @see {@link https://cta-wave.github.io/Resources/common-media-client-data--cta-5004-b.html#event | CTA-5004-B Event}\n *\n * @public\n */\nexport const CmcdEventType = {\n\t/**\n\t * A change in the bitrate.\n\t */\n\tBITRATE_CHANGE: CMCD_EVENT_BITRATE_CHANGE as typeof CMCD_EVENT_BITRATE_CHANGE,\n\n\t/**\n\t * A change in the player state.\n\t */\n\tPLAY_STATE: CMCD_EVENT_PLAY_STATE as typeof CMCD_EVENT_PLAY_STATE,\n\n\t/**\n\t * A change in the playback rate.\n\t */\n\tPLAYBACK_RATE: CMCD_EVENT_PLAYBACK_RATE as typeof CMCD_EVENT_PLAYBACK_RATE,\n\n\t/**\n\t * An error event.\n\t */\n\tERROR: CMCD_EVENT_ERROR as typeof CMCD_EVENT_ERROR,\n\n\t/**\n\t * A periodic report sent on a time interval.\n\t */\n\tTIME_INTERVAL: CMCD_EVENT_TIME_INTERVAL as typeof CMCD_EVENT_TIME_INTERVAL,\n\n\t/**\n\t * A change of the content ID.\n\t */\n\tCONTENT_ID: CMCD_EVENT_CONTENT_ID as typeof CMCD_EVENT_CONTENT_ID,\n\n\t/**\n\t * A change in the player's backgrounded state.\n\t */\n\tBACKGROUNDED_MODE: CMCD_EVENT_BACKGROUNDED_MODE as typeof CMCD_EVENT_BACKGROUNDED_MODE,\n\n\t/**\n\t * The player was muted.\n\t */\n\tMUTE: CMCD_EVENT_MUTE as typeof CMCD_EVENT_MUTE,\n\n\t/**\n\t * The player was unmuted.\n\t */\n\tUNMUTE: CMCD_EVENT_UNMUTE as typeof CMCD_EVENT_UNMUTE,\n\n\t/**\n\t * The player view was expanded.\n\t */\n\tPLAYER_EXPAND: CMCD_EVENT_PLAYER_EXPAND as typeof CMCD_EVENT_PLAYER_EXPAND,\n\n\t/**\n\t * The player view was collapsed.\n\t */\n\tPLAYER_COLLAPSE: CMCD_EVENT_PLAYER_COLLAPSE as typeof CMCD_EVENT_PLAYER_COLLAPSE,\n\n\t/**\n\t * The receipt of a response.\n\t */\n\tRESPONSE_RECEIVED: CMCD_EVENT_RESPONSE_RECEIVED as typeof CMCD_EVENT_RESPONSE_RECEIVED,\n\n\t/**\n\t * The start of an ad.\n\t */\n\tAD_START: CMCD_EVENT_AD_START as typeof CMCD_EVENT_AD_START,\n\n\t/**\n\t * The end of an ad.\n\t */\n\tAD_END: CMCD_EVENT_AD_END as typeof CMCD_EVENT_AD_END,\n\n\t/**\n\t * The start of an ad break.\n\t */\n\tAD_BREAK_START: CMCD_EVENT_AD_BREAK_START as typeof CMCD_EVENT_AD_BREAK_START,\n\n\t/**\n\t * The end of an ad break.\n\t */\n\tAD_BREAK_END: CMCD_EVENT_AD_BREAK_END as typeof CMCD_EVENT_AD_BREAK_END,\n\n\t/**\n\t * The user skipped an ad.\n\t */\n\tSKIP: CMCD_EVENT_SKIP as typeof CMCD_EVENT_SKIP,\n\n\t/**\n\t * A custom event.\n\t */\n\tCUSTOM_EVENT: CMCD_EVENT_CUSTOM_EVENT as typeof CMCD_EVENT_CUSTOM_EVENT,\n} as const\n\n/**\n * @public\n */\nexport type CmcdEventType = ValueOf<typeof CmcdEventType>;\n","import type { ValueOf } from '@svta/cml-utils'\n\n/**\n * Common Media Client Data Object Type\n *\n * @public\n *\n * @enum\n *\n * @see {@link https://cta-wave.github.io/Resources/common-media-client-data--cta-5004-b.html#object-type | CTA-5004-B Object Type}\n */\nexport const CmcdObjectType = {\n\t/**\n\t * text file, such as a manifest or playlist\n\t */\n\tMANIFEST: 'm',\n\n\t/**\n\t * audio only\n\t */\n\tAUDIO: 'a',\n\n\t/**\n\t * video only\n\t */\n\tVIDEO: 'v',\n\n\t/**\n\t * muxed audio and video\n\t */\n\tMUXED: 'av',\n\n\t/**\n\t * init segment\n\t */\n\tINIT: 'i',\n\n\t/**\n\t * caption or subtitle\n\t */\n\tCAPTION: 'c',\n\n\t/**\n\t * ISOBMFF timed text track\n\t */\n\tTIMED_TEXT: 'tt',\n\n\t/**\n\t * cryptographic key, license or certificate.\n\t */\n\tKEY: 'k',\n\n\t/**\n\t * other\n\t */\n\tOTHER: 'o',\n} as const\n\n/**\n * @public\n */\nexport type CmcdObjectType = ValueOf<typeof CmcdObjectType>;\n","import type { ValueOf } from '@svta/cml-utils'\n\n/**\n * CMCD version 2 player states for the 'sta' key.\n *\n *\n * @enum\n *\n * @public\n *\n * @see {@link https://cta-wave.github.io/Resources/common-media-client-data--cta-5004-b.html#state | CTA-5004-B State}\n */\nexport const CmcdPlayerState = {\n\t/**\n\t * Starting: Initial startup of the player.\n\t */\n\tSTARTING: 's',\n\n\t/**\n\t * Playing: The player is actively rendering content.\n\t */\n\tPLAYING: 'p',\n\n\t/**\n\t * Seeking: The player is seeking to a new position.\n\t */\n\tSEEKING: 'k',\n\n\t/**\n\t * Rebuffering: The player is buffering data during playback.\n\t */\n\tREBUFFERING: 'r',\n\n\t/**\n\t * Paused: The player is paused.\n\t */\n\tPAUSED: 'a',\n\n\t/**\n\t * Waiting: The player is waiting for a user action or another event.\n\t */\n\tWAITING: 'w',\n\n\t/**\n\t * Ended: The media has finished playing.\n\t */\n\tENDED: 'e',\n\n\t/**\n\t * Fatal Error: The player has encountered a fatal error.\n\t */\n\tFATAL_ERROR: 'f',\n\n\t/**\n\t * Quit: User initiated end of playback before media asset completion.\n\t */\n\tQUIT: 'q',\n\n\t/**\n\t * Preloading: The player is loading assets ahead of starting to provide a fast startup. The expectation is that playback will commence at a future time.\n\t */\n\tPRELOADING: 'd',\n} as const\n\n/**\n * @public\n */\nexport type CmcdPlayerState = ValueOf<typeof CmcdPlayerState>;\n","import type { ValueOf } from '@svta/cml-utils'\n\n/**\n * CMCD query reporting mode: CMCD data transmitted as a `CMCD=` URL\n * query parameter.\n *\n * @public\n */\nexport const CMCD_RECORDED_REPORT_MODE_QUERY = 'query' as const\n\n/**\n * CMCD header reporting mode: CMCD data transmitted as `CMCD-*` HTTP\n * headers.\n *\n * @public\n */\nexport const CMCD_RECORDED_REPORT_MODE_HEADER = 'header' as const\n\n/**\n * CMCD event reporting mode: CMCD data transmitted as a POST body to an\n * event-target URL.\n *\n * @public\n */\nexport const CMCD_RECORDED_REPORT_MODE_EVENT = 'event' as const\n\n/**\n * Reporting mode in which `CmcdReportRecorder` observed a captured\n * report.\n *\n * @enum\n *\n * @public\n */\nexport const CmcdRecordedReportMode = {\n\tQUERY: CMCD_RECORDED_REPORT_MODE_QUERY as typeof CMCD_RECORDED_REPORT_MODE_QUERY,\n\tHEADER: CMCD_RECORDED_REPORT_MODE_HEADER as typeof CMCD_RECORDED_REPORT_MODE_HEADER,\n\tEVENT: CMCD_RECORDED_REPORT_MODE_EVENT as typeof CMCD_RECORDED_REPORT_MODE_EVENT,\n} as const\n\n/**\n * @public\n */\nexport type CmcdRecordedReportMode = ValueOf<typeof CmcdRecordedReportMode>\n","import type { ValueOf } from '@svta/cml-utils'\n\n/**\n * Manifest or playlist request classification.\n *\n * @public\n */\nexport const CMCD_RECORDED_REQUEST_TYPE_MANIFEST = 'manifest' as const\n\n/**\n * Media segment request classification.\n *\n * @public\n */\nexport const CMCD_RECORDED_REQUEST_TYPE_SEGMENT = 'segment' as const\n\n/**\n * CMCD event-mode report request classification (POST to a URL in\n * `eventTargetUrls`).\n *\n * @public\n */\nexport const CMCD_RECORDED_REQUEST_TYPE_EVENT = 'event' as const\n\n/**\n * Default classification for requests the recorder did not recognize\n * as manifest, segment, or event.\n *\n * @public\n */\nexport const CMCD_RECORDED_REQUEST_TYPE_UNKNOWN = 'unknown' as const\n\n/**\n * Classification of a captured request, used by `CmcdReportRecorder`\n * for filtering.\n *\n * @enum\n *\n * @public\n */\nexport const CmcdRecordedRequestType = {\n\tMANIFEST: CMCD_RECORDED_REQUEST_TYPE_MANIFEST as typeof CMCD_RECORDED_REQUEST_TYPE_MANIFEST,\n\tSEGMENT: CMCD_RECORDED_REQUEST_TYPE_SEGMENT as typeof CMCD_RECORDED_REQUEST_TYPE_SEGMENT,\n\tEVENT: CMCD_RECORDED_REQUEST_TYPE_EVENT as typeof CMCD_RECORDED_REQUEST_TYPE_EVENT,\n\tUNKNOWN: CMCD_RECORDED_REQUEST_TYPE_UNKNOWN as typeof CMCD_RECORDED_REQUEST_TYPE_UNKNOWN,\n} as const\n\n/**\n * @public\n */\nexport type CmcdRecordedRequestType = ValueOf<typeof CmcdRecordedRequestType>\n","import type { HttpRequest } from '@svta/cml-utils'\nimport type { CmcdRequestDeliver, CmcdTransportAdapter } from './CmcdTransportAdapter.ts'\n\nasync function toHttpRequest(request: Request): Promise<HttpRequest> {\n\tconst headers: Record<string, string> = {}\n\trequest.headers.forEach((value, name) => {\n\t\theaders[name.toLowerCase()] = value\n\t})\n\n\tlet body: string | undefined\n\tif (request.body) {\n\t\ttry {\n\t\t\tbody = await request.text()\n\t\t} catch {\n\t\t\tbody = undefined\n\t\t}\n\t}\n\n\treturn {\n\t\turl: request.url,\n\t\tmethod: request.method,\n\t\theaders,\n\t\tbody,\n\t}\n}\n\n/**\n * Create a transport adapter for `CmcdReportRecorder` that patches\n * `globalThis.fetch` to capture requests with CMCD data. The patched\n * `fetch` normalizes each request to `HttpRequest` (lowercase headers,\n * body read as a UTF-8 string).\n *\n * The patched `fetch` reads each body once with `Request.text()` for\n * inspection. This read is safe for the body types that CMCD reports use\n * in practice: `string`, `Blob`, `ArrayBuffer`, `FormData`, and\n * `URLSearchParams`. The underlying `fetch` can read those bodies again.\n * Do not pass a `ReadableStream` as `init.body`. The patched `fetch`\n * consumes the stream, and the underlying `fetch` receives an\n * already-disturbed stream.\n *\n * @public\n */\nexport function createFetchTransport(): CmcdTransportAdapter {\n\treturn {\n\t\tattach(deliver: CmcdRequestDeliver): () => void {\n\t\t\tconst origFetch = globalThis.fetch\n\n\t\t\tglobalThis.fetch = async (\n\t\t\t\tinput: RequestInfo | URL,\n\t\t\t\tinit?: RequestInit,\n\t\t\t): Promise<Response> => {\n\t\t\t\tconst inspect = input instanceof Request\n\t\t\t\t\t? input.clone()\n\t\t\t\t\t: new Request(input, init)\n\t\t\t\tconst httpRequest = await toHttpRequest(inspect)\n\t\t\t\tconst synthetic = deliver(httpRequest)\n\t\t\t\tif (synthetic) {\n\t\t\t\t\treturn synthetic\n\t\t\t\t}\n\t\t\t\treturn origFetch.call(globalThis, input as RequestInfo, init)\n\t\t\t}\n\n\t\t\treturn () => {\n\t\t\t\tglobalThis.fetch = origFetch\n\t\t\t}\n\t\t},\n\t}\n}\n","import type { HttpRequest } from '@svta/cml-utils'\nimport type { CmcdRequestDeliver, CmcdTransportAdapter } from './CmcdTransportAdapter.ts'\n\ntype XhrInstance = XMLHttpRequest & {\n\t_cmcdMethod?: string;\n\t_cmcdUrl?: string;\n\t_cmcdHeaders?: Record<string, string>;\n}\n\nasync function completeXhrWith(xhr: XhrInstance, response: Response): Promise<void> {\n\tconst text = await response.clone().text().catch(() => '')\n\tconst ProgressEventCtor: typeof ProgressEvent | typeof Event =\n\t\ttypeof ProgressEvent !== 'undefined' ? ProgressEvent : Event\n\n\tqueueMicrotask(() => {\n\t\ttry {\n\t\t\tObject.defineProperty(xhr, 'status', { value: response.status, configurable: true })\n\t\t\tObject.defineProperty(xhr, 'statusText', { value: response.statusText, configurable: true })\n\t\t\tObject.defineProperty(xhr, 'readyState', { value: 4, configurable: true })\n\t\t\tObject.defineProperty(xhr, 'responseURL', { value: xhr._cmcdUrl ?? '', configurable: true })\n\t\t\tObject.defineProperty(xhr, 'response', { value: text, configurable: true })\n\t\t\tObject.defineProperty(xhr, 'responseText', { value: text, configurable: true })\n\n\t\t\tif (typeof xhr.onload === 'function') {\n\t\t\t\txhr.onload.call(xhr, new ProgressEventCtor('load') as ProgressEvent<EventTarget>)\n\t\t\t}\n\t\t\tif (typeof xhr.onloadend === 'function') {\n\t\t\t\txhr.onloadend.call(xhr, new ProgressEventCtor('loadend') as ProgressEvent<EventTarget>)\n\t\t\t}\n\t\t} catch {\n\t\t\t// MockXhr may not allow defineProperty on some properties;\n\t\t\t// for shim simplicity we set them directly as a fallback.\n\t\t\tconst target = xhr as unknown as Record<string, unknown>\n\t\t\ttarget['status'] = response.status\n\t\t\ttarget['statusText'] = response.statusText\n\t\t\ttarget['readyState'] = 4\n\t\t\ttarget['responseURL'] = xhr._cmcdUrl ?? ''\n\t\t\ttarget['response'] = text\n\t\t\ttarget['responseText'] = text\n\t\t\tif (typeof xhr.onload === 'function') {\n\t\t\t\txhr.onload.call(xhr as unknown as XMLHttpRequest, new ProgressEventCtor('load') as ProgressEvent<EventTarget>)\n\t\t\t}\n\t\t\tif (typeof xhr.onloadend === 'function') {\n\t\t\t\txhr.onloadend.call(xhr as unknown as XMLHttpRequest, new ProgressEventCtor('loadend') as ProgressEvent<EventTarget>)\n\t\t\t}\n\t\t}\n\t})\n}\n\n/**\n * Create a transport adapter for `CmcdReportRecorder` that patches\n * `XMLHttpRequest.prototype` to capture requests with CMCD data.\n *\n * @public\n */\nexport function createXhrTransport(): CmcdTransportAdapter {\n\treturn {\n\t\tattach(deliver: CmcdRequestDeliver): () => void {\n\t\t\tconst Xhr = globalThis.XMLHttpRequest\n\t\t\tif (!Xhr) {\n\t\t\t\treturn () => { /* no XHR to detach */ }\n\t\t\t}\n\t\t\tconst origOpen = Xhr.prototype.open\n\t\t\tconst origSetRequestHeader = Xhr.prototype.setRequestHeader\n\t\t\tconst origSend = Xhr.prototype.send\n\n\t\t\tXhr.prototype.open = function (this: XhrInstance, method: string, url: string | URL): void {\n\t\t\t\tthis._cmcdMethod = method\n\t\t\t\tthis._cmcdUrl = typeof url === 'string' ? url : url.toString()\n\t\t\t\tthis._cmcdHeaders = {}\n\t\t\t\t// eslint-disable-next-line prefer-rest-params\n\t\t\t\treturn origOpen.apply(this, arguments as unknown as Parameters<typeof origOpen>)\n\t\t\t}\n\n\t\t\tXhr.prototype.setRequestHeader = function (this: XhrInstance, name: string, value: string): void {\n\t\t\t\tif (this._cmcdHeaders) {\n\t\t\t\t\tthis._cmcdHeaders[name.toLowerCase()] = value\n\t\t\t\t}\n\t\t\t\treturn origSetRequestHeader.apply(this, [name, value])\n\t\t\t}\n\n\t\t\tXhr.prototype.send = function (this: XhrInstance, body?: Document | XMLHttpRequestBodyInit | null): void {\n\t\t\t\tconst httpRequest: HttpRequest = {\n\t\t\t\t\turl: this._cmcdUrl ?? '',\n\t\t\t\t\tmethod: (this._cmcdMethod ?? 'GET').toUpperCase(),\n\t\t\t\t\theaders: this._cmcdHeaders ?? {},\n\t\t\t\t\tbody: (typeof Document !== 'undefined' && body instanceof Document ? undefined : body as BodyInit | null | undefined) ?? undefined,\n\t\t\t\t}\n\n\t\t\t\tconst synthetic = deliver(httpRequest)\n\n\t\t\t\tif (synthetic) {\n\t\t\t\t\tcompleteXhrWith(this, synthetic)\n\t\t\t\t\treturn\n\t\t\t\t}\n\n\t\t\t\treturn origSend.apply(this, [body])\n\t\t\t}\n\n\t\t\treturn () => {\n\t\t\t\tXhr.prototype.open = origOpen\n\t\t\t\tXhr.prototype.setRequestHeader = origSetRequestHeader\n\t\t\t\tXhr.prototype.send = origSend\n\t\t\t}\n\t\t},\n\t}\n}\n","import type { HttpRequest } from '@svta/cml-utils'\nimport { CMCD_PARAM } from './CMCD_PARAM.ts'\nimport type { CmcdRecordedReport } from './CmcdRecordedReport.ts'\nimport type { CmcdRecordedReportMode } from './CmcdRecordedReportMode.ts'\nimport type { CmcdReportRecorderOptions } from './CmcdReportRecorderOptions.ts'\nimport type { CmcdReportRecorderWaitOptions } from './CmcdReportRecorderWaitOptions.ts'\nimport { CmcdRecordedRequestType } from './CmcdRecordedRequestType.ts'\nimport { createFetchTransport } from './createFetchTransport.ts'\nimport { createXhrTransport } from './createXhrTransport.ts'\n\nconst MANIFEST_EXTENSIONS = /\\.(m3u8|mpd)(\\?|$|\\/)/i\nconst SEGMENT_EXTENSIONS = /\\.(m4s|m4v|m4a|mp4|ts|aac)(\\?|$|\\/)/i\n\nfunction classifyUrl(url: string, isEventTarget: boolean): CmcdRecordedRequestType {\n\tif (isEventTarget) {\n\t\treturn CmcdRecordedRequestType.EVENT\n\t}\n\tif (MANIFEST_EXTENSIONS.test(url)) {\n\t\treturn CmcdRecordedRequestType.MANIFEST\n\t}\n\tif (SEGMENT_EXTENSIONS.test(url)) {\n\t\treturn CmcdRecordedRequestType.SEGMENT\n\t}\n\treturn CmcdRecordedRequestType.UNKNOWN\n}\n\nfunction hasCmcdHeader(headers: Record<string, string> | undefined): boolean {\n\tif (!headers) {\n\t\treturn false\n\t}\n\tfor (const name in headers) {\n\t\tif (name.toLowerCase().startsWith('cmcd-')) {\n\t\t\treturn true\n\t\t}\n\t}\n\treturn false\n}\n\nfunction detectReportingMode(\n\turl: string,\n\theaders: Record<string, string> | undefined,\n\tisEventTarget: boolean,\n): CmcdRecordedReportMode | null {\n\tif (isEventTarget) {\n\t\treturn 'event'\n\t}\n\tif (hasCmcdHeader(headers)) {\n\t\treturn 'header'\n\t}\n\treturn url.includes(`${CMCD_PARAM}=`) ? 'query' : null\n}\n\ntype CmcdReportWaiter = {\n\ttype: CmcdRecordedRequestType | undefined\n\tcount: number\n\tresolve: (r: CmcdRecordedReport[]) => void\n\treject: (e: Error) => void\n}\n\n/**\n * Test helper that records CMCD reports from the XHR and fetch\n * transports for assertions in e2e tests. The recorder normalizes each\n * captured request to {@link @svta/cml-utils!HttpRequest | HttpRequest},\n * so tests are identical regardless of which transport the player uses.\n *\n * @example\n * {@includeCode ../test/CmcdReportRecorder.test.ts#example}\n *\n * @public\n */\nexport class CmcdReportRecorder {\n\tprivate reports: CmcdRecordedReport[] = []\n\tprivate detachers: (() => void)[] = []\n\tprivate attached = false\n\tprivate eventTargetUrls: readonly string[] = []\n\tprivate waiters = new Map<ReturnType<typeof setTimeout>, CmcdReportWaiter>()\n\tprivate onReport: ((report: CmcdRecordedReport) => void) | undefined\n\tprivate waitTimeout = 15000\n\n\tprivate readonly deliver = (request: HttpRequest): Response | undefined => {\n\t\tconst url = request.url\n\t\tconst method = (request.method ?? 'GET').toUpperCase()\n\t\tconst isEventTarget = method === 'POST' && this.eventTargetUrls.some((t) => url.startsWith(t))\n\n\t\tconst reportingMode = detectReportingMode(url, request.headers, isEventTarget)\n\t\tif (reportingMode === null) {\n\t\t\treturn undefined\n\t\t}\n\n\t\tconst captured: CmcdRecordedReport = {\n\t\t\trequest,\n\t\t\ttype: classifyUrl(url, isEventTarget),\n\t\t\treportingMode,\n\t\t\ttimestamp: Date.now(),\n\t\t}\n\t\tthis.reports.push(captured)\n\t\tif (this.onReport) {\n\t\t\ttry {\n\t\t\t\tthis.onReport(captured)\n\t\t\t} catch (err) {\n\t\t\t\tconsole.error('CmcdReportRecorder onReport listener threw:', err)\n\t\t\t}\n\t\t}\n\t\tthis.notifyWaiters()\n\n\t\treturn isEventTarget ? new Response(null, { status: 204 }) : undefined\n\t}\n\n\tprivate getMatching(type: CmcdRecordedRequestType | undefined): CmcdRecordedReport[] {\n\t\treturn type === undefined\n\t\t\t? [...this.reports]\n\t\t\t: this.reports.filter((r) => r.type === type)\n\t}\n\n\tprivate notifyWaiters(): void {\n\t\tfor (const [timer, waiter] of this.waiters) {\n\t\t\tconst matching = this.getMatching(waiter.type)\n\t\t\tif (matching.length >= waiter.count) {\n\t\t\t\tclearTimeout(timer)\n\t\t\t\tthis.waiters.delete(timer)\n\t\t\t\twaiter.resolve(matching)\n\t\t\t}\n\t\t}\n\t}\n\n\tprivate waitFor(\n\t\ttype: CmcdRecordedRequestType | undefined,\n\t\toptions: CmcdReportRecorderWaitOptions,\n\t): Promise<CmcdRecordedReport[]> {\n\t\tconst count = options.count ?? 1\n\t\tconst timeout = options.timeout ?? this.waitTimeout\n\n\t\tconst matching = this.getMatching(type)\n\t\tif (matching.length >= count) {\n\t\t\treturn Promise.resolve(matching)\n\t\t}\n\n\t\treturn new Promise<CmcdRecordedReport[]>((resolve, reject) => {\n\t\t\tconst timer = setTimeout(() => {\n\t\t\t\tthis.waiters.delete(timer)\n\t\t\t\tconst current = this.getMatching(type)\n\t\t\t\treject(new Error(\n\t\t\t\t\t`Timeout waiting for ${count} ${type ?? 'any'} CMCD report(s). Got ${current.length}. Total recorded: ${this.reports.length}.`,\n\t\t\t\t))\n\t\t\t}, timeout)\n\n\t\t\tthis.waiters.set(timer, { type, count, resolve, reject })\n\t\t})\n\t}\n\n\t/**\n\t * Install transport patches and start recording CMCD reports.\n\t * If the recorder is already attached, this call does nothing. The\n\t * recorder keeps the previous options and silently ignores the new\n\t * `options` argument. To re-attach with different options, call\n\t * `detach()` first.\n\t *\n\t * @public\n\t */\n\tattach(options: CmcdReportRecorderOptions = {}): void {\n\t\tif (this.attached) {\n\t\t\treturn\n\t\t}\n\t\tthis.attached = true\n\t\tthis.eventTargetUrls = options.eventTargetUrls ?? []\n\t\tthis.onReport = options.onReport\n\t\tthis.waitTimeout = options.waitTimeout ?? 15000\n\n\t\tconst transports = options.transports ?? [createXhrTransport(), createFetchTransport()]\n\t\tfor (const transport of transports) {\n\t\t\tthis.detachers.push(transport.attach(this.deliver))\n\t\t}\n\t}\n\n\t/**\n\t * Remove transport patches and stop recording. Rejects any pending\n\t * wait promises with `Error('Recorder detached while waiting')`.\n\t *\n\t * @public\n\t */\n\tdetach(): void {\n\t\tif (!this.attached) {\n\t\t\treturn\n\t\t}\n\t\tfor (const detacher of this.detachers) {\n\t\t\tdetacher()\n\t\t}\n\t\tthis.detachers = []\n\t\tthis.attached = false\n\t\tthis.eventTargetUrls = []\n\t\tthis.onReport = undefined\n\n\t\tfor (const [timer, waiter] of this.waiters) {\n\t\t\tclearTimeout(timer)\n\t\t\twaiter.reject(new Error('Recorder detached while waiting'))\n\t\t}\n\t\tthis.waiters.clear()\n\t}\n\n\t/**\n\t * Discard all recorded reports. Does not affect the attached state.\n\t *\n\t * @public\n\t */\n\tclear(): void {\n\t\tthis.reports = []\n\t}\n\n\t/**\n\t * Return a copy of all recorded reports.\n\t *\n\t * @public\n\t */\n\tgetReports(): CmcdRecordedReport[] {\n\t\treturn [...this.reports]\n\t}\n\n\t/**\n\t * Wait until at least `count` reports of any type are recorded.\n\t * Resolves with all matching reports. Rejects with a diagnostic error\n\t * on timeout. `count` defaults to 1. `timeout` defaults to the\n\t * recorder's `waitTimeout` option (default 15000 ms).\n\t *\n\t * @public\n\t */\n\twaitForReports(options: CmcdReportRecorderWaitOptions = {}): Promise<CmcdRecordedReport[]> {\n\t\treturn this.waitFor(undefined, options)\n\t}\n\n\t/**\n\t * Wait until at least `count` manifest reports are recorded.\n\t * Resolves with all matching reports. Rejects with a diagnostic error\n\t * on timeout. `count` defaults to 1. `timeout` defaults to the\n\t * recorder's `waitTimeout` option (default 15000 ms).\n\t *\n\t * @public\n\t */\n\twaitForManifest(options: CmcdReportRecorderWaitOptions = {}): Promise<CmcdRecordedReport[]> {\n\t\treturn this.waitFor(CmcdRecordedRequestType.MANIFEST, options)\n\t}\n\n\t/**\n\t * Wait until at least `count` segment reports are recorded.\n\t * Resolves with all matching reports. Rejects with a diagnostic error\n\t * on timeout. `count` defaults to 1. `timeout` defaults to the\n\t * recorder's `waitTimeout` option (default 15000 ms).\n\t *\n\t * @public\n\t */\n\twaitForSegments(options: CmcdReportRecorderWaitOptions = {}): Promise<CmcdRecordedReport[]> {\n\t\treturn this.waitFor(CmcdRecordedRequestType.SEGMENT, options)\n\t}\n\n\t/**\n\t * Wait until at least `count` event-mode reports are recorded.\n\t * Resolves with all matching reports. Rejects with a diagnostic error\n\t * on timeout. `count` defaults to 1. `timeout` defaults to the\n\t * recorder's `waitTimeout` option (default 15000 ms).\n\t *\n\t * @public\n\t */\n\twaitForEvents(options: CmcdReportRecorderWaitOptions = {}): Promise<CmcdRecordedReport[]> {\n\t\treturn this.waitFor(CmcdRecordedRequestType.EVENT, options)\n\t}\n}\n","import {\n\tCMCD_EVENT_BACKGROUNDED_MODE,\n\tCMCD_EVENT_BITRATE_CHANGE,\n\tCMCD_EVENT_CONTENT_ID,\n\tCMCD_EVENT_PLAY_STATE,\n\tCMCD_EVENT_PLAYBACK_RATE,\n\ttype CmcdEventType,\n} from './CmcdEventType.ts'\nimport type { CmcdKey } from './CmcdKey.ts'\n\n/**\n * Maps each state-change event type to the persistent field whose value\n * the event signals.\n *\n * The key table (`CMCD_KEY_SPECS`) marks the field as always sent on its\n * event, so the key filter of `prepareCmcdData` does not remove it.\n * `CmcdReporter` deduplicates events against the field value. It drops an\n * event whose field has no value and restores the field if a transform\n * removes it.\n *\n * Sending the field with each state-change event is a library choice.\n * The exception is the exit from backgrounded mode, which CTA-5004-B\n * defines as a `b` event without `bg`. CTA-5004-B requires the field only\n * on the `ps` event, which MUST carry `sta`. CTA-5004-B states no such rule\n * for `pr`, `c`, or `bc`. `validateCmcdStructure` follows CTA-5004-B and\n * does not read this map.\n *\n * Iteration order matters: `CmcdReporter.update()` records state-change\n * events in map order when several tracked fields change in one call.\n * Do not reorder entries without auditing reporter behavior.\n *\n * @internal\n */\nexport const CMCD_STATE_EVENT_FIELDS: ReadonlyMap<CmcdEventType, CmcdKey> = /* @__PURE__ */ new Map([\n\t[CMCD_EVENT_PLAY_STATE, 'sta'],\n\t[CMCD_EVENT_PLAYBACK_RATE, 'pr'],\n\t[CMCD_EVENT_CONTENT_ID, 'cid'],\n\t[CMCD_EVENT_BACKGROUNDED_MODE, 'bg'],\n\t[CMCD_EVENT_BITRATE_CHANGE, 'br'],\n])\n","import type { ValueOf } from '@svta/cml-utils'\n\n/**\n * CMCD `query` transmission mode.\n *\n * @public\n */\nexport const CMCD_QUERY = 'query' as const\n\n/**\n * CMCD `headers` transmission mode.\n *\n * @public\n */\nexport const CMCD_HEADERS = 'headers' as const\n\n/**\n * CMCD `json` transmission mode.\n *\n * @public\n *\n * @deprecated JSON transmission mode is deprecated and will be removed in future versions.\n */\nexport const CMCD_JSON = 'json' as const\n\n/**\n * CMCD transmission modes.\n *\n * @enum\n *\n * @public\n */\nexport const CmcdTransmissionMode = {\n\t/**\n\t * JSON\n\t *\n\t * @deprecated JSON transmission mode is deprecated and will be removed in future versions.\n\t */\n\tJSON: CMCD_JSON as typeof CMCD_JSON,\n\n\t/**\n\t * Query string\n\t */\n\tQUERY: CMCD_QUERY as typeof CMCD_QUERY,\n\n\t/**\n\t * Request headers\n\t */\n\tHEADERS: CMCD_HEADERS as typeof CMCD_HEADERS,\n\n} as const\n\n/**\n * @public\n */\nexport type CmcdTransmissionMode = ValueOf<typeof CmcdTransmissionMode>;\n","import { CMCD_INNER_LIST_KEYS } from './CMCD_INNER_LIST_KEYS.ts'\nimport { CMCD_V2 } from './CMCD_V2.ts'\nimport { toBareValue } from './toBareValue.ts'\n\n/**\n * Up-convert version 1 CMCD data to version 2.\n *\n * - Wraps scalar values in arrays for inner-list keys.\n * - Wraps `nor` string in an array.\n *\n * The function returns version 2 data (has `v: 2`) unchanged. An inner list\n * with parameters, which `decodeCmcd` returns as an `SfItem` that wraps the\n * list, also stays unchanged.\n *\n * @internal\n */\nexport function upConvertToV2(obj: Record<string, any>): Record<string, any> {\n\tif (toBareValue(obj['v']) === CMCD_V2) {\n\t\treturn obj\n\t}\n\n\tconst result: Record<string, any> = {}\n\n\tfor (const [key, value] of Object.entries(obj)) {\n\t\tif (value == null) {\n\t\t\tresult[key] = value\n\t\t\tcontinue\n\t\t}\n\n\t\tif (CMCD_INNER_LIST_KEYS.has(key) && !Array.isArray(toBareValue(value))) {\n\t\t\tresult[key] = [value]\n\t\t}\n\t\telse if (key === 'nor' && typeof value === 'string') {\n\t\t\tresult[key] = [value]\n\t\t}\n\t\telse {\n\t\t\tresult[key] = value\n\t\t}\n\t}\n\n\treturn result\n}\n","import type { SfBareItem } from '@svta/cml-structured-field-values'\nimport { decodeSfDict, SfItem, symbolToStr } from '@svta/cml-structured-field-values'\nimport type { Cmcd } from './Cmcd.ts'\nimport type { CmcdData } from './CmcdData.ts'\nimport type { CmcdDecodeOptions } from './CmcdDecodeOptions.ts'\nimport type { CmcdValue } from './CmcdValue.ts'\nimport { upConvertToV2 } from './upConvertToV2.ts'\n\n// Define the input type for reduceValue\ntype ReduceValueInput = SfBareItem | SfItem | ReduceValueInput[];\n\n// Define the output type for reduceValue - matches what CMCD values can be, including arrays\ntype ReduceValueOutput = CmcdValue | ReduceValueOutput[];\n\nfunction reduceValue(value: ReduceValueInput, useSymbol: boolean | undefined): ReduceValueOutput {\n\tif (Array.isArray(value)) {\n\t\treturn value.map(item => reduceValue(item, useSymbol))\n\t}\n\n\t// Tokens reduce to plain strings unless the caller opted into\n\t// preservation, where the parser's own representation passes through:\n\t// a registry symbol, or an SfToken when `useSymbol` is `false`. Both\n\t// re-encode as bare tokens, so preserved output round-trips.\n\tif (typeof value === 'symbol') {\n\t\treturn useSymbol === undefined ? symbolToStr(value) : (value as unknown as ReduceValueOutput)\n\t}\n\n\tif (value instanceof SfItem) {\n\t\t// Params are data: an item that carries them stays an SfItem, with\n\t\t// its value reduced the same way a bare member's would be. Only\n\t\t// param-less wrappers unwrap.\n\t\treturn value.params\n\t\t\t? new SfItem(reduceValue(value.value, useSymbol), value.params)\n\t\t\t: reduceValue(value.value, useSymbol)\n\t}\n\n\treturn value as ReduceValueOutput\n};\n\n/**\n * Decode a CMCD string to an object.\n *\n * @param cmcd - The CMCD string to decode.\n * @param options - Options for decoding.\n *\n * @returns The decoded CMCD object.\n *\n * @see {@link https://cta-wave.github.io/Resources/common-media-client-data--cta-5004-b.html#payload-definition-for-headers-and-query-argument-transmission | CTA-5004-B Payload Definition}\n *\n * @public\n *\n * @example\n * {@includeCode ../test/decodeCmcd.test.ts#example}\n */\nexport function decodeCmcd(cmcd: string, options: CmcdDecodeOptions & { convertToLatest: true }): Cmcd\n/**\n * Decode a CMCD string to an object.\n *\n * @typeParam T - The type of the decoded object. Defaults to {@link CmcdData}.\n * @param cmcd - The CMCD string to decode.\n * @param options - Options for decoding.\n *\n * @returns The decoded CMCD object.\n *\n * @public\n */\nexport function decodeCmcd<T extends CmcdData = CmcdData>(cmcd: string, options?: CmcdDecodeOptions): T\nexport function decodeCmcd(cmcd: string, options?: CmcdDecodeOptions): CmcdData | Cmcd {\n\tif (!cmcd) {\n\t\treturn {} as CmcdData\n\t}\n\n\tconst sfDict = decodeSfDict(cmcd, options)\n\n\t// Each dictionary member is reduced whole, not via `item.value`, so\n\t// member-level and inner-list-level params survive decoding.\n\tconst result: Record<string, unknown> = {}\n\tfor (const [key, item] of Object.entries(sfDict as Record<string, SfItem>)) {\n\t\tresult[key] = reduceValue(item, options?.useSymbol)\n\t}\n\n\tif (options?.convertToLatest) {\n\t\treturn upConvertToV2(result) as Cmcd\n\t}\n\n\treturn result as CmcdData\n}\n","import type { HttpRequest, HttpResponse } from '@svta/cml-utils'\nimport { uuid } from '@svta/cml-utils'\nimport { CMCD_DEFAULT_TIME_INTERVAL } from './CMCD_DEFAULT_TIME_INTERVAL.ts'\nimport { CMCD_MIME_TYPE } from './CMCD_MIME_TYPE.ts'\nimport { CMCD_REQUEST_PROVENANCE } from './CMCD_REQUEST_PROVENANCE.ts'\nimport { CMCD_V2 } from './CMCD_V2.ts'\nimport type { Cmcd } from './Cmcd.ts'\nimport type { CmcdEncodeOptions } from './CmcdEncodeOptions.ts'\nimport type { CmcdEventReportConfig } from './CmcdEventReportConfig.ts'\nimport { CMCD_EVENT_BACKGROUNDED_MODE, CMCD_EVENT_CUSTOM_EVENT, CMCD_EVENT_ERROR, CMCD_EVENT_RESPONSE_RECEIVED, CMCD_EVENT_TIME_INTERVAL, CmcdEventType } from './CmcdEventType.ts'\nimport { CMCD_STATE_EVENT_FIELDS } from './CMCD_STATE_EVENT_FIELDS.ts'\nimport type { CmcdKey } from './CmcdKey.ts'\nimport type { CmcdObjectTypeList } from './CmcdObjectTypeList.ts'\nimport type { CmcdReportConfig } from './CmcdReportConfig.ts'\nimport type { CmcdReporterConfig } from './CmcdReporterConfig.ts'\nimport type { CmcdReporterCustomData } from './CmcdReporterCustomData.ts'\nimport type { CmcdRequestProvenance } from './CmcdRequestProvenance.ts'\nimport type { CmcdRequestReportConfig } from './CmcdRequestReportConfig.ts'\nimport type { CmcdReportingMode } from './CmcdReportingMode.ts'\nimport { CMCD_EVENT_MODE, CMCD_REQUEST_MODE } from './CmcdReportingMode.ts'\nimport type { CmcdRequestReport } from './CmcdRequestReport.ts'\nimport type { CmcdTransformRequest } from './CmcdTransformRequest.ts'\nimport { CMCD_HEADERS, CMCD_QUERY } from './CmcdTransmissionMode.ts'\nimport type { CmcdVersion } from './CmcdVersion.ts'\nimport { decodeCmcd } from './decodeCmcd.ts'\nimport { encodeCmcd } from './encodeCmcd.ts'\nimport { encodePreparedCmcd } from './encodePreparedCmcd.ts'\nimport { isValid } from './isValid.ts'\nimport { prepareCmcdData } from './prepareCmcdData.ts'\nimport { replaceCmcdParam } from './replaceCmcdParam.ts'\nimport { toBareValue } from './toBareValue.ts'\nimport { toPreparedCmcdHeaders } from './toPreparedCmcdHeaders.ts'\n\ntype CmcdReportConfigNormalized = CmcdReportConfig & {\n\tversion: CmcdVersion;\n}\n\ntype CmcdEventReportConfigNormalized<C> = CmcdEventReportConfig<C> & CmcdReportConfigNormalized & {\n\tevents: CmcdEventType[];\n\tinterval: number;\n\tbatchSize: number;\n}\n\ntype CmcdReporterConfigNormalized<C> = CmcdReporterConfig<C> & CmcdReportConfigNormalized & {\n\tsid: string;\n\teventTargets: CmcdEventReportConfigNormalized<C>[];\n\tsessionRetention: number;\n}\n\nfunction createEncodingOptions(reportingMode: CmcdReportingMode, config: CmcdReportConfig & Pick<CmcdRequestReportConfig, 'customHeaderMap'>, baseUrl?: string): CmcdEncodeOptions {\n\tconst enabledKeySet = new Set(config.enabledKeys ?? [])\n\n\treturn {\n\t\tversion: config.version || CMCD_V2,\n\t\treportingMode,\n\t\tfilter: (key: CmcdKey) => enabledKeySet.has(key),\n\t\tbaseUrl,\n\t\tcustomHeaderMap: config.customHeaderMap,\n\t}\n}\n\n/**\n * Tracked state field for deduplication and auto-fired events.\n */\ntype StateField = 'sta' | 'pr' | 'cid' | 'bg' | 'br'\n\n/**\n * One row in the STATE_FIELDS dispatch table.\n *\n * `snapshot` returns the value stored in `lastEmitted` for deduplication\n * comparisons. Reference types must clone. Otherwise the baseline would\n * share a reference with the caller's input, and in-place mutation would\n * silently corrupt the baseline.\n */\ntype StateFieldEntry = {\n\tfield: StateField\n\tevent: CmcdEventType\n\tequal: (a: unknown, b: unknown) => boolean\n\tsnapshot: (v: unknown) => unknown\n}\n\n/**\n * Deep equality for CmcdObjectTypeList (used for `br` deduplication).\n *\n * Arrays with the same elements in different positions count as different.\n * Players that construct `br` consistently get correct deduplication.\n * Reordered arrays produce extra events, which is the safer failure.\n */\nfunction cmcdObjectTypeListEqual(a: CmcdObjectTypeList, b: CmcdObjectTypeList): boolean {\n\tif (a === b) return true\n\tif (a.length !== b.length) return false\n\n\tfor (let i = 0; i < a.length; i++) {\n\t\tconst ai = a[i]\n\t\tconst bi = b[i]\n\t\tif (ai === bi) continue\n\t\tif ((typeof ai === 'number' ? ai : ai.value) !== (typeof bi === 'number' ? bi : bi.value)) return false\n\n\t\t// ExclusiveRecord: params (when defined) has exactly one key\n\t\tconst ap = typeof ai === 'number' ? undefined : ai.params\n\t\tconst bp = typeof bi === 'number' ? undefined : bi.params\n\t\tconst ak = ap && Object.keys(ap)[0]\n\t\tconst bk = bp && Object.keys(bp)[0]\n\t\tif (ak !== bk) return false\n\t\tif (ak !== undefined && bk !== undefined && ap && bp && ap[ak as keyof typeof ap] !== bp[bk as keyof typeof bp]) return false\n\t}\n\n\treturn true\n}\n\n/**\n * Equality for `br` deduplication. A `br` value can be an `SfItem` that\n * wraps the list, as `decodeCmcd` returns for an inner list with\n * parameters. Two values are equal when their lists are equal. The\n * parameters of the list are not compared.\n */\nfunction brEqual(a: unknown, b: unknown): boolean {\n\tconst listA = toBareValue(a)\n\tconst listB = toBareValue(b)\n\n\tif (!Array.isArray(listA) || !Array.isArray(listB)) {\n\t\treturn Object.is(a, b)\n\t}\n\n\treturn cmcdObjectTypeListEqual(listA, listB)\n}\n\nconst equal = Object.is\nconst identity = <T>(v: T): T => v\n\n/**\n * Maps each tracked state field to its event type and equality function.\n * Order matters: `update()` fires events in this order for multi-field updates.\n */\nconst STATE_FIELDS: readonly StateFieldEntry[] = /* @__PURE__ */ Array.from(\n\tCMCD_STATE_EVENT_FIELDS,\n\t([event, field]): StateFieldEntry => {\n\t\tif (field === 'br') {\n\t\t\treturn {\n\t\t\t\tevent,\n\t\t\t\tfield,\n\t\t\t\tequal: brEqual,\n\t\t\t\tsnapshot: (v) => Array.isArray(v) ? v.slice() : copyItemValue(v),\n\t\t\t}\n\t\t}\n\t\treturn { event, field: field as StateField, equal, snapshot: identity }\n\t},\n)\n\nconst STATE_FIELDS_BY_EVENT: ReadonlyMap<CmcdEventType, StateFieldEntry> = /* @__PURE__ */ new Map(\n\t/* @__PURE__ */ STATE_FIELDS.map(e => [e.event, e]),\n)\n\nfunction buildRequiredEventKeys(): ReadonlyMap<CmcdEventType, CmcdKey> {\n\treturn new Map([\n\t\t...CMCD_STATE_EVENT_FIELDS,\n\t\t[CMCD_EVENT_CUSTOM_EVENT, 'cen'] as const,\n\t\t[CMCD_EVENT_ERROR, 'ec'] as const,\n\t\t[CMCD_EVENT_RESPONSE_RECEIVED, 'url'] as const,\n\t])\n}\n\n/**\n * Maps each event type to the key that a report of that type must keep,\n * beyond `e` and `ts`. Built from the state-change table plus the three\n * event types whose required key is event data, not player state.\n */\nconst CMCD_REQUIRED_EVENT_KEYS: ReadonlyMap<CmcdEventType, CmcdKey> = /* @__PURE__ */ buildRequiredEventKeys()\n\n/**\n * Copies a value with the `SfItem` structure, including its `params` record\n * and the list of an `SfItem` that wraps a list.\n *\n * The copy keeps the prototype because `prepareCmcdData`, the formatter map,\n * validation, and the structured-field encoder all branch on\n * `instanceof SfItem`. A plain spread (and `structuredClone`) would return a\n * prototype-less object and silently change the encoded output.\n */\nfunction copyItemValue(value: unknown): unknown {\n\tif (value === null || typeof value !== 'object') {\n\t\treturn value\n\t}\n\n\tconst copy = Object.assign(Object.create(Object.getPrototypeOf(value)), value) as { params?: unknown; value?: unknown; }\n\n\tif (copy.params !== null && typeof copy.params === 'object') {\n\t\tcopy.params = { ...copy.params }\n\t}\n\n\tif (Array.isArray(copy.value)) {\n\t\tcopy.value = copy.value.map(copyItemValue)\n\t}\n\n\treturn copy\n}\n\n/**\n * Copies the nested values of a report in place. A transform cannot mutate\n * the reporter's data store, or another target's report for the same event,\n * through an array or an `SfItem` it received.\n *\n * The copy is complete for the CMCD value space. `CmcdValue` and\n * `CmcdCustomValue` admit only primitives, `SfItem<primitive>`, and arrays of\n * those. `decodeCmcd` also returns an `SfItem` that wraps a list, and the\n * copy includes that list. `SfItem.params` is a flat record. The reporter calls this function\n * where a transform is configured, at session end on the ended session's\n * store, and on the request's stored player-facing view. The session-end\n * copy detaches the frozen snapshot from caller-held references.\n */\nfunction copyReportValues(data: Cmcd): Cmcd {\n\tconst record = data as Record<string, unknown>\n\n\tfor (const key in record) {\n\t\tconst value = record[key]\n\n\t\tif (Array.isArray(value)) {\n\t\t\tconst copy = new Array(value.length)\n\n\t\t\tfor (let i = 0; i < value.length; i++) {\n\t\t\t\tcopy[i] = copyItemValue(value[i])\n\t\t\t}\n\n\t\t\trecord[key] = copy\n\t\t}\n\t\telse if (value !== null && typeof value === 'object') {\n\t\t\trecord[key] = copyItemValue(value)\n\t\t}\n\t}\n\n\treturn data\n}\n\n/**\n * Decodes the per-call data snapshot of a provenance record into new,\n * encodable report data. Tokens decode as `SfToken` and items with params\n * as `SfItem` (`useSymbol: false`), so every value re-encodes with its\n * original type. Only `recordResponseReceived()` calls this function.\n * Returns an empty object when the record is absent, has no snapshot, or\n * the snapshot does not parse (a value this reporter did not write). The\n * response then reports its derived keys over the session's data alone.\n */\nfunction decodeSnapshot(provenance: unknown): Cmcd {\n\tconst encoded = (provenance !== null && typeof provenance === 'object')\n\t\t? (provenance as { data?: unknown; }).data\n\t\t: undefined\n\n\tif (typeof encoded !== 'string' || !encoded) {\n\t\treturn {}\n\t}\n\n\ttry {\n\t\treturn decodeCmcd(encoded, { useSymbol: false }) as Cmcd\n\t}\n\tcatch {\n\t\treturn {}\n\t}\n}\n\n/**\n * Creates a session's frozen base provenance record: the issuing `sid`, and\n * the `cid` that is current at creation time. `update()` creates a new record\n * on every `cid` change. Requests issued before a mid-session content change\n * keep their original `cid`, while later requests get the new one.\n */\nfunction mintProvenance(sid: string, cid: string | undefined): CmcdRequestProvenance {\n\treturn Object.freeze(typeof cid === 'string' && cid ? { sid, cid } : { sid })\n}\n\nfunction defaultRequester(request: HttpRequest): Promise<{ status: number; }> {\n\tconst { url, ...init } = request\n\treturn fetch(url, init)\n}\n\nfunction createCmcdReporterConfig<C>(config: Partial<CmcdReporterConfig<C>>): CmcdReporterConfigNormalized<C> {\n\t// Apply top-level config defaults\n\tconst {\n\t\tversion = CMCD_V2,\n\t\teventTargets = [],\n\t\tsid = uuid(),\n\t\ttransmissionMode = CMCD_QUERY,\n\t\t...rest\n\t} = config\n\n\t// Type-checked, never type-coerced: a numeric string or boolean falls\n\t// back to the default instead of converting, and a Symbol must not\n\t// throw under Math.floor's ToNumber.\n\tconst retention = config.sessionRetention\n\tconst sessionRetention = typeof retention === 'number' ? Math.floor(retention) : NaN\n\n\treturn {\n\t\t...rest,\n\t\tversion,\n\t\ttransmissionMode,\n\t\tsid,\n\t\tsessionRetention: sessionRetention >= 0 ? sessionRetention : 2,\n\t\t// Apply target config defaults\n\t\teventTargets: eventTargets.reduce((acc, target) => {\n\t\t\tif (target?.url && target.events?.length) {\n\t\t\t\tacc.push({\n\t\t\t\t\tversion: target.version || CMCD_V2,\n\t\t\t\t\tenabledKeys: target.enabledKeys?.slice() || [],\n\t\t\t\t\turl: target.url,\n\t\t\t\t\tevents: target.events.slice(),\n\t\t\t\t\tinterval: target.interval ?? CMCD_DEFAULT_TIME_INTERVAL,\n\t\t\t\t\tbatchSize: target.batchSize || 1,\n\t\t\t\t\ttransform: target.transform,\n\t\t\t\t})\n\t\t\t}\n\t\t\treturn acc\n\t\t}, [] as CmcdEventReportConfigNormalized<C>[]),\n\t}\n}\n\ntype CmcdTarget = {\n\tsn: number;\n\tmsdSent: boolean;\n}\n\ntype CmcdEventTarget = CmcdTarget & {\n\t/**\n\t * Complete, encoded report lines not yet sent. Encoding happens at queue\n\t * time, so a value that cannot serialize throws inside the recording call.\n\t * Later mutation of the source values cannot change a queued line.\n\t */\n\tqueue: string[];\n\tdisposed: boolean;\n}\n\n/**\n * The state owned by one session (one `sid`). This state stores everything\n * CTA-5004-B scopes to the session. A report can belong to an ended session:\n * a response that completes after a `sid` change, or a re-queued batch. Such\n * a report uses its own session's data and counters, not the current\n * session's.\n */\ntype CmcdSession<C> = {\n\tsid: string;\n\t/**\n\t * Frozen base provenance record for this session: its `sid` and the\n\t * `cid` current at creation time. The reporter writes the record under\n\t * {@link CMCD_REQUEST_PROVENANCE} on every request it returns. A request\n\t * created with per-call data gets a per-request record: the base record\n\t * plus that data encoded. `update()` creates a new record on every `cid`\n\t * change, so a record describes the state at request time. Already-issued\n\t * requests keep their record. Attribution reads the record's `sid` (see\n\t * `resolveSession()`).\n\t */\n\tprovenance: CmcdRequestProvenance;\n\tdata: Cmcd;\n\tmsd: number;\n\tlastEmitted: Partial<Pick<Cmcd, StateField>>;\n\teventTargets: Map<CmcdEventReportConfigNormalized<C>, CmcdEventTarget>;\n\trequestTarget: CmcdTarget;\n}\n\n/**\n * The CMCD reporter.\n *\n * `C` describes the player's own `customData`, which the reporter passes to\n * each configured `transform`. TypeScript infers `C` from the configuration,\n * so an annotation on one `transform` types the request in every other\n * `transform`. The default leaves `customData` values `unknown`.\n *\n * @typeParam C - The type of the player's `customData`. Defaults to\n * `Record<string, unknown>`.\n *\n * @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}\n *\n * @public\n */\nexport class CmcdReporter<C = Record<string, unknown>> {\n\tprivate timeOrigin = performance.timeOrigin || performance.timing?.fetchStart || Date.now() - performance.now()\n\tprivate config: CmcdReporterConfigNormalized<C>\n\n\t/**\n\t * Retained sessions keyed by `sid`, in insertion order: oldest first,\n\t * current session last. `config.sessionRetention` limits the ended-session\n\t * count. CTA-5004-B expects a `sid` to be unique per playback session. A\n\t * reused `sid` replaces the earlier session with that `sid` at the newest\n\t * position (see `startSession()`).\n\t */\n\tprivate sessions = new Map<string, CmcdSession<C>>()\n\tprivate session: CmcdSession<C>\n\n\t/**\n\t * Active time-interval timers by target config. Timers continue across\n\t * session changes (their callbacks report into whichever session is\n\t * current when they fire), so the reporter owns them, not the session.\n\t */\n\tprivate intervals = new Map<CmcdEventReportConfigNormalized<C>, ReturnType<typeof setInterval>>()\n\tprivate started = false\n\n\tprivate requester: (request: HttpRequest) => Promise<{ status: number; }>\n\n\t/**\n\t * Creates a new CMCD reporter.\n\t *\n\t * @param config - The configuration for the CMCD reporter.\n\t * @param requester - The function that sends the request.\n\t * The default is a simple wrapper around the\n\t * native `fetch` API.\n\t */\n\tconstructor(config: Partial<CmcdReporterConfig<C>>, requester: (request: HttpRequest) => Promise<{ status: number; }> = defaultRequester) {\n\t\tthis.config = createCmcdReporterConfig(config)\n\t\tthis.session = this.createSession(this.config.sid, {\n\t\t\tcid: this.config.cid,\n\t\t\tv: this.config.version,\n\t\t})\n\t\tthis.sessions.set(this.session.sid, this.session)\n\t\tthis.requester = requester\n\t}\n\n\t/**\n\t * Creates the state for a new session: initial counters, flags, queues, and\n\t * deduplication baseline for every configured target.\n\t */\n\tprivate createSession(sid: string, data: Cmcd): CmcdSession<C> {\n\t\tconst eventTargets = new Map<CmcdEventReportConfigNormalized<C>, CmcdEventTarget>()\n\n\t\tfor (const target of this.config.eventTargets) {\n\t\t\teventTargets.set(target, {\n\t\t\t\tsn: 0,\n\t\t\t\tmsdSent: false,\n\t\t\t\tqueue: [],\n\t\t\t\tdisposed: false,\n\t\t\t})\n\t\t}\n\n\t\treturn {\n\t\t\tsid,\n\t\t\t// Frozen because it is handed out on every returned request; the\n\t\t\t// sid value, not the record's identity, is what attributes.\n\t\t\tprovenance: mintProvenance(sid, data.cid),\n\t\t\tdata,\n\t\t\tmsd: NaN,\n\t\t\t// A session that does not start backgrounded has no exit to report.\n\t\t\t// CTA-5004-B defines a `b` event without `bg` as the exit.\n\t\t\tlastEmitted: toBareValue(data.bg) === true ? {} : { bg: false },\n\t\t\teventTargets,\n\t\t\trequestTarget: {\n\t\t\t\tsn: 0,\n\t\t\t\tmsdSent: false,\n\t\t\t},\n\t\t}\n\t}\n\n\t/**\n\t * Starts the CMCD reporter. The player calls this method when it enables the\n\t * reporter.\n\t *\n\t * This method fires an initial time-interval event immediately (synchronously),\n\t * before the first interval elapses. Populate the CMCD data (sid, cid, and\n\t * others) before calling start().\n\t */\n\tstart(): void {\n\t\tthis.started = true\n\n\t\t// The initial time-interval event is fired synchronously per target, so a\n\t\t// throwing transform must not abort the loop: later targets would never\n\t\t// have their intervals armed and would report nothing for the session,\n\t\t// and a retried start() would fail on the same target again. Same\n\t\t// continue-then-rethrow contract as `emitEvent()`.\n\t\tlet failure: { error: unknown; } | undefined\n\n\t\t// The fan-out is pinned to the session that was current when start()\n\t\t// was called: a transform can synchronously rotate the session, and\n\t\t// pairing the new session with the old session's targets would let a\n\t\t// report consume another session's sequence numbers.\n\t\tconst session = this.session\n\n\t\tsession.eventTargets.forEach((target, config) => {\n\t\t\t// Disarm any existing timer so repeated start() calls do not leak intervals.\n\t\t\tthis.disarmInterval(config)\n\n\t\t\t// A target disposed via HTTP 410 stays silent for the rest of the\n\t\t\t// session. Armed before the initial event so a throwing transform\n\t\t\t// leaves the timer in the same state a successful start() would,\n\t\t\t// rather than silently disabling the target.\n\t\t\tif (target.disposed || !this.armInterval(config)) {\n\t\t\t\treturn\n\t\t\t}\n\n\t\t\ttry {\n\t\t\t\tthis.recordTargetEvent(session, target, config, CMCD_EVENT_TIME_INTERVAL)\n\t\t\t\tthis.processEventTargets()\n\t\t\t}\n\t\t\tcatch (error) {\n\t\t\t\tfailure ??= { error }\n\t\t\t}\n\t\t})\n\n\t\tif (failure) {\n\t\t\tthrow failure.error\n\t\t}\n\t}\n\n\t/**\n\t * Starts the time-interval timer for an event target when its config\n\t * requires one. Returns whether a timer started. The callback reports into\n\t * whichever session is current when the timer fires.\n\t */\n\tprivate armInterval(config: CmcdEventReportConfigNormalized<C>): boolean {\n\t\t// If the interval is 0 or the TIME_INTERVAL event is not enabled, do not start the interval.\n\t\tif (config.interval === 0 || !config.events.includes(CMCD_EVENT_TIME_INTERVAL)) {\n\t\t\treturn false\n\t\t}\n\n\t\tthis.intervals.set(config, setInterval(() => {\n\t\t\tconst session = this.session\n\t\t\tconst target = session.eventTargets.get(config)\n\n\t\t\tif (target) {\n\t\t\t\tthis.recordTargetEvent(session, target, config, CMCD_EVENT_TIME_INTERVAL)\n\t\t\t\tthis.processEventTargets()\n\t\t\t}\n\t\t}, config.interval * 1000))\n\n\t\treturn true\n\t}\n\n\t/**\n\t * Stops the CMCD reporter. The player calls this method when it disables the\n\t * reporter.\n\t *\n\t * @param flush - Whether to flush the event targets.\n\t */\n\tstop(flush: boolean = false): void {\n\t\tthis.started = false\n\n\t\tif (flush) {\n\t\t\tthis.flush()\n\t\t}\n\n\t\tfor (const config of this.config.eventTargets) {\n\t\t\tthis.disarmInterval(config)\n\t\t}\n\t}\n\n\t/**\n\t * Sends all outstanding event reports, regardless of the batch size or\n\t * interval. Use this method when the player is destroyed or a playback\n\t * session ends.\n\t */\n\tflush(): void {\n\t\tthis.processEventTargets(true)\n\t}\n\n\t/**\n\t * Updates the CMCD data.\n\t *\n\t * The player calls this method when data changes. The tracked state fields\n\t * are `sta`, `pr`, `cid`, `bg`, and `br`. If a new value for one of them\n\t * differs from the last reported value for that field, the reporter fires\n\t * the matching state-change event. The comparison uses the last reported\n\t * value, not the previous persisted value. The first state-change event in\n\t * a new session therefore always fires, even when the persisted value did\n\t * not change across the `sid` boundary.\n\t *\n\t * The `bg` field is an exception. A session that does not start with\n\t * `bg: true` begins with `false` as its last reported `bg` value.\n\t * `bg: false` therefore fires `BACKGROUNDED_MODE` only if the session\n\t * started with `bg: true` or reported `bg: true`. CTA-5004-B defines a\n\t * `b` event without `bg` as the exit from backgrounded mode, so the exit\n\t * report does not carry `bg`. A target transform can add `bg: false` to\n\t * the exit report. The encoder writes that value as `?0`.\n\t *\n\t * Multi-field updates fire the events in this order: `sta`, `pr`, `cid`,\n\t * `bg`, `br`. The order of keys in the input object does not affect the\n\t * firing order.\n\t *\n\t * A state-change event can include context fields, for example `bl`, `mtp`,\n\t * `pt`, `ltc`. Those fields must be in the data store before the state field\n\t * changes. Either pass them with the state field in the same `update()`\n\t * call, or persist them with earlier `update()` calls. An auto-fired event\n\t * reports the current content of the data store. `TIME_INTERVAL` events also\n\t * read the data store, and the caller cannot add per-call data to them. The\n\t * player must therefore update the fields it wants in periodic reports with\n\t * this method.\n\t *\n\t * A `sid` change resets the deduplication baseline.\n\t *\n\t * `sid` and `msd` are session-owned. The reporter tracks them itself and\n\t * writes them into every outgoing report, so this method is the only way\n\t * to change them. A per-call value on {@link CmcdReporter.recordEvent},\n\t * {@link CmcdReporter.createRequestReport}, or\n\t * {@link CmcdReporter.recordResponseReceived} has no effect.\n\t * `msd` must be a finite number of milliseconds between `0` and\n\t * `999_999_999_999_999` (the RFC 8941 integer maximum). The reporter\n\t * rounds `msd` to the nearest integer and ignores invalid values.\n\t *\n\t * @param data - The data to update.\n\t */\n\tupdate(data: Partial<Cmcd>): void {\n\t\tif (data.sid && data.sid !== this.session.sid) {\n\t\t\tthis.startSession(data.sid)\n\t\t}\n\n\t\tconst session = this.session\n\t\tconst { msd } = data\n\n\t\t// CTA-5004-B defines msd as integer milliseconds, sent once per session.\n\t\t// 0 is a valid instant-start value; anything non-finite or negative is\n\t\t// ignored so it can neither reach the wire nor consume the send gate.\n\t\t// The rounded value must also fit an RFC 8941 structured-field integer\n\t\t// (at most 999_999_999_999_999), or serialization throws after the\n\t\t// gate is already consumed.\n\t\tif (typeof msd === 'number' && Number.isFinite(msd) && msd >= 0) {\n\t\t\tconst rounded = Math.round(msd)\n\n\t\t\tif (rounded <= 999_999_999_999_999) {\n\t\t\t\tsession.msd = rounded\n\t\t\t}\n\t\t}\n\n\t\t// sid and msd are session-owned: tracked in their own fields, stripped\n\t\t// from the persistent store, and stamped onto each report at queue time.\n\t\tsession.data = { ...session.data, ...data, sid: undefined, msd: undefined }\n\n\t\t// A cid change re-mints the session's base provenance record, so a\n\t\t// request issued from here on carries the new cid while requests\n\t\t// already in flight keep the one they were issued under. Their late\n\t\t// responses then report the content the request was actually about.\n\t\tif (session.data.cid !== session.provenance.cid) {\n\t\t\tsession.provenance = mintProvenance(session.sid, session.data.cid)\n\t\t}\n\n\t\t// Auto-trigger state-change events for any tracked field whose value\n\t\t// differs from the last wire-emitted value. Comparing against lastEmitted\n\t\t// (not the pre-merge value) ensures correctness after a session change,\n\t\t// and unifies the comparison basis with recordEvent's internal dedup.\n\t\tfor (const entry of STATE_FIELDS) {\n\t\t\tif (entry.field in data && !entry.equal(session.data[entry.field], session.lastEmitted[entry.field])) {\n\t\t\t\tthis.recordEvent(entry.event)\n\t\t\t}\n\t\t}\n\t}\n\n\t/**\n\t * Starts a new session. The reporter retains the current session for late\n\t * responses and creates a new current session. It then sends the ended\n\t * sessions' queued reports and removes the oldest sessions beyond the\n\t * configured retention.\n\t *\n\t * The ended session's snapshot is frozen: the reporter detaches its value\n\t * graph, so nested values from earlier `update()` calls cannot mutate the\n\t * snapshot. The new session starts from a shallow copy of that graph, which\n\t * preserves the data store. All fields, including `cid`, `br`, and custom\n\t * keys, survive a `sid` change as before. CTA-5004-B expects a `sid` to be\n\t * unique per playback session, so a reused `sid` replaces the retained\n\t * session with that `sid`. The replaced session's remaining state is lost,\n\t * as if removed, and the reporter attributes its late responses to the\n\t * replacement.\n\t */\n\tprivate startSession(sid: string): void {\n\t\tthis.session.data = copyReportValues({ ...this.session.data })\n\t\tthis.session = this.createSession(sid, { ...this.session.data })\n\n\t\t// Map.set keeps an existing key's insertion position, so a reused\n\t\t// sid must be deleted first: re-inserting at the newest position\n\t\t// keeps oldest-first eviction from ever reaching the current\n\t\t// session, and ages out genuinely older sessions ahead of it.\n\t\tthis.sessions.delete(sid)\n\t\tthis.sessions.set(sid, this.session)\n\n\t\t// Drain ended sessions before eviction can destroy their queues: a\n\t\t// partial batch the ended session could never fill again leaves now.\n\t\tthis.processEventTargets()\n\n\t\t// An evicted session's unsent queues die with it, and its stale\n\t\t// responses drop, because its sid no longer names a retained\n\t\t// session. The current session was inserted last, so oldest-first\n\t\t// eviction never reaches it, and `Infinity` retention never evicts.\n\t\tfor (const key of this.sessions.keys()) {\n\t\t\tif (this.sessions.size <= this.config.sessionRetention + 1) {\n\t\t\t\tbreak\n\t\t\t}\n\n\t\t\tthis.sessions.delete(key)\n\t\t}\n\n\t\t// Timers keep ticking across session changes. Configs whose timer was\n\t\t// disarmed by a 410 in the previous session re-arm here, because the\n\t\t// new session's targets are fresh; the immediate report start() fires\n\t\t// is not repeated.\n\t\tif (this.started) {\n\t\t\tfor (const config of this.config.eventTargets) {\n\t\t\t\tif (!this.intervals.has(config)) {\n\t\t\t\t\tthis.armInterval(config)\n\t\t\t\t}\n\t\t\t}\n\t\t}\n\t}\n\n\t/**\n\t * Records an event. The player calls this method when an event occurs.\n\t *\n\t * For state-change events (`PLAY_STATE`, `PLAYBACK_RATE`, `CONTENT_ID`,\n\t * `BACKGROUNDED_MODE`, `BITRATE_CHANGE`), this method:\n\t * 1. Writes the state field from `data` (if present) into the reporter's\n\t * data store, as `update()` would.\n\t * 2. Discards the event if the state field has no value after that write\n\t * (never set, or cleared with `update({ field: undefined })`).\n\t * 3. Suppresses the event if the field's current value equals the\n\t * last reported value (no state transition). {@link CmcdReporter.update}\n\t * describes the `bg` value that a new session starts with.\n\t *\n\t * The reporter always records all other event types.\n\t *\n\t * For state-change events, prefer {@link CmcdReporter.update}, also for\n\t * context fields in a combined call like\n\t * `update({ sta: 'p', bl: [3000], mtp: [8500] })`. After `update()`\n\t * auto-fires a state-change event, deduplication suppresses a\n\t * `recordEvent()` call for the same event, and that call's `data` is\n\t * silently lost.\n\t *\n\t * Call `recordEvent()` directly for events whose data comes with the event\n\t * call. Examples: `CUSTOM_EVENT` with `cen`, `ERROR` with `ec`, ad lifecycle\n\t * events, `MUTE`/`UNMUTE`, `PLAYER_EXPAND`/`PLAYER_COLLAPSE`, `SKIP`. For\n\t * `RESPONSE_RECEIVED`, prefer {@link CmcdReporter.recordResponseReceived},\n\t * which derives the per-response fields automatically.\n\t *\n\t * @param type - The type of event to record.\n\t * @param data - Additional data to record with the event. This data applies\n\t * only to this event report. The exception is the state field\n\t * of a state-change event, which the reporter also writes into\n\t * its data store. The reporter ignores session-owned keys\n\t * (`sid`, `msd`) supplied here and writes its own values.\n\t */\n\trecordEvent(type: CmcdEventType, data: Partial<Cmcd> = {}): void {\n\t\tthis.emitEvent(this.session, type, data)\n\t}\n\n\t/**\n\t * Records an event for every configured target of a session. State-change\n\t * deduplication runs once, before the per-target loop.\n\t *\n\t * @param session - The session the event belongs to. Everything the event\n\t * touches (data store, deduplication baseline, counters,\n\t * queues) is that session's. Only `recordResponseReceived()`\n\t * ever passes an ended session.\n\t * @param type - The type of event to record.\n\t * @param data - Additional data to record with the event.\n\t * @param request - The media request that triggered the event, when\n\t * one exists. Only `recordResponseReceived()` sets this\n\t * parameter, which the reporter passes to each target's\n\t * `transform`.\n\t */\n\tprivate emitEvent(session: CmcdSession<C>, type: CmcdEventType, data: Partial<Cmcd>, request?: HttpRequest): void {\n\t\tconst entry = STATE_FIELDS_BY_EVENT.get(type)\n\t\tif (entry) {\n\t\t\tconst field = entry.field\n\t\t\tconst incoming = data[field]\n\n\t\t\tif (incoming !== undefined) {\n\t\t\t\tObject.assign(session.data, { [field]: incoming })\n\t\t\t}\n\n\t\t\tconst current = session.data[field]\n\n\t\t\t// Never emit a state-change event whose state field has no value.\n\t\t\t// Catches both \"no value ever set\" and \"previous value was cleared to\n\t\t\t// undefined\".\n\t\t\tif (current === undefined) {\n\t\t\t\treturn\n\t\t\t}\n\n\t\t\tif (entry.equal(current, session.lastEmitted[field])) {\n\t\t\t\treturn\n\t\t\t}\n\n\t\t\tObject.assign(session.lastEmitted, { [field]: entry.snapshot(current) })\n\t\t}\n\n\t\t// A throwing transform must not abort the fan-out. The dedup baseline\n\t\t// above is already committed and is never rolled back, so aborting here\n\t\t// would strand the transition: targets after the throwing one would\n\t\t// never receive it, and the caller's retry would be deduped away.\n\t\tlet failure: { error: unknown; } | undefined\n\n\t\tsession.eventTargets.forEach((target, config) => {\n\t\t\ttry {\n\t\t\t\tthis.recordTargetEvent(session, target, config, type, data, request)\n\t\t\t}\n\t\t\tcatch (error) {\n\t\t\t\tfailure ??= { error }\n\t\t\t}\n\t\t})\n\n\t\tthis.processEventTargets()\n\n\t\t// Surfaced only once every target has had its turn and the queues have\n\t\t// been processed. Transforms must not throw; this makes the violation\n\t\t// visible without letting it starve unrelated targets.\n\t\tif (failure) {\n\t\t\tthrow failure.error\n\t\t}\n\t}\n\n\t/**\n\t * Records an event for a target. The reporter calls this method when an\n\t * event occurs.\n\t *\n\t * @param target - The target to record the event for.\n\t * @param config - The configuration for the target.\n\t * @param type - The type of event to record.\n\t * @param data - Additional data to record with the event. This data\n\t * only applies to this event report. Use `update()` for\n\t * persistent data.\n\t * @param request - The media request that triggered the event, when\n\t * one exists. The target's `transform` receives it.\n\t */\n\tprivate recordTargetEvent(session: CmcdSession<C>, target: CmcdEventTarget, config: CmcdEventReportConfigNormalized<C>, type: CmcdEventType, data: Partial<Cmcd> = {}, request?: HttpRequest): void {\n\t\tif (target.disposed || !config.events.includes(type)) {\n\t\t\treturn\n\t\t}\n\n\t\t// The session's sid is stamped over any per-call value here so a\n\t\t// transform sees the session identity the report will carry.\n\t\tconst item: Cmcd = {\n\t\t\t...session.data,\n\t\t\t...data,\n\t\t\tsid: session.sid,\n\t\t\te: type,\n\t\t\tts: data.ts ?? Date.now(),\n\t\t}\n\n\t\t// CTA-5004-B defines a `b` event without `bg` as the exit from\n\t\t// backgrounded mode. A transform can add `bg: false`, which the encoder\n\t\t// writes as `?0`.\n\t\tif (type === CMCD_EVENT_BACKGROUNDED_MODE && toBareValue(item.bg) === false) {\n\t\t\tdelete item.bg\n\t\t}\n\n\t\tconst { transform } = config\n\n\t\tif (!transform) {\n\t\t\tthis.queueTargetEvent(session, target, config, item, type)\n\t\t\treturn\n\t\t}\n\n\t\t// The spread above is shallow, so nested values are still shared with\n\t\t// the persistent store and with sibling targets' inputs; a transform\n\t\t// gets its own detached copy so in-place mutation reaches neither.\n\t\tcopyReportValues(item)\n\n\t\t// Captured so a transform cannot strip a key the event requires.\n\t\t// `CmcdKey` spans custom keys too, so index through a record view.\n\t\tconst requiredKey = CMCD_REQUIRED_EVENT_KEYS.get(type)\n\t\tconst requiredValue = requiredKey ? (item as Record<string, unknown>)[requiredKey] : undefined\n\t\tconst ts = item.ts\n\n\t\tconst report = transform(item, request)\n\n\t\t// A cancelled report consumes neither a sequence number nor msd.\n\t\tif (report == null) {\n\t\t\treturn\n\t\t}\n\n\t\t// Restore, never fabricate: a required key that was already absent (or\n\t\t// already unusable) before the transform ran is not restored. The\n\t\t// restore covers removal and substitution with any value that `isValid`\n\t\t// rejects, `false` included.\n\t\tif (!isValid(report.ts)) {\n\t\t\treport.ts = ts\n\t\t}\n\n\t\tif (requiredKey && isValid(requiredValue) && !isValid((report as Record<string, unknown>)[requiredKey])) {\n\t\t\tObject.assign(report, { [requiredKey]: requiredValue })\n\t\t}\n\n\t\tthis.queueTargetEvent(session, target, config, report, type)\n\t}\n\n\t/**\n\t * Writes the reporter-owned fields into a finished event report, encodes\n\t * the report, and pushes the encoded line to the target's queue.\n\t *\n\t * This method runs after any transform. A transform cannot bypass the\n\t * target's `events` filter through `e`, break `sn` continuity, or replace\n\t * the session identity in `sid` and `msd`. Encoding here makes a report\n\t * that cannot serialize throw inside the recording call, instead of failing\n\t * the batch send and re-queueing forever.\n\t *\n\t * @param target - The target to queue the report for.\n\t * @param config - The configuration for the target.\n\t * @param report - The finished report data.\n\t * @param type - The type of event being reported.\n\t */\n\tprivate queueTargetEvent(session: CmcdSession<C>, target: CmcdEventTarget, config: CmcdEventReportConfigNormalized<C>, report: Cmcd, type: CmcdEventType): void {\n\t\treport.e = type\n\t\treport.sn = target.sn++\n\t\treport.sid = session.sid\n\n\t\t// msd may only ride a report through the once-per-target gate, and only\n\t\t// when the target's key filter will retain it (msd is never force-added\n\t\t// at encode time): consuming the gate for a report that filters msd out\n\t\t// would silently drop it for the session. A value smuggled in via\n\t\t// per-call data or a transform is stripped, so the gate stays the\n\t\t// single source of once-per-session semantics.\n\t\tif (!isNaN(session.msd) && !target.msdSent && config.enabledKeys?.includes('msd')) {\n\t\t\treport.msd = session.msd\n\t\t\ttarget.msdSent = true\n\t\t}\n\t\telse {\n\t\t\tdelete report.msd\n\t\t}\n\n\t\ttarget.queue.push(encodeCmcd(report, createEncodingOptions(CMCD_EVENT_MODE, config)))\n\t}\n\n\t/**\n\t * Records a response-received event. The player calls this method when a\n\t * media request response has fully arrived.\n\t *\n\t * This method derives these `rr` event keys automatically:\n\t *\n\t * - `url` - the original requested URL (before any redirects)\n\t * - `rc` - the HTTP response status code\n\t * - `ts` - the request initiation time (from `resourceTiming.startTime`)\n\t * - `ttfb` - time to first byte (from `resourceTiming.responseStart`)\n\t * - `ttlb` - time to last byte (from `resourceTiming.duration`)\n\t *\n\t * If the player has additional keys like `ttfbb`, `cmsdd`, `cmsds`, and\n\t * `smrt`, pass them in the `data` parameter.\n\t *\n\t * The request's `customData` is generic, so a player can pass a request with\n\t * its own keys (for example `{ requestType: 'segment' }`) without a cast. The\n\t * reporter reads only the provenance record that\n\t * {@link CmcdReporter.createRequestReport} writes there. Every other key\n\t * stays unchanged and visible to an event target's `transform` through its\n\t * `request` argument.\n\t *\n\t * A reporter with a concrete `C` requires the request to satisfy that type.\n\t * TypeScript therefore rejects a call whose request the configured\n\t * transforms could not read. See {@link CmcdReporterCustomData}.\n\t *\n\t * The provenance record that {@link CmcdReporter.createRequestReport}\n\t * stored on the request's `customData` (under\n\t * {@link CMCD_REQUEST_PROVENANCE}) selects the session by `sid`. A record\n\t * that names no retained session drops the response (see\n\t * `CmcdReporterConfig.sessionRetention`). A request without a record reports\n\t * under the current session, as in version 2.4.0. The request-time data then\n\t * comes from `customData.cmcd`. A per-call `data.sid` cannot substitute. The\n\t * reporter accepts any record whose `sid` names a retained session. The\n\t * record may come from another reporter with the same session attributes,\n\t * or be hand-built. If the request has a record, a response that completes\n\t * after a `sid` change reports under its own retained session, with that\n\t * session's data snapshot and sequence numbers.\n\t *\n\t * With a record, request-time report keys come from the record's encoded\n\t * per-call `data` snapshot, which the reporter decodes for each response.\n\t * The record's `cid` replaces the session's current `cid` in the report. A\n\t * response that completes after a mid-session content change therefore\n\t * reports its request-time values.\n\t *\n\t * @typeParam RD - The `customData` of this request. Defaults to the\n\t * reporter's own `C`.\n\t *\n\t * @param response - The HTTP response received.\n\t * @param data - Additional CMCD data to include with the event.\n\t * Values provided here override the derived values.\n\t * The reporter ignores session-owned keys (`sid`, `msd`)\n\t * supplied here.\n\t */\n\trecordResponseReceived<RD extends CmcdReporterCustomData<C> = C>(response: HttpResponse<HttpRequest<RD & { cmcd?: Cmcd; [CMCD_REQUEST_PROVENANCE]?: CmcdRequestProvenance }>>, data: Partial<Cmcd> = {}): void {\n\t\tconst { request } = response\n\n\t\tconst url = data.url ?? request?.url\n\n\t\tif (!url) {\n\t\t\treturn\n\t\t}\n\n\t\tconst provenance = request.customData?.[CMCD_REQUEST_PROVENANCE]\n\t\tconst session = provenance === undefined ? this.session : this.resolveSession(provenance)\n\n\t\tif (!session) {\n\t\t\treturn\n\t\t}\n\n\t\tconst cmcd = provenance === undefined ? { ...request.customData?.cmcd } : decodeSnapshot(provenance)\n\n\t\t// The record's cid is the content the request was issued under. It\n\t\t// overrides the session store's current value so a response landing\n\t\t// after a mid-session content change keeps its meaning, and it\n\t\t// yields to the decoded snapshot and per-call data above it.\n\t\tconst { cid } = (provenance ?? {}) as { cid?: unknown; }\n\n\t\tconst derived: Partial<Cmcd> = {\n\t\t\turl: replaceCmcdParam(url),\n\t\t\trc: response.status,\n\t\t}\n\n\t\tconst timing = response.resourceTiming\n\n\t\tif (timing) {\n\t\t\tif (timing.startTime != null) {\n\t\t\t\tderived.ts = Math.round(this.timeOrigin + timing.startTime)\n\n\t\t\t\tif (timing.responseStart != null) {\n\t\t\t\t\tderived.ttfb = Math.round(timing.responseStart - timing.startTime)\n\t\t\t\t}\n\t\t\t}\n\n\t\t\tif (timing.duration != null) {\n\t\t\t\tderived.ttlb = Math.round(timing.duration)\n\t\t\t}\n\t\t}\n\n\t\tthis.emitEvent(session, CMCD_EVENT_RESPONSE_RECEIVED, {\n\t\t\t...(typeof cid === 'string' && cid ? { cid } : undefined),\n\t\t\t...cmcd,\n\t\t\t...derived,\n\t\t\t...data,\n\t\t}, request)\n\t}\n\n\t/**\n\t * Resolves the session that a provenance record names. The record's `sid`\n\t * must name one of this reporter's retained sessions, or the reporter\n\t * discards the response. A record that names a removed or unknown `sid`\n\t * resolves nothing. Any other attribution would be wrong. The reporter reads\n\t * the `sid` as a plain property. A record\n\t * copied through JSON therefore resolves the same session, and a hand-built\n\t * record that names a retained session is accepted.\n\t */\n\tprivate resolveSession(provenance: unknown): CmcdSession<C> | undefined {\n\t\tif (provenance === null || typeof provenance !== 'object') {\n\t\t\treturn undefined\n\t\t}\n\n\t\tconst { sid } = provenance as { sid?: unknown; }\n\n\t\treturn typeof sid === 'string' ? this.sessions.get(sid) : undefined\n\t}\n\n\t/**\n\t * Applies the CMCD request report data to the request. The player calls this\n\t * method before sending the request.\n\t *\n\t * @param req - The request to apply the CMCD request report to.\n\t * @returns The request with the CMCD request report applied.\n\t *\n\t * @deprecated Use {@link CmcdReporter.createRequestReport} instead.\n\t */\n\tapplyRequestReport(req: HttpRequest): HttpRequest {\n\t\treturn this.createRequestReport(req) ?? req\n\t}\n\n\t/**\n\t * Checks whether request reporting is enabled.\n\t *\n\t * @returns `true` if request reporting is enabled, `false` otherwise.\n\t */\n\tisRequestReportingEnabled(): boolean {\n\t\treturn !!this.config.enabledKeys?.length\n\t}\n\n\t/**\n\t * The provenance record to write on a returned request. It is the session's\n\t * frozen base record, extended with the caller's per-call data encoded as a\n\t * CMCD string when there is any. Requests without per-call data share the\n\t * base record, so the reporter writes only one property. The snapshot never\n\t * contains reporter-written fields. A value that cannot encode contributes\n\t * no snapshot and does not fail the request. The response still attributes\n\t * and reports derived keys over session data, matching the tolerance of\n\t * `decodeSnapshot()` when reading.\n\t */\n\tprivate createRequestProvenance(data: Partial<Cmcd> | undefined, baseUrl: string | undefined): CmcdRequestProvenance {\n\t\tconst base = this.session.provenance\n\n\t\tif (!data) {\n\t\t\treturn base\n\t\t}\n\n\t\ttry {\n\t\t\tconst encoded = encodeCmcd(data as Cmcd, {\n\t\t\t\tversion: this.config.version,\n\t\t\t\treportingMode: CMCD_REQUEST_MODE,\n\t\t\t\tbaseUrl,\n\t\t\t})\n\n\t\t\treturn encoded ? Object.freeze({ ...base, data: encoded }) : base\n\t\t}\n\t\tcatch {\n\t\t\treturn base\n\t\t}\n\t}\n\n\t/**\n\t * Creates a new request with the CMCD request report data applied. The\n\t * player calls this method before sending the request.\n\t *\n\t * A reporter with a concrete `C` requires the request's `customData` to\n\t * satisfy that type. TypeScript therefore rejects a call whose request the\n\t * configured transform could not read. See\n\t * {@link CmcdReporterCustomData}.\n\t *\n\t * @typeParam R - The type of the request. Its `customData` must satisfy\n\t * the reporter's `C`.\n\t *\n\t * @param request - The request to apply the CMCD request report to.\n\t * @param data - The data to apply to the request. This data only\n\t * applies to this request report. Use `update()` for\n\t * persistent data.\n\t * @returns The request with the CMCD request report applied.\n\t */\n\tcreateRequestReport<R extends HttpRequest<CmcdReporterCustomData<C>> = HttpRequest<C>>(request: R, data?: Partial<Cmcd>): R & CmcdRequestReport<R['customData']> {\n\t\tconst { customData = {}, headers = {}, ...rest } = request\n\t\tconst report = {\n\t\t\t...rest,\n\t\t\theaders: {\n\t\t\t\t...headers,\n\t\t\t},\n\t\t\tcustomData: {\n\t\t\t\t...customData,\n\t\t\t\tcmcd: {},\n\t\t\t\t// Session provenance rides every returned request, including\n\t\t\t\t// ones this method does not decorate (request reporting\n\t\t\t\t// disabled, or a transform cancels below): the request was\n\t\t\t\t// still issued by this session, and its response still needs\n\t\t\t\t// attribution. The per-call data is captured on the record\n\t\t\t\t// here, before any early return, key filter, or transform\n\t\t\t\t// can lose it, so a late response reports the caller's own\n\t\t\t\t// request-time inputs.\n\t\t\t\t[CMCD_REQUEST_PROVENANCE]: this.createRequestProvenance(data, request.url),\n\t\t\t},\n\t\t} as R & CmcdRequestReport<R['customData']>\n\n\t\tif (!this.config.enabledKeys?.length || !report.url) {\n\t\t\treturn report\n\t\t}\n\n\t\t// Request reports are always current-session. The session's sid is\n\t\t// stamped over any per-call value here so a transform sees the\n\t\t// session identity the report will carry.\n\t\tconst session = this.session\n\t\tconst merged: Cmcd = { ...session.data, ...data, sid: session.sid }\n\t\tconst { transform } = this.config\n\t\tlet cmcdData: Cmcd | null = merged\n\n\t\tif (transform) {\n\t\t\t// The spread above is shallow, so nested values are still shared\n\t\t\t// with the persistent store.\n\t\t\tcopyReportValues(merged)\n\n\t\t\t// The caller's request is passed, not the internal clone, so a\n\t\t\t// transform cannot alter the outgoing report through it.\n\t\t\tcmcdData = transform(merged, request as CmcdTransformRequest<C>)\n\n\t\t\t// A cancelled report consumes neither a sequence number nor msd.\n\t\t\tif (cmcdData == null) {\n\t\t\t\treturn report\n\t\t\t}\n\t\t}\n\n\t\t// Reporter-owned fields are stamped after the transform runs.\n\t\tcmcdData.sn = session.requestTarget.sn++\n\t\tcmcdData.sid = session.sid\n\n\t\t// msd may only ride a report through the once-per-session gate; a value\n\t\t// smuggled in via per-call data or the transform is stripped, so the\n\t\t// gate stays the single source of once-per-session semantics. The gate\n\t\t// is consumed after preparation, and only if the key filter retained\n\t\t// msd, so a filtered-out msd is not silently dropped for the session.\n\t\tconst sendMsd = !isNaN(session.msd) && !session.requestTarget.msdSent\n\n\t\tif (sendMsd) {\n\t\t\tcmcdData.msd = session.msd\n\t\t}\n\t\telse {\n\t\t\tdelete cmcdData.msd\n\t\t}\n\n\t\tconst options = createEncodingOptions(CMCD_REQUEST_MODE, this.config, report.url)\n\n\t\t// The player-facing view is detached from the persistent store:\n\t\t// prepareCmcdData builds a fresh object but copies values by\n\t\t// reference, and players read this object to identify requests, so a\n\t\t// shared array would leak mutation into the store. The reporter never\n\t\t// reads it back; the response path works from the encoded snapshot on\n\t\t// the provenance record.\n\t\tconst cmcd = report.customData.cmcd = copyReportValues(prepareCmcdData(cmcdData, options))\n\n\t\tif (sendMsd && cmcd.msd !== undefined) {\n\t\t\tsession.requestTarget.msdSent = true\n\t\t}\n\n\t\tconst encoded = encodePreparedCmcd(cmcd)\n\n\t\tswitch (this.config.transmissionMode) {\n\t\t\tcase CMCD_QUERY:\n\t\t\t\tif (encoded) {\n\t\t\t\t\treport.url = replaceCmcdParam(report.url, encoded)\n\t\t\t\t}\n\t\t\t\tbreak\n\n\t\t\tcase CMCD_HEADERS:\n\t\t\t\tObject.assign(report.headers, toPreparedCmcdHeaders(cmcd, options.customHeaderMap))\n\t\t\t\tbreak\n\t\t}\n\n\t\treturn report\n\t}\n\n\t/**\n\t * Processes the event targets. The reporter calls this method when an event\n\t * occurs.\n\t *\n\t * @param flush - Whether to flush the event targets.\n\t */\n\tprivate processEventTargets(flush: boolean = false): void {\n\t\tlet reprocess = false\n\n\t\t// Oldest session first, so an archived session's late reports leave\n\t\t// ahead of current traffic.\n\t\tthis.sessions.forEach((session) => {\n\t\t\t// An archived session receives no further regular events, so its\n\t\t\t// queues could never fill a batch again; its remainders are always\n\t\t\t// drain-eligible, preserving the pre-existing behavior of unsent\n\t\t\t// old-sid events draining after a session change.\n\t\t\tconst drain = flush || session !== this.session\n\n\t\t\tsession.eventTargets.forEach((target, config) => {\n\t\t\t\tconst { queue } = target\n\n\t\t\t\t// A disposed target's queue can be non-empty again if a failed\n\t\t\t\t// batch was re-queued after disposal; it must stay unsent.\n\t\t\t\tif (target.disposed || !queue.length) {\n\t\t\t\t\treturn\n\t\t\t\t}\n\n\t\t\t\tif (queue.length < config.batchSize && !drain) {\n\t\t\t\t\treturn\n\t\t\t\t}\n\n\t\t\t\tconst deleteCount = drain ? queue.length : config.batchSize\n\t\t\t\tconst events = queue.splice(0, deleteCount)\n\t\t\t\tthis.sendEventReport(session, config, events).catch(() => {\n\t\t\t\t\t// Re-queue events that failed to send. The target belongs\n\t\t\t\t\t// to the batch's own session, so a failure after a session\n\t\t\t\t\t// change re-queues there, never into the current session.\n\t\t\t\t\ttarget.queue.unshift(...events)\n\t\t\t\t})\n\n\t\t\t\treprocess ||= queue.length > 0\n\t\t\t})\n\t\t})\n\n\t\tif (reprocess) {\n\t\t\tthis.processEventTargets()\n\t\t}\n\t}\n\n\t/**\n\t * Sends an event report. The reporter calls this method when a batch is\n\t * ready.\n\t *\n\t * @param config - The target config to send the event report to.\n\t * @param data - The encoded report lines to send in the event report.\n\t */\n\tprivate async sendEventReport(session: CmcdSession<C>, config: CmcdEventReportConfigNormalized<C>, data: string[]): Promise<void> {\n\t\tconst response = await this.requester({\n\t\t\turl: config.url,\n\t\t\tmethod: 'POST',\n\t\t\theaders: {\n\t\t\t\t'Content-Type': CMCD_MIME_TYPE,\n\t\t\t},\n\t\t\tbody: data.join('\\n'),\n\t\t})\n\n\t\tconst { status } = response\n\n\t\tif (status === 410) {\n\t\t\t// CTA-5004-B scopes 410 suppression to \"the remainder of the\n\t\t\t// current session\". The batch's own session is disposed, so a\n\t\t\t// delayed 410 that lands after a session change silences the\n\t\t\t// session that sent it, never the one that replaced it.\n\t\t\tthis.disposeEventTarget(session, config)\n\t\t} else if (status === 429 || (status > 499 && status < 600)) {\n\t\t\tthrow new Error(`Event report failed with status ${status}`)\n\t\t}\n\t}\n\n\t/**\n\t * Cancels the time-interval timer for an event target config and clears the\n\t * stored id. Safe to call when no timer is active (clearInterval(undefined)\n\t * does nothing).\n\t */\n\tprivate disarmInterval(config: CmcdEventReportConfigNormalized<C>): void {\n\t\tclearInterval(this.intervals.get(config))\n\t\tthis.intervals.delete(config)\n\t}\n\n\t/**\n\t * Silences an event target URL for the remainder of its session after the\n\t * collector signals that the target is gone (HTTP 410). The method clears\n\t * the queues and blocks further enqueues for every config in the session\n\t * that reports to the URL (the CTA-5004-B suppression scope). For the\n\t * current session, the method also cancels those configs' timers. A session\n\t * started after the disposal gets new target state and is unaffected.\n\t */\n\tprivate disposeEventTarget(session: CmcdSession<C>, config: CmcdEventReportConfigNormalized<C>): void {\n\t\tsession.eventTargets.forEach((target, sibling) => {\n\t\t\tif (sibling.url !== config.url || target.disposed) {\n\t\t\t\treturn\n\t\t\t}\n\n\t\t\ttarget.disposed = true\n\t\t\ttarget.queue.length = 0\n\n\t\t\t// The timer belongs to the live session only; an archived session's\n\t\t\t// disposal is bookkeeping and must not silence current reporting.\n\t\t\tif (session === this.session) {\n\t\t\t\tthis.disarmInterval(sibling)\n\t\t\t}\n\t\t})\n\t}\n}\n","import type { ValueOf } from '@svta/cml-utils'\n\n/**\n * Common Media Client Data Streaming Format\n *\n * @enum\n *\n * @see {@link https://cta-wave.github.io/Resources/common-media-client-data--cta-5004-b.html#streaming-format | CTA-5004-B Streaming Format}\n *\n * @public\n */\nexport const CmcdStreamingFormat = {\n\t/**\n\t * MPEG DASH\n\t */\n\tDASH: 'd',\n\n\t/**\n\t * HTTP Live Streaming (HLS)\n\t */\n\tHLS: 'h',\n\n\t/**\n\t * Smooth Streaming\n\t */\n\tSMOOTH: 's',\n\n\t/**\n\t * Other\n\t */\n\tOTHER: 'o',\n} as const\n\n/**\n * @public\n */\nexport type CmcdStreamingFormat = ValueOf<typeof CmcdStreamingFormat>;\n","import type { ValueOf } from '@svta/cml-utils'\n\n/**\n * Common Media Client Data Stream Type\n *\n * @enum\n *\n * @see {@link https://cta-wave.github.io/Resources/common-media-client-data--cta-5004-b.html#stream-type | CTA-5004-B Stream Type}\n *\n * @public\n */\nexport const CmcdStreamType = {\n\t/**\n\t * All segments are available, for example VOD\n\t */\n\tVOD: 'v',\n\n\t/**\n\t * Segments become available over time, for example LIVE\n\t */\n\tLIVE: 'l',\n\n\t/**\n\t * Low latency stream\n\t */\n\tLOW_LATENCY: 'll',\n} as const\n\n/**\n * @public\n */\nexport type CmcdStreamType = ValueOf<typeof CmcdStreamType>;\n","import type { ValueOf } from '@svta/cml-utils'\n\n/**\n * CMCD validation severity level: error.\n *\n * @public\n */\nexport const CMCD_VALIDATION_SEVERITY_ERROR = 'error' as const\n\n/**\n * CMCD validation severity level: warning.\n *\n * @public\n */\nexport const CMCD_VALIDATION_SEVERITY_WARNING = 'warning' as const\n\n/**\n * CMCD validation severity level.\n *\n * @public\n */\nexport const CmcdValidationSeverity = {\n\tERROR: CMCD_VALIDATION_SEVERITY_ERROR as typeof CMCD_VALIDATION_SEVERITY_ERROR,\n\tWARNING: CMCD_VALIDATION_SEVERITY_WARNING as typeof CMCD_VALIDATION_SEVERITY_WARNING,\n} as const\n\n/**\n * CMCD validation severity level.\n *\n * @public\n */\nexport type CmcdValidationSeverity = ValueOf<typeof CmcdValidationSeverity>;\n","/**\n * Converts a record of header fields to a `Headers` instance if necessary.\n *\n * @param headers - A `Headers` instance or a plain record of header fields.\n * @returns A `Headers` instance.\n *\n * @internal\n */\nexport function ensureHeaders(headers: Record<string, string> | Headers): Headers {\n\treturn headers instanceof Headers ? headers : new Headers(headers)\n}\n","import type { Cmcd } from './Cmcd.ts'\nimport type { CmcdData } from './CmcdData.ts'\nimport type { CmcdDecodeOptions } from './CmcdDecodeOptions.ts'\nimport { CMCD_HEADER_FIELDS } from './CmcdHeaderField.ts'\nimport { decodeCmcd } from './decodeCmcd.ts'\nimport { ensureHeaders } from './ensureHeaders.ts'\nimport { upConvertToV2 } from './upConvertToV2.ts'\n\n/**\n * Decode CMCD data from request headers.\n *\n * @param headers - The request headers to decode.\n * @param options - Options for decoding.\n *\n * @returns The decoded CMCD data.\n *\n * @see {@link https://cta-wave.github.io/Resources/common-media-client-data--cta-5004-b.html#header-field-definition | CTA-5004-B Header Field Definition}\n *\n * @public\n *\n * @example\n * {@includeCode ../test/fromCmcdHeaders.test.ts#example}\n */\nexport function fromCmcdHeaders(headers: Record<string, string> | Headers, options: CmcdDecodeOptions & { convertToLatest: true }): Cmcd\n/**\n * Decode CMCD data from request headers.\n *\n * @param headers - The request headers to decode.\n * @param options - Options for decoding.\n *\n * @returns The decoded CMCD data.\n *\n * @public\n */\nexport function fromCmcdHeaders(headers: Record<string, string> | Headers, options?: CmcdDecodeOptions): CmcdData\nexport function fromCmcdHeaders(headers: Record<string, string> | Headers, options?: CmcdDecodeOptions): CmcdData | Cmcd {\n\tconst h = ensureHeaders(headers)\n\n\tconst result: Record<string, unknown> = {}\n\tfor (const field of CMCD_HEADER_FIELDS) {\n\t\tconst value = h.get(field)\n\t\tif (value) {\n\t\t\tObject.assign(result, decodeCmcd(value))\n\t\t}\n\t}\n\n\tif (options?.convertToLatest) {\n\t\treturn upConvertToV2(result) as Cmcd\n\t}\n\n\treturn result as CmcdData\n}\n","import { CMCD_PARAM } from './CMCD_PARAM.ts'\nimport type { Cmcd } from './Cmcd.ts'\nimport type { CmcdData } from './CmcdData.ts'\nimport type { CmcdDecodeOptions } from './CmcdDecodeOptions.ts'\nimport { decodeCmcd } from './decodeCmcd.ts'\n\n/**\n * Decode CMCD data from a query string.\n *\n * @param query - The query string to decode.\n * @param options - Options for decoding.\n *\n * @returns The decoded CMCD data.\n *\n * @see {@link https://cta-wave.github.io/Resources/common-media-client-data--cta-5004-b.html#query-argument-definition | CTA-5004-B Query Argument Definition}\n *\n * @public\n *\n * @example\n * {@includeCode ../test/fromCmcdQuery.test.ts#example}\n */\nexport function fromCmcdQuery(query: string | URLSearchParams, options: CmcdDecodeOptions & { convertToLatest: true }): Cmcd\n/**\n * Decode CMCD data from a query string.\n *\n * @param query - The query string to decode.\n * @param options - Options for decoding.\n *\n * @returns The decoded CMCD data.\n *\n * @public\n */\nexport function fromCmcdQuery(query: string | URLSearchParams, options?: CmcdDecodeOptions): CmcdData\nexport function fromCmcdQuery(query: string | URLSearchParams, options?: CmcdDecodeOptions): CmcdData | Cmcd {\n\tif (typeof query === 'string') {\n\t\tquery = new URLSearchParams(query)\n\t}\n\n\tconst value = query.get(CMCD_PARAM)\n\n\treturn decodeCmcd(value ?? '', options as CmcdDecodeOptions)\n}\n","import type { Cmcd } from './Cmcd.ts'\nimport type { CmcdData } from './CmcdData.ts'\nimport type { CmcdDecodeOptions } from './CmcdDecodeOptions.ts'\nimport { decodeCmcd } from './decodeCmcd.ts'\n\n/**\n * Decode CMCD data from a URL encoded string.\n *\n * A `+` decodes as a space, as in `application/x-www-form-urlencoded`.\n * A `%2B` decodes as a `+`.\n *\n * @param url - The URL encoded string to decode.\n * @param options - Options for decoding.\n *\n * @returns The decoded CMCD data.\n *\n * @see {@link https://cta-wave.github.io/Resources/common-media-client-data--cta-5004-b.html#query-argument-definition | CTA-5004-B Query Argument Definition}\n *\n * @public\n *\n * @example\n * {@includeCode ../test/fromCmcdUrl.test.ts#example}\n */\nexport function fromCmcdUrl(url: string, options: CmcdDecodeOptions & { convertToLatest: true }): Cmcd\n/**\n * Decode CMCD data from a URL encoded string.\n *\n * @param url - The URL encoded string to decode.\n * @param options - Options for decoding.\n *\n * @returns The decoded CMCD data.\n *\n * @public\n */\nexport function fromCmcdUrl(url: string, options?: CmcdDecodeOptions): CmcdData\nexport function fromCmcdUrl(url: string, options?: CmcdDecodeOptions): CmcdData | Cmcd {\n\treturn decodeCmcd(decodeURIComponent(url.replace(/^CMCD=/, '').replace(/\\+/g, ' ')), options as CmcdDecodeOptions)\n}\n","import { CMCD_REQUEST_KEYS } from './CMCD_REQUEST_KEYS.ts'\nimport type { Cmcd } from './Cmcd.ts'\nimport type { CmcdKey } from './CmcdKey.ts'\nimport { isCmcdCustomKey } from './isCmcdCustomKey.ts'\n\nconst CMCD_REQUEST_KEY_SET: ReadonlySet<string> = /* @__PURE__ */ new Set(CMCD_REQUEST_KEYS)\n\n/**\n * Check if a key is a valid CMCD request key.\n *\n * @param key - The key to check.\n *\n * @returns `true` if the key is a valid CMCD request key, `false` otherwise.\n *\n * @public\n *\n * @example\n * {@includeCode ../test/isCmcdRequestKey.test.ts#example}\n */\nexport function isCmcdRequestKey(key: string): key is keyof Cmcd {\n\treturn CMCD_REQUEST_KEY_SET.has(key) ||\n\t\tisCmcdCustomKey(key as CmcdKey)\n}\n","import { CMCD_RESPONSE_KEYS } from './CMCD_RESPONSE_KEYS.ts'\nimport type { Cmcd } from './Cmcd.ts'\n\nconst CMCD_RESPONSE_KEY_SET: ReadonlySet<string> = /* @__PURE__ */ new Set(CMCD_RESPONSE_KEYS)\n\n/**\n * Check if a key is a valid CMCD response key.\n *\n * @param key - The key to check.\n *\n * @returns `true` if the key is a valid CMCD response key, `false` otherwise.\n *\n * @public\n *\n * @example\n * {@includeCode ../test/isCmcdResponseReceivedKey.test.ts#example}\n */\nexport function isCmcdResponseReceivedKey(key: string): key is keyof Cmcd {\n\treturn CMCD_RESPONSE_KEY_SET.has(key)\n}\n","import { CMCD_EVENT_KEYS } from './CMCD_EVENT_KEYS.ts'\nimport type { Cmcd } from './Cmcd.ts'\nimport { isCmcdRequestKey } from './isCmcdRequestKey.ts'\nimport { isCmcdResponseReceivedKey } from './isCmcdResponseReceivedKey.ts'\n\nconst CMCD_EVENT_KEY_SET: ReadonlySet<string> = /* @__PURE__ */ new Set(CMCD_EVENT_KEYS)\n\n/**\n * Check if a key is a valid CMCD event key.\n *\n * @param key - The key to check.\n *\n * @returns `true` if the key is a valid CMCD event key, `false` otherwise.\n *\n * @public\n *\n * @example\n * {@includeCode ../test/isCmcdEventKey.test.ts#example}\n */\nexport function isCmcdEventKey(key: string): key is keyof Cmcd {\n\treturn isCmcdRequestKey(key) ||\n\t\tisCmcdResponseReceivedKey(key) ||\n\t\tCMCD_EVENT_KEY_SET.has(key)\n}\n","import { CMCD_V2 } from './CMCD_V2.ts'\nimport type { CmcdData } from './CmcdData.ts'\nimport type { CmcdV1Data } from './CmcdData.ts'\n\n/**\n * Check if a CMCD data object is version 1.\n *\n * @param data - The CMCD data object to check.\n *\n * @returns `true` if the data is version 1, `false` otherwise.\n *\n * @public\n *\n * @example\n * {@includeCode ../test/isCmcdV1Data.test.ts#example}\n */\nexport function isCmcdV1Data(data: CmcdData): data is CmcdV1Data {\n\treturn data.v !== CMCD_V2\n}\n","import { CMCD_V1_KEYS } from './CMCD_V1_KEYS.ts'\nimport type { CmcdKey } from './CmcdKey.ts'\nimport { isCmcdCustomKey } from './isCmcdCustomKey.ts'\n\nconst CMCD_V1_KEY_SET: ReadonlySet<string> = /* @__PURE__ */ new Set(CMCD_V1_KEYS)\n\n/**\n * Filter for CMCD version 1 keys.\n *\n * @param key - The CMCD key to filter.\n *\n * @returns `true` if the key should be included, `false` otherwise.\n *\n * @public\n *\n * @example\n * {@includeCode ../test/isCmcdV1Key.test.ts#example}\n */\nexport function isCmcdV1Key(key: string): key is CmcdKey {\n\treturn CMCD_V1_KEY_SET.has(key) || isCmcdCustomKey(key as CmcdKey)\n}\n","import { CMCD_V2 } from './CMCD_V2.ts'\nimport type { CmcdData } from './CmcdData.ts'\nimport type { CmcdV2Data } from './CmcdData.ts'\n\n/**\n * Check if a CMCD data object is version 2.\n *\n * @param data - The CMCD data object to check.\n *\n * @returns `true` if the data is version 2, `false` otherwise.\n *\n * @public\n *\n * @example\n * {@includeCode ../test/isCmcdV2Data.test.ts#example}\n */\nexport function isCmcdV2Data(data: CmcdData): data is CmcdV2Data {\n\treturn data.v === CMCD_V2\n}\n","import type { Cmcd } from './Cmcd.ts'\nimport type { CmcdEncodeOptions } from './CmcdEncodeOptions.ts'\nimport { encodeCmcd } from './encodeCmcd.ts'\nimport { percentEncode } from './percentEncode.ts'\n\n/**\n * Convert a CMCD object to a URL encoded string.\n *\n * Only letters, digits, `-`, `.`, `_`, and `~` stay unencoded, as in the\n * query examples of CTA-5004-B.\n *\n * @param cmcd - The CMCD object to convert.\n * @param options - Options for encoding.\n *\n * @returns The URL encoded CMCD data.\n *\n * @see {@link https://cta-wave.github.io/Resources/common-media-client-data--cta-5004-b.html#query-argument-definition | CTA-5004-B Query Argument Definition}\n *\n * @public\n */\nexport function toCmcdUrl(cmcd: Cmcd, options: CmcdEncodeOptions = {}): string {\n\tif (!cmcd) {\n\t\treturn ''\n\t}\n\n\tconst params = encodeCmcd(cmcd, options)\n\n\treturn percentEncode(params)\n}\n","import { CMCD_PARAM } from './CMCD_PARAM.ts'\nimport type { Cmcd } from './Cmcd.ts'\nimport type { CmcdEncodeOptions } from './CmcdEncodeOptions.ts'\nimport { toCmcdUrl } from './toCmcdUrl.ts'\n\n/**\n * Convert a CMCD object to a query arg.\n *\n * @param cmcd - The CMCD object to convert.\n * @param options - Options for encoding.\n *\n * @returns The CMCD query arg.\n *\n * @see {@link https://cta-wave.github.io/Resources/common-media-client-data--cta-5004-b.html#query-argument-definition | CTA-5004-B Query Argument Definition}\n *\n * @public\n *\n * @example\n * {@includeCode ../test/toCmcdQuery.test.ts#example}\n */\nexport function toCmcdQuery(cmcd: Cmcd, options: CmcdEncodeOptions = {}): string {\n\tif (!cmcd) {\n\t\treturn ''\n\t}\n\n\tconst value = toCmcdUrl(cmcd, options)\n\n\treturn `${CMCD_PARAM}=${value}`\n}\n","import { type SfBareItem, SfItem } from '@svta/cml-structured-field-values'\n\n/**\n * Convert a value to a CMCD value.\n *\n * @param value - The value to convert to a CMCD value.\n * @param params - The parameters of the CMCD value.\n * @returns The CMCD value.\n *\n * @public\n */\nexport function toCmcdValue<V extends SfBareItem, P>(value: V, params?: P): SfItem<V, P> {\n\treturn new SfItem(value, params)\n}\n","import type { CmcdValidationResult } from './CmcdValidationResult.ts'\nimport { CMCD_VALIDATION_SEVERITY_ERROR } from './CmcdValidationSeverity.ts'\n\n/**\n * Merges multiple validation results into a single result.\n *\n * @internal\n */\nexport function mergeValidationResults(...results: CmcdValidationResult[]): CmcdValidationResult {\n\tconst issues = results.flatMap(r => r.issues)\n\treturn {\n\t\tvalid: issues.every(i => i.severity !== CMCD_VALIDATION_SEVERITY_ERROR),\n\t\tissues,\n\t}\n}\n","import { CMCD_V1 } from './CMCD_V1.ts'\nimport type { CmcdValidationOptions } from './CmcdValidationOptions.ts'\nimport { toBareValue } from './toBareValue.ts'\n\n/**\n * Resolves the CMCD version from options, the payload's `v` key, or the default (version 1).\n *\n * @internal\n */\nexport function resolveVersion(data: Record<string, unknown>, options?: CmcdValidationOptions): number {\n\tif (options?.version === 1 || options?.version === 2) {\n\t\treturn options.version\n\t}\n\n\tconst payloadVersion = toBareValue(data['v'])\n\tif (payloadVersion === 1 || payloadVersion === 2) {\n\t\treturn payloadVersion\n\t}\n\n\treturn CMCD_V1\n}\n","import { CMCD_KEYS } from './CMCD_KEYS.ts'\nimport { CMCD_V1 } from './CMCD_V1.ts'\nimport { CMCD_V1_KEYS } from './CMCD_V1_KEYS.ts'\nimport type { CmcdKey } from './CmcdKey.ts'\nimport type { CmcdValidationOptions } from './CmcdValidationOptions.ts'\nimport type { CmcdValidationResult } from './CmcdValidationResult.ts'\nimport { CMCD_VALIDATION_SEVERITY_ERROR } from './CmcdValidationSeverity.ts'\nimport { isCmcdCustomKey } from './isCmcdCustomKey.ts'\nimport { resolveVersion } from './resolveVersion.ts'\n\nconst CMCD_V1_KEY_SET: ReadonlySet<string> = /* @__PURE__ */ new Set(CMCD_V1_KEYS)\nconst CMCD_KEY_SET: ReadonlySet<string> = /* @__PURE__ */ new Set(CMCD_KEYS)\n\n/**\n * Validates that all keys in a CMCD payload are recognized spec keys or valid custom keys.\n *\n * @example\n * {@includeCode ../test/validateCmcdKeys.test.ts#example}\n *\n * @param data - The CMCD payload to validate.\n * @param options - Validation options.\n * @returns The validation result.\n *\n * @see {@link https://cta-wave.github.io/Resources/common-media-client-data--cta-5004-b.html#reserved-keys | CTA-5004-B Reserved Keys}\n *\n * @public\n */\nexport function validateCmcdKeys(data: Record<string, unknown>, options?: CmcdValidationOptions): CmcdValidationResult {\n\tconst version = resolveVersion(data, options)\n\tconst validKeySet = version === CMCD_V1 ? CMCD_V1_KEY_SET : CMCD_KEY_SET\n\tconst issues: CmcdValidationResult['issues'] = []\n\n\tfor (const key of Object.keys(data)) {\n\t\tif (isCmcdCustomKey(key as CmcdKey)) {\n\t\t\tcontinue\n\t\t}\n\n\t\tif (!validKeySet.has(key)) {\n\t\t\tissues.push({\n\t\t\t\tkey,\n\t\t\t\tmessage: `Unknown CMCD key \"${key}\" for version ${version}.`,\n\t\t\t\tseverity: CMCD_VALIDATION_SEVERITY_ERROR,\n\t\t\t})\n\t\t}\n\t}\n\n\treturn {\n\t\tvalid: issues.length === 0,\n\t\tissues,\n\t}\n}\n","import type { CmcdKey } from './CmcdKey.ts'\n\n/**\n * Maps each aggregate bitrate key to the exact bitrate key that supersedes it.\n *\n * Per CTA-5004-B, `ab` MUST NOT be sent when the encoded bitrate `br` is\n * known. `lab` and `tab` follow the same rule for the lowest bitrate `lb`\n * and the top bitrate `tb`.\n *\n * @internal\n */\nexport const CMCD_AGGREGATE_BITRATE_KEYS: Record<string, CmcdKey> = {\n\tab: 'br',\n\tlab: 'lb',\n\ttab: 'tb',\n}\n","/**\n * Maps a key to the object types (`ot`) for which CTA-5004-B allows the key.\n *\n * A key that is absent from this map is allowed for every object type.\n * `d` (Object duration) and `tpb` (Top playable bitrate) MUST NOT be sent for\n * other object types.\n *\n * @internal\n */\nexport const CMCD_KEY_OBJECT_TYPES: Record<string, readonly string[]> = {\n\td: ['a', 'v', 'av', 'tt', 'c', 'o'] as const,\n\ttpb: ['a', 'v', 'av', 'c'] as const,\n}\n","import { CMCD_AGGREGATE_BITRATE_KEYS } from './CMCD_AGGREGATE_BITRATE_KEYS.ts'\nimport { CMCD_EVENT_KEYS } from './CMCD_EVENT_KEYS.ts'\nimport { CMCD_KEY_OBJECT_TYPES } from './CMCD_KEY_OBJECT_TYPES.ts'\nimport { CMCD_RESPONSE_KEYS } from './CMCD_RESPONSE_KEYS.ts'\nimport { CMCD_V1 } from './CMCD_V1.ts'\nimport { CMCD_EVENT_CUSTOM_EVENT, CMCD_EVENT_ERROR, CMCD_EVENT_PLAY_STATE, CMCD_EVENT_RESPONSE_RECEIVED } from './CmcdEventType.ts'\nimport { CMCD_EVENT_MODE, CMCD_REQUEST_MODE } from './CmcdReportingMode.ts'\nimport type { CmcdValidationIssue } from './CmcdValidationIssue.ts'\nimport type { CmcdValidationOptions } from './CmcdValidationOptions.ts'\nimport type { CmcdValidationResult } from './CmcdValidationResult.ts'\nimport { CMCD_VALIDATION_SEVERITY_ERROR, CMCD_VALIDATION_SEVERITY_WARNING } from './CmcdValidationSeverity.ts'\nimport { resolveVersion } from './resolveVersion.ts'\nimport { toBareValue } from './toBareValue.ts'\nimport { toTokenString } from './toTokenString.ts'\n\n/**\n * Validates the structural rules of a CMCD payload.\n *\n * @example\n * {@includeCode ../test/validateCmcdStructure.test.ts#example}\n *\n * @param data - The CMCD payload to validate.\n * @param options - Validation options.\n * @returns The validation result.\n *\n * @see {@link https://cta-wave.github.io/Resources/common-media-client-data--cta-5004-b.html#data-payload-definition-what-data-to-send | CTA-5004-B Data Payload Definition}\n *\n * @public\n */\nexport function validateCmcdStructure(data: Record<string, unknown>, options?: CmcdValidationOptions): CmcdValidationResult {\n\tconst version = resolveVersion(data, options)\n\tconst issues: CmcdValidationIssue[] = []\n\n\t// Request mode checks\n\tif (options?.reportingMode === CMCD_REQUEST_MODE) {\n\t\tfor (const key of CMCD_EVENT_KEYS) {\n\t\t\tif (key in data) {\n\t\t\t\tissues.push({\n\t\t\t\t\tkey,\n\t\t\t\t\tmessage: `Event key \"${key}\" must not be present in request mode.`,\n\t\t\t\t\tseverity: CMCD_VALIDATION_SEVERITY_ERROR\n\t\t\t\t})\n\t\t\t}\n\t\t}\n\t\tfor (const key of CMCD_RESPONSE_KEYS) {\n\t\t\tif (key in data) {\n\t\t\t\tissues.push({\n\t\t\t\t\tkey,\n\t\t\t\t\tmessage: `Response key \"${key}\" must not be present in request mode.`,\n\t\t\t\t\tseverity: CMCD_VALIDATION_SEVERITY_ERROR\n\t\t\t\t})\n\t\t\t}\n\t\t}\n\t}\n\n\t// Event mode checks\n\tif (options?.reportingMode === CMCD_EVENT_MODE) {\n\t\tif (!('e' in data)) {\n\t\t\tissues.push({\n\t\t\t\tkey: 'e',\n\t\t\t\tmessage: 'Event mode requires the \"e\" key to be present.',\n\t\t\t\tseverity: CMCD_VALIDATION_SEVERITY_ERROR\n\t\t\t})\n\t\t}\n\t\tif (!('ts' in data)) {\n\t\t\tissues.push({\n\t\t\t\tkey: 'ts',\n\t\t\t\tmessage: 'Event mode requires the \"ts\" key to be present.',\n\t\t\t\tseverity: CMCD_VALIDATION_SEVERITY_ERROR\n\t\t\t})\n\t\t}\n\t}\n\n\t// Custom event checks\n\tif ('e' in data) {\n\t\tconst eventType = toTokenString(data['e'])\n\n\t\tif (eventType === CMCD_EVENT_CUSTOM_EVENT) {\n\t\t\tif (!('cen' in data)) {\n\t\t\t\tissues.push({\n\t\t\t\t\tkey: 'cen',\n\t\t\t\t\tmessage: 'Custom event (e=\"ce\") requires the \"cen\" key to be present.',\n\t\t\t\t\tseverity: CMCD_VALIDATION_SEVERITY_ERROR\n\t\t\t\t})\n\t\t\t}\n\t\t}\n\t\telse {\n\t\t\tif ('cen' in data) {\n\t\t\t\tissues.push({\n\t\t\t\t\tkey: 'cen',\n\t\t\t\t\tmessage: 'The \"cen\" key must only be present when e=\"ce\".',\n\t\t\t\t\tseverity: CMCD_VALIDATION_SEVERITY_ERROR\n\t\t\t\t})\n\t\t\t}\n\t\t}\n\n\t\t// Response-received key restriction and required url\n\t\tif (eventType === CMCD_EVENT_RESPONSE_RECEIVED) {\n\t\t\tif (!('url' in data)) {\n\t\t\t\tissues.push({\n\t\t\t\t\tkey: 'url',\n\t\t\t\t\tmessage: 'Response received event (e=\"rr\") requires the \"url\" key to be present.',\n\t\t\t\t\tseverity: CMCD_VALIDATION_SEVERITY_ERROR\n\t\t\t\t})\n\t\t\t}\n\t\t}\n\t\telse {\n\t\t\tfor (const key of CMCD_RESPONSE_KEYS) {\n\t\t\t\tif (key in data) {\n\t\t\t\t\tissues.push({\n\t\t\t\t\t\tkey,\n\t\t\t\t\t\tmessage: `Response key \"${key}\" must only be present when e=\"rr\".`,\n\t\t\t\t\t\tseverity: CMCD_VALIDATION_SEVERITY_ERROR\n\t\t\t\t\t})\n\t\t\t\t}\n\t\t\t}\n\t\t}\n\n\t\t// Play state change event requires sta\n\t\tif (eventType === CMCD_EVENT_PLAY_STATE && !('sta' in data)) {\n\t\t\tissues.push({\n\t\t\t\tkey: 'sta',\n\t\t\t\tmessage: 'Play state change event (e=\"ps\") requires the \"sta\" key to be present.',\n\t\t\t\tseverity: CMCD_VALIDATION_SEVERITY_ERROR\n\t\t\t})\n\t\t}\n\n\t\t// Error event requires ec\n\t\tif (eventType === CMCD_EVENT_ERROR && !('ec' in data)) {\n\t\t\tissues.push({\n\t\t\t\tkey: 'ec',\n\t\t\t\tmessage: 'Error event (e=\"e\") requires the \"ec\" key to be present.',\n\t\t\t\tseverity: CMCD_VALIDATION_SEVERITY_ERROR\n\t\t\t})\n\t\t}\n\t}\n\n\t// Object type checks\n\tconst ot = version > 1 ? toTokenString(data['ot']) : undefined\n\tif (ot !== undefined) {\n\t\tfor (const key in CMCD_KEY_OBJECT_TYPES) {\n\t\t\tconst objectTypes = CMCD_KEY_OBJECT_TYPES[key]\n\t\t\tif (key in data && !objectTypes.includes(ot)) {\n\t\t\t\tissues.push({\n\t\t\t\t\tkey,\n\t\t\t\t\tmessage: `Key \"${key}\" must not be present when \"ot\" is \"${ot}\". Expected \"ot\" to be one of: ${objectTypes.join(', ')}.`,\n\t\t\t\t\tseverity: CMCD_VALIDATION_SEVERITY_ERROR\n\t\t\t\t})\n\t\t\t}\n\t\t}\n\t}\n\n\t// Aggregate bitrate checks\n\tif (version > 1) {\n\t\tfor (const key in CMCD_AGGREGATE_BITRATE_KEYS) {\n\t\t\tconst exactKey = CMCD_AGGREGATE_BITRATE_KEYS[key]\n\t\t\tif (key in data && exactKey in data) {\n\t\t\t\tissues.push({\n\t\t\t\t\tkey,\n\t\t\t\t\tmessage: `Key \"${key}\" must not be present when \"${exactKey}\" is present.`,\n\t\t\t\t\tseverity: CMCD_VALIDATION_SEVERITY_ERROR\n\t\t\t\t})\n\t\t\t}\n\t\t}\n\t}\n\n\t// Version key checks\n\tconst v = toBareValue(data['v'])\n\tif ('v' in data && v !== 1 && v !== 2) {\n\t\tissues.push({\n\t\t\tkey: 'v',\n\t\t\tmessage: `Unsupported CMCD version \"${String(v)}\". Expected 1 or 2.`,\n\t\t\tseverity: CMCD_VALIDATION_SEVERITY_ERROR\n\t\t})\n\t}\n\telse if (version > 1 && !('v' in data)) {\n\t\tissues.push({\n\t\t\tkey: 'v',\n\t\t\tmessage: 'Version 2 payloads require the \"v\" key to be present.',\n\t\t\tseverity: CMCD_VALIDATION_SEVERITY_ERROR\n\t\t})\n\t}\n\telse if (version === CMCD_V1 && 'v' in data) {\n\t\tissues.push({\n\t\t\tkey: 'v',\n\t\t\tmessage: 'Version 1 payloads should omit the \"v\" key (v1 is the default).',\n\t\t\tseverity: CMCD_VALIDATION_SEVERITY_WARNING\n\t\t})\n\t}\n\n\treturn {\n\t\tvalid: issues.every(i => i.severity !== CMCD_VALIDATION_SEVERITY_ERROR),\n\t\tissues,\n\t}\n}\n","/**\n * CMCD key value type: inner list of integers with token identifiers.\n *\n * @internal\n */\nexport const CMCD_KEY_TYPE_NUMBER_LIST = 'number[]' as const\n\n/**\n * CMCD key value type: inner list of strings.\n *\n * @internal\n */\nexport const CMCD_KEY_TYPE_STRING_LIST = 'string[]' as const\n\n/**\n * CMCD key value type: integer.\n *\n * @internal\n */\nexport const CMCD_KEY_TYPE_INTEGER = 'integer' as const\n\n/**\n * CMCD key value type: number (decimal).\n *\n * @internal\n */\nexport const CMCD_KEY_TYPE_NUMBER = 'number' as const\n\n/**\n * CMCD key value type: boolean.\n *\n * @internal\n */\nexport const CMCD_KEY_TYPE_BOOLEAN = 'boolean' as const\n\n/**\n * CMCD key value type: string.\n *\n * @internal\n */\nexport const CMCD_KEY_TYPE_STRING = 'string' as const\n\n/**\n * CMCD key value type: token.\n *\n * @internal\n */\nexport const CMCD_KEY_TYPE_TOKEN = 'token' as const\n\n/**\n * Maps each CMCD key to its value type for version 2.\n * CMCD_V1_KEY_TYPE_OVERRIDES handles the keys that differ between version 1 and version 2.\n *\n * @internal\n */\nexport const CMCD_KEY_TYPES: Record<string, string> = {\n\t// List keys (inner list of integers with token identifiers)\n\tab: CMCD_KEY_TYPE_NUMBER_LIST,\n\tbl: CMCD_KEY_TYPE_NUMBER_LIST,\n\tbr: CMCD_KEY_TYPE_NUMBER_LIST,\n\tbsa: CMCD_KEY_TYPE_NUMBER_LIST,\n\tbsd: CMCD_KEY_TYPE_NUMBER_LIST,\n\tbsda: CMCD_KEY_TYPE_NUMBER_LIST,\n\tlab: CMCD_KEY_TYPE_NUMBER_LIST,\n\tlb: CMCD_KEY_TYPE_NUMBER_LIST,\n\tmtp: CMCD_KEY_TYPE_NUMBER_LIST,\n\tpb: CMCD_KEY_TYPE_NUMBER_LIST,\n\ttab: CMCD_KEY_TYPE_NUMBER_LIST,\n\ttb: CMCD_KEY_TYPE_NUMBER_LIST,\n\ttbl: CMCD_KEY_TYPE_NUMBER_LIST,\n\ttpb: CMCD_KEY_TYPE_NUMBER_LIST,\n\n\t// String array keys (inner list of strings)\n\tec: CMCD_KEY_TYPE_STRING_LIST,\n\tnor: CMCD_KEY_TYPE_STRING_LIST,\n\n\t// Integer keys\n\td: CMCD_KEY_TYPE_INTEGER,\n\tdfa: CMCD_KEY_TYPE_INTEGER,\n\tdl: CMCD_KEY_TYPE_INTEGER,\n\tltc: CMCD_KEY_TYPE_INTEGER,\n\tmsd: CMCD_KEY_TYPE_INTEGER,\n\tpt: CMCD_KEY_TYPE_INTEGER,\n\trc: CMCD_KEY_TYPE_INTEGER,\n\trtp: CMCD_KEY_TYPE_INTEGER,\n\tsn: CMCD_KEY_TYPE_INTEGER,\n\tts: CMCD_KEY_TYPE_INTEGER,\n\tttfb: CMCD_KEY_TYPE_INTEGER,\n\tttfbb: CMCD_KEY_TYPE_INTEGER,\n\tttlb: CMCD_KEY_TYPE_INTEGER,\n\tv: CMCD_KEY_TYPE_INTEGER,\n\n\t// Number keys\n\tpr: CMCD_KEY_TYPE_NUMBER,\n\n\t// Boolean keys\n\tbg: CMCD_KEY_TYPE_BOOLEAN,\n\tbs: CMCD_KEY_TYPE_BOOLEAN,\n\tnr: CMCD_KEY_TYPE_BOOLEAN,\n\tsu: CMCD_KEY_TYPE_BOOLEAN,\n\n\t// String keys\n\tcdn: CMCD_KEY_TYPE_STRING,\n\tcen: CMCD_KEY_TYPE_STRING,\n\tcid: CMCD_KEY_TYPE_STRING,\n\tcmsdd: CMCD_KEY_TYPE_STRING,\n\tcmsds: CMCD_KEY_TYPE_STRING,\n\tcs: CMCD_KEY_TYPE_STRING,\n\th: CMCD_KEY_TYPE_STRING,\n\tnrr: CMCD_KEY_TYPE_STRING,\n\tsid: CMCD_KEY_TYPE_STRING,\n\tsmrt: CMCD_KEY_TYPE_STRING,\n\turl: CMCD_KEY_TYPE_STRING,\n\n\t// Token keys\n\te: CMCD_KEY_TYPE_TOKEN,\n\tot: CMCD_KEY_TYPE_TOKEN,\n\tsf: CMCD_KEY_TYPE_TOKEN,\n\tst: CMCD_KEY_TYPE_TOKEN,\n\tsta: CMCD_KEY_TYPE_TOKEN,\n}\n\n/**\n * Version 1 types of the keys that differ from version 2.\n *\n * @internal\n */\nexport const CMCD_V1_KEY_TYPE_OVERRIDES: Record<string, string> = {\n\tbl: CMCD_KEY_TYPE_INTEGER,\n\tbr: CMCD_KEY_TYPE_INTEGER,\n\tmtp: CMCD_KEY_TYPE_INTEGER,\n\ttb: CMCD_KEY_TYPE_INTEGER,\n\tnor: CMCD_KEY_TYPE_STRING,\n}\n","/**\n * Maps CMCD keys to their maximum string length.\n *\n * @internal\n */\nexport const CMCD_STRING_LENGTH_LIMITS: Record<string, number> = {\n\tsid: 64,\n\tcid: 128,\n\tcdn: 128,\n\th: 128,\n\tcen: 64,\n}\n\n/**\n * Maximum length for custom key values.\n *\n * @internal\n */\nexport const CMCD_CUSTOM_KEY_VALUE_MAX_LENGTH = 64\n","/**\n * Maps token keys to their valid values.\n *\n * @internal\n */\nexport const CMCD_TOKEN_VALUES: Record<string, readonly string[]> = {\n\te: ['bc', 'ps', 'pr', 'e', 't', 'c', 'b', 'm', 'um', 'pe', 'pc', 'rr', 'as', 'ae', 'abs', 'abe', 'sk', 'ce'] as const,\n\tot: ['m', 'a', 'v', 'av', 'i', 'c', 'tt', 'k', 'o'] as const,\n\tsf: ['d', 'h', 's', 'o'] as const,\n\tst: ['v', 'l', 'll'] as const,\n\tsta: ['s', 'p', 'k', 'r', 'a', 'w', 'e', 'f', 'q', 'd'] as const,\n}\n","import { CMCD_KEY_TYPE_BOOLEAN, CMCD_KEY_TYPE_INTEGER, CMCD_KEY_TYPE_NUMBER, CMCD_KEY_TYPE_NUMBER_LIST, CMCD_KEY_TYPE_STRING, CMCD_KEY_TYPE_STRING_LIST, CMCD_KEY_TYPE_TOKEN, CMCD_KEY_TYPES, CMCD_V1_KEY_TYPE_OVERRIDES } from './CMCD_KEY_TYPES.ts'\nimport { CMCD_CUSTOM_KEY_VALUE_MAX_LENGTH, CMCD_STRING_LENGTH_LIMITS } from './CMCD_STRING_LENGTH_LIMITS.ts'\nimport { CMCD_TOKEN_VALUES } from './CMCD_TOKEN_VALUES.ts'\nimport { CMCD_V1 } from './CMCD_V1.ts'\nimport type { CmcdKey } from './CmcdKey.ts'\nimport type { CmcdValidationIssue } from './CmcdValidationIssue.ts'\nimport type { CmcdValidationOptions } from './CmcdValidationOptions.ts'\nimport type { CmcdValidationResult } from './CmcdValidationResult.ts'\nimport { CMCD_VALIDATION_SEVERITY_ERROR, CMCD_VALIDATION_SEVERITY_WARNING } from './CmcdValidationSeverity.ts'\nimport { isCmcdCustomKey } from './isCmcdCustomKey.ts'\nimport { resolveVersion } from './resolveVersion.ts'\nimport { toBareValue } from './toBareValue.ts'\nimport { toTokenString } from './toTokenString.ts'\n\nconst HUNDRED_ROUNDING_UNITS: Record<string, string> = {\n\tbl: 'ms',\n\tdl: 'ms',\n\tmtp: 'kbps',\n\trtp: 'kbps',\n\ttbl: 'ms',\n}\n\nfunction isFiniteNumber(value: unknown): value is number {\n\treturn typeof value === 'number' && Number.isFinite(value)\n}\n\nfunction isInteger(value: unknown): value is number {\n\treturn Number.isInteger(value)\n}\n\n// CTA-5004 Table 1 states every rounding rule with MUST. CTA-5004-B Table 1 uses SHOULD for bl and tbl.\nfunction validateRounding(key: string, value: number, version: number, issues: CmcdValidationIssue[], index?: number): void {\n\tconst unit = HUNDRED_ROUNDING_UNITS[key]\n\tif (!unit || value % 100 === 0) {\n\t\treturn\n\t}\n\tconst should = key === 'tbl' || (key === 'bl' && version !== CMCD_V1)\n\tconst target = index === undefined ? `Key \"${key}\"` : `Key \"${key}\" array element [${index}]`\n\tissues.push({\n\t\tkey,\n\t\tmessage: `${target} ${should ? 'should' : 'must'} be rounded to the nearest 100 ${unit}. Received ${value}.`,\n\t\tseverity: should ? CMCD_VALIDATION_SEVERITY_WARNING : CMCD_VALIDATION_SEVERITY_ERROR\n\t})\n}\n\nfunction validateListValue(key: string, value: unknown, version: number, issues: CmcdValidationIssue[]): void {\n\tif (!Array.isArray(value)) {\n\t\tissues.push({\n\t\t\tkey,\n\t\t\tmessage: `Key \"${key}\" must be an array.`,\n\t\t\tseverity: CMCD_VALIDATION_SEVERITY_ERROR\n\t\t})\n\t\treturn\n\t}\n\tfor (let i = 0; i < value.length; i++) {\n\t\tconst element = toBareValue(value[i])\n\t\tif (!isInteger(element)) {\n\t\t\tissues.push({\n\t\t\t\tkey,\n\t\t\t\tmessage: `Key \"${key}\" array element [${i}] must be a finite integer.`,\n\t\t\t\tseverity: CMCD_VALIDATION_SEVERITY_ERROR\n\t\t\t})\n\t\t}\n\t\telse {\n\t\t\tvalidateRounding(key, element, version, issues, i)\n\t\t}\n\t}\n}\n\nfunction validateStringArrayValue(key: string, value: unknown, issues: CmcdValidationIssue[]): void {\n\tif (!Array.isArray(value)) {\n\t\tissues.push({\n\t\t\tkey,\n\t\t\tmessage: `Key \"${key}\" must be an array.`,\n\t\t\tseverity: CMCD_VALIDATION_SEVERITY_ERROR\n\t\t})\n\t\treturn\n\t}\n\tfor (let i = 0; i < value.length; i++) {\n\t\tif (typeof toBareValue(value[i]) !== 'string') {\n\t\t\tissues.push({\n\t\t\t\tkey,\n\t\t\t\tmessage: `Key \"${key}\" array element [${i}] must be a string.`,\n\t\t\t\tseverity: CMCD_VALIDATION_SEVERITY_ERROR\n\t\t\t})\n\t\t}\n\t}\n}\n\n/**\n * Validates that all values in a CMCD payload conform to the expected types and constraints.\n *\n * @example\n * {@includeCode ../test/validateCmcdValues.test.ts#example}\n *\n * @param data - The CMCD payload to validate.\n * @param options - Validation options.\n * @returns The validation result.\n *\n * @see {@link https://cta-wave.github.io/Resources/common-media-client-data--cta-5004-b.html#reserved-keys | CTA-5004-B Reserved Keys}\n *\n * @public\n */\nexport function validateCmcdValues(data: Record<string, unknown>, options?: CmcdValidationOptions): CmcdValidationResult {\n\tconst version = resolveVersion(data, options)\n\tconst issues: CmcdValidationIssue[] = []\n\n\tfor (const [key, entry] of Object.entries(data)) {\n\t\tconst value = toBareValue(entry)\n\t\tif (isCmcdCustomKey(key as CmcdKey)) {\n\t\t\t// Custom key values must be string or token, max 64 chars\n\t\t\tif (typeof value !== 'string') {\n\t\t\t\tissues.push({\n\t\t\t\t\tkey,\n\t\t\t\t\tmessage: `Custom key \"${key}\" value must be a string or token.`,\n\t\t\t\t\tseverity: CMCD_VALIDATION_SEVERITY_ERROR\n\t\t\t\t})\n\t\t\t}\n\t\t\telse if (value.length > CMCD_CUSTOM_KEY_VALUE_MAX_LENGTH) {\n\t\t\t\tissues.push({\n\t\t\t\t\tkey,\n\t\t\t\t\tmessage: `Custom key \"${key}\" value exceeds maximum length of ${CMCD_CUSTOM_KEY_VALUE_MAX_LENGTH}.`,\n\t\t\t\t\tseverity: CMCD_VALIDATION_SEVERITY_ERROR\n\t\t\t\t})\n\t\t\t}\n\t\t\tcontinue\n\t\t}\n\n\t\t// Version value check\n\t\tif (key === 'v') {\n\t\t\tif (value !== 1 && value !== 2) {\n\t\t\t\tissues.push({\n\t\t\t\t\tkey,\n\t\t\t\t\tmessage: `Key \"v\" must be 1 or 2.`,\n\t\t\t\t\tseverity: CMCD_VALIDATION_SEVERITY_ERROR\n\t\t\t\t})\n\t\t\t}\n\t\t\tcontinue\n\t\t}\n\n\t\t// Determine expected type\n\t\tlet expectedType = CMCD_KEY_TYPES[key]\n\t\tif (!expectedType) {\n\t\t\tcontinue\n\t\t}\n\n\t\tif (version === CMCD_V1 && key in CMCD_V1_KEY_TYPE_OVERRIDES) {\n\t\t\texpectedType = CMCD_V1_KEY_TYPE_OVERRIDES[key]\n\t\t}\n\n\t\tswitch (expectedType) {\n\t\t\tcase CMCD_KEY_TYPE_INTEGER:\n\t\t\t\tif (!isInteger(value)) {\n\t\t\t\t\tissues.push({\n\t\t\t\t\t\tkey,\n\t\t\t\t\t\tmessage: `Key \"${key}\" must be a finite integer.`,\n\t\t\t\t\t\tseverity: CMCD_VALIDATION_SEVERITY_ERROR\n\t\t\t\t\t})\n\t\t\t\t}\n\t\t\t\telse {\n\t\t\t\t\tvalidateRounding(key, value, version, issues)\n\t\t\t\t}\n\t\t\t\tbreak\n\n\t\t\tcase CMCD_KEY_TYPE_NUMBER:\n\t\t\t\tif (!isFiniteNumber(value)) {\n\t\t\t\t\tissues.push({\n\t\t\t\t\t\tkey,\n\t\t\t\t\t\tmessage: `Key \"${key}\" must be a finite number.`,\n\t\t\t\t\t\tseverity: CMCD_VALIDATION_SEVERITY_ERROR\n\t\t\t\t\t})\n\t\t\t\t}\n\t\t\t\tbreak\n\n\t\t\tcase CMCD_KEY_TYPE_BOOLEAN:\n\t\t\t\tif (typeof value !== 'boolean') {\n\t\t\t\t\tissues.push({\n\t\t\t\t\t\tkey,\n\t\t\t\t\t\tmessage: `Key \"${key}\" must be a boolean.`,\n\t\t\t\t\t\tseverity: CMCD_VALIDATION_SEVERITY_ERROR\n\t\t\t\t\t})\n\t\t\t\t}\n\t\t\t\tbreak\n\n\t\t\tcase CMCD_KEY_TYPE_STRING:\n\t\t\t\tif (typeof value !== 'string') {\n\t\t\t\t\tissues.push({\n\t\t\t\t\t\tkey,\n\t\t\t\t\t\tmessage: `Key \"${key}\" must be a string.`,\n\t\t\t\t\t\tseverity: CMCD_VALIDATION_SEVERITY_ERROR\n\t\t\t\t\t})\n\t\t\t\t}\n\t\t\t\telse if (key in CMCD_STRING_LENGTH_LIMITS && value.length > CMCD_STRING_LENGTH_LIMITS[key]) {\n\t\t\t\t\tissues.push({\n\t\t\t\t\t\tkey,\n\t\t\t\t\t\tmessage: `Key \"${key}\" exceeds maximum length of ${CMCD_STRING_LENGTH_LIMITS[key]}.`,\n\t\t\t\t\t\tseverity: CMCD_VALIDATION_SEVERITY_ERROR\n\t\t\t\t\t})\n\t\t\t\t}\n\t\t\t\tbreak\n\n\t\t\tcase CMCD_KEY_TYPE_TOKEN: {\n\t\t\t\tconst validValues = CMCD_TOKEN_VALUES[key]\n\t\t\t\tconst token = toTokenString(value)\n\t\t\t\tif (validValues && (token === undefined || !validValues.includes(token))) {\n\t\t\t\t\tissues.push({\n\t\t\t\t\t\tkey,\n\t\t\t\t\t\tmessage: `Key \"${key}\" has invalid token value \"${token ?? String(value)}\". Expected one of: ${validValues.join(', ')}.`,\n\t\t\t\t\t\tseverity: CMCD_VALIDATION_SEVERITY_ERROR\n\t\t\t\t\t})\n\t\t\t\t}\n\t\t\t\tbreak\n\t\t\t}\n\n\t\t\tcase CMCD_KEY_TYPE_NUMBER_LIST:\n\t\t\t\tvalidateListValue(key, value, version, issues)\n\t\t\t\tbreak\n\n\t\t\tcase CMCD_KEY_TYPE_STRING_LIST:\n\t\t\t\tvalidateStringArrayValue(key, value, issues)\n\t\t\t\tbreak\n\t\t}\n\t}\n\n\treturn {\n\t\tvalid: issues.every(i => i.severity !== CMCD_VALIDATION_SEVERITY_ERROR),\n\t\tissues,\n\t}\n}\n","import type { CmcdValidationOptions } from './CmcdValidationOptions.ts'\nimport type { CmcdValidationResult } from './CmcdValidationResult.ts'\nimport { mergeValidationResults } from './mergeValidationResults.ts'\nimport { validateCmcdKeys } from './validateCmcdKeys.ts'\nimport { validateCmcdStructure } from './validateCmcdStructure.ts'\nimport { validateCmcdValues } from './validateCmcdValues.ts'\n\n/**\n * Validates a CMCD payload by checking keys, values, and structure.\n *\n * @example\n * {@includeCode ../test/validateCmcd.test.ts#example}\n *\n * @param data - The CMCD payload to validate.\n * @param options - Validation options.\n * @returns The validation result.\n *\n * @see {@link https://cta-wave.github.io/Resources/common-media-client-data--cta-5004-b.html#data-payload-definition-what-data-to-send | CTA-5004-B Data Payload Definition}\n *\n * @public\n */\nexport function validateCmcd(data: Record<string, unknown>, options?: CmcdValidationOptions): CmcdValidationResult {\n\treturn mergeValidationResults(\n\t\tvalidateCmcdKeys(data, options),\n\t\tvalidateCmcdValues(data, options),\n\t\tvalidateCmcdStructure(data, options),\n\t)\n}\n","import type { CmcdData } from './CmcdData.ts'\nimport type { CmcdEventsValidationResult } from './CmcdEventsValidationResult.ts'\nimport { CMCD_EVENT_MODE } from './CmcdReportingMode.ts'\nimport type { CmcdValidationOptions } from './CmcdValidationOptions.ts'\nimport type { CmcdValidationResult } from './CmcdValidationResult.ts'\nimport type { CmcdValidationIssue } from './CmcdValidationIssue.ts'\nimport { CMCD_VALIDATION_SEVERITY_ERROR } from './CmcdValidationSeverity.ts'\nimport { decodeCmcd } from './decodeCmcd.ts'\nimport { mergeValidationResults } from './mergeValidationResults.ts'\nimport { validateCmcd } from './validateCmcd.ts'\n\n/**\n * Validates a raw CMCD string as an event-mode payload.\n *\n * This function decodes the string internally and validates it with\n * `reportingMode` set to `'event'`. The input may contain multiple\n * newline-separated events, for example an `application/cmcd` POST body.\n * The function validates each line independently and merges the results.\n *\n * @param cmcd - The raw CMCD-encoded string to validate. May contain\n * multiple newline-separated event lines.\n * @param options - Validation options (excluding `reportingMode`).\n * @returns The validation result including decoded data per event line.\n *\n * @example\n * {@includeCode ../test/validateCmcdEvents.test.ts#example}\n *\n * @see {@link https://cta-wave.github.io/Resources/common-media-client-data--cta-5004-b.html#body-definition | CTA-5004-B Body Definition}\n *\n * @public\n */\nexport function validateCmcdEvents(cmcd: string, options?: Omit<CmcdValidationOptions, 'reportingMode'>): CmcdEventsValidationResult {\n\tconst opts = { ...options, reportingMode: CMCD_EVENT_MODE } as const\n\tconst lines = cmcd.split(/\\r?\\n/).filter(line => line.length > 0)\n\n\tif (lines.length === 0) {\n\t\treturn {\n\t\t\tvalid: false,\n\t\t\tissues: [{\n\t\t\t\tmessage: 'Empty event mode payload. At least one event line is required.',\n\t\t\t\tseverity: CMCD_VALIDATION_SEVERITY_ERROR,\n\t\t\t}],\n\t\t\tdata: [],\n\t\t}\n\t}\n\n\tconst bodyIssues: CmcdValidationIssue[] = []\n\tif (cmcd.endsWith('\\n')) {\n\t\tbodyIssues.push({\n\t\t\tmessage: 'Event report body must not end with a line feed.',\n\t\t\tseverity: CMCD_VALIDATION_SEVERITY_ERROR,\n\t\t})\n\t}\n\n\tconst decodedLines: CmcdData[] = []\n\tconst lineResults: CmcdValidationResult[] = []\n\n\tfor (let i = 0; i < lines.length; i++) {\n\t\ttry {\n\t\t\tconst data = decodeCmcd(lines[i])\n\t\t\tdecodedLines.push(data)\n\t\t\tlineResults.push(validateCmcd(data, opts))\n\t\t} catch {\n\t\t\tdecodedLines.push({} as CmcdData)\n\t\t\tlineResults.push({\n\t\t\t\tvalid: false,\n\t\t\t\tissues: [{\n\t\t\t\t\tmessage: `Failed to decode event line ${i + 1}: invalid structured field syntax.`,\n\t\t\t\t\tseverity: CMCD_VALIDATION_SEVERITY_ERROR,\n\t\t\t\t}],\n\t\t\t})\n\t\t}\n\t}\n\n\tconst result = mergeValidationResults({ valid: true, issues: bodyIssues }, ...lineResults)\n\treturn { ...result, data: decodedLines }\n}\n","import type { HttpRequest } from '@svta/cml-utils'\nimport { CMCD_MIME_TYPE } from './CMCD_MIME_TYPE.ts'\nimport type { CmcdEventsValidationResult } from './CmcdEventsValidationResult.ts'\nimport type { CmcdValidationOptions } from './CmcdValidationOptions.ts'\nimport { CMCD_VALIDATION_SEVERITY_ERROR } from './CmcdValidationSeverity.ts'\nimport { ensureHeaders } from './ensureHeaders.ts'\nimport { validateCmcdEvents } from './validateCmcdEvents.ts'\n\n/**\n * Validates a full HTTP request as an event-mode payload.\n *\n * Accepts an {@link @svta/cml-utils!HttpRequest | HttpRequest} object.\n *\n * This function validates that the request uses the POST method and has\n * the correct `Content-Type` header (`application/cmcd`). It also\n * validates the body content with {@link validateCmcdEvents}.\n *\n * @param request - An `HttpRequest` to validate.\n * @param options - Validation options (excluding `reportingMode`).\n * @returns The validation result including decoded data per event line.\n *\n * @example {@includeCode ../test/validateCmcdEventReport.test.ts#example}\n *\n * @see {@link https://cta-wave.github.io/Resources/common-media-client-data--cta-5004-b.html#event-mode | CTA-5004-B Event Mode}\n *\n * @public\n */\nexport function validateCmcdEventReport(request: HttpRequest, options?: Omit<CmcdValidationOptions, 'reportingMode'>): CmcdEventsValidationResult {\n\tconst issues: CmcdEventsValidationResult['issues'] = []\n\n\tif (request.method !== 'POST') {\n\t\tissues.push({\n\t\t\tmessage: `Invalid HTTP method '${request.method ?? 'GET'}'. Event reports must use POST.`,\n\t\t\tseverity: CMCD_VALIDATION_SEVERITY_ERROR,\n\t\t})\n\t}\n\n\tconst contentType = request.headers ? ensureHeaders(request.headers).get('Content-Type') : undefined\n\n\tif (!contentType) {\n\t\tissues.push({\n\t\t\tmessage: `Missing Content-Type header. Event reports must use '${CMCD_MIME_TYPE}'.`,\n\t\t\tseverity: CMCD_VALIDATION_SEVERITY_ERROR,\n\t\t})\n\t} else {\n\t\tconst mediaType = contentType.split(';')[0].trim().toLowerCase()\n\t\tif (mediaType !== CMCD_MIME_TYPE) {\n\t\t\tissues.push({\n\t\t\t\tmessage: `Invalid Content-Type '${mediaType}'. Event reports must use '${CMCD_MIME_TYPE}'.`,\n\t\t\t\tseverity: CMCD_VALIDATION_SEVERITY_ERROR,\n\t\t\t})\n\t\t}\n\t}\n\n\tconst body = request.body\n\tif (body === undefined || body === null) {\n\t\tissues.push({\n\t\t\tmessage: 'Missing request body. Event reports must include a body.',\n\t\t\tseverity: CMCD_VALIDATION_SEVERITY_ERROR,\n\t\t})\n\t\treturn {\n\t\t\tvalid: false,\n\t\t\tissues,\n\t\t\tdata: [],\n\t\t}\n\t}\n\n\tif (typeof body !== 'string') {\n\t\tissues.push({\n\t\t\tmessage: 'Request body must be a string.',\n\t\t\tseverity: CMCD_VALIDATION_SEVERITY_ERROR,\n\t\t})\n\t\treturn {\n\t\t\tvalid: false,\n\t\t\tissues,\n\t\t\tdata: [],\n\t\t}\n\t}\n\n\tconst bodyResult = validateCmcdEvents(body, options)\n\n\treturn {\n\t\tvalid: issues.length === 0 && bodyResult.valid,\n\t\tissues: [...issues, ...bodyResult.issues],\n\t\tdata: bodyResult.data,\n\t}\n}\n","import { CMCD_HEADER_MAP } from './CMCD_HEADER_MAP.ts'\nimport type { CmcdData } from './CmcdData.ts'\nimport type { CmcdDataValidationResult } from './CmcdDataValidationResult.ts'\nimport { type CmcdHeaderField, CMCD_HEADER_FIELDS } from './CmcdHeaderField.ts'\nimport type { CmcdKey } from './CmcdKey.ts'\nimport { CMCD_REQUEST_MODE } from './CmcdReportingMode.ts'\nimport type { CmcdValidationOptions } from './CmcdValidationOptions.ts'\nimport type { CmcdValidationResult } from './CmcdValidationResult.ts'\nimport { CMCD_VALIDATION_SEVERITY_ERROR } from './CmcdValidationSeverity.ts'\nimport { decodeCmcd } from './decodeCmcd.ts'\nimport { ensureHeaders } from './ensureHeaders.ts'\nimport { isCmcdCustomKey } from './isCmcdCustomKey.ts'\nimport { mergeValidationResults } from './mergeValidationResults.ts'\nimport { validateCmcd } from './validateCmcd.ts'\n\n/**\n * Validates CMCD HTTP headers by checking shard placement and payload validity.\n *\n * This function accepts raw CMCD header strings and decodes each shard\n * internally. It verifies that each key is in its correct header shard.\n * The function then merges all shards and runs payload validation (keys,\n * values, and structure) on the merged data.\n *\n * @example\n * {@includeCode ../test/validateCmcdHeaders.test.ts#example}\n *\n * @param headers - A `Headers` instance or a record of CMCD header fields to raw encoded strings.\n * @param options - Validation options (excluding `reportingMode`).\n * @returns The validation result including decoded data.\n *\n * @see {@link https://cta-wave.github.io/Resources/common-media-client-data--cta-5004-b.html#header-field-definition | CTA-5004-B Header Field Definition}\n *\n * @public\n */\nexport function validateCmcdHeaders(headers: Record<string, string> | Headers, options?: Omit<CmcdValidationOptions, 'reportingMode'>): CmcdDataValidationResult {\n\tconst h = ensureHeaders(headers)\n\tconst issues: CmcdValidationResult['issues'] = []\n\tconst decoded: Partial<Record<CmcdHeaderField, Record<string, unknown>>> = {}\n\n\tfor (const headerField of CMCD_HEADER_FIELDS) {\n\t\tconst raw = h.get(headerField)\n\t\tif (!raw) {\n\t\t\tcontinue\n\t\t}\n\n\t\tlet shard: Record<string, unknown>\n\t\ttry {\n\t\t\tshard = decodeCmcd(raw)\n\t\t} catch {\n\t\t\tissues.push({\n\t\t\t\tkey: headerField,\n\t\t\t\tmessage: `Failed to decode \"${headerField}\" header: invalid structured field syntax.`,\n\t\t\t\tseverity: CMCD_VALIDATION_SEVERITY_ERROR,\n\t\t\t})\n\t\t\tcontinue\n\t\t}\n\t\tdecoded[headerField] = shard\n\n\t\tfor (const key of Object.keys(shard)) {\n\t\t\tif (isCmcdCustomKey(key as CmcdKey)) {\n\t\t\t\tcontinue\n\t\t\t}\n\n\t\t\tconst expectedHeader = CMCD_HEADER_MAP[key as keyof typeof CMCD_HEADER_MAP]\n\t\t\tif (expectedHeader && expectedHeader !== headerField) {\n\t\t\t\tissues.push({\n\t\t\t\t\tkey,\n\t\t\t\t\tmessage: `Key \"${key}\" is in \"${headerField}\" but should be in \"${expectedHeader}\".`,\n\t\t\t\t\tseverity: CMCD_VALIDATION_SEVERITY_ERROR,\n\t\t\t\t})\n\t\t\t}\n\t\t}\n\t}\n\n\tconst shardResult: CmcdValidationResult = {\n\t\tvalid: issues.length === 0,\n\t\tissues,\n\t}\n\n\tconst merged: Record<string, unknown> = Object.assign({}, ...CMCD_HEADER_FIELDS.map(f => decoded[f]).filter(Boolean))\n\tconst payloadResult = validateCmcd(merged, { ...options, reportingMode: CMCD_REQUEST_MODE })\n\n\tconst result = mergeValidationResults(shardResult, payloadResult)\n\treturn { ...result, data: merged as CmcdData }\n}\n","import type { HttpRequest } from '@svta/cml-utils'\nimport { CMCD_PARAM } from './CMCD_PARAM.ts'\nimport type { CmcdData } from './CmcdData.ts'\nimport type { CmcdDataValidationResult } from './CmcdDataValidationResult.ts'\nimport { type CmcdHeaderField, CMCD_HEADER_FIELDS } from './CmcdHeaderField.ts'\nimport { CMCD_REQUEST_MODE } from './CmcdReportingMode.ts'\nimport type { CmcdValidationOptions } from './CmcdValidationOptions.ts'\nimport type { CmcdValidationResult } from './CmcdValidationResult.ts'\nimport { CMCD_VALIDATION_SEVERITY_ERROR } from './CmcdValidationSeverity.ts'\nimport { decodeCmcd } from './decodeCmcd.ts'\nimport { ensureHeaders } from './ensureHeaders.ts'\nimport { mergeValidationResults } from './mergeValidationResults.ts'\nimport { validateCmcd } from './validateCmcd.ts'\nimport { validateCmcdHeaders } from './validateCmcdHeaders.ts'\n\n/**\n * Validates CMCD data from a request as a request-mode payload.\n *\n * Accepts a\n * {@link https://developer.mozilla.org/en-US/docs/Web/API/Request | Request}\n * object or an {@link @svta/cml-utils!HttpRequest | HttpRequest} object.\n *\n * The function checks the HTTP headers for CMCD data first. If the\n * request has CMCD headers, {@link validateCmcdHeaders} validates them,\n * including shard placement. Otherwise, the function validates the CMCD\n * query parameter of the URL. A request with CMCD data in both the\n * headers and the `CMCD` query parameter is an error. The function still\n * validates the headers and returns their data.\n *\n * @param request - A `Request` or `HttpRequest` to validate.\n * @param options - Validation options (excluding `reportingMode`).\n * @returns The validation result including decoded data.\n *\n * @example\n * {@includeCode ../test/validateCmcdRequest.test.ts#example}\n *\n * @see {@link https://cta-wave.github.io/Resources/common-media-client-data--cta-5004-b.html#request-mode | CTA-5004-B Request Mode}\n *\n * @public\n */\nexport function validateCmcdRequest(request: Request | HttpRequest, options?: Omit<CmcdValidationOptions, 'reportingMode'>): CmcdDataValidationResult {\n\tconst headers = extractHeaderRecord(request.headers)\n\tconst param = getCmcdQueryParam(request.url)\n\n\tif (headers) {\n\t\tconst result = validateCmcdHeaders(headers, options)\n\n\t\tif (!param) {\n\t\t\treturn result\n\t\t}\n\n\t\tconst conflict: CmcdValidationResult = {\n\t\t\tvalid: false,\n\t\t\tissues: [{\n\t\t\t\tmessage: 'CMCD data found in both request headers and the \"CMCD\" query parameter. A request must use only one transmission mode.',\n\t\t\t\tseverity: CMCD_VALIDATION_SEVERITY_ERROR,\n\t\t\t}],\n\t\t}\n\n\t\treturn { ...mergeValidationResults(conflict, result), data: result.data }\n\t}\n\n\tif (!param) {\n\t\treturn {\n\t\t\tvalid: false,\n\t\t\tissues: [{\n\t\t\t\tmessage: hasCmcdInFragment(request.url)\n\t\t\t\t\t? 'No CMCD data found in request headers or query parameters. The URL fragment contains a \"CMCD\" parameter. A server never receives the fragment.'\n\t\t\t\t\t: 'No CMCD data found in request headers or query parameters.',\n\t\t\t\tseverity: CMCD_VALIDATION_SEVERITY_ERROR,\n\t\t\t}],\n\t\t\tdata: {} as CmcdData,\n\t\t}\n\t}\n\n\tlet data: CmcdData\n\ttry {\n\t\tdata = decodeCmcd(param)\n\t} catch {\n\t\treturn {\n\t\t\tvalid: false,\n\t\t\tissues: [{\n\t\t\t\tmessage: 'Failed to decode CMCD query parameter: invalid structured field syntax.',\n\t\t\t\tseverity: CMCD_VALIDATION_SEVERITY_ERROR,\n\t\t\t}],\n\t\t\tdata: {} as CmcdData,\n\t\t}\n\t}\n\n\tconst result = validateCmcd(data, { ...options, reportingMode: CMCD_REQUEST_MODE })\n\treturn { ...result, data }\n}\n\nconst CMCD_IN_FRAGMENT = /(?:^|[?&])CMCD=/\n\nfunction getCmcdQueryParam(url: string): string | null {\n\tconst hash = url.indexOf('#')\n\tconst path = hash < 0 ? url : url.slice(0, hash)\n\tconst start = path.indexOf('?')\n\n\tif (start < 0) {\n\t\treturn null\n\t}\n\n\treturn new URLSearchParams(path.slice(start + 1)).get(CMCD_PARAM)\n}\n\nfunction hasCmcdInFragment(url: string): boolean {\n\tconst hash = url.indexOf('#')\n\n\treturn hash >= 0 && CMCD_IN_FRAGMENT.test(url.slice(hash + 1))\n}\n\nfunction extractHeaderRecord(headers: Headers | Record<string, string> | undefined): Partial<Record<CmcdHeaderField, string>> | undefined {\n\tif (!headers) {\n\t\treturn undefined\n\t}\n\n\tconst h = ensureHeaders(headers)\n\tconst result: Partial<Record<CmcdHeaderField, string>> = {}\n\tlet found = false\n\n\tfor (const field of CMCD_HEADER_FIELDS) {\n\t\tconst value = h.get(field)\n\n\t\tif (value) {\n\t\t\tresult[field] = value\n\t\t\tfound = true\n\t\t}\n\t}\n\n\treturn found ? result : undefined\n}\n"],"mappings":"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"}
|