1 | import fs from 'fs';
|
2 | import path from 'path';
|
3 |
|
4 | const BASE_LOCATION = Symbol('base configuration file location');
|
5 | const CONFIG_FILE_NAME = Symbol('configuration file name');
|
6 | const LOCATION = Symbol('configuration file location');
|
7 | const SERIALIZERS = Symbol('configuration file serializers');
|
8 |
|
9 | function suffixPath(configLocation, configFileName) {
|
10 | const suffix = path.sep + configFileName;
|
11 | return configLocation.substr(-suffix.length) !== suffix
|
12 | ? configLocation + suffix
|
13 | : configLocation;
|
14 | }
|
15 |
|
16 | function readJsonOrReturnObject(jsonPath) {
|
17 | try {
|
18 | return JSON.parse(fs.readFileSync(jsonPath));
|
19 | } catch (_error) {
|
20 | return {};
|
21 | }
|
22 | }
|
23 |
|
24 |
|
25 |
|
26 |
|
27 | export default class ConfigManager {
|
28 | |
29 |
|
30 |
|
31 |
|
32 |
|
33 |
|
34 |
|
35 | constructor(configLocation, baseConfigLocation, configFileName) {
|
36 | this[BASE_LOCATION] = baseConfigLocation;
|
37 | this[CONFIG_FILE_NAME] = configFileName;
|
38 | this[LOCATION] = configLocation;
|
39 | this[SERIALIZERS] = {};
|
40 |
|
41 | this.read();
|
42 | }
|
43 |
|
44 | |
45 |
|
46 |
|
47 |
|
48 |
|
49 |
|
50 |
|
51 | registerConfig(configName, defaultValue, serialize) {
|
52 | if (!this[configName]) {
|
53 | this[configName] = defaultValue || null;
|
54 | }
|
55 |
|
56 | Object.assign(this[SERIALIZERS], {
|
57 | [configName]: serialize,
|
58 | });
|
59 |
|
60 | return this[configName];
|
61 | }
|
62 |
|
63 | |
64 |
|
65 |
|
66 | getLocation() {
|
67 | return this[LOCATION];
|
68 | }
|
69 |
|
70 | |
71 |
|
72 |
|
73 |
|
74 |
|
75 | getStatus() {
|
76 | return [this[LOCATION], this[BASE_LOCATION]]
|
77 | .map((configLocation) =>
|
78 | suffixPath(configLocation, this[CONFIG_FILE_NAME])
|
79 | )
|
80 | .map((configLocation) => ({
|
81 | path: configLocation,
|
82 | exists: fs.existsSync(configLocation),
|
83 | }));
|
84 | }
|
85 |
|
86 | |
87 |
|
88 |
|
89 | read() {
|
90 | Object.assign(
|
91 | this,
|
92 | this.getStatus().reduce(
|
93 | (config, file) =>
|
94 | file.exists
|
95 | ? Object.assign(
|
96 | readJsonOrReturnObject(file.path),
|
97 | config
|
98 | )
|
99 | : config,
|
100 | {}
|
101 | )
|
102 | );
|
103 | }
|
104 |
|
105 | |
106 |
|
107 |
|
108 |
|
109 |
|
110 | save() {
|
111 | const configStatus = this.getStatus();
|
112 |
|
113 | const configLocation =
|
114 |
|
115 |
|
116 | (
|
117 | configStatus.find((loc) => loc.exists) ||
|
118 | configStatus[configStatus.length - 1]
|
119 | ).path;
|
120 |
|
121 | return new Promise((resolve, reject) =>
|
122 | fs.writeFile(configLocation, this.toString(), (error) => {
|
123 | return error ? reject(error) : resolve(configLocation);
|
124 | })
|
125 | );
|
126 | }
|
127 |
|
128 | |
129 |
|
130 |
|
131 |
|
132 |
|
133 | toString() {
|
134 | const serializedConfig = Object.keys(this[SERIALIZERS]).reduce(
|
135 | (config, serializerName) => {
|
136 | const serializerFn = this[SERIALIZERS][serializerName];
|
137 | const serialized =
|
138 | typeof serializerFn === 'function'
|
139 | ? serializerFn(this[serializerName])
|
140 | : this[serializerName];
|
141 |
|
142 | return serialized !== null && serialized !== undefined
|
143 | ? Object.assign(config, {
|
144 | [serializerName]: serialized,
|
145 | })
|
146 | : config;
|
147 | },
|
148 | {}
|
149 | );
|
150 |
|
151 | return JSON.stringify(serializedConfig, null, '\t');
|
152 | }
|
153 | }
|