prismcast 1.9.0 → 1.10.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/dist/app.d.ts +1 -1
- package/dist/app.js +27 -9
- package/dist/app.js.map +1 -1
- package/dist/browser/cdp.js +7 -7
- package/dist/browser/cdp.js.map +1 -1
- package/dist/browser/channelSelection.d.ts +41 -11
- package/dist/browser/channelSelection.js +75 -24
- package/dist/browser/channelSelection.js.map +1 -1
- package/dist/browser/display.d.ts +1 -1
- package/dist/browser/index.d.ts +8 -8
- package/dist/browser/index.js +42 -43
- package/dist/browser/index.js.map +1 -1
- package/dist/browser/login.d.ts +2 -2
- package/dist/browser/login.js +1 -1
- package/dist/browser/manifestInterceptor.d.ts +77 -0
- package/dist/browser/manifestInterceptor.js +323 -0
- package/dist/browser/manifestInterceptor.js.map +1 -0
- package/dist/browser/precaching.js +4 -4
- package/dist/browser/tuning/comcastPolymer.d.ts +1 -1
- package/dist/browser/tuning/cox.d.ts +1 -1
- package/dist/browser/tuning/directv.d.ts +1 -1
- package/dist/browser/tuning/directv.js +61 -62
- package/dist/browser/tuning/directv.js.map +1 -1
- package/dist/browser/tuning/fox.d.ts +1 -1
- package/dist/browser/tuning/fox.js +171 -14
- package/dist/browser/tuning/fox.js.map +1 -1
- package/dist/browser/tuning/hbo.d.ts +1 -1
- package/dist/browser/tuning/hbo.js +6 -6
- package/dist/browser/tuning/hbo.js.map +1 -1
- package/dist/browser/tuning/hulu.d.ts +1 -1
- package/dist/browser/tuning/hulu.js +117 -110
- package/dist/browser/tuning/hulu.js.map +1 -1
- package/dist/browser/tuning/shared.d.ts +3 -3
- package/dist/browser/tuning/shared.js +5 -5
- package/dist/browser/tuning/sling.d.ts +1 -1
- package/dist/browser/tuning/sling.js +28 -28
- package/dist/browser/tuning/sling.js.map +1 -1
- package/dist/browser/tuning/spectrum.d.ts +1 -1
- package/dist/browser/tuning/spectrum.js +21 -22
- package/dist/browser/tuning/spectrum.js.map +1 -1
- package/dist/browser/tuning/thumbnailRow.d.ts +1 -1
- package/dist/browser/tuning/thumbnailRow.js +1 -1
- package/dist/browser/tuning/tileClick.d.ts +1 -1
- package/dist/browser/tuning/tileClick.js +5 -5
- package/dist/browser/tuning/xfinity.d.ts +1 -1
- package/dist/browser/tuning/youtubeTv.d.ts +1 -1
- package/dist/browser/tuning/youtubeTv.js +17 -18
- package/dist/browser/tuning/youtubeTv.js.map +1 -1
- package/dist/browser/video.d.ts +20 -6
- package/dist/browser/video.js +30 -38
- package/dist/browser/video.js.map +1 -1
- package/dist/channels/index.d.ts +1 -2
- package/dist/channels/index.js +73 -40
- package/dist/channels/index.js.map +1 -1
- package/dist/config/channelForm.d.ts +58 -0
- package/dist/config/channelForm.js +129 -0
- package/dist/config/channelForm.js.map +1 -0
- package/dist/config/consistencyProbe.d.ts +7 -0
- package/dist/config/consistencyProbe.js +143 -0
- package/dist/config/consistencyProbe.js.map +1 -0
- package/dist/config/health.d.ts +4 -3
- package/dist/config/health.js +75 -62
- package/dist/config/health.js.map +1 -1
- package/dist/config/index.d.ts +1 -1
- package/dist/config/index.js +19 -12
- package/dist/config/index.js.map +1 -1
- package/dist/config/paths.d.ts +9 -3
- package/dist/config/paths.js +12 -4
- package/dist/config/paths.js.map +1 -1
- package/dist/config/persistence.context.d.ts +8 -0
- package/dist/config/persistence.context.js +30 -0
- package/dist/config/persistence.context.js.map +1 -0
- package/dist/config/persistence.d.ts +110 -12
- package/dist/config/persistence.js +351 -32
- package/dist/config/persistence.js.map +1 -1
- package/dist/config/presets.d.ts +14 -4
- package/dist/config/presets.js +84 -75
- package/dist/config/presets.js.map +1 -1
- package/dist/config/profiles.d.ts +2 -2
- package/dist/config/profiles.js +7 -9
- package/dist/config/profiles.js.map +1 -1
- package/dist/config/servicePacks.d.ts +2 -2
- package/dist/config/servicePacks.js +28 -28
- package/dist/config/servicePacks.js.map +1 -1
- package/dist/config/services.d.ts +62 -36
- package/dist/config/services.js +150 -136
- package/dist/config/services.js.map +1 -1
- package/dist/config/sites.d.ts +3 -3
- package/dist/config/sites.js +16 -16
- package/dist/config/sites.js.map +1 -1
- package/dist/config/userChannels.d.ts +500 -41
- package/dist/config/userChannels.js +1201 -312
- package/dist/config/userChannels.js.map +1 -1
- package/dist/config/userConfig.d.ts +103 -10
- package/dist/config/userConfig.js +277 -117
- package/dist/config/userConfig.js.map +1 -1
- package/dist/config/userProfiles.d.ts +4 -2
- package/dist/config/userProfiles.js +72 -26
- package/dist/config/userProfiles.js.map +1 -1
- package/dist/hdhr/channelMap.js +8 -11
- package/dist/hdhr/channelMap.js.map +1 -1
- package/dist/hdhr/deviceId.js +10 -9
- package/dist/hdhr/deviceId.js.map +1 -1
- package/dist/hdhr/discover.js +4 -5
- package/dist/hdhr/discover.js.map +1 -1
- package/dist/hdhr/index.js +6 -10
- package/dist/hdhr/index.js.map +1 -1
- package/dist/index.js +12 -12
- package/dist/index.js.map +1 -1
- package/dist/native/codecInference.d.ts +44 -0
- package/dist/native/codecInference.js +327 -0
- package/dist/native/codecInference.js.map +1 -0
- package/dist/native/decrypt.d.ts +1 -1
- package/dist/native/index.d.ts +5 -5
- package/dist/native/index.js +42 -64
- package/dist/native/index.js.map +1 -1
- package/dist/native/probe.d.ts +27 -9
- package/dist/native/probe.js +158 -67
- package/dist/native/probe.js.map +1 -1
- package/dist/native/proxy.d.ts +4 -2
- package/dist/native/proxy.js +52 -49
- package/dist/native/proxy.js.map +1 -1
- package/dist/native/tokenExpiry.d.ts +22 -0
- package/dist/native/tokenExpiry.js +153 -0
- package/dist/native/tokenExpiry.js.map +1 -0
- package/dist/routes/auth.js +6 -10
- package/dist/routes/auth.js.map +1 -1
- package/dist/routes/components.js +2 -2
- package/dist/routes/components.js.map +1 -1
- package/dist/routes/config/channels/endpoints/browse.d.ts +6 -0
- package/dist/routes/config/channels/endpoints/browse.js +195 -0
- package/dist/routes/config/channels/endpoints/browse.js.map +1 -0
- package/dist/routes/config/channels/endpoints/bulk.d.ts +6 -0
- package/dist/routes/config/channels/endpoints/bulk.js +128 -0
- package/dist/routes/config/channels/endpoints/bulk.js.map +1 -0
- package/dist/routes/config/channels/endpoints/crud.d.ts +6 -0
- package/dist/routes/config/channels/endpoints/crud.js +504 -0
- package/dist/routes/config/channels/endpoints/crud.js.map +1 -0
- package/dist/routes/config/channels/endpoints/importExport.d.ts +6 -0
- package/dist/routes/config/channels/endpoints/importExport.js +131 -0
- package/dist/routes/config/channels/endpoints/importExport.js.map +1 -0
- package/dist/routes/config/channels/endpoints/predefined.d.ts +6 -0
- package/dist/routes/config/channels/endpoints/predefined.js +78 -0
- package/dist/routes/config/channels/endpoints/predefined.js.map +1 -0
- package/dist/routes/config/channels/endpoints/prefs.d.ts +6 -0
- package/dist/routes/config/channels/endpoints/prefs.js +58 -0
- package/dist/routes/config/channels/endpoints/prefs.js.map +1 -0
- package/dist/routes/config/channels/endpoints/service.d.ts +6 -0
- package/dist/routes/config/channels/endpoints/service.js +149 -0
- package/dist/routes/config/channels/endpoints/service.js.map +1 -0
- package/dist/routes/config/channels/endpoints/tags.d.ts +6 -0
- package/dist/routes/config/channels/endpoints/tags.js +185 -0
- package/dist/routes/config/channels/endpoints/tags.js.map +1 -0
- package/dist/routes/config/channels/http/handler.d.ts +10 -0
- package/dist/routes/config/channels/http/handler.js +20 -0
- package/dist/routes/config/channels/http/handler.js.map +1 -0
- package/dist/routes/config/channels/http/playlistHint.d.ts +25 -0
- package/dist/routes/config/channels/http/playlistHint.js +40 -0
- package/dist/routes/config/channels/http/playlistHint.js.map +1 -0
- package/dist/routes/config/channels/http/serviceWarning.d.ts +10 -0
- package/dist/routes/config/channels/http/serviceWarning.js +28 -0
- package/dist/routes/config/channels/http/serviceWarning.js.map +1 -0
- package/dist/routes/config/channels/index.d.ts +3 -3
- package/dist/routes/config/channels/index.js +1 -1
- package/dist/routes/config/channels/index.js.map +1 -1
- package/dist/routes/config/channels/{routes.d.ts → setup.d.ts} +1 -1
- package/dist/routes/config/channels/setup.js +23 -0
- package/dist/routes/config/channels/setup.js.map +1 -0
- package/dist/routes/config/channels/table.d.ts +9 -9
- package/dist/routes/config/channels/table.js +124 -76
- package/dist/routes/config/channels/table.js.map +1 -1
- package/dist/routes/config/http/envelope.d.ts +111 -0
- package/dist/routes/config/http/envelope.js +103 -0
- package/dist/routes/config/http/envelope.js.map +1 -0
- package/dist/routes/config/index.d.ts +9 -9
- package/dist/routes/config/index.js +2 -2
- package/dist/routes/config/index.js.map +1 -1
- package/dist/routes/config/services.js +69 -68
- package/dist/routes/config/services.js.map +1 -1
- package/dist/routes/config/settings.d.ts +1 -1
- package/dist/routes/config/settings.js +45 -38
- package/dist/routes/config/settings.js.map +1 -1
- package/dist/routes/debug.js +12 -11
- package/dist/routes/debug.js.map +1 -1
- package/dist/routes/icons.js +2 -2
- package/dist/routes/icons.js.map +1 -1
- package/dist/routes/logs.js +19 -30
- package/dist/routes/logs.js.map +1 -1
- package/dist/routes/mpegts.js +1 -1
- package/dist/routes/playlist.d.ts +1 -1
- package/dist/routes/playlist.js +37 -26
- package/dist/routes/playlist.js.map +1 -1
- package/dist/routes/root/content.js +27 -6
- package/dist/routes/root/content.js.map +1 -1
- package/dist/routes/root/index.js +2 -5
- package/dist/routes/root/index.js.map +1 -1
- package/dist/routes/root/scripts/channels.js +16 -16
- package/dist/routes/root/scripts/channels.js.map +1 -1
- package/dist/routes/root/scripts/config.js +59 -59
- package/dist/routes/root/scripts/config.js.map +1 -1
- package/dist/routes/root/scripts/index.d.ts +4 -4
- package/dist/routes/root/scripts/shared.js +24 -10
- package/dist/routes/root/scripts/shared.js.map +1 -1
- package/dist/routes/root/scripts/status.d.ts +4 -0
- package/dist/routes/root/scripts/status.handlers.d.ts +182 -0
- package/dist/routes/root/scripts/status.handlers.js +713 -0
- package/dist/routes/root/scripts/status.handlers.js.map +1 -0
- package/dist/routes/root/scripts/status.js +86 -488
- package/dist/routes/root/scripts/status.js.map +1 -1
- package/dist/routes/root/styles.js +5 -5
- package/dist/routes/services.js +18 -15
- package/dist/routes/services.js.map +1 -1
- package/dist/routes/sse.d.ts +16 -0
- package/dist/routes/sse.js +29 -0
- package/dist/routes/sse.js.map +1 -0
- package/dist/routes/streams.js +10 -23
- package/dist/routes/streams.js.map +1 -1
- package/dist/routes/ui.d.ts +2 -2
- package/dist/routes/upgrade.js +6 -7
- package/dist/routes/upgrade.js.map +1 -1
- package/dist/service/commands.context.d.ts +6 -0
- package/dist/service/commands.context.js +47 -0
- package/dist/service/commands.context.js.map +1 -0
- package/dist/service/commands.d.ts +53 -8
- package/dist/service/commands.js +171 -188
- package/dist/service/commands.js.map +1 -1
- package/dist/service/generators.context.d.ts +6 -0
- package/dist/service/generators.context.js +45 -0
- package/dist/service/generators.context.js.map +1 -0
- package/dist/service/generators.d.ts +56 -16
- package/dist/service/generators.js +499 -383
- package/dist/service/generators.js.map +1 -1
- package/dist/service/index.d.ts +2 -2
- package/dist/streaming/clients.d.ts +2 -2
- package/dist/streaming/clients.js +2 -2
- package/dist/streaming/codec.d.ts +2 -2
- package/dist/streaming/codec.js +0 -1
- package/dist/streaming/codec.js.map +1 -1
- package/dist/streaming/fmp4Segmenter.d.ts +2 -2
- package/dist/streaming/fmp4Segmenter.js +12 -12
- package/dist/streaming/hls.d.ts +3 -3
- package/dist/streaming/hls.js +81 -70
- package/dist/streaming/hls.js.map +1 -1
- package/dist/streaming/hlsResume.d.ts +3 -3
- package/dist/streaming/hlsResume.js +5 -5
- package/dist/streaming/hlsSegments.d.ts +5 -2
- package/dist/streaming/hlsSegments.js +14 -9
- package/dist/streaming/hlsSegments.js.map +1 -1
- package/dist/streaming/monitor.d.ts +12 -12
- package/dist/streaming/monitor.js +80 -54
- package/dist/streaming/monitor.js.map +1 -1
- package/dist/streaming/mp4Parser.d.ts +34 -4
- package/dist/streaming/mp4Parser.js +111 -29
- package/dist/streaming/mp4Parser.js.map +1 -1
- package/dist/streaming/mpegts.d.ts +1 -1
- package/dist/streaming/mpegts.js +13 -10
- package/dist/streaming/mpegts.js.map +1 -1
- package/dist/streaming/playlistBuilder.d.ts +1 -1
- package/dist/streaming/playlistBuilder.js +2 -2
- package/dist/streaming/preroll.d.ts +9 -9
- package/dist/streaming/preroll.js +39 -41
- package/dist/streaming/preroll.js.map +1 -1
- package/dist/streaming/pretune.js +4 -4
- package/dist/streaming/pretune.js.map +1 -1
- package/dist/streaming/recovery.d.ts +3 -3
- package/dist/streaming/recovery.js +4 -4
- package/dist/streaming/registry.d.ts +6 -6
- package/dist/streaming/setup.d.ts +9 -8
- package/dist/streaming/setup.js +97 -49
- package/dist/streaming/setup.js.map +1 -1
- package/dist/streaming/showInfo.d.ts +9 -3
- package/dist/streaming/showInfo.js +26 -18
- package/dist/streaming/showInfo.js.map +1 -1
- package/dist/streaming/statusEmitter.d.ts +4 -4
- package/dist/streaming/statusEmitter.js +2 -2
- package/dist/types/channels.d.ts +133 -34
- package/dist/types/channels.js +39 -1
- package/dist/types/channels.js.map +1 -1
- package/dist/types/config.d.ts +20 -1
- package/dist/types/index.d.ts +9 -8
- package/dist/types/index.js +1 -0
- package/dist/types/index.js.map +1 -1
- package/dist/types/profiles.d.ts +5 -4
- package/dist/types/selection.d.ts +48 -4
- package/dist/types/streaming.d.ts +1 -1
- package/dist/upgrade/commands.context.d.ts +6 -0
- package/dist/upgrade/commands.context.js +29 -0
- package/dist/upgrade/commands.context.js.map +1 -0
- package/dist/upgrade/commands.d.ts +29 -2
- package/dist/upgrade/commands.js +87 -134
- package/dist/upgrade/commands.js.map +1 -1
- package/dist/upgrade/detection.context.d.ts +6 -0
- package/dist/upgrade/detection.context.js +24 -0
- package/dist/upgrade/detection.context.js.map +1 -0
- package/dist/upgrade/detection.d.ts +140 -10
- package/dist/upgrade/detection.js +153 -66
- package/dist/upgrade/detection.js.map +1 -1
- package/dist/upgrade/index.d.ts +2 -2
- package/dist/utils/chromeFetch.d.ts +1 -1
- package/dist/utils/chromeFetch.js +1 -1
- package/dist/utils/clock.d.ts +14 -0
- package/dist/utils/clock.js +28 -0
- package/dist/utils/clock.js.map +1 -0
- package/dist/utils/debugFilter.d.ts +1 -1
- package/dist/utils/debugFilter.js +6 -4
- package/dist/utils/debugFilter.js.map +1 -1
- package/dist/utils/delay.d.ts +2 -3
- package/dist/utils/delay.js +10 -16
- package/dist/utils/delay.js.map +1 -1
- package/dist/utils/evaluate.js +12 -14
- package/dist/utils/evaluate.js.map +1 -1
- package/dist/utils/ffmpeg.context.d.ts +6 -0
- package/dist/utils/ffmpeg.context.js +31 -0
- package/dist/utils/ffmpeg.context.js.map +1 -0
- package/dist/utils/ffmpeg.d.ts +85 -29
- package/dist/utils/ffmpeg.js +126 -129
- package/dist/utils/ffmpeg.js.map +1 -1
- package/dist/utils/fileLogger.d.ts +18 -2
- package/dist/utils/fileLogger.js +58 -30
- package/dist/utils/fileLogger.js.map +1 -1
- package/dist/utils/format.d.ts +1 -1
- package/dist/utils/format.js +2 -2
- package/dist/utils/format.js.map +1 -1
- package/dist/utils/html.js +1 -3
- package/dist/utils/html.js.map +1 -1
- package/dist/utils/index.d.ts +21 -20
- package/dist/utils/index.js +1 -0
- package/dist/utils/index.js.map +1 -1
- package/dist/utils/logger.js +16 -20
- package/dist/utils/logger.js.map +1 -1
- package/dist/utils/m3u.d.ts +18 -3
- package/dist/utils/m3u.js +28 -14
- package/dist/utils/m3u.js.map +1 -1
- package/dist/utils/memo.d.ts +19 -0
- package/dist/utils/memo.js +53 -0
- package/dist/utils/memo.js.map +1 -0
- package/dist/utils/morganStream.js +2 -2
- package/dist/utils/morganStream.js.map +1 -1
- package/dist/utils/pid.d.ts +2 -2
- package/dist/utils/pid.js +2 -2
- package/dist/utils/platform.d.ts +1 -1
- package/dist/utils/platform.js +3 -3
- package/dist/utils/platform.js.map +1 -1
- package/dist/utils/retry.d.ts +2 -0
- package/dist/utils/retry.js +9 -7
- package/dist/utils/retry.js.map +1 -1
- package/dist/utils/sanitize.d.ts +2 -2
- package/dist/utils/sanitize.js +4 -4
- package/dist/utils/timing.d.ts +6 -3
- package/dist/utils/timing.js +10 -6
- package/dist/utils/timing.js.map +1 -1
- package/dist/utils/version.d.ts +3 -2
- package/dist/utils/version.js +14 -27
- package/dist/utils/version.js.map +1 -1
- package/package.json +13 -7
- package/dist/native/intercept.d.ts +0 -35
- package/dist/native/intercept.js +0 -181
- package/dist/native/intercept.js.map +0 -1
- package/dist/routes/config/channels/routes.js +0 -1505
- package/dist/routes/config/channels/routes.js.map +0 -1
|
@@ -1,4 +1,5 @@
|
|
|
1
|
-
import type { Channel, ChannelListingEntry, ChannelMap, StoredChannel, StoredChannelMap } from "../types/index.
|
|
1
|
+
import type { Channel, ChannelDelta, ChannelIdentity, ChannelListingEntry, ChannelMap, ChannelSortField, CustomizableField, ResolvedChannel, ResolvedChannelMap, SortDirection, StoredChannel, StoredChannelMap } from "../types/index.ts";
|
|
2
|
+
import { type Migration, type ValidationIssue } from "./persistence.ts";
|
|
2
3
|
/**
|
|
3
4
|
* User-defined channel with all channel properties.
|
|
4
5
|
*/
|
|
@@ -22,6 +23,7 @@ export interface UserChannelsLoadResult {
|
|
|
22
23
|
channels: StoredChannelMap;
|
|
23
24
|
parseError: boolean;
|
|
24
25
|
parseErrorMessage?: string;
|
|
26
|
+
recoveredFromBackup: boolean;
|
|
25
27
|
serviceSelections: Record<string, string>;
|
|
26
28
|
tagRegistry: TagRegistry;
|
|
27
29
|
}
|
|
@@ -40,6 +42,178 @@ export declare function hasChannelsParseError(): boolean;
|
|
|
40
42
|
* @returns The error message or undefined.
|
|
41
43
|
*/
|
|
42
44
|
export declare function getChannelsParseErrorMessage(): string | undefined;
|
|
45
|
+
/**
|
|
46
|
+
* Compound data type for the channels file store. Carries channel entries alongside the metadata keys that are stored in the same JSON file. The framework
|
|
47
|
+
* uses schemaVersion and migrationsApplied for migration tracking; everything else is application-owned.
|
|
48
|
+
*/
|
|
49
|
+
interface ChannelsFileData {
|
|
50
|
+
channels: StoredChannelMap;
|
|
51
|
+
migrationsApplied: string[];
|
|
52
|
+
schemaVersion: number;
|
|
53
|
+
serviceSelections: Record<string, string>;
|
|
54
|
+
tagRegistry: TagRegistry;
|
|
55
|
+
}
|
|
56
|
+
/**
|
|
57
|
+
* Parses raw channels.json content into the compound data type. Extracts channel entries, service selections, tag registry, and framework metadata
|
|
58
|
+
* (schemaVersion, migrationsApplied) from the top-level JSON object. Also performs structural normalization for legacy field/key naming so consumer code only
|
|
59
|
+
* sees the current shape; the schemaVersion progression governs when the cleanup is persisted to disk via the migration framework.
|
|
60
|
+
* @param raw - The raw JSON string from the file.
|
|
61
|
+
* @returns The parsed compound data.
|
|
62
|
+
*/
|
|
63
|
+
declare function parseChannelsFile(raw: string): ChannelsFileData;
|
|
64
|
+
/**
|
|
65
|
+
* Normalizes a single stored entry as a delta against a base channel. Delta fields are dropped when they are no-ops: undefined values, nulls against a base
|
|
66
|
+
* that has no such field, and values that match the base exactly. Array-valued fields use JSON.stringify for equality with case-insensitive canonical sorting
|
|
67
|
+
* for the fields listed in CANONICAL_SORTED_ARRAY_FIELDS so authoring-order differences do not defeat the match. Non-delta fields (e.g., canonicalKey) pass
|
|
68
|
+
* through unchanged so the stored entry retains its relationship metadata.
|
|
69
|
+
* @param stored - The raw stored entry.
|
|
70
|
+
* @param base - The base Channel to diff against (predefined definition for overrides, resolved canonical for variants).
|
|
71
|
+
* @returns The normalized entry, or null when every field is a no-op and the entry would carry no information.
|
|
72
|
+
*/
|
|
73
|
+
declare function normalizeEntryAgainstBase(stored: StoredChannel, base: Channel): StoredChannel | null;
|
|
74
|
+
/**
|
|
75
|
+
* Classification of a channel entry. Canonical and variant cases carry enough context (predefined entry, stored entry, canonicalKey for variants) that callers
|
|
76
|
+
* do not need to re-read the source maps.
|
|
77
|
+
*/
|
|
78
|
+
type EntryClassification = {
|
|
79
|
+
kind: "canonical";
|
|
80
|
+
predefined: Channel;
|
|
81
|
+
stored: StoredChannel | undefined;
|
|
82
|
+
} | {
|
|
83
|
+
kind: "variant";
|
|
84
|
+
canonicalKey: string;
|
|
85
|
+
predefined: Channel | undefined;
|
|
86
|
+
stored: StoredChannel | undefined;
|
|
87
|
+
} | {
|
|
88
|
+
kind: "standalone";
|
|
89
|
+
stored: StoredChannel;
|
|
90
|
+
};
|
|
91
|
+
/**
|
|
92
|
+
* Classifies a channel entry by consulting both the predefined catalog and the user's stored map. The kind determines how the entry is resolved, normalized, and
|
|
93
|
+
* displayed.
|
|
94
|
+
*
|
|
95
|
+
* Precondition: at least one of the predefined catalog or the stored map must have the key. Callers iterate over the union of key sets and therefore always
|
|
96
|
+
* satisfy this. Violating the precondition throws rather than returning a nullable - the alternative is a defensive undefined check at every call site for a
|
|
97
|
+
* case that never occurs, which is both dead code and a misleading contract.
|
|
98
|
+
* @param key - The channel key.
|
|
99
|
+
* @param stored - The stored entry from the user's channels map (if any).
|
|
100
|
+
* @returns The classification. Never undefined; see the precondition.
|
|
101
|
+
* @throws Error when neither PREDEFINED_CHANNELS nor the caller's stored map contains the key.
|
|
102
|
+
*/
|
|
103
|
+
declare function classifyEntry(key: string, stored: StoredChannel | undefined): EntryClassification;
|
|
104
|
+
/**
|
|
105
|
+
* Computes the field-name allowlist for a stored entry's expected shape. Stored entries fall into two structural shapes determined by classification:
|
|
106
|
+
*
|
|
107
|
+
* - Canonical-shaped (kind = canonical or standalone): allowed fields are DELTA_ELIGIBLE_IDENTITY_KEYS ∪ DELTA_ELIGIBLE_BINDING_KEYS. The full delta surface.
|
|
108
|
+
* - Variant-shaped (kind = variant): allowed fields are DELTA_ELIGIBLE_BINDING_KEYS plus the structural canonicalKey discriminator. Identity inherits from the
|
|
109
|
+
* canonical and must not appear on variants per the architectural principle.
|
|
110
|
+
*
|
|
111
|
+
* Single source of truth for the shape rule. Used by filterToDeltaSurface (normalizer pre-strip) and by the customization accessor's per-pass walks. Routes
|
|
112
|
+
* shape determination through classifyEntry so any caller automatically picks up classifier improvements - no parallel logic for "is this a variant?".
|
|
113
|
+
* @param key - The channel key for classification.
|
|
114
|
+
* @param stored - The stored entry for classification.
|
|
115
|
+
* @returns The set of field names allowed for this entry's shape.
|
|
116
|
+
*/
|
|
117
|
+
declare function getAllowedFieldsForShape(key: string, stored: StoredChannel): ReadonlySet<string>;
|
|
118
|
+
/**
|
|
119
|
+
* Filters a stored entry to its expected delta surface, stripping any field outside the allowed shape. Returns both the filtered entry and the names of any
|
|
120
|
+
* fields that were stripped, so callers can surface diagnostics.
|
|
121
|
+
*
|
|
122
|
+
* The shape rule is enforced here at storage-write time (called from normalizeChannelDeltas) so legacy data with orphan fields - non-delta-eligible identity
|
|
123
|
+
* (pacificStationId), non-delta-eligible binding (DOM hooks), or identity-on-variants - cleans up automatically on next save. The `stripped` array lets the
|
|
124
|
+
* caller log a warning when cleanup happens, giving operators visibility into the violation.
|
|
125
|
+
* @param key - The channel key for shape classification.
|
|
126
|
+
* @param stored - The stored entry to filter.
|
|
127
|
+
* @returns The filtered entry plus the list of stripped field names.
|
|
128
|
+
*/
|
|
129
|
+
declare function filterToDeltaSurface(key: string, stored: StoredChannel): {
|
|
130
|
+
filtered: StoredChannel;
|
|
131
|
+
stripped: readonly string[];
|
|
132
|
+
};
|
|
133
|
+
/**
|
|
134
|
+
* Resolves a variant by layering canonical identity, the predefined variant entry (service binding), and the user delta in order. The canonical contributes
|
|
135
|
+
* ONLY identity (name, stationId, channelNumber, tags, etc.) - its service binding is for the canonical service and would be structurally wrong for any other
|
|
136
|
+
* service variant. The variant's binding is supplied by the predefined variant entry (typically: discovery-driven channelSelector, service-specific URL,
|
|
137
|
+
* profile overrides) and the user's stored delta.
|
|
138
|
+
*
|
|
139
|
+
* Fields propagate through the delta-overlay kernel so null-means-clear and undefined-means-inherit semantics apply uniformly at every layer.
|
|
140
|
+
*
|
|
141
|
+
* Precondition: at least one of predefined or stored must be defined. A variant with no binding source has nothing to resolve; the result would have no URL
|
|
142
|
+
* and no selector, and downstream consumers would fail at the consumption site. classifyEntry only returns a "variant" classification when at least one
|
|
143
|
+
* source carries canonicalKey, so the precondition is satisfied by the only in-tree caller (getMergedChannelMap). Other callers must guarantee the same.
|
|
144
|
+
* @param canonical - The resolved canonical channel. Variant identity inherits from here; canonical binding is intentionally stripped via pickIdentity.
|
|
145
|
+
* @param predefined - The predefined variant entry, if the key has one. Contributes service-binding fields and any per-variant channelNumber override.
|
|
146
|
+
* @param stored - The user's stored delta for this variant, if any. Applied last so user edits win over predefined variant fields.
|
|
147
|
+
* @returns The fully resolved variant.
|
|
148
|
+
*/
|
|
149
|
+
declare function resolveVariant(canonical: ResolvedChannel, predefined: Channel | undefined, stored: StoredChannel | undefined): ResolvedChannel;
|
|
150
|
+
/**
|
|
151
|
+
* Emits a dangling-canonical warning at most once per (variant, canonical) pair for the lifetime of this process. Called from getMergedChannelMap whenever a
|
|
152
|
+
* variant references a canonical that is not present in the resolved map.
|
|
153
|
+
* @param variantKey - The variant key whose canonicalKey points at a missing canonical.
|
|
154
|
+
* @param canonicalKey - The missing canonical key.
|
|
155
|
+
*/
|
|
156
|
+
declare function warnDanglingCanonical(variantKey: string, canonicalKey: string): void;
|
|
157
|
+
/**
|
|
158
|
+
* Builds the Pass 1 resolved-canonical map for a given stored map. Iterates every key present in either the predefined catalog or the stored map, resolves
|
|
159
|
+
* non-variant entries (canonicals and standalones), and returns the resulting ChannelMap. Variants are deliberately skipped - they depend on this map and are
|
|
160
|
+
* resolved in Pass 2 by the caller.
|
|
161
|
+
*
|
|
162
|
+
* This is shared by getMergedChannelMap (which uses the map directly as the starting point for its full resolution) and normalizeChannelDeltas (which uses the
|
|
163
|
+
* map as a source of bases for diffing variant deltas).
|
|
164
|
+
* @param stored - The stored channels map.
|
|
165
|
+
* @returns The resolved-canonical map, keyed by channel key.
|
|
166
|
+
*/
|
|
167
|
+
declare function buildResolvedCanonicals(stored: StoredChannelMap): ResolvedChannelMap;
|
|
168
|
+
/**
|
|
169
|
+
* Strips null fields from a stored entry. Null is a delta-only convention meaning "clear this field on the base"; without a base to clear against, nulls
|
|
170
|
+
* have no meaning and get dropped. Used by normalizeChannelDeltas for standalone user channels and for dangling-canonical variants that fall back to
|
|
171
|
+
* standalone-style normalization.
|
|
172
|
+
* @param stored - The raw stored entry.
|
|
173
|
+
* @returns The entry with null-valued fields removed.
|
|
174
|
+
*/
|
|
175
|
+
declare function stripNulls(stored: StoredChannel): StoredChannel;
|
|
176
|
+
/**
|
|
177
|
+
* Normalizes the stored channels map to its minimal delta form. Each entry is classified, diffed against its applicable base, and any no-op fields are
|
|
178
|
+
* stripped. Standalone user channels have no base, so nulls are stripped but everything else is preserved.
|
|
179
|
+
*
|
|
180
|
+
* The flow is uniform across kinds:
|
|
181
|
+
*
|
|
182
|
+
* - Canonical (predefined with user override): base is the predefined channel.
|
|
183
|
+
* - Variant: base is the resolved canonical layered with the predefined variant's service fields (the view the user sees in the form/table, so the delta
|
|
184
|
+
* records only what differs from that).
|
|
185
|
+
* - Standalone: no base, null values are stripped as a storage convention.
|
|
186
|
+
*
|
|
187
|
+
* Entries whose normalized delta is empty collapse to nothing and get dropped - a redundant override carries no information, and resolution falls through to
|
|
188
|
+
* the default.
|
|
189
|
+
* @param channels - The raw channel entries to normalize.
|
|
190
|
+
* @returns The normalized channel map.
|
|
191
|
+
*/
|
|
192
|
+
declare function normalizeChannelDeltas(channels: StoredChannelMap): StoredChannelMap;
|
|
193
|
+
/**
|
|
194
|
+
* Prepares channels data for writing to disk. Injects metadata from module state (serviceSelections, tagRegistry) into the serializable output. The metadata
|
|
195
|
+
* is always pulled from module state rather than from the file data, because route handlers may have modified metadata in memory since the last file read.
|
|
196
|
+
* Delta normalization is handled by mutateChannels() before the data reaches this hook.
|
|
197
|
+
* @param data - The compound channels data with already-normalized channels.
|
|
198
|
+
* @returns The serializable output with channels and current metadata.
|
|
199
|
+
*/
|
|
200
|
+
declare function prepareChannelsForWrite(data: ChannelsFileData): unknown;
|
|
201
|
+
/**
|
|
202
|
+
* Pre-write integrity validator for the channels store. Detects two classes of suspicious mutations:
|
|
203
|
+
*
|
|
204
|
+
* 1. Identity-field loss: a stored channel's identity field went from set to undefined without canonical fallback. Catches code that
|
|
205
|
+
* accidentally drops user-authored channel data while normalizing or transforming entries.
|
|
206
|
+
* 2. Metadata wholesale clear: a top-level metadata collection (serviceSelections, tagRegistry.tags, tagRegistry.deletedTags) went from non-empty to empty
|
|
207
|
+
* in a single mutation. Catches code that accidentally drops the entire collection (the original bug class - if a future writer or fn regression empties
|
|
208
|
+
* one of these, this guard logs loudly even though the change is structurally allowed).
|
|
209
|
+
*
|
|
210
|
+
* Both checks are log-only - issues surface as warnings without blocking the write. Genuine wholesale clears (operator clears all selections via UI) are the
|
|
211
|
+
* rare false-positive case here; in practice those happen via per-entry mutations rather than a single empty assignment.
|
|
212
|
+
* @param prev - Pre-mutation snapshot of the file data.
|
|
213
|
+
* @param next - Post-mutation, post-normalize file data.
|
|
214
|
+
* @returns Issues found, or empty array.
|
|
215
|
+
*/
|
|
216
|
+
declare function validateChannelsIntegrity(prev: ChannelsFileData, next: ChannelsFileData): ValidationIssue[];
|
|
43
217
|
/**
|
|
44
218
|
* Reads the current channels from disk without acquiring the serialization lock. Returns the parsed channels with metadata and parse status. Use this for
|
|
45
219
|
* read-only access and startup initialization. For modifications, use mutateChannels() instead.
|
|
@@ -47,13 +221,38 @@ export declare function getChannelsParseErrorMessage(): string | undefined;
|
|
|
47
221
|
*/
|
|
48
222
|
export declare function readChannels(): Promise<UserChannelsLoadResult>;
|
|
49
223
|
/**
|
|
50
|
-
*
|
|
51
|
-
*
|
|
52
|
-
*
|
|
53
|
-
*
|
|
54
|
-
*
|
|
224
|
+
* Pre-write integrity guard. Compares the channels map captured immediately after parse against the channels map about to be written, and reports identity
|
|
225
|
+
* fields that have been silently dropped without a canonical fallback.
|
|
226
|
+
*
|
|
227
|
+
* Allowed transitions for any identity field:
|
|
228
|
+
* - value -> same value (no change)
|
|
229
|
+
* - value -> different value (legitimate update)
|
|
230
|
+
* - value -> null (explicit clear; null is the codebase-wide "clear this field" signal)
|
|
231
|
+
* - field absent -> any value (new data)
|
|
232
|
+
*
|
|
233
|
+
* Forbidden transition (what this guard catches):
|
|
234
|
+
* - value -> undefined / missing WHERE the canonical (for variants and predefined-overrides) does not provide the same value
|
|
235
|
+
*
|
|
236
|
+
* Variant inheritance is honored: stripping a stored field that matches the canonical's value is delta minimization, not data loss, and is allowed. The check
|
|
237
|
+
* is non-blocking: it surfaces suspicious patterns for operator review without aborting legitimate code paths.
|
|
238
|
+
* @param before - The channels map captured immediately after parse, before the caller's mutation ran.
|
|
239
|
+
* @param after - The channels map after the caller's mutation and delta normalization.
|
|
240
|
+
* @returns A list of "key.field" strings naming each detected silent drop. Empty list means no losses.
|
|
241
|
+
*/
|
|
242
|
+
declare function detectIdentityFieldLoss(before: StoredChannelMap, after: StoredChannelMap): string[];
|
|
243
|
+
/**
|
|
244
|
+
* Serialized read-modify-write operation on channels.json. The mutation function receives the full file data (channels + serviceSelections + tagRegistry +
|
|
245
|
+
* framework metadata) and modifies it in place. The store handles atomicity, serialization, corruption guard, backup, schema migrations, and pre-write
|
|
246
|
+
* integrity validation. Delta normalization is applied to data.channels after the caller's mutation and before the file write so that the normalized result is
|
|
247
|
+
* available for the post-write cache hydration.
|
|
248
|
+
*
|
|
249
|
+
* After a successful write, the in-memory caches that mirror persisted state (loadedUserChannels, loadedTagRegistry, services.ts serviceSelections Map,
|
|
250
|
+
* runtime service groups) are hydrated from the just-written normalized data. This is the single direction caches flow: data is the source of truth, caches
|
|
251
|
+
* are derived. Callers must never poke caches directly and rely on a later save to pick up the change - all mutations go through this function.
|
|
252
|
+
* @param fn - Mutation function. Receives the full file data. Modify in place; return value is ignored.
|
|
253
|
+
* @throws FileStoreParseError if channels.json contains invalid JSON and the .bak rotation is also unparseable.
|
|
55
254
|
*/
|
|
56
|
-
export declare function mutateChannels(fn: (
|
|
255
|
+
export declare function mutateChannels(fn: (data: ChannelsFileData) => void): Promise<void>;
|
|
57
256
|
/**
|
|
58
257
|
* Deletes a user channel by key.
|
|
59
258
|
* @param key - The channel key to delete.
|
|
@@ -61,26 +260,137 @@ export declare function mutateChannels(fn: (channels: StoredChannelMap) => void)
|
|
|
61
260
|
* @throws If the file cannot be written.
|
|
62
261
|
*/
|
|
63
262
|
export declare function deleteUserChannel(key: string): Promise<void>;
|
|
263
|
+
/**
|
|
264
|
+
* Removes all user override entries for a canonical channel - both the canonical-stored entry and the active service variant's stored entry (when one resolves
|
|
265
|
+
* via explicit selection or service-filter fallback). Returns the stored entry that was deleted (canonical takes precedence; falls back to the variant entry
|
|
266
|
+
* when canonical is absent) so callers can compute downstream effects like the playlist reload hint without duplicating the lookup.
|
|
267
|
+
*
|
|
268
|
+
* Callers wrap the call in mutateChannels() and pass the resulting StoredChannelMap. The helper operates on the map directly; it does not own the mutation
|
|
269
|
+
* lifecycle, allowing callers to combine the dual-delete with other operations (e.g., setting serviceSelections) in the same atomic write.
|
|
270
|
+
* @param channels - The stored channels map to mutate in place.
|
|
271
|
+
* @param canonicalKey - The canonical channel key. The active variant is resolved internally via resolveServiceKey.
|
|
272
|
+
* @returns The stored entry that existed pre-deletion (canonical first, variant fallback). Undefined when neither entry existed.
|
|
273
|
+
*/
|
|
274
|
+
export declare function clearChannelOverrides(channels: StoredChannelMap, canonicalKey: string): StoredChannel | undefined;
|
|
275
|
+
/**
|
|
276
|
+
* Merges a partial ChannelDelta into a stored entry. Returns a new entry with the existing fields preserved and the delta's fields layered on top. Used by
|
|
277
|
+
* bulk operations that update one or more delta fields across many channels - the helper handles both the "no entry exists yet" case (uses an empty record)
|
|
278
|
+
* and the "entry exists with prior overrides" case (preserves them) without forcing each call site to write the spread + assign manually.
|
|
279
|
+
*
|
|
280
|
+
* The merged entry is returned in StoredChannel shape; callers assign it back to data.channels[key]. The post-mutation normalizer (filterToDeltaSurface +
|
|
281
|
+
* normalizeEntryAgainstBase) handles delta minimization and shape enforcement, so callers can pass arbitrary ChannelDelta keys without pre-validating them.
|
|
282
|
+
* @param stored - The existing stored entry, or undefined when the channel has no prior overrides.
|
|
283
|
+
* @param delta - Fields to assign onto the entry. Null values flow through unchanged for the delta-clear semantic.
|
|
284
|
+
* @returns The merged stored entry.
|
|
285
|
+
*/
|
|
286
|
+
export declare function applyChannelDelta(stored: StoredChannel | undefined, delta: ChannelDelta): StoredChannel;
|
|
64
287
|
/**
|
|
65
288
|
* Resets all user channels by deleting the channels file.
|
|
66
289
|
* @throws If the file exists but cannot be deleted.
|
|
67
290
|
*/
|
|
68
291
|
export declare function resetUserChannels(): Promise<void>;
|
|
292
|
+
/**
|
|
293
|
+
* Classifies which stored entries are legitimate legacy variants eligible for canonicalKey stamping. A legitimate legacy variant has a hyphenated key whose
|
|
294
|
+
* prefix matches a predefined canonical AND every stored identity field either is absent or matches the canonical's value. Entries with diverging identity
|
|
295
|
+
* are user-created standalones that happen to share the hyphenated key shape (e.g., "abc-kabc" as a local affiliate with its own channel number and station
|
|
296
|
+
* ID) and must be left alone - stamping them would mark them for delta normalization and silently destroy the user's custom identity.
|
|
297
|
+
*
|
|
298
|
+
* Array-valued identity fields (tags) compare via JSON.stringify with case-insensitive canonical sorting so historical write order does not defeat the match.
|
|
299
|
+
* @param channels - The raw stored channel entries.
|
|
300
|
+
* @returns Keys that should receive a canonicalKey stamp. Empty when nothing needs migrating.
|
|
301
|
+
*/
|
|
302
|
+
declare function collectLegacyVariantStamps(channels: StoredChannelMap): string[];
|
|
69
303
|
/**
|
|
70
304
|
* Initializes user channels by loading them from the file. This should be called once at server startup. Also builds service groups and loads service selections.
|
|
71
305
|
*/
|
|
72
306
|
export declare function initializeUserChannels(): Promise<void>;
|
|
73
307
|
/**
|
|
74
|
-
*
|
|
75
|
-
*
|
|
76
|
-
*
|
|
77
|
-
*
|
|
78
|
-
*
|
|
79
|
-
*
|
|
308
|
+
* Extracts the identity-only subset of a channel. Used by resolveVariant and normalizeChannelDeltas to compute the inheritance base for variants: a variant
|
|
309
|
+
* inherits identity from its canonical but must contribute its own service binding (URL, channelSelector, profile, etc.) - the canonical's binding is for the
|
|
310
|
+
* canonical service and is structurally wrong for any other service.
|
|
311
|
+
*
|
|
312
|
+
* The fields copied are exactly those listed in CHANNEL_IDENTITY_KEYS, the single source of truth for the identity partition. Array-valued fields are shallow-
|
|
313
|
+
* copied so downstream mutation cannot leak back into the source.
|
|
314
|
+
* @param channel - The channel to extract identity from. Typed as ResolvedChannel because that is the shape after canonical resolution; CanonicalChannel is
|
|
315
|
+
* structurally compatible.
|
|
316
|
+
* @returns A new ChannelIdentity object with just the identity fields populated.
|
|
317
|
+
*/
|
|
318
|
+
export declare function pickIdentity(channel: ResolvedChannel): ChannelIdentity;
|
|
319
|
+
/**
|
|
320
|
+
* Overlays a stored channel (full definition or delta) onto a base. Allowlisted delta fields in the stored entry override the base: a null value clears the
|
|
321
|
+
* field from the resolved object, a defined value replaces it, and missing fields inherit from the base. Non-delta fields on the stored entry (e.g.,
|
|
322
|
+
* canonicalKey) pass through so the resolved channel retains its relationship metadata. The returned object is a fresh reference with a defensive copy of any
|
|
323
|
+
* array-valued fields, so callers can mutate it without corrupting the base.
|
|
324
|
+
*
|
|
325
|
+
* This is the single delta-overlay kernel used by both predefined overrides and user variants. The base may be:
|
|
326
|
+
*
|
|
327
|
+
* - A predefined CanonicalChannel for canonical-override resolution.
|
|
328
|
+
* - A ChannelIdentity-only intermediate during variant resolution (URL is supplied by the variant binding overlay).
|
|
329
|
+
* - A fully resolved canonical for variant base computation.
|
|
330
|
+
*
|
|
331
|
+
* Internally typed as ResolvedChannel for the input shape; intermediate variant-resolution states pass through a cast because url is required on
|
|
332
|
+
* ResolvedChannel but is supplied by the next overlay. The contract is: after the full resolveVariant chain, the result has every required field populated.
|
|
333
|
+
* @param base - The base channel to inherit from.
|
|
334
|
+
* @param stored - The stored entry (delta) to overlay.
|
|
335
|
+
* @returns A new ResolvedChannel with the base's fields and the stored entry's overrides applied.
|
|
336
|
+
*/
|
|
337
|
+
declare function overlayDelta(base: ResolvedChannel, stored: StoredChannel): ResolvedChannel;
|
|
338
|
+
/**
|
|
339
|
+
* Shared overlay kernel used by overlayDelta and overlayVariantBinding. Walks the stored entry's fields and applies them to a clone of base under three rules:
|
|
340
|
+
* fields in allowedFields apply with delta semantics (null clears, undefined skips, value overrides); non-allowed fields either pass through (delta) or are
|
|
341
|
+
* silently dropped (variant overlay) per passThroughOthers; canonicalKey is always allowed regardless of the gate so resolved variants retain their relationship
|
|
342
|
+
* metadata. The kernel exists to keep the two overlays from drifting - identical control flow lived in both call sites before this consolidation.
|
|
343
|
+
* @param base - The base channel to clone and overlay onto.
|
|
344
|
+
* @param stored - The stored entry whose fields override the base.
|
|
345
|
+
* @param options - allowedFields selects which fields apply with delta semantics; passThroughOthers controls whether non-allowed fields flow through or are
|
|
346
|
+
* dropped. canonicalKey is always passed through.
|
|
347
|
+
* @returns A new ResolvedChannel with overlay applied.
|
|
348
|
+
*/
|
|
349
|
+
declare function applyOverlayKernel(base: ResolvedChannel, stored: StoredChannel, options: {
|
|
350
|
+
allowedFields: ReadonlySet<string>;
|
|
351
|
+
passThroughOthers: boolean;
|
|
352
|
+
}): ResolvedChannel;
|
|
353
|
+
/**
|
|
354
|
+
* Variant-binding-only overlay. Like overlayDelta but applies only fields in CHANNEL_BINDING_KEYS - identity fields on the variant entry are silently dropped
|
|
355
|
+
* during resolution. This enforces the architectural principle that variants are pure tuning data: how to reach the channel via this service. Identity
|
|
356
|
+
* (channelNumber, hdhrEnabled, tags, name, etc.) is a property of the channel as a whole and lives only on the canonical entry.
|
|
357
|
+
*
|
|
358
|
+
* Used by resolveVariant for both predefined-variant and stored-variant overlays. Legacy data, hand-edited files, or future migrations that put identity
|
|
359
|
+
* fields on variant entries are inert at resolution time - canonical's identity always wins. canonicalKey passes through as relationship metadata so the
|
|
360
|
+
* resolved variant can still be identified as a variant.
|
|
361
|
+
*
|
|
362
|
+
* Null/undefined semantics match overlayDelta: null clears the field; undefined inherits.
|
|
363
|
+
* @param base - The base channel (typically canonical identity from pickIdentity).
|
|
364
|
+
* @param stored - The variant entry (predefined or user-stored).
|
|
365
|
+
* @returns A new ResolvedChannel with binding fields applied from the variant.
|
|
80
366
|
*/
|
|
81
|
-
|
|
367
|
+
declare function overlayVariantBinding(base: ResolvedChannel, stored: StoredChannel): ResolvedChannel;
|
|
82
368
|
/**
|
|
83
|
-
*
|
|
369
|
+
* Resolves a stored channel entry into a fully populated ResolvedChannel. Handles the two non-variant cases:
|
|
370
|
+
*
|
|
371
|
+
* 1. Predefined override (key matches a predefined entry): the stored entry is a delta over the predefined canonical definition.
|
|
372
|
+
* 2. Standalone user channel (no predefined equivalent): the stored entry is already a full channel; a defensive copy is returned so downstream mutations
|
|
373
|
+
* cannot leak into loadedUserChannels.
|
|
374
|
+
*
|
|
375
|
+
* Variants are resolved by getMergedChannelMap via the layered overlay (canonical identity -> predefined variant binding -> user delta). Callers that need a
|
|
376
|
+
* resolved variant should read from channelsRef (via getResolvedChannel) rather than calling this function with a variant key.
|
|
377
|
+
* @param key - The channel key (must not be a variant key).
|
|
378
|
+
* @param stored - The stored channel data.
|
|
379
|
+
* @returns A fully resolved channel with identity and binding both populated.
|
|
380
|
+
*/
|
|
381
|
+
export declare function resolveStoredChannel(key: string, stored: StoredChannel): ResolvedChannel;
|
|
382
|
+
/**
|
|
383
|
+
* Returns the merged channel map (predefined + user) without filtering by enabled status or service variants. Used internally for building service groups.
|
|
384
|
+
* Resolves deltas into fully populated channels.
|
|
385
|
+
*
|
|
386
|
+
* Built from buildResolvedCanonicals (Pass 1: canonicals and standalones) plus a variant pass (Pass 2: layered canonical identity -> predefined variant
|
|
387
|
+
* binding -> user delta). The dangling-canonical path preserves whatever data exists so the user does not silently lose anything when a canonicalKey points
|
|
388
|
+
* at a missing entry.
|
|
389
|
+
* @returns The complete merged channel map.
|
|
390
|
+
*/
|
|
391
|
+
declare function getMergedChannelMap(): ResolvedChannelMap;
|
|
392
|
+
/**
|
|
393
|
+
* Returns the full channel listing with source classification and enabled status. This is the authoritative merge point for predefined and user channels - all
|
|
84
394
|
* code that needs a merged view of channels should use this function (or getAllChannels() which delegates to it).
|
|
85
395
|
*
|
|
86
396
|
* For each channel key, the source is classified as:
|
|
@@ -91,7 +401,7 @@ export declare function resolveStoredChannel(key: string, stored: StoredChannel)
|
|
|
91
401
|
* The enabled field reflects whether the channel is available for streaming. Predefined-only channels can be disabled via configuration; user and override
|
|
92
402
|
* channels are always enabled.
|
|
93
403
|
*
|
|
94
|
-
* Service variants (non-canonical keys in service groups) are filtered out from this listing
|
|
404
|
+
* Service variants (non-canonical keys in service groups) are filtered out from this listing - they are accessed via the service selection mechanism instead.
|
|
95
405
|
*
|
|
96
406
|
* Override entries produce a new resolved Channel object (via resolveStoredChannel()), which is a different reference from PREDEFINED_CHANNELS[key]. The service
|
|
97
407
|
* system (services.ts) relies on this reference difference to detect user overrides via isUserOverride(). Predefined-only entries preserve the original reference.
|
|
@@ -101,12 +411,73 @@ export declare function resolveStoredChannel(key: string, stored: StoredChannel)
|
|
|
101
411
|
* @returns Sorted array of channel listing entries.
|
|
102
412
|
*/
|
|
103
413
|
export declare function getChannelListing(): ChannelListingEntry[];
|
|
414
|
+
/**
|
|
415
|
+
* Predicate for "visible" channels - entries that are both enabled and available under the current service filter. This is the single source of truth for what
|
|
416
|
+
* "visible" means across bulk operations, the playlist, and the merged channel map. Every site that filters the listing by visibility routes through this
|
|
417
|
+
* predicate so the definition lives in exactly one place.
|
|
418
|
+
* @param entry - The listing entry to test.
|
|
419
|
+
* @returns True when the channel is enabled and passes the service filter.
|
|
420
|
+
*/
|
|
421
|
+
export declare function isVisibleChannel(entry: ChannelListingEntry): boolean;
|
|
422
|
+
/**
|
|
423
|
+
* Returns the subset of getChannelListing() that is enabled and available under the current service filter. Built on top of isVisibleChannel so the visibility
|
|
424
|
+
* predicate lives in one place.
|
|
425
|
+
* @returns Listing entries that pass the visibility predicate.
|
|
426
|
+
*/
|
|
427
|
+
export declare function getVisibleChannels(): ChannelListingEntry[];
|
|
104
428
|
/**
|
|
105
429
|
* Returns all available channels (predefined + user), with user channels taking precedence on key conflicts. Disabled predefined channels are excluded. Built on
|
|
106
430
|
* top of getChannelListing() to ensure a single merging code path.
|
|
107
431
|
* @returns The merged channel map with disabled predefined channels filtered out.
|
|
108
432
|
*/
|
|
109
|
-
export declare function getAllChannels():
|
|
433
|
+
export declare function getAllChannels(): ResolvedChannelMap;
|
|
434
|
+
/**
|
|
435
|
+
* Returns a copy of the raw stored user channels map - the unresolved entries as they exist in channels.json. Used by the consistency probe to check
|
|
436
|
+
* cross-store invariants without applying delta resolution. Callers should not rely on the shape for anything beyond key/canonicalKey inspection.
|
|
437
|
+
* @returns Shallow copy of the loaded user channels.
|
|
438
|
+
*/
|
|
439
|
+
export declare function getStoredUserChannels(): StoredChannelMap;
|
|
440
|
+
/**
|
|
441
|
+
* Where a customized field's override lives in storage. "canonical" means the override is on the canonical channel's stored entry (typically identity fields
|
|
442
|
+
* like name, stationId, tags). "variant" means the override is on the active service variant's stored entry (typically binding fields like url,
|
|
443
|
+
* channelSelector). The form's save handler uses this to route changes to the correct entry; the per-field reset uses it to compute the resetValue from the
|
|
444
|
+
* matching predefined source.
|
|
445
|
+
*/
|
|
446
|
+
export type CustomizationStoredIn = "canonical" | "variant";
|
|
447
|
+
/**
|
|
448
|
+
* Per-field customization metadata: where the override is stored and what the field would resolve to if the override were removed (the per-field "reset to
|
|
449
|
+
* default" value).
|
|
450
|
+
*/
|
|
451
|
+
export interface ChannelCustomizationEntry {
|
|
452
|
+
resetValue: unknown;
|
|
453
|
+
storedIn: CustomizationStoredIn;
|
|
454
|
+
}
|
|
455
|
+
/**
|
|
456
|
+
* Result of getChannelCustomizations. Carries the per-field provenance map and identifies the active service variant (if a non-canonical service is resolved
|
|
457
|
+
* via explicit selection or service-filter fallback). Callers - the channel edit form's render and save paths - rely on both pieces to display the right
|
|
458
|
+
* "modified from default" indicators and to route saves to the correct entry.
|
|
459
|
+
*/
|
|
460
|
+
export interface ChannelCustomizations {
|
|
461
|
+
activeVariantKey: string | undefined;
|
|
462
|
+
customizations: Map<CustomizableField, ChannelCustomizationEntry>;
|
|
463
|
+
}
|
|
464
|
+
/**
|
|
465
|
+
* Returns the customization provenance for the given canonical channel. The form layer uses this as the single source of truth for which fields are
|
|
466
|
+
* customized (instead of comparing resolved values to predefined values, which produces false positives when a non-canonical service is active and the
|
|
467
|
+
* resolved value legitimately differs from the canonical's predefined value).
|
|
468
|
+
*
|
|
469
|
+
* Resolution: for each field present in the user's canonical-stored entry, mark customized with storedIn="canonical" and resetValue from computeResetValue.
|
|
470
|
+
* For each field present in the active variant's stored entry, mark customized with storedIn="variant" and resetValue from computeResetValue (which handles
|
|
471
|
+
* variant-inheritance fallback). Variant entries override canonical entries on the same field name because variant resolution overlays the variant's value
|
|
472
|
+
* last.
|
|
473
|
+
*
|
|
474
|
+
* Pass 2 (variant-stored fields) restricts the walked field set via getAllowedFieldsForShape so identity fields encountered on a variant entry are silently
|
|
475
|
+
* dropped from the customization map, matching the resolver's behavior. The "canonicalKey" field is similarly excluded from both passes - structural metadata,
|
|
476
|
+
* not user-customizable.
|
|
477
|
+
* @param canonicalKey - The canonical channel key.
|
|
478
|
+
* @returns The customization provenance map and the active variant key (when applicable).
|
|
479
|
+
*/
|
|
480
|
+
export declare function getChannelCustomizations(canonicalKey: string): ChannelCustomizations;
|
|
110
481
|
/**
|
|
111
482
|
* Returns the raw stored channel data (without predefined channels). Entries may be full Channel definitions or ChannelDelta overrides.
|
|
112
483
|
* @returns The stored channel map.
|
|
@@ -118,10 +489,13 @@ export declare function getUserChannels(): StoredChannelMap;
|
|
|
118
489
|
*/
|
|
119
490
|
export declare function getTagRegistry(): TagRegistry;
|
|
120
491
|
/**
|
|
121
|
-
*
|
|
492
|
+
* Persists a new tag registry state. Goes through mutateChannels so the file write, integrity validation, and post-mutate cache hydration all run uniformly -
|
|
493
|
+
* after the call returns, both disk and module-state cache reflect the new value. The caller's input arrays are not mutated; both are sorted non-destructively
|
|
494
|
+
* via sortTags so storage shares one canonical ordering.
|
|
122
495
|
* @param registry - The new tag registry state.
|
|
496
|
+
* @throws FileStoreParseError if channels.json contains invalid JSON and the .bak rotation is also unparseable.
|
|
123
497
|
*/
|
|
124
|
-
export declare function setTagRegistry(registry: TagRegistry): void
|
|
498
|
+
export declare function setTagRegistry(registry: TagRegistry): Promise<void>;
|
|
125
499
|
/**
|
|
126
500
|
* Returns the active tag vocabulary: predefined tags minus user-deleted tags, plus user-created tags, sorted alphabetically. This is the single source of truth
|
|
127
501
|
* for which tags are visible, assignable, and queryable throughout the system. Tags not in this list are invisible to the UI and rejected by the ?tag= query
|
|
@@ -130,25 +504,43 @@ export declare function setTagRegistry(registry: TagRegistry): void;
|
|
|
130
504
|
*/
|
|
131
505
|
export declare function getActiveTagVocabulary(): string[];
|
|
132
506
|
/**
|
|
133
|
-
* Returns a channel's effective tags
|
|
134
|
-
* the active vocabulary are filtered out, ensuring only assignable and queryable tags are visible in the UI and playlist responses.
|
|
507
|
+
* Returns a channel's effective tags - the intersection of the channel's assigned tags with the active vocabulary. Tags that exist on the channel but are not in
|
|
508
|
+
* the active vocabulary are filtered out, ensuring only assignable and queryable tags are visible in the UI and playlist responses. Output preserves the source
|
|
509
|
+
* order of channel.tags; every write path (sortTags) keeps that source order canonical, so in practice the returned array is sorted.
|
|
135
510
|
* @param channel - The channel to get effective tags for.
|
|
136
|
-
* @returns
|
|
511
|
+
* @returns Effective tag strings in source order, or empty array if the channel has no tags or none are in the active vocabulary.
|
|
137
512
|
*/
|
|
138
|
-
export declare function getChannelEffectiveTags(channel:
|
|
513
|
+
export declare function getChannelEffectiveTags(channel: ResolvedChannel): string[];
|
|
514
|
+
/**
|
|
515
|
+
* Returns whether a channel is effectively included in the HDHomeRun lineup. Codifies the sparse-storage convention that absent or true means included, and only
|
|
516
|
+
* an explicit `false` means excluded. This is the single source of truth for the convention - every site that needs to ask "is HDHR enabled for this channel?"
|
|
517
|
+
* routes through this helper rather than reaching for the inline `channel.hdhrEnabled !== false` pattern. Storage-shape inspections that ask a different
|
|
518
|
+
* question ("did the client send literal false?", "did the user override?") stay inline because they are not asking about effective state.
|
|
519
|
+
* @param channel - The channel to evaluate.
|
|
520
|
+
* @returns True when the channel is effectively included in the HDHR lineup.
|
|
521
|
+
*/
|
|
522
|
+
export declare function getEffectiveHdhrEnabled(channel: ResolvedChannel): boolean;
|
|
139
523
|
/**
|
|
140
524
|
* Case-insensitive tag comparison. Tags are freeform strings with preserved casing, but all matching throughout the system is case-insensitive. This function
|
|
141
|
-
* is the single source of truth for that policy
|
|
525
|
+
* is the single source of truth for that policy - all tag identity checks should use it rather than inline toLowerCase() calls.
|
|
142
526
|
* @param a - The first tag.
|
|
143
527
|
* @param b - The second tag.
|
|
144
528
|
* @returns True if the tags match case-insensitively.
|
|
145
529
|
*/
|
|
146
530
|
export declare function tagsMatch(a: string, b: string): boolean;
|
|
147
531
|
/**
|
|
148
|
-
*
|
|
532
|
+
* Checks whether a tag is present in the active vocabulary under case-insensitive identity. This is the single source of truth for "does this tag exist?"
|
|
533
|
+
* questions - tag endpoints (create/rename collision, bulk-tags vocabulary check) route through this instead of ad-hoc Set+toLowerCase comparisons so the
|
|
534
|
+
* case-insensitive policy lives in exactly one place (tagsMatch), not in parallel implementations.
|
|
535
|
+
* @param tag - The tag to check.
|
|
536
|
+
* @returns True if the active vocabulary contains a tag matching case-insensitively.
|
|
537
|
+
*/
|
|
538
|
+
export declare function isInVocabulary(tag: string): boolean;
|
|
539
|
+
/**
|
|
540
|
+
* Applies a tag transformation across channels and persists the result. This is the single source of truth for batch tag mutations - delete, rename, and bulk
|
|
149
541
|
* toggle all route through this function. The caller provides a filter (which channels to transform) and a transform (how to modify each channel's tags). This
|
|
150
542
|
* function handles loading stored channel data, applying the transform, and saving. Delta normalization in mutateChannels() handles predefined channel
|
|
151
|
-
* delta computation automatically
|
|
543
|
+
* delta computation automatically - callers do not need to reason about deltas vs. full definitions.
|
|
152
544
|
* @param filter - Predicate selecting which listing entries to transform. Receives each ChannelListingEntry from getChannelListing().
|
|
153
545
|
* @param transform - Pure function mapping a channel's current resolved tags to its new tags. Receives the channel's current tags array (may be empty, ordering
|
|
154
546
|
* not guaranteed). Must return the desired tags array (may be empty to clear all tags). The returned array is sorted before storage.
|
|
@@ -159,11 +551,20 @@ export declare function transformChannelTags(filter: (entry: ChannelListingEntry
|
|
|
159
551
|
error?: string;
|
|
160
552
|
}>;
|
|
161
553
|
/**
|
|
162
|
-
* Returns the predefined channel definition for a key.
|
|
554
|
+
* Returns the predefined channel definition for a key as a fully-resolved view. For predefined variant entries (which carry only service-specific fields plus
|
|
555
|
+
* canonicalKey), overlays the variant's binding onto its predefined canonical so callers receive the resolved view - canonical identity inherited onto the
|
|
556
|
+
* variant. This matches what the user sees in the form/table and is the correct base for delta-from-predefined computations in crud.ts and channelForm.ts.
|
|
557
|
+
*
|
|
558
|
+
* Always returns ResolvedChannel-shaped data: identity fields (name, tags, hdhrEnabled, etc.) are always available, sourced from the canonical when this key is
|
|
559
|
+
* a variant. CanonicalChannel and VariantChannel both assign structurally to ResolvedChannel since the identity fields are optional in both types.
|
|
560
|
+
*
|
|
561
|
+
* Returns undefined when the key is not predefined OR when the catalog is internally inconsistent (variant references a missing canonical). The latter case is
|
|
562
|
+
* structurally impossible by construction of the flattener, so observing it is a real corruption indicator: the function logs once per offending key and
|
|
563
|
+
* returns undefined rather than fabricating a half-resolved view that would lie about its identity fields.
|
|
163
564
|
* @param key - The channel key to look up.
|
|
164
|
-
* @returns The predefined channel, or undefined if the key is not predefined.
|
|
565
|
+
* @returns The resolved predefined channel, or undefined if the key is not predefined or the catalog is inconsistent.
|
|
165
566
|
*/
|
|
166
|
-
export declare function getPredefinedChannel(key: string):
|
|
567
|
+
export declare function getPredefinedChannel(key: string): ResolvedChannel | undefined;
|
|
167
568
|
/**
|
|
168
569
|
* Checks if a channel key exists in the predefined channels.
|
|
169
570
|
* @param key - The channel key to check.
|
|
@@ -215,7 +616,7 @@ export declare function getChannelLogo(channelKey: string): string | undefined;
|
|
|
215
616
|
*/
|
|
216
617
|
export declare function isUserChannel(key: string): boolean;
|
|
217
618
|
/**
|
|
218
|
-
* Checks if a predefined channel is disabled. The disabled state is determined solely by the disabledPredefined list in config
|
|
619
|
+
* Checks if a predefined channel is disabled. The disabled state is determined solely by the disabledPredefined list in config - the user's explicit visibility
|
|
219
620
|
* intent. Property overrides (HDHR toggle, name change, tag edits) stored as deltas in channels.json are orthogonal and do not affect the enabled/disabled state.
|
|
220
621
|
* @param key - The channel key to check.
|
|
221
622
|
* @returns True if the channel is predefined and disabled.
|
|
@@ -226,6 +627,38 @@ export declare function isPredefinedChannelDisabled(key: string): boolean;
|
|
|
226
627
|
* @returns Array of disabled channel keys.
|
|
227
628
|
*/
|
|
228
629
|
export declare function getDisabledPredefinedChannels(): string[];
|
|
630
|
+
/**
|
|
631
|
+
* Disables one or more predefined channels by adding their keys to the disabledPredefined list in user config. Idempotent.
|
|
632
|
+
* @param keys - The predefined channel keys to disable. Duplicates within the input array and pre-existing disabled entries are handled idempotently.
|
|
633
|
+
*/
|
|
634
|
+
export declare function disablePredefinedChannels(keys: readonly string[]): Promise<void>;
|
|
635
|
+
/**
|
|
636
|
+
* Enables one or more predefined channels by removing their keys from the disabledPredefined list in user config. Idempotent.
|
|
637
|
+
* @param keys - The predefined channel keys to enable. Entries that aren't in the disabled list are ignored.
|
|
638
|
+
*/
|
|
639
|
+
export declare function enablePredefinedChannels(keys: readonly string[]): Promise<void>;
|
|
640
|
+
/**
|
|
641
|
+
* Persists a partial update of channel-table display preferences (sort field, sort direction, visible columns) to config.json. Only fields present in `prefs`
|
|
642
|
+
* are written; absent fields are left untouched. The mutate fn copies the new values into data and the runtime CONFIG cache is updated post-write to match.
|
|
643
|
+
* Single-call replacement for the prior set-then-save pattern, consistent with mutateServiceSelections, mutateEnabledServices, and setTagRegistry.
|
|
644
|
+
* @param prefs - Subset of display preferences to update.
|
|
645
|
+
* @throws FileStoreParseError if config.json contains invalid JSON and the .bak rotation is also unparseable.
|
|
646
|
+
*/
|
|
647
|
+
export declare function mutateChannelDisplayPrefs(prefs: {
|
|
648
|
+
channelSortDirection?: SortDirection;
|
|
649
|
+
channelSortField?: ChannelSortField;
|
|
650
|
+
visibleColumns?: readonly string[];
|
|
651
|
+
}): Promise<void>;
|
|
652
|
+
/**
|
|
653
|
+
* Marks the first-run Service Setup wizard as completed. Writes the flag to runtime CONFIG and persists to config.json in one call - the operation is a single
|
|
654
|
+
* one-way transition (setupCompleted goes from false/absent to true once, never back), so splitting into set+save would be ceremony without benefit.
|
|
655
|
+
*
|
|
656
|
+
* Persistence note: setupCompleted is intentionally absent from CONFIG_METADATA and PRESERVED_FIELDS in userConfig.ts, so filterDefaults strips it from the
|
|
657
|
+
* on-disk shape during the write below. This is by design - the flag is observably derived from "has the user configured any services or channels" and
|
|
658
|
+
* initializeUserChannels() re-infers it at startup from that observable state. The mutateConfig call here is a no-op on the file but keeps the runtime
|
|
659
|
+
* mutation pathway uniform with every other CONFIG.channels writer; the flag survives across restarts via inference, not persistence.
|
|
660
|
+
*/
|
|
661
|
+
export declare function markSetupCompleted(): Promise<void>;
|
|
229
662
|
/**
|
|
230
663
|
* Returns all predefined channels regardless of disabled state, excluding service variants. Used by the UI to show all predefined channels including disabled ones.
|
|
231
664
|
* Service variants are internal implementation details of channel delivery and are not channels themselves.
|
|
@@ -321,14 +754,40 @@ export interface ChannelsValidationResult {
|
|
|
321
754
|
*/
|
|
322
755
|
export declare function validateImportedChannels(data: unknown, validProfiles: string[]): ChannelsValidationResult;
|
|
323
756
|
/**
|
|
324
|
-
*
|
|
325
|
-
*
|
|
326
|
-
*
|
|
327
|
-
|
|
328
|
-
|
|
329
|
-
|
|
330
|
-
|
|
331
|
-
|
|
332
|
-
|
|
333
|
-
|
|
334
|
-
|
|
757
|
+
* Sorts tags case-insensitively using locale-aware comparison. This is the single source of truth for tag ordering. Every write path (parseTagInput, PATCH
|
|
758
|
+
* handlers, computePredefinedDelta, transformChannelTags, setTagRegistry) routes through this so stored tag arrays share one canonical ordering. The channels
|
|
759
|
+
* normalizer is a READER of that invariant - it uses sortTags on both sides when comparing a delta's tags against a predefined's tags, making the JSON.stringify
|
|
760
|
+
* equality check canonical regardless of how either side was originally populated.
|
|
761
|
+
* @param tags - Any iterable of tag strings (array, Set, generator). Not mutated.
|
|
762
|
+
* @returns A new array with the same elements in canonical case-insensitive order.
|
|
763
|
+
*/
|
|
764
|
+
export declare function sortTags(tags: Iterable<string>): string[];
|
|
765
|
+
/**
|
|
766
|
+
* Parses a comma-separated tag input string into a normalized tag array. Trims whitespace, drops empty entries, deduplicates case-sensitively via Set (so
|
|
767
|
+
* distinct casings survive as distinct tags), then sorts via sortTags so every caller produces identical normalized arrays.
|
|
768
|
+
* @param raw - The comma-separated tag input from a form field or inline editor. An empty or whitespace-only string returns an empty array.
|
|
769
|
+
* @returns Sorted, case-sensitively-deduplicated array of trimmed tag strings.
|
|
770
|
+
*/
|
|
771
|
+
export declare function parseTagInput(raw: string): string[];
|
|
772
|
+
export declare const __internalForTests: {
|
|
773
|
+
applyOverlayKernel: typeof applyOverlayKernel;
|
|
774
|
+
buildResolvedCanonicals: typeof buildResolvedCanonicals;
|
|
775
|
+
channelsMigrations: Record<number, Migration<ChannelsFileData>>;
|
|
776
|
+
classifyEntry: typeof classifyEntry;
|
|
777
|
+
collectLegacyVariantStamps: typeof collectLegacyVariantStamps;
|
|
778
|
+
detectIdentityFieldLoss: typeof detectIdentityFieldLoss;
|
|
779
|
+
filterToDeltaSurface: typeof filterToDeltaSurface;
|
|
780
|
+
getAllowedFieldsForShape: typeof getAllowedFieldsForShape;
|
|
781
|
+
getMergedChannelMap: typeof getMergedChannelMap;
|
|
782
|
+
normalizeChannelDeltas: typeof normalizeChannelDeltas;
|
|
783
|
+
normalizeEntryAgainstBase: typeof normalizeEntryAgainstBase;
|
|
784
|
+
overlayDelta: typeof overlayDelta;
|
|
785
|
+
overlayVariantBinding: typeof overlayVariantBinding;
|
|
786
|
+
parseChannelsFile: typeof parseChannelsFile;
|
|
787
|
+
prepareChannelsForWrite: typeof prepareChannelsForWrite;
|
|
788
|
+
resolveVariant: typeof resolveVariant;
|
|
789
|
+
stripNulls: typeof stripNulls;
|
|
790
|
+
validateChannelsIntegrity: typeof validateChannelsIntegrity;
|
|
791
|
+
warnDanglingCanonical: typeof warnDanglingCanonical;
|
|
792
|
+
};
|
|
793
|
+
export {};
|