aboutsummaryrefslogtreecommitdiffstats
path: root/packages/main/src/controllers/initConfig.ts
diff options
context:
space:
mode:
Diffstat (limited to 'packages/main/src/controllers/initConfig.ts')
-rw-r--r--packages/main/src/controllers/initConfig.ts90
1 files changed, 90 insertions, 0 deletions
diff --git a/packages/main/src/controllers/initConfig.ts b/packages/main/src/controllers/initConfig.ts
new file mode 100644
index 0000000..1d40762
--- /dev/null
+++ b/packages/main/src/controllers/initConfig.ts
@@ -0,0 +1,90 @@
1/*
2 * Copyright (C) 2021-2022 Kristóf Marussy <kristof@marussy.com>
3 *
4 * This file is part of Sophie.
5 *
6 * Sophie is free software: you can redistribute it and/or modify
7 * it under the terms of the GNU Affero General Public License as
8 * published by the Free Software Foundation, version 3.
9 *
10 * This program is distributed in the hope that it will be useful,
11 * but WITHOUT ANY WARRANTY; without even the implied warranty of
12 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
13 * GNU Affero General Public License for more details.
14 *
15 * You should have received a copy of the GNU Affero General Public License
16 * along with this program. If not, see <https://www.gnu.org/licenses/>.
17 *
18 * SPDX-License-Identifier: AGPL-3.0-only
19 */
20
21import { debounce } from 'lodash-es';
22import { applySnapshot, getSnapshot, onSnapshot } from 'mobx-state-tree';
23import ms from 'ms';
24
25import type ConfigPersistenceService from '../services/ConfigPersistenceService';
26import type { Config, ConfigSnapshotOut } from '../stores/Config';
27import type Disposer from '../utils/Disposer';
28import { getLogger } from '../utils/log';
29
30const DEFAULT_CONFIG_DEBOUNCE_TIME = ms('1s');
31
32const log = getLogger('config');
33
34export default async function initConfig(
35 config: Config,
36 persistenceService: ConfigPersistenceService,
37 debounceTime: number = DEFAULT_CONFIG_DEBOUNCE_TIME,
38): Promise<Disposer> {
39 log.trace('Initializing config controller');
40
41 let lastSnapshotOnDisk: ConfigSnapshotOut | null = null;
42
43 async function readConfig(): Promise<boolean> {
44 const result = await persistenceService.readConfig();
45 if (result.found) {
46 try {
47 applySnapshot(config, result.data);
48 lastSnapshotOnDisk = getSnapshot(config);
49 } catch (err) {
50 log.error('Failed to apply config snapshot', result.data, err);
51 }
52 }
53 return result.found;
54 }
55
56 async function writeConfig(): Promise<void> {
57 const snapshot = getSnapshot(config);
58 await persistenceService.writeConfig(snapshot);
59 lastSnapshotOnDisk = snapshot;
60 }
61
62 if (!await readConfig()) {
63 log.info('Config file was not found');
64 await writeConfig();
65 log.info('Created config file');
66 }
67
68 const disposeOnSnapshot = onSnapshot(config, debounce((snapshot) => {
69 // We can compare snapshots by reference, since it is only recreated on store changes.
70 if (lastSnapshotOnDisk !== snapshot) {
71 writeConfig().catch((err) => {
72 log.error('Failed to write config on config change', err);
73 });
74 }
75 }, debounceTime));
76
77 const disposeWatcher = persistenceService.watchConfig(async () => {
78 try {
79 await readConfig();
80 } catch (err) {
81 log.error('Failed to read config', err);
82 }
83 }, debounceTime);
84
85 return () => {
86 log.trace('Disposing config controller');
87 disposeWatcher();
88 disposeOnSnapshot();
89 };
90}