-
Notifications
You must be signed in to change notification settings - Fork 2
/
Copy pathconfig.js
258 lines (224 loc) · 7.22 KB
/
config.js
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
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
const console = require('console')
const convict = require('convict')
const fs = require('fs')
const process = require('process')
const DATABASE_SCHEMA = {
authDatabase: {
default: '',
doc: 'The database to authenticate against when supplying a username and password',
envTemplate: 'DB_{database}_AUTH_SOURCE',
format: String,
},
authMechanism: {
default: '',
doc: 'If no authentication mechanism is specified or the mechanism DEFAULT is specified, the driver will attempt to authenticate using the SCRAM-SHA-1 authentication method if it is available on the MongoDB server. If the server does not support SCRAM-SHA-1 the driver will authenticate using MONGODB-CR.',
envTemplate: 'DB_{database}_AUTH_MECHANISM',
format: String,
},
default: {
default: false,
doc: 'Whether this database should be used as the default (main) database',
envTemplate: 'DB_{database}_DEFAULT',
format: Boolean,
},
hosts: {
default:
'Comma-separated string of MongoDB hosts, including port (e.g. localhost,localhost:27018,localhost:27019)',
doc: 'Database hosts',
format: String,
envTemplate: 'DB_{database}_HOSTS',
},
id: {
default: '',
doc: 'Database unique identifier',
format: String,
},
maxPoolSize: {
doc: 'The maximum number of connections in the connection pool',
format: Number,
default: 0,
envTemplate: 'DB_{database}_MAX_POOL',
},
password: {
doc: 'The access password, if one is needed',
format: String,
default: '',
envTemplate: 'DB_{database}_PASSWORD',
},
readPreference: {
doc: 'How MongoDB routes read operations to the members of a replica set - see https://docs.mongodb.com/manual/reference/read-preference/',
format: [
'primary',
'primaryPreferred',
'secondary',
'secondaryPreferred',
'nearest',
],
default: 'secondaryPreferred',
},
replicaSet: {
doc: 'The name of the replica set to identify the hosts',
format: String,
default: '',
},
ssl: {
doc: 'Whether to initiate the connection with TLS/SSL',
format: Boolean,
default: false,
},
username: {
doc: 'The access username, if one is needed',
format: String,
default: '',
envTemplate: 'DB_{database}_USERNAME',
},
}
const MAIN_SCHEMA = {
databases: {
default: [],
doc: 'Configuration block for each of the databases used throughout the application',
format: Array,
},
enableCollectionDatabases: {
default: false,
doc: 'Whether to use a database specified in the collection endpoint',
format: Boolean,
},
env: {
arg: 'node_env',
default: 'development',
doc: 'The applicaton environment.',
env: 'NODE_ENV',
format: String,
},
}
function transformLegacyDatabaseBlock(name, block) {
const hosts = block.hosts
.map(({host, port}) => {
return `${host}:${port || 27017}`
})
.join(',')
const newBlock = {
id: name,
}
Object.keys(block).forEach((key) => {
if (block[key] !== undefined && block[key] !== '') {
newBlock[key] = block[key]
}
})
newBlock.hosts = hosts
return newBlock
}
const mainConfig = convict(MAIN_SCHEMA)
const loadConfig = () => {
// Load environment dependent configuration.
const environment = mainConfig.get('env')
const filePath = `./config/mongodb.${environment}.json`
try {
const configFile = fs.readFileSync(filePath, 'utf8')
const data = JSON.parse(configFile)
// Checking for legacy database blocks, which consist of objects
// where keys are database names.
if (data.databases && !Array.isArray(data.databases)) {
data.databases = Object.keys(data.databases).map((name) => {
return transformLegacyDatabaseBlock(name, data.databases[name])
})
const exampleConfig = JSON.stringify(
{
databases: data.databases,
},
null,
2,
)
console.warn(
`The current MongoDB configuration uses a \`databases\` object. This syntax has been deprecated and will be removed in a future release. Please update your database configuration to:\n\n${exampleConfig}`,
)
}
data.databases = data.databases || []
let defaultDatabase = data.databases.find((database) => {
return database.default === true
})
// Checking for the legacy `database` property, which indicates the
// default database.
if (defaultDatabase === undefined && data.database !== undefined) {
defaultDatabase = data.databases.find((database, index) => {
if (database.id === data.database) {
data.databases[index].default = true
const exampleConfig = JSON.stringify(
{
databases: data.databases,
},
null,
2,
)
console.warn(
`The current MongoDB configuration uses a \`database\` property to indicate the default database. This syntax has been deprecated and will be removed in a future release. Please update your database configuration to:\n\n${exampleConfig}`,
)
return true
}
return false
})
}
// Checking for legacy syntax, where database details for the default
// database are declared at the root level, instead of inside the
// `databases` property.
if (!defaultDatabase && Array.isArray(data.hosts)) {
const legacyBlock = {
authDatabase: data.authDatabase,
authMechanism: data.authMechanism,
hosts: data.hosts,
maxPoolSize: data.maxPoolSize,
password: data.password,
readPreference: data.readPreference,
replicaSet: data.replicaSet,
ssl: data.ssl,
username: data.username,
}
const newBlock = transformLegacyDatabaseBlock(data.database, legacyBlock)
data.databases.push(newBlock)
const exampleConfig = JSON.stringify(
{
databases: [newBlock],
},
null,
2,
)
console.warn(
`The current MongoDB configuration uses a \`hosts\` array at the root level. This syntax has been deprecated and will be removed in a future release. Please update your database configuration to:\n\n${exampleConfig}`,
)
}
mainConfig.load(data)
mainConfig.validate()
// Validating databases.
const databases = mainConfig.get('databases')
databases.forEach((database, databaseIndex) => {
const databaseConfig = convict(DATABASE_SCHEMA)
databaseConfig.load(database)
databaseConfig.validate()
const schema = databaseConfig.getSchema().properties
// Listening for database-specific environment variables.
// e.g. DB_testdb_USERNAME
Object.keys(schema).forEach((key) => {
if (typeof schema[key].envTemplate === 'string') {
const envVar = schema[key].envTemplate.replace(
'{database}',
databaseIndex,
)
if (process.env[envVar]) {
mainConfig.set(
`databases[${databaseIndex}].${key}`,
process.env[envVar],
)
}
}
})
})
return mainConfig
} catch (error) {
console.error(error)
}
}
loadConfig()
module.exports = mainConfig
module.exports.mainConfig = mainConfig
module.exports.loadConfig = loadConfig