prismcast 1.13.0 → 1.14.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 +88 -6
- package/dist/app.js +287 -154
- package/dist/app.js.map +1 -1
- package/dist/browser/cdp.d.ts +6 -17
- package/dist/browser/cdp.js +6 -57
- package/dist/browser/cdp.js.map +1 -1
- package/dist/browser/index.d.ts +106 -23
- package/dist/browser/index.js +292 -225
- package/dist/browser/index.js.map +1 -1
- package/dist/browser/precaching.d.ts +25 -11
- package/dist/browser/precaching.js +245 -97
- package/dist/browser/precaching.js.map +1 -1
- package/dist/browser/tabCapture.js +3 -10
- package/dist/browser/tabCapture.js.map +1 -1
- package/dist/browser/tuning/comcastPolymer.js +13 -14
- package/dist/browser/tuning/comcastPolymer.js.map +1 -1
- package/dist/browser/tuning/hbo.js +34 -17
- package/dist/browser/tuning/hbo.js.map +1 -1
- package/dist/browser/video.d.ts +1 -1
- package/dist/browser/video.js +3 -3
- package/dist/channels/index.js +5 -5
- package/dist/channels/index.js.map +1 -1
- package/dist/cliHelp.d.ts +11 -0
- package/dist/cliHelp.js +148 -0
- package/dist/cliHelp.js.map +1 -0
- package/dist/config/channelForm.js +5 -4
- package/dist/config/channelForm.js.map +1 -1
- package/dist/config/consistencyProbe.d.ts +2 -4
- package/dist/config/consistencyProbe.js +8 -51
- package/dist/config/consistencyProbe.js.map +1 -1
- package/dist/config/index.d.ts +107 -55
- package/dist/config/index.js +499 -267
- package/dist/config/index.js.map +1 -1
- package/dist/config/paths.d.ts +13 -8
- package/dist/config/paths.js +21 -25
- package/dist/config/paths.js.map +1 -1
- package/dist/config/persistence.d.ts +57 -11
- package/dist/config/persistence.js +127 -44
- package/dist/config/persistence.js.map +1 -1
- package/dist/config/reactivity.d.ts +60 -36
- package/dist/config/reactivity.js +89 -116
- package/dist/config/reactivity.js.map +1 -1
- package/dist/config/services.d.ts +61 -26
- package/dist/config/services.js +137 -68
- package/dist/config/services.js.map +1 -1
- package/dist/config/streamSettings.d.ts +24 -0
- package/dist/config/streamSettings.js +17 -0
- package/dist/config/streamSettings.js.map +1 -0
- package/dist/config/userChannels.d.ts +60 -52
- package/dist/config/userChannels.js +138 -188
- package/dist/config/userChannels.js.map +1 -1
- package/dist/config/userConfig.d.ts +224 -61
- package/dist/config/userConfig.js +351 -134
- package/dist/config/userConfig.js.map +1 -1
- package/dist/hdhr/discover.d.ts +7 -1
- package/dist/hdhr/discover.js +12 -6
- package/dist/hdhr/discover.js.map +1 -1
- package/dist/hdhr/index.d.ts +51 -10
- package/dist/hdhr/index.js +108 -112
- package/dist/hdhr/index.js.map +1 -1
- package/dist/hdhr/udp.d.ts +11 -4
- package/dist/hdhr/udp.js +25 -20
- package/dist/hdhr/udp.js.map +1 -1
- package/dist/index.js +16 -143
- package/dist/index.js.map +1 -1
- package/dist/native/index.d.ts +1 -1
- package/dist/native/index.js +4 -3
- package/dist/native/index.js.map +1 -1
- package/dist/native/proxy.d.ts +1 -1
- package/dist/native/proxy.js +36 -28
- package/dist/native/proxy.js.map +1 -1
- package/dist/routes/cdp.d.ts +7 -6
- package/dist/routes/cdp.js +9 -8
- package/dist/routes/cdp.js.map +1 -1
- package/dist/routes/components.d.ts +23 -5
- package/dist/routes/components.js +21 -4
- package/dist/routes/components.js.map +1 -1
- package/dist/routes/config/channels/endpoints/browse.js +39 -29
- package/dist/routes/config/channels/endpoints/browse.js.map +1 -1
- package/dist/routes/config/channels/endpoints/bulk.js +2 -6
- package/dist/routes/config/channels/endpoints/bulk.js.map +1 -1
- package/dist/routes/config/channels/endpoints/predefined.js +5 -15
- package/dist/routes/config/channels/endpoints/predefined.js.map +1 -1
- package/dist/routes/config/channels/endpoints/prefs.js +7 -6
- package/dist/routes/config/channels/endpoints/prefs.js.map +1 -1
- package/dist/routes/config/channels/endpoints/service.js +6 -5
- package/dist/routes/config/channels/endpoints/service.js.map +1 -1
- package/dist/routes/config/channels/endpoints/tags.js +4 -16
- package/dist/routes/config/channels/endpoints/tags.js.map +1 -1
- package/dist/routes/config/channels/table.d.ts +2 -1
- package/dist/routes/config/channels/table.js +11 -13
- package/dist/routes/config/channels/table.js.map +1 -1
- package/dist/routes/config/http/envelope.d.ts +6 -3
- package/dist/routes/config/http/envelope.js +18 -5
- package/dist/routes/config/http/envelope.js.map +1 -1
- package/dist/routes/config/index.d.ts +21 -13
- package/dist/routes/config/index.js +47 -34
- package/dist/routes/config/index.js.map +1 -1
- package/dist/routes/config/settings.d.ts +43 -6
- package/dist/routes/config/settings.js +225 -125
- package/dist/routes/config/settings.js.map +1 -1
- package/dist/routes/config/vocabulary.d.ts +24 -0
- package/dist/routes/config/vocabulary.js +33 -0
- package/dist/routes/config/vocabulary.js.map +1 -0
- package/dist/routes/debug.js +28 -13
- package/dist/routes/debug.js.map +1 -1
- package/dist/routes/root/content.js +33 -26
- package/dist/routes/root/content.js.map +1 -1
- package/dist/routes/root/scripts/channels.js +23 -11
- package/dist/routes/root/scripts/channels.js.map +1 -1
- package/dist/routes/root/scripts/config.d.ts +1 -1
- package/dist/routes/root/scripts/config.js +127 -79
- package/dist/routes/root/scripts/config.js.map +1 -1
- package/dist/routes/root/scripts/shared.js +34 -23
- package/dist/routes/root/scripts/shared.js.map +1 -1
- package/dist/routes/root/scripts/status.handlers.d.ts +8 -13
- package/dist/routes/root/scripts/status.handlers.js +35 -21
- package/dist/routes/root/scripts/status.handlers.js.map +1 -1
- package/dist/routes/root/styles.js +13 -16
- package/dist/routes/root/styles.js.map +1 -1
- package/dist/routes/services.js +12 -16
- package/dist/routes/services.js.map +1 -1
- package/dist/routes/theme.js +12 -12
- package/dist/routes/theme.js.map +1 -1
- package/dist/routes/ui.d.ts +4 -3
- package/dist/routes/ui.js +17 -13
- package/dist/routes/ui.js.map +1 -1
- package/dist/service/generators.js +12 -9
- package/dist/service/generators.js.map +1 -1
- package/dist/streaming/captureSession.d.ts +4 -4
- package/dist/streaming/captureSession.js +6 -7
- package/dist/streaming/captureSession.js.map +1 -1
- package/dist/streaming/codec.d.ts +12 -2
- package/dist/streaming/codec.js +40 -28
- package/dist/streaming/codec.js.map +1 -1
- package/dist/streaming/fmp4Segmenter.d.ts +14 -4
- package/dist/streaming/fmp4Segmenter.js +99 -79
- package/dist/streaming/fmp4Segmenter.js.map +1 -1
- package/dist/streaming/hls.d.ts +21 -14
- package/dist/streaming/hls.js +148 -122
- package/dist/streaming/hls.js.map +1 -1
- package/dist/streaming/hlsResume.d.ts +36 -13
- package/dist/streaming/hlsResume.js +68 -37
- package/dist/streaming/hlsResume.js.map +1 -1
- package/dist/streaming/monitor.d.ts +5 -3
- package/dist/streaming/monitor.js +47 -37
- package/dist/streaming/monitor.js.map +1 -1
- package/dist/streaming/mp4Parser.d.ts +29 -4
- package/dist/streaming/mp4Parser.js +49 -7
- package/dist/streaming/mp4Parser.js.map +1 -1
- package/dist/streaming/playlistBuilder.d.ts +1 -2
- package/dist/streaming/playlistBuilder.js +2 -3
- package/dist/streaming/playlistBuilder.js.map +1 -1
- package/dist/streaming/preroll.d.ts +43 -16
- package/dist/streaming/preroll.js +112 -62
- package/dist/streaming/preroll.js.map +1 -1
- package/dist/streaming/pretune.d.ts +2 -2
- package/dist/streaming/pretune.js +11 -7
- package/dist/streaming/pretune.js.map +1 -1
- package/dist/streaming/recovery.d.ts +29 -2
- package/dist/streaming/recovery.js +43 -4
- package/dist/streaming/recovery.js.map +1 -1
- package/dist/streaming/registry.d.ts +13 -10
- package/dist/streaming/registry.js +6 -5
- package/dist/streaming/registry.js.map +1 -1
- package/dist/streaming/setup.d.ts +29 -20
- package/dist/streaming/setup.js +181 -170
- package/dist/streaming/setup.js.map +1 -1
- package/dist/streaming/showInfo.d.ts +24 -12
- package/dist/streaming/showInfo.js +120 -113
- package/dist/streaming/showInfo.js.map +1 -1
- package/dist/streaming/statusEmitter.d.ts +15 -10
- package/dist/streaming/statusEmitter.js +24 -20
- package/dist/streaming/statusEmitter.js.map +1 -1
- package/dist/types/config.d.ts +24 -13
- package/dist/types/config.js +5 -1
- package/dist/types/config.js.map +1 -1
- package/dist/types/index.d.ts +3 -2
- package/dist/types/index.js +2 -1
- package/dist/types/index.js.map +1 -1
- package/dist/types/profiles.d.ts +2 -2
- package/dist/types/selection.d.ts +12 -10
- package/dist/types/streaming.d.ts +12 -5
- package/dist/types/streaming.js +12 -5
- package/dist/types/streaming.js.map +1 -1
- package/dist/utils/debugFilter.d.ts +3 -2
- package/dist/utils/debugFilter.js +7 -5
- package/dist/utils/debugFilter.js.map +1 -1
- package/dist/{hdhr → utils}/deviceId.d.ts +1 -1
- package/dist/{hdhr → utils}/deviceId.js +11 -29
- package/dist/utils/deviceId.js.map +1 -0
- package/dist/utils/errors.d.ts +7 -0
- package/dist/utils/errors.js +12 -3
- package/dist/utils/errors.js.map +1 -1
- package/dist/utils/fileLogger.d.ts +23 -12
- package/dist/utils/fileLogger.js +73 -41
- package/dist/utils/fileLogger.js.map +1 -1
- package/dist/utils/httpErrors.d.ts +13 -0
- package/dist/utils/httpErrors.js +22 -0
- package/dist/utils/httpErrors.js.map +1 -0
- package/dist/utils/index.d.ts +3 -0
- package/dist/utils/index.js +3 -0
- package/dist/utils/index.js.map +1 -1
- package/dist/utils/logger.d.ts +9 -8
- package/dist/utils/logger.js +64 -20
- package/dist/utils/logger.js.map +1 -1
- package/dist/utils/markup.js +8 -3
- package/dist/utils/markup.js.map +1 -1
- package/dist/utils/plainObject.d.ts +6 -0
- package/dist/utils/plainObject.js +18 -0
- package/dist/utils/plainObject.js.map +1 -0
- package/dist/utils/runtimeIdentity.context.js +1 -29
- package/dist/utils/runtimeIdentity.context.js.map +1 -1
- package/dist/utils/runtimeIdentity.d.ts +17 -6
- package/dist/utils/runtimeIdentity.js +50 -17
- package/dist/utils/runtimeIdentity.js.map +1 -1
- package/package.json +5 -5
- package/dist/hdhr/deviceId.js.map +0 -1
|
@@ -7,46 +7,19 @@
|
|
|
7
7
|
*
|
|
8
8
|
* - Variant entries with a canonicalKey (in channels.json) reference a canonical that exists in PREDEFINED_CHANNELS or the user's stored channels.
|
|
9
9
|
* - User domain mappings (in profiles.json) reference profiles that exist as builtin or user-defined.
|
|
10
|
-
* - The service tag filter (in config.json's channels.enabledServices) contains only recognized service tags.
|
|
11
10
|
*
|
|
12
|
-
*
|
|
13
|
-
*
|
|
11
|
+
* The probe reports what an operator must act on and changes nothing: each issue is logged, because the right repair depends on what the operator intended. A
|
|
12
|
+
* rule the running process can enforce on its own belongs where the process applies it - an unknown service tag never reaches the running filter because the
|
|
13
|
+
* services module restricts the filter itself - rather than here.
|
|
14
14
|
*
|
|
15
15
|
* Adding a new check is a single function returning ConsistencyIssue[]; collectConsistencyIssues calls each registered check function and aggregates the
|
|
16
16
|
* results into one array.
|
|
17
17
|
*/
|
|
18
|
-
import { LOG, formatError } from "../utils/index.js";
|
|
19
|
-
import { getAllServiceTags, mutateEnabledServices } from "./services.js";
|
|
20
18
|
import { getUserDomains, getUserProfiles } from "./userProfiles.js";
|
|
21
|
-
import {
|
|
19
|
+
import { LOG } from "../utils/index.js";
|
|
22
20
|
import { PREDEFINED_CHANNELS } from "../channels/index.js";
|
|
23
21
|
import { getBuiltinProfile } from "./sites.js";
|
|
24
22
|
import { getStoredUserChannels } from "./userChannels.js";
|
|
25
|
-
/**
|
|
26
|
-
* Validates that every service tag in CONFIG.channels.enabledServices is recognized, and when unknown tags remain its auto-fix persists the cleaned list through
|
|
27
|
-
* mutateEnabledServices. In practice initializeUserChannels already strips unrecognized tags from the in-memory CONFIG.channels.enabledServices before the probe
|
|
28
|
-
* runs - a memory-only cleanup that does not rewrite config.json - so the probe usually sees a clean list and the persisting auto-fix does not fire.
|
|
29
|
-
*/
|
|
30
|
-
function checkServiceTagFilter() {
|
|
31
|
-
if (CONFIG.channels.enabledServices.length === 0) {
|
|
32
|
-
return [];
|
|
33
|
-
}
|
|
34
|
-
const knownTags = new Set(getAllServiceTags().map((tag) => tag.tag));
|
|
35
|
-
const enabledSet = new Set(CONFIG.channels.enabledServices);
|
|
36
|
-
const invalid = [...enabledSet.difference(knownTags)];
|
|
37
|
-
if (invalid.length === 0) {
|
|
38
|
-
return [];
|
|
39
|
-
}
|
|
40
|
-
return [{
|
|
41
|
-
autoFix: async () => {
|
|
42
|
-
// mutateEnabledServices persists the cleaned list to config.json and updates the in-memory cache atomically.
|
|
43
|
-
await mutateEnabledServices([...enabledSet.intersection(knownTags)]);
|
|
44
|
-
},
|
|
45
|
-
category: "unknown-service-tag",
|
|
46
|
-
description: "Service filter contains unrecognized tag(s): " + invalid.join(", "),
|
|
47
|
-
severity: "warning"
|
|
48
|
-
}];
|
|
49
|
-
}
|
|
50
23
|
/**
|
|
51
24
|
* Validates that every variant entry's canonicalKey points at a channel that exists either in the predefined catalog or the user's stored channels. Dangling
|
|
52
25
|
* canonical references usually mean the user deleted the canonical without cleaning the variants up; we surface for operator action rather than auto-fixing
|
|
@@ -101,16 +74,13 @@ function checkDomainProfiles() {
|
|
|
101
74
|
*/
|
|
102
75
|
function collectConsistencyIssues() {
|
|
103
76
|
return [
|
|
104
|
-
...checkServiceTagFilter(),
|
|
105
77
|
...checkVariantCanonicals(),
|
|
106
78
|
...checkDomainProfiles()
|
|
107
79
|
];
|
|
108
80
|
}
|
|
109
81
|
/**
|
|
110
|
-
* Runs the consistency probe at startup. Logs every issue
|
|
111
|
-
* - a consistency error is recoverable runtime state, not an unbootable system.
|
|
112
|
-
*
|
|
113
|
-
* Auto-fix failures are themselves logged but do not propagate. The probe is best-effort hygiene; a failure here must not bring down the server.
|
|
82
|
+
* Runs the consistency probe at startup. Logs every issue at its severity and changes nothing, so an operator sees in the log what needs their action before the
|
|
83
|
+
* next restart. Errors do not block startup - a consistency error is recoverable runtime state, not an unbootable system.
|
|
114
84
|
*/
|
|
115
85
|
export async function runConsistencyProbeAtStartup() {
|
|
116
86
|
const issues = collectConsistencyIssues();
|
|
@@ -119,8 +89,7 @@ export async function runConsistencyProbeAtStartup() {
|
|
|
119
89
|
}
|
|
120
90
|
for (const issue of issues) {
|
|
121
91
|
const message = "Consistency probe (" + issue.category + ", " + issue.severity + "): " + issue.description;
|
|
122
|
-
//
|
|
123
|
-
// attention rather than auto-cleanup can mark itself error and surface accordingly. Add a test to assert this behavior once an error-severity check exists.
|
|
92
|
+
// An error-severity issue is logged at error, so a check whose issue needs the operator before the next restart surfaces accordingly.
|
|
124
93
|
if (issue.severity === "error") {
|
|
125
94
|
LOG.error(message);
|
|
126
95
|
}
|
|
@@ -128,19 +97,7 @@ export async function runConsistencyProbeAtStartup() {
|
|
|
128
97
|
LOG.warn(message);
|
|
129
98
|
}
|
|
130
99
|
}
|
|
131
|
-
//
|
|
132
|
-
// and look up each settlement by index (length-paired by construction; Promise.allSettled preserves input order and arity), logging rejected reasons as
|
|
133
|
-
// warnings while leaving successful fixes intact.
|
|
134
|
-
const eligible = issues.filter((issue) => (issue.severity === "warning") && issue.autoFix);
|
|
135
|
-
const results = await Promise.allSettled(eligible.map(async (issue) => issue.autoFix?.()));
|
|
136
|
-
for (const [index, issue] of eligible.entries()) {
|
|
137
|
-
const result = results[index];
|
|
138
|
-
if (result?.status === "rejected") {
|
|
139
|
-
LOG.warn("Consistency probe auto-fix failed for %s: %s.", issue.category, formatError(result.reason));
|
|
140
|
-
}
|
|
141
|
-
}
|
|
142
|
-
// Defensive: paired with the per-issue severity dispatch above. No checker currently emits severity:"error", so this aggregate report is unreachable today;
|
|
143
|
-
// it remains in place so a future error-severity check produces the operator-visible summary line without any further wiring.
|
|
100
|
+
// Paired with the per-issue severity dispatch above: any error-severity issue also produces one operator-visible summary line counting them.
|
|
144
101
|
const errors = issues.filter((issue) => issue.severity === "error").length;
|
|
145
102
|
if (errors > 0) {
|
|
146
103
|
LOG.error("Consistency probe found %d error(s) requiring operator review.", errors);
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"consistencyProbe.js","sourceRoot":"","sources":["../../src/config/consistencyProbe.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;;;;;GAgBG;AACH,OAAO,EAAE,
|
|
1
|
+
{"version":3,"file":"consistencyProbe.js","sourceRoot":"","sources":["../../src/config/consistencyProbe.ts"],"names":[],"mappings":"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"}
|
package/dist/config/index.d.ts
CHANGED
|
@@ -1,16 +1,25 @@
|
|
|
1
|
-
import type { ApplyResult,
|
|
1
|
+
import type { ApplyResult, ChangeRejection, ConfigChange, ConfigChangePartition } from "./reactivity.ts";
|
|
2
|
+
import { mutateConfigThen, readConfig } from "./userConfig.ts";
|
|
3
|
+
import type { ProcessFieldPath, UserConfig } from "./userConfig.ts";
|
|
2
4
|
import type { Config, Nullable } from "../types/index.ts";
|
|
3
|
-
import { mutateConfig, readConfig } from "./userConfig.ts";
|
|
4
5
|
/**
|
|
5
6
|
* CLI override map. Keys are dot-separated CONFIG_METADATA paths (e.g., "server.port", "paths.chromeDataDir"). Values are the parsed CLI flag values. Applied as the
|
|
6
7
|
* highest-priority merge pass in mergeConfiguration().
|
|
7
8
|
*/
|
|
8
9
|
export type CliOverrides = Record<string, unknown>;
|
|
9
10
|
export interface ConfigStore {
|
|
10
|
-
readonly
|
|
11
|
+
readonly mutateConfigThen: typeof mutateConfigThen;
|
|
11
12
|
readonly readConfig: typeof readConfig;
|
|
12
13
|
}
|
|
13
14
|
export declare let CONFIG: Config;
|
|
15
|
+
/**
|
|
16
|
+
* The error a save throws when the configuration it would write fails validation. The store writes nothing when its mutation throws, so the file, the running
|
|
17
|
+
* configuration and the loaded snapshot all stay as they were. Its message is the validation reason alone, complete sentences an operator can act on, so a
|
|
18
|
+
* route answers it as the validation error it is.
|
|
19
|
+
*/
|
|
20
|
+
export declare class ConfigurationRejectedError extends Error {
|
|
21
|
+
name: string;
|
|
22
|
+
}
|
|
14
23
|
/**
|
|
15
24
|
* Indicates whether a user config file parse error occurred during initialization. The web UI displays a warning when this is true.
|
|
16
25
|
*/
|
|
@@ -21,69 +30,121 @@ export declare let configParseError: boolean;
|
|
|
21
30
|
export declare let configParseErrorMessage: string | undefined;
|
|
22
31
|
/**
|
|
23
32
|
* Initializes the configuration by loading the user config file, merging with defaults, applying environment variable overrides, and applying CLI overrides. This
|
|
24
|
-
* must be called at startup before any code accesses CONFIG. After initialization, the CONFIG object contains the final merged values.
|
|
33
|
+
* must be called at startup before any code accesses CONFIG. After initialization, the CONFIG object contains the final merged values. A file whose stored
|
|
34
|
+
* capture values need a correction, or whose HDHomeRun DeviceID the boot corrected, is written once through the store, the one write storing every correction
|
|
35
|
+
* the file needs, unless the store could not read the file or the configuration carries a hard error.
|
|
25
36
|
* @param cliOverrides - Optional CLI flag overrides, applied at the highest priority level.
|
|
37
|
+
* @param io - The config store the boot reads from and makes its one correcting write through.
|
|
26
38
|
*/
|
|
27
39
|
export declare function initializeConfiguration(cliOverrides?: CliOverrides, io?: ConfigStore): Promise<void>;
|
|
28
40
|
/**
|
|
29
|
-
*
|
|
30
|
-
*
|
|
31
|
-
*
|
|
32
|
-
*
|
|
33
|
-
|
|
34
|
-
|
|
35
|
-
|
|
36
|
-
*
|
|
37
|
-
*
|
|
41
|
+
* Returns the loaded snapshot: the configuration file as last loaded, merged and normalized exactly as the next boot would read it. Where it differs from CONFIG,
|
|
42
|
+
* the running process does not yet reflect the file. The settings form renders from it, so a page loaded after a save shows what is saved rather than what is
|
|
43
|
+
* running, and submitting that page cannot post the running value back over a change waiting for a restart.
|
|
44
|
+
* @returns The loaded snapshot. Callers read it and never mutate it.
|
|
45
|
+
*/
|
|
46
|
+
export declare function getLoadedConfiguration(): Readonly<Config>;
|
|
47
|
+
/**
|
|
48
|
+
* Answers which saved settings the running process does not yet reflect: the gap between CONFIG and the loaded snapshot, partitioned by reactivity class. Its
|
|
49
|
+
* held members are the settings pending a restart, and its live and next-stream members are the settings a handler could not realize. The view covers the
|
|
50
|
+
* settings surface alone, the paths CONFIG_METADATA declares, because a leaf the process wrote and the loaded snapshot does not hold, which only a process
|
|
51
|
+
* write the file refused leaves, is the process ahead of the file rather than a save the user is waiting on. Derived on every call from CONFIG and the loaded
|
|
52
|
+
* snapshot, so it holds no state of its own. A reconcile publishes the snapshot only once it has committed what its handlers realized, so a caller that does
|
|
53
|
+
* not wait on the store's queue reads CONFIG and the snapshot as the last completed reconcile left them, and a change a save introduces is never listed as
|
|
54
|
+
* unrealized while its handlers are still running.
|
|
55
|
+
* @returns The settings-surface gap, partitioned into held, live, and next-stream changes, each carrying the running value as previous and the saved value as
|
|
56
|
+
* current.
|
|
57
|
+
*/
|
|
58
|
+
export declare function getConfigurationGap(): ConfigChangePartition;
|
|
59
|
+
/**
|
|
60
|
+
* The one entry for a write to the settings surface - the settings save, the import, and the debug page all go through it. Inside the store's own mutation it
|
|
61
|
+
* applies the caller's mutator to the current file, builds the candidate exactly as the next boot would read that file, and refuses an invalid candidate by
|
|
62
|
+
* throwing ConfigurationRejectedError with the validation reason, so the store writes nothing. A file the store cannot parse or cannot read refuses the
|
|
63
|
+
* mutation inside the store the same way. Once the file is written, the save reconciles that candidate as the write's follow-up and answers with its result.
|
|
38
64
|
*
|
|
39
|
-
*
|
|
40
|
-
*
|
|
41
|
-
*
|
|
42
|
-
*
|
|
43
|
-
*
|
|
65
|
+
* One queue: the store's chain serializes each write's read-modify-write together with its follow-up, a save's reconcile or a process write's commit, which
|
|
66
|
+
* runs while the store's queue is held, so no write reads the file while another write's reconcile or commit is running, and overlapping saves commit in the
|
|
67
|
+
* order their writes landed. A config-change handler never writes the configuration, because the reconcile or the process write's commit it runs inside holds
|
|
68
|
+
* the store's queue, and a write it awaited would wait on that queue and never settle.
|
|
69
|
+
* @param mutator - Applies the caller's change to the current file in place. A throw inside it writes nothing.
|
|
70
|
+
* @param io - The config store the save writes through.
|
|
71
|
+
* @returns What the reconcile realized, the restart-class changes this save holds for a restart, and the changes of this save a handler refused.
|
|
72
|
+
* @throws ConfigurationRejectedError when the candidate fails validation, and the store's own error when the file cannot be parsed, read, or written.
|
|
73
|
+
*/
|
|
74
|
+
export declare function saveConfiguration(mutator: (current: UserConfig) => void, io?: ConfigStore): Promise<ApplyResult>;
|
|
75
|
+
/**
|
|
76
|
+
* The leaves a process write answers, keyed by the dot path of a field the process owns, so a path PROCESS_FIELDS does not declare as a state field is a
|
|
77
|
+
* compile error.
|
|
78
|
+
*/
|
|
79
|
+
export type ProcessFieldValues = Readonly<Partial<Record<ProcessFieldPath, unknown>>>;
|
|
80
|
+
/**
|
|
81
|
+
* What a process write answers: whether the file took the write. The running configuration holds the leaves whatever the file did, so persisted false means
|
|
82
|
+
* the change is in effect but reverts when the process restarts, which a caller acting for the user reports to them.
|
|
83
|
+
*/
|
|
84
|
+
export interface ProcessWriteResult {
|
|
85
|
+
readonly persisted: boolean;
|
|
86
|
+
}
|
|
87
|
+
/**
|
|
88
|
+
* The operation for every field the process owns, the leaves the settings form never writes: the setup flag, the disabled predefined channels, the display
|
|
89
|
+
* preferences, the service list, and the discovered DVR host. Inside the store's own mutation it answers the leaves from the file the store just read and sets
|
|
90
|
+
* each on that file, and once the write has landed its follow-up commits exactly those leaves: their handlers are dispatched whatever CONFIG held before, and
|
|
91
|
+
* each leaf is set on CONFIG and then on the loaded snapshot. It builds no candidate and validates nothing beyond the store's own write normalization, because
|
|
92
|
+
* the process already holds the values it writes, and every other difference between CONFIG and the file, a hand edit or a refused setting among them, stays
|
|
93
|
+
* for the next settings save to reconcile and report.
|
|
44
94
|
*
|
|
45
|
-
*
|
|
46
|
-
*
|
|
47
|
-
*
|
|
48
|
-
*
|
|
49
|
-
*
|
|
50
|
-
|
|
51
|
-
export declare function reloadConfiguration(io?: ConfigStore): Promise<ApplyResult>;
|
|
52
|
-
/**
|
|
53
|
-
* Live-applies the "logging." subset of a config diff. The debug filter is applied live by commitDebugFilter during reloadConfiguration - the runtime filter is
|
|
54
|
-
* updated right after CONFIG is committed and before the diff dispatches - so it reports applied with no restart, which is what lets a debug-filter change take
|
|
55
|
-
* effect immediately instead of waiting for one. The remaining logging fields (httpLogLevel, maxSize) are consumed when the logger and HTTP middleware are wired
|
|
56
|
-
* at startup, so they defer to a restart.
|
|
95
|
+
* When the store refuses the write - it could not read or parse the file, or the callback, the write, or its readback failed - the leaves are answered again
|
|
96
|
+
* from the running configuration, one warning names them with the store's error, and they are committed to CONFIG alone; the operation resolves with persisted
|
|
97
|
+
* false, because the process owns the value and the file is only its record. The warning comes before the commit so a commit that throws propagates with the
|
|
98
|
+
* store's error already on record. A readback that fails is such a refusal though the file may hold the leaves, and the loaded snapshot takes them at the
|
|
99
|
+
* next settings save that lands. A rejection that arrives once the follow-up has begun is rethrown instead, because that write has landed: committing and
|
|
100
|
+
* dispatching the leaves a second time would log a refusal the file never made.
|
|
57
101
|
*
|
|
58
|
-
*
|
|
59
|
-
*
|
|
60
|
-
*
|
|
102
|
+
* A caller's fields answers from its argument alone and changes nothing it reaches, because it may run twice, once on the file the store read and once on the
|
|
103
|
+
* clone of CONFIG the refused path hands it, and Readonly holds only its argument's top level. A handler for a process field never writes the configuration,
|
|
104
|
+
* because the commit it runs inside holds the store's queue; a handler that refuses a process leaf leaves it committed regardless.
|
|
105
|
+
* @param fields - Answers the leaves to write, keyed by path, from the stored configuration it is handed.
|
|
106
|
+
* @param io - The config store the write goes through.
|
|
107
|
+
* @returns Whether the file took the write: persisted is true once the write has landed and false when the store refused it.
|
|
108
|
+
* @throws Whatever a follow-up that has begun rejects with, such as the class resolver's error for a leaf no setting or state entry classifies, and whatever
|
|
109
|
+
* the refused path's commit throws once its warning is logged.
|
|
61
110
|
*/
|
|
62
|
-
export declare function
|
|
111
|
+
export declare function writeProcessFields(fields: (stored: Readonly<UserConfig>) => ProcessFieldValues, io?: ConfigStore): Promise<ProcessWriteResult>;
|
|
112
|
+
/**
|
|
113
|
+
* Realizes a change to the persisted debug filter: the candidate's filter becomes the runtime filter unless an env or CLI source owns it. Applying a filter
|
|
114
|
+
* cannot fail, so the handler refuses nothing. It is exported, as every module-registered handler is, so a suite that resets the registry re-registers it.
|
|
115
|
+
* @param _changes - The change under the handler's path; the candidate carries the filter, so the handler reads it there instead.
|
|
116
|
+
* @param next - The candidate running configuration.
|
|
117
|
+
* @returns No rejections.
|
|
118
|
+
*/
|
|
119
|
+
export declare function applyDebugFilterChange(_changes: readonly ConfigChange[], next: Readonly<Config>): Promise<readonly ChangeRejection[]>;
|
|
63
120
|
/**
|
|
64
121
|
* Returns a deep copy of the default configuration. Used by the web UI to display default values and handle reset operations.
|
|
65
122
|
* @returns A copy of the default configuration.
|
|
66
123
|
*/
|
|
67
124
|
export declare function getDefaults(): Config;
|
|
68
125
|
/**
|
|
69
|
-
* Validates that a configuration value is
|
|
70
|
-
*
|
|
71
|
-
*
|
|
72
|
-
*
|
|
73
|
-
* @param
|
|
126
|
+
* Validates that a configuration value is an integer at or above its floor and at or below an optional ceiling. The floor is the minimum the setting's metadata
|
|
127
|
+
* declares, and 1 when none is declared, so a setting whose metadata allows zero accepts it and an integer setting with no declared minimum stays positive. It
|
|
128
|
+
* returns an error message rather than throwing, so the caller can collect every error before reporting them. Every message is a complete sentence naming the
|
|
129
|
+
* value it refused, and a value below the floor draws a message naming the floor it applied, because a save joins the messages into the reason it answers with.
|
|
130
|
+
* @param name - The configuration name for error messages, typically the environment variable name or the setting's label.
|
|
131
|
+
* @param value - The value to validate.
|
|
132
|
+
* @param min - The declared minimum (inclusive). When it is omitted, the floor is 1.
|
|
74
133
|
* @param max - Optional maximum allowed value (inclusive).
|
|
75
134
|
* @returns Error message if invalid, null if valid.
|
|
76
135
|
*/
|
|
77
|
-
export declare function
|
|
136
|
+
export declare function validateInteger(name: string, value: number, min?: number, max?: number): Nullable<string>;
|
|
78
137
|
/**
|
|
79
|
-
* Validates that a configuration value is a
|
|
138
|
+
* Validates that a configuration value is a number, fractional or whole, at or above its floor and at or below an optional ceiling. The floor is the minimum the
|
|
139
|
+
* setting's metadata declares, and when none is declared the value must be positive, so zero is accepted only where the metadata says it is. Every message is a
|
|
140
|
+
* complete sentence naming the value it refused and, for a value below the floor, the floor it applied.
|
|
80
141
|
* @param name - The configuration name for error messages.
|
|
81
142
|
* @param value - The value to validate.
|
|
82
|
-
* @param min -
|
|
143
|
+
* @param min - The declared minimum (inclusive). When it is omitted, the value must be greater than zero.
|
|
83
144
|
* @param max - Optional maximum allowed value (inclusive).
|
|
84
145
|
* @returns Error message if invalid, null if valid.
|
|
85
146
|
*/
|
|
86
|
-
export declare function
|
|
147
|
+
export declare function validateNumber(name: string, value: number, min?: number, max?: number): Nullable<string>;
|
|
87
148
|
/** The settings whose value the server refuses to start with out of range. Each entry is a CONFIG_METADATA path, and the floor, the ceiling, and the name the
|
|
88
149
|
* error reports all come from that path's metadata - the same metadata the settings form validates a save against. One declaration of a bound means a value
|
|
89
150
|
* the form accepts is a value the boot accepts, and there is no second copy to fall out of step with the first.
|
|
@@ -97,21 +158,12 @@ export declare function validatePositiveNumber(name: string, value: number, min?
|
|
|
97
158
|
*/
|
|
98
159
|
export declare const STARTUP_BOUNDED_SETTINGS: readonly string[];
|
|
99
160
|
/**
|
|
100
|
-
* Validates
|
|
101
|
-
*
|
|
102
|
-
*
|
|
103
|
-
* application lets reloadConfiguration reuse the same hard-error and capture-coercion checks without silently coercing a live save.
|
|
161
|
+
* Validates the running configuration and throws if it carries any hard error. It runs at startup once the configuration is initialized, collects every hard
|
|
162
|
+
* error, and throws once with the complete list, so the operator can fix every issue in one pass. A correctable value never reaches here uncorrected, because
|
|
163
|
+
* the configuration is corrected as it is built.
|
|
104
164
|
* @throws If any configuration value is invalid. The error message lists all invalid values.
|
|
105
165
|
*/
|
|
106
166
|
export declare function validateConfiguration(): void;
|
|
107
|
-
/**
|
|
108
|
-
* Persists the capture configuration that validateConfiguration coerced at startup back to disk so the on-disk state matches the live CONFIG. A no-op unless a
|
|
109
|
-
* coercion actually occurred. Without this, a config file holding an unsupported capture value (native mode, or a captureCodecs list missing the h264 baseline)
|
|
110
|
-
* stays divergent from the coerced live CONFIG forever, and the reload-validation path would then reject every later save on the resulting phantom capture diff.
|
|
111
|
-
* filterDefaults strips any value equal to its default on write, so a config coerced back to the FFmpeg/h264 defaults leaves a clean file with no capture override.
|
|
112
|
-
* Failures degrade gracefully: the live CONFIG is already coerced, so a write failure only means the divergence persists until the next successful save or boot.
|
|
113
|
-
*/
|
|
114
|
-
export declare function persistCoercedConfig(io?: ConfigStore): Promise<void>;
|
|
115
167
|
/**
|
|
116
168
|
* Displays the active configuration at startup. This helps operators verify their settings and diagnose connection issues. We log only the most commonly adjusted
|
|
117
169
|
* values to keep output concise while providing useful debugging information.
|