summaryrefslogtreecommitdiff
path: root/src/config
diff options
context:
space:
mode:
author2 * r + 2 * t <61896496+soramanew@users.noreply.github.com>2025-04-26 22:36:23 +1000
committer2 * r + 2 * t <61896496+soramanew@users.noreply.github.com>2025-04-26 22:36:23 +1000
commit3c579d0e275cdaf6f2c9589abade94bde7905c82 (patch)
tree4b825dc642cb6eb9a060e54bf8d69288fbee4904 /src/config
parentschemes: fix (diff)
downloadcaelestia-shell-3c579d0e275cdaf6f2c9589abade94bde7905c82.tar.gz
caelestia-shell-3c579d0e275cdaf6f2c9589abade94bde7905c82.tar.bz2
caelestia-shell-3c579d0e275cdaf6f2c9589abade94bde7905c82.zip
clean
Remove everything
Diffstat (limited to 'src/config')
-rw-r--r--src/config/defaults.ts183
-rw-r--r--src/config/funcs.ts124
-rw-r--r--src/config/index.ts26
-rw-r--r--src/config/literals.ts336
-rw-r--r--src/config/types.ts93
5 files changed, 0 insertions, 762 deletions
diff --git a/src/config/defaults.ts b/src/config/defaults.ts
deleted file mode 100644
index a5ebbbc..0000000
--- a/src/config/defaults.ts
+++ /dev/null
@@ -1,183 +0,0 @@
-import { Astal } from "astal/gtk3";
-
-export default {
- style: {
- transparency: "normal", // One of "off", "low", "normal", "high"
- borders: true,
- vibrant: false, // Extra saturation
- },
- config: {
- notifyOnError: true,
- },
- // Modules
- bar: {
- vertical: true,
- style: "gaps", // One of "gaps", "panel", "embedded"
- layout: {
- type: "centerbox", // One of "centerbox", "flowbox"
- centerbox: {
- start: ["osIcon", "activeWindow", "mediaPlaying", "brightnessSpacer"],
- center: ["workspaces"],
- end: [
- "volumeSpacer",
- "tray",
- "statusIcons",
- "pkgUpdates",
- "notifCount",
- "battery",
- "dateTime",
- "power",
- ],
- },
- flowbox: [
- "osIcon",
- "workspaces",
- "brightnessSpacer",
- "activeWindow",
- "volumeSpacer",
- "dateTime",
- "tray",
- "battery",
- "statusIcons",
- "notifCount",
- "power",
- ],
- },
- modules: {
- workspaces: {
- shown: 5,
- showLabels: false,
- labels: ["󰮯", "󰮯", "󰮯", "󰮯", "󰮯"],
- xalign: -1,
- showWindows: false,
- },
- dateTime: {
- format: "%d/%m/%y %R",
- detailedFormat: "%c",
- },
- },
- },
- launcher: {
- style: "lines", // One of "lines", "round"
- actionPrefix: ">", // Prefix for launcher actions
- apps: {
- maxResults: 30, // Actual max results, -1 for infinite
- },
- files: {
- maxResults: 40, // Actual max results, -1 for infinite
- fdOpts: ["-a", "-t", "f"], // Options to pass to `fd`
- shortenThreshold: 30, // Threshold to shorten paths in characters
- },
- math: {
- maxResults: 40, // Actual max results, -1 for infinite
- },
- todo: {
- notify: true,
- },
- wallpaper: {
- maxResults: 20, // Actual max results, -1 for infinite
- showAllEmpty: true, // Show all wallpapers when search is empty
- style: "medium", // One of "compact", "medium", "large"
- },
- disabledActions: ["logout", "shutdown", "reboot", "hibernate"], // Actions to hide, see launcher/actions.tsx for available actions
- },
- notifpopups: {
- maxPopups: -1,
- expire: false,
- agoTime: true, // Whether to show time in ago format, e.g. 10 mins ago, or raw time, e.g. 10:42
- },
- osds: {
- volume: {
- position: Astal.WindowAnchor.RIGHT, // Top = 2, Right = 4, Left = 8, Bottom = 16
- margin: 20,
- hideDelay: 1500,
- showValue: true,
- },
- brightness: {
- position: Astal.WindowAnchor.LEFT, // Top = 2, Right = 4, Left = 8, Bottom = 16
- margin: 20,
- hideDelay: 1500,
- showValue: true,
- },
- lock: {
- spacing: 5,
- caps: {
- hideDelay: 1000,
- },
- num: {
- hideDelay: 1000,
- },
- },
- },
- sidebar: {
- showOnStartup: false,
- modules: {
- headlines: {
- enabled: true,
- },
- },
- },
- navbar: {
- persistent: false, // Whether to show all the time or only on hover
- appearWidth: 10, // The width in pixels of the hover area for the navbar to show up
- showLabels: false, // Whether to show labels for active buttons
- },
- // Services
- math: {
- maxHistory: 100,
- },
- updates: {
- interval: 900000,
- },
- weather: {
- interval: 600000,
- apiKey: "", // An API key from https://weatherapi.com for accessing weather data
- location: "", // Location as a string or empty to autodetect
- imperial: false,
- },
- cpu: {
- interval: 2000,
- },
- gpu: {
- interval: 2000,
- },
- memory: {
- interval: 5000,
- },
- storage: {
- interval: 5000,
- },
- wallpapers: {
- paths: [
- {
- recursive: true, // Whether to search recursively
- path: "~/Pictures/Wallpapers", // Path to search
- threshold: 0.8, // The threshold to filter wallpapers by size (e.g. 0.8 means wallpaper must be at least 80% of the screen size), 0 to disable
- },
- ],
- },
- calendar: {
- webcals: [] as string[], // An array of urls to ICS files which you can curl
- upcomingDays: 7, // Number of days which count as upcoming
- notify: true,
- },
- thumbnailer: {
- maxAttempts: 5,
- timeBetweenAttempts: 300,
- defaults: {
- width: 100,
- height: 100,
- exact: true,
- },
- },
- news: {
- apiKey: "", // An API key from https://newsdata.io for accessing news
- countries: ["current"], // A list of country codes or "current" for the current location
- categories: ["business", "top", "technology", "world"], // A list of news categories to filter by
- languages: ["en"], // A list of languages codes to filter by
- domains: [] as string[], // A list of news domains to pull from, see https://newsdata.io/news-sources for available domains
- excludeDomains: ["news.google.com"], // A list of news domains to exclude, e.g. bbc.co.uk
- timezone: "", // A timezone to filter by, e.g. "America/New_York", see https://en.wikipedia.org/wiki/List_of_tz_database_time_zones
- pages: 3, // Number of pages to pull (each page is 10 articles)
- },
-};
diff --git a/src/config/funcs.ts b/src/config/funcs.ts
deleted file mode 100644
index 77ee8dd..0000000
--- a/src/config/funcs.ts
+++ /dev/null
@@ -1,124 +0,0 @@
-import { notify } from "@/utils/system";
-import { Gio, GLib, monitorFile, readFileAsync, Variable, writeFileAsync } from "astal";
-import config from ".";
-import { loadStyleAsync } from "../../app";
-import defaults from "./defaults";
-import types from "./types";
-
-type Settings<T> = { [P in keyof T]: T[P] extends object & { length?: never } ? Settings<T[P]> : Variable<T[P]> };
-
-const CONFIG = `${GLib.get_user_config_dir()}/caelestia/shell.json`;
-
-const warn = (msg: string) => {
- console.warn(`[CONFIG] ${msg}`);
- if (config.config.notifyOnError.get())
- notify({
- summary: "Invalid config",
- body: msg,
- icon: "dialog-error-symbolic",
- urgency: "critical",
- });
-};
-
-const isObject = (o: any): o is object => typeof o === "object" && o !== null && !Array.isArray(o);
-
-const isCorrectType = (v: any, type: string | string[] | number[], path: string) => {
- if (Array.isArray(type)) {
- // type is array of valid values
- if (!type.includes(v as never)) {
- warn(`Invalid value for ${path}: ${v} != ${type.map(v => `"${v}"`).join(" | ")}`);
- return false;
- }
- } else if (type.startsWith("array of ")) {
- // Array of ...
- if (Array.isArray(v)) {
- // Remove invalid items but always return true
- const arrType = type.slice(9);
- try {
- // Recursively check type
- const type = JSON.parse(arrType);
- if (Array.isArray(type)) {
- v.splice(0, v.length, ...v.filter((item, i) => isCorrectType(item, type, `${path}[${i}]`)));
- } else {
- const valid = v.filter((item, i) =>
- Object.entries(type).every(([k, t]) => {
- if (!item.hasOwnProperty(k)) {
- warn(`Invalid shape for ${path}[${i}]: ${JSON.stringify(item)} != ${arrType}`);
- return false;
- }
- return isCorrectType(item[k], t as any, `${path}[${i}].${k}`);
- })
- );
- v.splice(0, v.length, ...valid); // In-place filter
- }
- } catch {
- const valid = v.filter((item, i) => {
- if (typeof item !== arrType) {
- warn(`Invalid type for ${path}[${i}]: ${typeof item} != ${arrType}`);
- return false;
- }
- return true;
- });
- v.splice(0, v.length, ...valid); // In-place filter
- }
- } else {
- // Type is array but value is not
- warn(`Invalid type for ${path}: ${typeof v} != ${type}`);
- return false;
- }
- } else if (typeof v !== type) {
- // Value is not correct type
- warn(`Invalid type for ${path}: ${typeof v} != ${type}`);
- return false;
- }
-
- return true;
-};
-
-const deepMerge = <T extends object, U extends object>(a: T, b: U, path = ""): T & U => {
- const merged: { [k: string]: any } = { ...b };
- for (const [k, v] of Object.entries(a)) {
- if (b.hasOwnProperty(k)) {
- const bv = b[k as keyof U];
- if (isObject(v) && isObject(bv)) merged[k] = deepMerge(v, bv, `${path}${k}.`);
- else if (!isCorrectType(bv, types[path + k], path + k)) merged[k] = v;
- } else merged[k] = v;
- }
- return merged as any;
-};
-
-export const convertSettings = <T extends object>(obj: T): Settings<T> =>
- Object.fromEntries(Object.entries(obj).map(([k, v]) => [k, isObject(v) ? convertSettings(v) : Variable(v)])) as any;
-
-const updateSection = (from: { [k: string]: any }, to: { [k: string]: any }, path = "") => {
- for (const [k, v] of Object.entries(from)) {
- if (to.hasOwnProperty(k)) {
- if (isObject(v)) updateSection(v, to[k], `${path}${k}.`);
- else if (!Array.isArray(v) || JSON.stringify(to[k].get()) !== JSON.stringify(v)) to[k].set(v);
- } else warn(`Unknown config key: ${path}${k}`);
- }
-};
-
-export const updateConfig = async () => {
- if (GLib.file_test(CONFIG, GLib.FileTest.EXISTS))
- updateSection(deepMerge(defaults, JSON.parse(await readFileAsync(CONFIG))), config);
- else updateSection(defaults, config);
- await loadStyleAsync();
- console.log("[LOG] Config updated");
-};
-
-export const initConfig = async () => {
- monitorFile(CONFIG, (_, e) => {
- if (e === Gio.FileMonitorEvent.CHANGES_DONE_HINT || e === Gio.FileMonitorEvent.DELETED)
- updateConfig().catch(warn);
- });
- await updateConfig().catch(warn);
-};
-
-export const setConfig = async (path: string, value: any) => {
- const conf = JSON.parse(await readFileAsync(CONFIG));
- let obj = conf;
- for (const p of path.split(".").slice(0, -1)) obj = obj[p];
- obj[path.split(".").at(-1)!] = value;
- await writeFileAsync(CONFIG, JSON.stringify(conf, null, 4));
-};
diff --git a/src/config/index.ts b/src/config/index.ts
deleted file mode 100644
index 80b4dc4..0000000
--- a/src/config/index.ts
+++ /dev/null
@@ -1,26 +0,0 @@
-import defaults from "./defaults";
-import { convertSettings } from "./funcs";
-
-const config = convertSettings(defaults);
-
-export const {
- style,
- bar,
- launcher,
- notifpopups,
- osds,
- sidebar,
- navbar,
- math,
- updates,
- weather,
- cpu,
- gpu,
- memory,
- storage,
- wallpapers,
- calendar,
- thumbnailer,
- news,
-} = config;
-export default config;
diff --git a/src/config/literals.ts b/src/config/literals.ts
deleted file mode 100644
index 1908c71..0000000
--- a/src/config/literals.ts
+++ /dev/null
@@ -1,336 +0,0 @@
-export const BAR_MODULES = [
- "osIcon",
- "activeWindow",
- "mediaPlaying",
- "brightnessSpacer",
- "workspaces",
- "volumeSpacer",
- "tray",
- "statusIcons",
- "pkgUpdates",
- "notifCount",
- "battery",
- "dateTime",
- "power",
-];
-
-export const NEWS_COUNTRIES = [
- "af", // Afghanistan
- "al", // Albania
- "dz", // Algeria
- "ad", // Andorra
- "ao", // Angola
- "ar", // Argentina
- "am", // Armenia
- "au", // Australia
- "at", // Austria
- "az", // Azerbaijan
- "bs", // Bahamas
- "bh", // Bahrain
- "bd", // Bangladesh
- "bb", // Barbados
- "by", // Belarus
- "be", // Belgium
- "bz", // Belize
- "bj", // Benin
- "bm", // Bermuda
- "bt", // Bhutan
- "bo", // Bolivia
- "ba", // Bosnia And Herzegovina
- "bw", // Botswana
- "br", // Brazil
- "bn", // Brunei
- "bg", // Bulgaria
- "bf", // Burkina fasco
- "bi", // Burundi
- "kh", // Cambodia
- "cm", // Cameroon
- "ca", // Canada
- "cv", // Cape Verde
- "ky", // Cayman Islands
- "cf", // Central African Republic
- "td", // Chad
- "cl", // Chile
- "cn", // China
- "co", // Colombia
- "km", // Comoros
- "cg", // Congo
- "ck", // Cook islands
- "cr", // Costa Rica
- "hr", // Croatia
- "cu", // Cuba
- "cw", // Curaçao
- "cy", // Cyprus
- "cz", // Czech republic
- "dk", // Denmark
- "dj", // Djibouti
- "dm", // Dominica
- "do", // Dominican republic
- "cd", // DR Congo
- "ec", // Ecuador
- "eg", // Egypt
- "sv", // El Salvador
- "gq", // Equatorial Guinea
- "er", // Eritrea
- "ee", // Estonia
- "sz", // Eswatini
- "et", // Ethiopia
- "fj", // Fiji
- "fi", // Finland
- "fr", // France
- "pf", // French polynesia
- "ga", // Gabon
- "gm", // Gambia
- "ge", // Georgia
- "de", // Germany
- "gh", // Ghana
- "gi", // Gibraltar
- "gr", // Greece
- "gd", // Grenada
- "gt", // Guatemala
- "gn", // Guinea
- "gy", // Guyana
- "ht", // Haiti
- "hn", // Honduras
- "hk", // Hong kong
- "hu", // Hungary
- "is", // Iceland
- "in", // India
- "id", // Indonesia
- "ir", // Iran
- "iq", // Iraq
- "ie", // Ireland
- "il", // Israel
- "it", // Italy
- "ci", // Ivory Coast
- "jm", // Jamaica
- "jp", // Japan
- "je", // Jersey
- "jo", // Jordan
- "kz", // Kazakhstan
- "ke", // Kenya
- "ki", // Kiribati
- "xk", // Kosovo
- "kw", // Kuwait
- "kg", // Kyrgyzstan
- "la", // Laos
- "lv", // Latvia
- "lb", // Lebanon
- "ls", // Lesotho
- "lr", // Liberia
- "ly", // Libya
- "li", // Liechtenstein
- "lt", // Lithuania
- "lu", // Luxembourg
- "mo", // Macau
- "mk", // Macedonia
- "mg", // Madagascar
- "mw", // Malawi
- "my", // Malaysia
- "mv", // Maldives
- "ml", // Mali
- "mt", // Malta
- "mh", // Marshall Islands
- "mr", // Mauritania
- "mu", // Mauritius
- "mx", // Mexico
- "fm", // Micronesia
- "md", // Moldova
- "mc", // Monaco
- "mn", // Mongolia
- "me", // Montenegro
- "ma", // Morocco
- "mz", // Mozambique
- "mm", // Myanmar
- "na", // Namibia
- "nr", // Nauru
- "np", // Nepal
- "nl", // Netherland
- "nc", // New caledonia
- "nz", // New zealand
- "ni", // Nicaragua
- "ne", // Niger
- "ng", // Nigeria
- "kp", // North korea
- "no", // Norway
- "om", // Oman
- "pk", // Pakistan
- "pw", // Palau
- "ps", // Palestine
- "pa", // Panama
- "pg", // Papua New Guinea
- "py", // Paraguay
- "pe", // Peru
- "ph", // Philippines
- "pl", // Poland
- "pt", // Portugal
- "pr", // Puerto rico
- "qa", // Qatar
- "ro", // Romania
- "ru", // Russia
- "rw", // Rwanda
- "lc", // Saint lucia
- "sx", // Saint martin(dutch)
- "ws", // Samoa
- "sm", // San Marino
- "st", // Sao tome and principe
- "sa", // Saudi arabia
- "sn", // Senegal
- "rs", // Serbia
- "sc", // Seychelles
- "sl", // Sierra Leone
- "sg", // Singapore
- "sk", // Slovakia
- "si", // Slovenia
- "sb", // Solomon Islands
- "so", // Somalia
- "za", // South africa
- "kr", // South korea
- "es", // Spain
- "lk", // Sri Lanka
- "sd", // Sudan
- "sr", // Suriname
- "se", // Sweden
- "ch", // Switzerland
- "sy", // Syria
- "tw", // Taiwan
- "tj", // Tajikistan
- "tz", // Tanzania
- "th", // Thailand
- "tl", // Timor-Leste
- "tg", // Togo
- "to", // Tonga
- "tt", // Trinidad and tobago
- "tn", // Tunisia
- "tr", // Turkey
- "tm", // Turkmenistan
- "tv", // Tuvalu
- "ug", // Uganda
- "ua", // Ukraine
- "ae", // United arab emirates
- "gb", // United kingdom
- "us", // United states of america
- "uy", // Uruguay
- "uz", // Uzbekistan
- "vu", // Vanuatu
- "va", // Vatican
- "ve", // Venezuela
- "vi", // Vietnam
- "vg", // Virgin Islands (British)
- "wo", // World
- "ye", // Yemen
- "zm", // Zambia
- "zw", // Zimbabwe
-];
-
-export const NEWS_CATEGORIES = [
- "business",
- "crime",
- "domestic",
- "education",
- "entertainment",
- "environment",
- "food",
- "health",
- "lifestyle",
- "other",
- "politics",
- "science",
- "sports",
- "technology",
- "top",
- "tourism",
- "world",
-];
-
-export const NEWS_LANGUAGES = [
- "af", // Afrikaans
- "sq", // Albanian
- "am", // Amharic
- "ar", // Arabic
- "hy", // Armenian
- "as", // Assamese
- "az", // Azerbaijani
- "bm", // Bambara
- "eu", // Basque
- "be", // Belarusian
- "bn", // Bengali
- "bs", // Bosnian
- "bg", // Bulgarian
- "my", // Burmese
- "ca", // Catalan
- "ckb", // Central Kurdish
- "zh", // Chinese
- "hr", // Croatian
- "cs", // Czech
- "da", // Danish
- "nl", // Dutch
- "en", // English
- "et", // Estonian
- "pi", // Filipino
- "fi", // Finnish
- "fr", // French
- "gl", // Galician
- "ka", // Georgian
- "de", // German
- "el", // Greek
- "gu", // Gujarati
- "ha", // Hausa
- "he", // Hebrew
- "hi", // Hindi
- "hu", // Hungarian
- "is", // Icelandic
- "id", // Indonesian
- "it", // Italian
- "jp", // Japanese
- "kn", // Kannada
- "kz", // Kazakh
- "kh", // Khmer
- "rw", // Kinyarwanda
- "ko", // Korean
- "ku", // Kurdish
- "lv", // Latvian
- "lt", // Lithuanian
- "lb", // Luxembourgish
- "mk", // Macedonian
- "ms", // Malay
- "ml", // Malayalam
- "mt", // Maltese
- "mi", // Maori
- "mr", // Marathi
- "mn", // Mongolian
- "ne", // Nepali
- "no", // Norwegian
- "or", // Oriya
- "ps", // Pashto
- "fa", // Persian
- "pl", // Polish
- "pt", // Portuguese
- "pa", // Punjabi
- "ro", // Romanian
- "ru", // Russian
- "sm", // Samoan
- "sr", // Serbian
- "sn", // Shona
- "sd", // Sindhi
- "si", // Sinhala
- "sk", // Slovak
- "sl", // Slovenian
- "so", // Somali
- "es", // Spanish
- "sw", // Swahili
- "sv", // Swedish
- "tg", // Tajik
- "ta", // Tamil
- "te", // Telugu
- "th", // Thai
- "zht", // Traditional chinese
- "tr", // Turkish
- "tk", // Turkmen
- "uk", // Ukrainian
- "ur", // Urdu
- "uz", // Uzbek
- "vi", // Vietnamese
- "cy", // Welsh
- "zu", // Zulu
-];
diff --git a/src/config/types.ts b/src/config/types.ts
deleted file mode 100644
index c8fb9b4..0000000
--- a/src/config/types.ts
+++ /dev/null
@@ -1,93 +0,0 @@
-import { BAR_MODULES, NEWS_CATEGORIES, NEWS_COUNTRIES, NEWS_LANGUAGES } from "./literals";
-
-const BOOL = "boolean";
-const STR = "string";
-const NUM = "number";
-const ARR = (type: string | string[]) => `array of ${typeof type === "string" ? type : JSON.stringify(type)}`;
-const OBJ_ARR = (shape: object) => ARR(JSON.stringify(shape));
-
-export default {
- "style.transparency": ["off", "low", "normal", "high"],
- "style.borders": BOOL,
- "style.vibrant": BOOL,
- "config.notifyOnError": BOOL,
- // Bar
- "bar.vertical": BOOL,
- "bar.style": ["gaps", "panel", "embedded"],
- "bar.layout.type": ["centerbox", "flowbox"],
- "bar.layout.centerbox.start": ARR(BAR_MODULES),
- "bar.layout.centerbox.center": ARR(BAR_MODULES),
- "bar.layout.centerbox.end": ARR(BAR_MODULES),
- "bar.layout.flowbox": ARR(BAR_MODULES),
- "bar.modules.workspaces.shown": NUM,
- "bar.modules.workspaces.showLabels": BOOL,
- "bar.modules.workspaces.labels": ARR(STR),
- "bar.modules.workspaces.xalign": NUM,
- "bar.modules.workspaces.showWindows": BOOL,
- "bar.modules.dateTime.format": STR,
- "bar.modules.dateTime.detailedFormat": STR,
- // Launcher
- "launcher.style": ["lines", "round"],
- "launcher.actionPrefix": STR,
- "launcher.apps.maxResults": NUM,
- "launcher.files.maxResults": NUM,
- "launcher.files.fdOpts": ARR(STR),
- "launcher.files.shortenThreshold": NUM,
- "launcher.math.maxResults": NUM,
- "launcher.todo.notify": BOOL,
- "launcher.wallpaper.maxResults": NUM,
- "launcher.wallpaper.showAllEmpty": BOOL,
- "launcher.wallpaper.style": ["compact", "medium", "large"],
- "launcher.disabledActions": ARR(STR),
- // Notif popups
- "notifpopups.maxPopups": NUM,
- "notifpopups.expire": BOOL,
- "notifpopups.agoTime": BOOL,
- // OSDs
- "osds.volume.position": [2, 4, 8, 16],
- "osds.volume.margin": NUM,
- "osds.volume.hideDelay": NUM,
- "osds.volume.showValue": BOOL,
- "osds.brightness.position": [2, 4, 8, 16],
- "osds.brightness.margin": NUM,
- "osds.brightness.hideDelay": NUM,
- "osds.brightness.showValue": BOOL,
- "osds.lock.spacing": NUM,
- "osds.lock.caps.hideDelay": NUM,
- "osds.lock.num.hideDelay": NUM,
- // Sidebar
- "sidebar.showOnStartup": BOOL,
- "sidebar.modules.headlines.enabled": BOOL,
- // Navbar
- "navbar.persistent": BOOL,
- "navbar.appearWidth": NUM,
- "navbar.showLabels": BOOL,
- // Services
- "math.maxHistory": NUM,
- "updates.interval": NUM,
- "weather.interval": NUM,
- "weather.apiKey": STR,
- "weather.location": STR,
- "weather.imperial": BOOL,
- "cpu.interval": NUM,
- "gpu.interval": NUM,
- "memory.interval": NUM,
- "storage.interval": NUM,
- "wallpapers.paths": OBJ_ARR({ recursive: BOOL, path: STR, threshold: NUM }),
- "calendar.webcals": ARR(STR),
- "calendar.upcomingDays": NUM,
- "calendar.notify": BOOL,
- "thumbnailer.maxAttempts": NUM,
- "thumbnailer.timeBetweenAttempts": NUM,
- "thumbnailer.defaults.width": NUM,
- "thumbnailer.defaults.height": NUM,
- "thumbnailer.defaults.exact": BOOL,
- "news.apiKey": STR,
- "news.countries": ARR(NEWS_COUNTRIES),
- "news.categories": ARR(NEWS_CATEGORIES),
- "news.languages": ARR(NEWS_LANGUAGES),
- "news.domains": ARR(STR),
- "news.excludeDomains": ARR(STR),
- "news.timezone": STR,
- "news.pages": NUM,
-} as { [k: string]: string | string[] | number[] };