Files
bonob/src/config.ts
Simon J a5689c3d4b Feature/move close stream (#176)
* Move stream destroy closer to where stream is retrieved

* Change BNB_SUBSONIC_URL to be of type URLBuilder to better handle URL construction rather than string concat, should addresse #169
2023-10-10 11:25:55 +11:00

110 lines
3.5 KiB
TypeScript

import { hostname } from "os";
import logger from "./logger";
import url from "./url_builder";
export const WORD = /^\w+$/;
export const COLOR = /^#?\w+$/;
type EnvVarOpts<T> = {
default: T | undefined;
legacy: string[] | undefined;
validationPattern: RegExp | undefined;
parser: ((value: string) => T) | undefined
};
export function envVar<T>(
name: string,
opts: Partial<EnvVarOpts<T>> = {
default: undefined,
legacy: undefined,
validationPattern: undefined,
parser: undefined
}
): T {
const result = [name, ...(opts.legacy || [])]
.map((it) => ({ key: it, value: process.env[it] }))
.find((it) => it.value);
if (
result &&
result.value &&
opts.validationPattern &&
!result.value.match(opts.validationPattern)
) {
throw `Invalid value specified for '${name}', must match ${opts.validationPattern}`;
}
if(result && result.value && result.key != name) {
logger.warn(`Configuration key '${result.key}' is deprecated, replace with '${name}'`)
}
let value: T | undefined = undefined;
if(result?.value && opts.parser) {
value = opts.parser(result?.value)
} else if(result?.value)
value = result?.value as any as T
return value == undefined ? opts.default as T : value;
}
export const bnbEnvVar = <T>(key: string, opts: Partial<EnvVarOpts<T>> = {}) =>
envVar(`BNB_${key}`, {
...opts,
legacy: [`BONOB_${key}`, ...(opts.legacy || [])],
});
const asBoolean = (value: string) => value == "true";
const asInt = (value: string) => Number.parseInt(value);
export default function () {
const port = bnbEnvVar<number>("PORT", { default: 4534, parser: asInt })!;
const bonobUrl = bnbEnvVar("URL", {
legacy: ["BONOB_WEB_ADDRESS"],
default: `http://${hostname()}:${port}`,
})!;
if (bonobUrl.match("localhost")) {
logger.error(
"BNB_URL containing localhost is almost certainly incorrect, sonos devices will not be able to communicate with bonob using localhost, please specify either public IP or DNS entry"
);
process.exit(1);
}
return {
port,
bonobUrl: url(bonobUrl),
secret: bnbEnvVar<string>("SECRET", { default: "bonob" })!,
authTimeout: bnbEnvVar<string>("AUTH_TIMEOUT", { default: "1h" })!,
icons: {
foregroundColor: bnbEnvVar<string>("ICON_FOREGROUND_COLOR", {
validationPattern: COLOR,
}),
backgroundColor: bnbEnvVar<string>("ICON_BACKGROUND_COLOR", {
validationPattern: COLOR,
}),
},
logRequests: bnbEnvVar<boolean>("SERVER_LOG_REQUESTS", { default: false, parser: asBoolean }),
sonos: {
serviceName: bnbEnvVar<string>("SONOS_SERVICE_NAME", { default: "bonob" })!,
discovery: {
enabled:
bnbEnvVar<boolean>("SONOS_DEVICE_DISCOVERY", { default: true, parser: asBoolean }),
seedHost: bnbEnvVar<string>("SONOS_SEED_HOST"),
},
autoRegister:
bnbEnvVar<boolean>("SONOS_AUTO_REGISTER", { default: false, parser: asBoolean }),
sid: bnbEnvVar<number>("SONOS_SERVICE_ID", { default: 246, parser: asInt }),
},
subsonic: {
url: url(bnbEnvVar("SUBSONIC_URL", { legacy: ["BONOB_NAVIDROME_URL"], default: `http://${hostname()}:4533` })!),
customClientsFor: bnbEnvVar<string>("SUBSONIC_CUSTOM_CLIENTS", { legacy: ["BONOB_NAVIDROME_CUSTOM_CLIENTS"] }),
artistImageCache: bnbEnvVar<string>("SUBSONIC_ARTIST_IMAGE_CACHE"),
},
scrobbleTracks: bnbEnvVar<boolean>("SCROBBLE_TRACKS", { default: true, parser: asBoolean }),
reportNowPlaying:
bnbEnvVar<boolean>("REPORT_NOW_PLAYING", { default: true, parser: asBoolean }),
};
}