-
Notifications
You must be signed in to change notification settings - Fork 1
Expand file tree
/
Copy pathindex.js
More file actions
93 lines (78 loc) · 2.38 KB
/
Copy pathindex.js
File metadata and controls
93 lines (78 loc) · 2.38 KB
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
import fs from 'fs';
import path from 'path';
const DEFAULT_CONFIG_PATH = '/etc/skpr/data/config.json';
let configPath = DEFAULT_CONFIG_PATH;
let configData = {};
let cachedMtimeMs = 0;
// throttle file stat calls to avoid excessive I/O
let statThrottleMs = 1000;
let lastStatCheck = 0;
function readJSONSafely(filePath) {
const raw = fs.readFileSync(filePath, 'utf8');
return JSON.parse(raw);
}
function tryReloadIfChanged(force = false) {
const now = Date.now();
if (!force && now - lastStatCheck < statThrottleMs) return;
lastStatCheck = now;
// Node >=16 supports { throwIfNoEntry }
const stat = fs.statSync(configPath, { throwIfNoEntry: false });
if (!stat) {
if (cachedMtimeMs !== -1) {
console.warn(`[skpr-config] File not found: ${configPath}`);
cachedMtimeMs = -1;
configData = {};
}
return;
}
const { mtimeMs } = stat;
if (force || mtimeMs !== cachedMtimeMs) {
try {
const next = readJSONSafely(configPath);
configData = next;
cachedMtimeMs = mtimeMs;
} catch (err) {
// Keep previous good config on parse error
console.error(`[skpr-config] Failed to parse ${configPath}: ${err.message}`);
}
}
}
/**
* Get a configuration value by key (e.g. "mongo.default.hostname").
* Refreshes from disk if the file changed since the last successful load.
*/
export function get(key) {
tryReloadIfChanged(false);
return configData[key];
}
/** Descriptive alias */
export const skprConfigGet = get;
/** Return a shallow copy of the entire config */
export function getAll() {
tryReloadIfChanged(false);
return { ...configData };
}
/** Force an immediate reload, skipping throttle */
export function reload() {
tryReloadIfChanged(true);
}
/**
* Configure the loader.
* @param {{ path?: string, statThrottleMs?: number }} opts
*/
export function configure(opts = {}) {
if (opts.path && opts.path !== configPath) {
configPath = path.resolve(opts.path);
cachedMtimeMs = 0;
lastStatCheck = 0;
}
if (typeof opts.statThrottleMs === 'number' && opts.statThrottleMs >= 0) {
statThrottleMs = opts.statThrottleMs;
}
tryReloadIfChanged(true);
}
/** Namespaced default export for ergonomic usage: skprConfig.get(...) */
const skprConfig = { get, skprConfigGet, getAll, reload, configure };
export default skprConfig;
// Warm up at import time; safe if file doesn’t exist yet
tryReloadIfChanged(true);