1
- var traverse = require ( 'traverse' ) ;
2
-
3
1
var parser = function ( val ) {
4
2
var parsedVal ;
5
3
try {
@@ -10,56 +8,129 @@ var parser = function(val) {
10
8
val = parsedVal ;
11
9
} else if ( Array . isArray ( parsedVal ) ) {
12
10
val = parsedVal ;
11
+ } else if ( typeof parsedVal === 'object' ) {
12
+ val = parsedVal ;
13
13
}
14
14
} catch ( error ) { }
15
15
return val ;
16
16
} ;
17
17
18
- var read = function ( config , parser ) {
19
- var tc = traverse ( config ) ;
20
- var tcKeyMap = { } ;
18
+ const OVERRIDES = {
19
+ MONGODB : {
20
+ REPLSETSERVERS : 'replSetServers' ,
21
+ REPLICANAME : 'replicaName' ,
22
+ MAX_POOL_SIZE : 'max_pool_size' ,
23
+ DBOPTIONS : 'dbOptions' ,
24
+ SERVEROPTIONS : 'serverOptions'
25
+ } ,
21
26
22
- // make paths case-insensitive. Useful while converting from uppercase env
23
- // vars to camelCase variables.
24
- tc . paths ( ) . forEach ( function ( path ) {
25
- // store paths as lowercase with their corresponding actual paths. will be
26
- // used while updating the value
27
- tcKeyMap [ path . join ( '_' ) . toLowerCase ( ) ] = path ;
28
- } ) ;
27
+ API : {
28
+ MAX_SOCKETS : 'max_sockets' ,
29
+ } ,
30
+
31
+ WEB : {
32
+ USE_INTERCOM : 'use_intercom' ,
33
+ SECURE_COOKIES : 'secure_cookies'
34
+ } ,
35
+
36
+ IGNOREPROXIES : 'ignoreProxies' ,
37
+ FILESTORAGE : 'fileStorage' ,
38
+ RELOADCONFIGAFTER : 'reloadConfigAfter'
39
+ } ;
40
+
41
+ /**
42
+ * Digs one level down in config document
43
+ *
44
+ * @param {[type] } config [description]
45
+ * @param {[type] } over [description]
46
+ * @param {[type] } name [description]
47
+ * @param {[type] } value [description]
48
+ * @return {[type] } [description]
49
+ */
50
+ function dig ( config , over , name , value ) {
51
+ let comps = name . split ( '_' ) ;
52
+
53
+ for ( let i = comps . length ; i > 0 ; i -- ) {
54
+ let n = comps . slice ( 0 , i ) . join ( '_' ) ;
55
+
56
+ if ( n in over ) {
57
+ let sub ;
58
+
59
+ if ( typeof over [ n ] === 'string' ) {
60
+ sub = over [ n ] ;
61
+ over [ n ] = { } ;
62
+ } else {
63
+ sub = Object . keys ( config ) . filter ( k => k . toUpperCase ( ) === n ) [ 0 ] ;
64
+ }
29
65
30
- var ref = process . env ;
31
- var env ;
32
- for ( env in ref ) {
33
- var val = ref [ env ] ;
66
+ name = comps . slice ( i ) . join ( '_' ) ;
34
67
35
- // we only care about env vars starting with "countly"
36
- if ( ! env . startsWith ( 'COUNTLY_' ) ) {
37
- continue ;
68
+ if ( ! name || comps . length === 1 ) {
69
+ config [ sub ] = value ;
70
+ return true ;
71
+ }
72
+
73
+ if ( typeof config [ sub ] === 'object' ) {
74
+ return dig ( config [ sub ] , over [ n ] , name , value ) ;
75
+ } else if ( sub ) {
76
+ config [ sub ] = { } ;
77
+ return dig ( config [ sub ] , over [ n ] , name , value ) ;
78
+ } else {
79
+ config [ n ] = { } ;
80
+ return dig ( config [ n ] , over [ n ] , name , value ) ;
81
+ }
82
+ } else if ( n === over ) {
83
+ name = over ;
84
+ config [ name ] = value ;
85
+ return true ;
38
86
}
39
- var path = env . split ( '_' ) ;
40
- if ( path . length < 2 ) {
41
- continue ;
87
+ }
88
+
89
+ for ( let i = 1 ; i <= comps . length ; i ++ ) {
90
+ let n = comps . slice ( 0 , i ) . join ( '_' ) ,
91
+ sub = Object . keys ( config ) . filter ( k => k . toUpperCase ( ) === n ) [ 0 ] ,
92
+ name = comps . slice ( i ) . join ( '_' ) ;
93
+
94
+ if ( sub ) {
95
+ if ( comps . length === 1 ) {
96
+ config [ sub ] = value ;
97
+ return true ;
98
+ } else {
99
+ config [ sub ] = typeof config [ sub ] === 'object' ? config [ sub ] : { } ;
100
+ return dig ( config [ sub ] , { } , name , value ) ;
101
+ }
42
102
}
103
+ }
43
104
44
- // get the underlying value of env var
45
- val = parser ( val ) ;
46
- if ( ! val ) {
47
- continue ;
105
+ comps . forEach ( ( c , i ) => {
106
+ if ( i === comps . length - 1 ) {
107
+ config [ c . toLowerCase ( ) ] = value ;
108
+ } else {
109
+ config = config [ c . toLowerCase ( ) ] = { } ;
48
110
}
111
+ } )
49
112
50
- // generate path from env vars, while removing the first COUNTLY_ part
51
- var newPath = path . slice ( 1 ) . map ( function ( node ) {
52
- return parser ( node . toLowerCase ( ) ) ;
53
- } ) ;
113
+ return true ;
114
+ }
54
115
55
- // if we dont have the new path defined in config, we might be creating a
56
- // new node
57
- var location = tcKeyMap [ newPath . join ( '_' ) ] || newPath ;
58
- tc . set ( location , val ) ;
116
+ module . exports = function ( mode , config , opts ) {
117
+ // back compatibility
118
+ if ( typeof mode === 'object' ) {
119
+ config = mode ;
120
+ mode = 'API' ;
121
+ opts = process . env ;
59
122
}
60
- } ;
123
+
124
+ if ( [ 'API' , 'FRONTEND' ] . indexOf ( mode ) === - 1 ) {
125
+ throw new Error ( 'Invalid config mode ' + mode ) ;
126
+ }
127
+
128
+ config = JSON . parse ( JSON . stringify ( config ) ) ;
129
+
130
+ Object . keys ( opts ) . filter ( n => n . indexOf ( `COUNTLY_CONFIG_${ mode } _` ) === 0 ) . forEach ( n => {
131
+ let comps = n . split ( '_' ) . slice ( 3 ) ;
132
+ dig ( config , OVERRIDES , comps . join ( '_' ) , parser ( opts [ n ] ) ) ;
133
+ } ) ;
61
134
62
- module . exports = function ( config ) {
63
- read ( config , parser ) ;
64
135
return config ;
65
136
} ;
0 commit comments