-
Notifications
You must be signed in to change notification settings - Fork 0
Expand file tree
/
Copy pathmigration.js
More file actions
121 lines (108 loc) · 4.06 KB
/
migration.js
File metadata and controls
121 lines (108 loc) · 4.06 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
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
// Update configuration file to the newest version, ensuring backward compatibility
import { readFile, writeFile } from "node:fs/promises";
const updates = [
// Version 0.2.3
{
key: "management.username",
to: "management.accounts",
transform: (value, data) => {
// Add the username and password as a key-value pair in accounts
if (data.management.password) {
return { [value]: data.management.password };
}
return {
["admin"]: "admin" // Default admin account
};
}
},
{
key: "management.password",
to: null // Remove this property after migration
},
{
key: "management.username",
to: null // Remove this property after migration
},
// Version 0.3.4
{
key: "management.trustedProxies",
to: "trustedProxies",
transform: (value, data) => {
if (data.management.trustedProxies) {
return data.management.trustedProxies;
}
return [];
}
},
{
key: "management.trustedProxies",
to: null // Remove this property after migration
},
{
key: "management._thrustedProxies",
to: null // Remove this property after migration
}
// Version X.X.X
// activate this in the next version (so that git does not delete values before migration)
// {
// key: "management.trustedProxies",
// to: null // Remove this property after migration
// },
];
export default async function updateConfigRefs(file) {
return new Promise(async (resolve, reject) => {
try {
let data = JSON.parse(await readFile(file, 'utf8'));
// Apply updates in the defined order
for (const { key, to, transform } of updates) {
const keys = key.split('.');
const lastKey = keys.pop();
const source = keys.reduce((obj, k) => obj?.[k], data);
if (source && lastKey in source) {
const value = source[lastKey];
// Apply transformation if specified
if (transform) {
const transformedValue = transform(value, data);
if (to) {
const toKeys = to.split('.');
const toLastKey = toKeys.pop();
const target = toKeys.reduce((obj, k) => obj[k] ??= {}, data);
// Merge transformed value into the target
if (typeof transformedValue === 'object' && !Array.isArray(transformedValue)) {
target[toLastKey] = { ...target[toLastKey], ...transformedValue };
} else {
target[toLastKey] = transformedValue;
}
}
}
// Remove the original property if `to` is null
if (to === null) {
delete source[lastKey];
}
}
}
// Write the updated data back to the file
await writeFile(file, JSON.stringify(data, null, 4), 'utf8');
resolve();
} catch (error) {
reject(error);
}
});
}
// Run the migration if this file is called directly with an argument
if (process.argv[1].split('/').pop() === import.meta.url.split('/').pop()) {
const configFile = process.argv[2] || "./config.json"; // Default config file path
if (!configFile) {
console.error('Error: Please provide a config file path as an argument');
process.exit(1);
}
updateConfigRefs(configFile)
.then(() => {
console.log(`Successfully migrated configuration file: ${configFile}`);
process.exit(0);
})
.catch(error => {
console.error(`Error migrating configuration: ${error.message}`);
process.exit(1);
});
}