@wordpress/env 6.0.0 → 7.0.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/README.md +109 -43
- package/lib/build-docker-compose-config.js +67 -96
- package/lib/cache.js +1 -0
- package/lib/cli.js +16 -3
- package/lib/commands/clean.js +14 -1
- package/lib/commands/destroy.js +12 -37
- package/lib/commands/index.js +1 -0
- package/lib/commands/install-path.js +1 -0
- package/lib/commands/logs.js +1 -0
- package/lib/commands/run.js +59 -3
- package/lib/commands/start.js +30 -8
- package/lib/commands/stop.js +1 -0
- package/lib/config/add-or-replace-port.js +12 -3
- package/lib/config/db-env.js +1 -0
- package/lib/config/detect-directory-type.js +1 -1
- package/lib/config/get-cache-directory.js +39 -0
- package/lib/config/get-config-from-environment-vars.js +86 -0
- package/lib/config/index.js +7 -5
- package/lib/config/load-config.js +92 -0
- package/lib/config/merge-configs.js +104 -0
- package/lib/config/parse-config.js +418 -157
- package/lib/config/parse-source-string.js +164 -0
- package/lib/config/post-process-config.js +202 -0
- package/lib/config/read-raw-config-file.js +7 -33
- package/lib/config/test/__snapshots__/config-integration.js.snap +271 -0
- package/lib/config/test/add-or-replace-port.js +29 -1
- package/lib/config/test/config-integration.js +143 -0
- package/lib/config/test/get-cache-directory.js +57 -0
- package/lib/config/test/merge-configs.js +111 -0
- package/lib/config/test/parse-config.js +342 -0
- package/lib/config/test/parse-source-string.js +154 -0
- package/lib/config/test/post-process-config.js +295 -0
- package/lib/config/test/read-raw-config-file.js +19 -63
- package/lib/config/test/validate-config.js +305 -0
- package/lib/config/validate-config.js +93 -54
- package/lib/env.js +2 -0
- package/lib/execute-after-setup.js +51 -0
- package/lib/get-host-user.js +31 -0
- package/lib/init-config.js +181 -63
- package/lib/md5.js +1 -0
- package/lib/parse-xdebug-mode.js +1 -0
- package/lib/retry.js +1 -0
- package/lib/test/__snapshots__/md5.js.snap +9 -0
- package/lib/test/build-docker-compose-config.js +134 -0
- package/lib/test/cache.js +154 -0
- package/lib/test/cli.js +149 -0
- package/lib/test/execute-after-setup.js +66 -0
- package/lib/test/md5.js +35 -0
- package/lib/test/parse-xdebug-mode.js +41 -0
- package/lib/wordpress.js +4 -19
- package/package.json +2 -2
- package/lib/config/config.js +0 -353
- package/lib/config/test/__snapshots__/config.js.snap +0 -83
- package/lib/config/test/config.js +0 -1241
|
@@ -0,0 +1,305 @@
|
|
|
1
|
+
'use strict';
|
|
2
|
+
/**
|
|
3
|
+
* Internal dependencies
|
|
4
|
+
*/
|
|
5
|
+
const {
|
|
6
|
+
ValidationError,
|
|
7
|
+
checkString,
|
|
8
|
+
checkPort,
|
|
9
|
+
checkStringArray,
|
|
10
|
+
checkObjectWithValues,
|
|
11
|
+
checkVersion,
|
|
12
|
+
checkValidURL,
|
|
13
|
+
} = require( '../validate-config' );
|
|
14
|
+
|
|
15
|
+
describe( 'validate-config', () => {
|
|
16
|
+
describe( 'checkString', () => {
|
|
17
|
+
it( 'throws when not a string', () => {
|
|
18
|
+
expect( () => checkString( 'test.json', 'test', 1234 ) ).toThrow(
|
|
19
|
+
new ValidationError(
|
|
20
|
+
'Invalid test.json: "test" must be a string.'
|
|
21
|
+
)
|
|
22
|
+
);
|
|
23
|
+
} );
|
|
24
|
+
|
|
25
|
+
it( 'passes for string', () => {
|
|
26
|
+
expect( () =>
|
|
27
|
+
checkString( 'test.json', 'test', 'test' )
|
|
28
|
+
).not.toThrow();
|
|
29
|
+
} );
|
|
30
|
+
} );
|
|
31
|
+
|
|
32
|
+
describe( 'checkPort', () => {
|
|
33
|
+
it( 'throws when not a number', () => {
|
|
34
|
+
expect( () => checkPort( 'test.json', 'test', 'test' ) ).toThrow(
|
|
35
|
+
new ValidationError(
|
|
36
|
+
'Invalid test.json: "test" must be an integer.'
|
|
37
|
+
)
|
|
38
|
+
);
|
|
39
|
+
|
|
40
|
+
expect( () =>
|
|
41
|
+
checkPort( 'test.json', 'test', { test: 'test' } )
|
|
42
|
+
).toThrow(
|
|
43
|
+
new ValidationError(
|
|
44
|
+
'Invalid test.json: "test" must be an integer.'
|
|
45
|
+
)
|
|
46
|
+
);
|
|
47
|
+
} );
|
|
48
|
+
|
|
49
|
+
it( 'throws when port out of range', () => {
|
|
50
|
+
expect( () => checkPort( 'test.json', 'test', -1 ) ).toThrow(
|
|
51
|
+
new ValidationError(
|
|
52
|
+
'Invalid test.json: "test" must be a valid port.'
|
|
53
|
+
)
|
|
54
|
+
);
|
|
55
|
+
|
|
56
|
+
expect( () => checkPort( 'test.json', 'test', 99999999 ) ).toThrow(
|
|
57
|
+
new ValidationError(
|
|
58
|
+
'Invalid test.json: "test" must be a valid port.'
|
|
59
|
+
)
|
|
60
|
+
);
|
|
61
|
+
} );
|
|
62
|
+
|
|
63
|
+
it( 'passes for valid port', () => {
|
|
64
|
+
expect( () =>
|
|
65
|
+
checkPort( 'test.json', 'test', 8888 )
|
|
66
|
+
).not.toThrow();
|
|
67
|
+
} );
|
|
68
|
+
} );
|
|
69
|
+
|
|
70
|
+
describe( 'checkStringArray', () => {
|
|
71
|
+
it( 'throws when not an array', () => {
|
|
72
|
+
expect( () =>
|
|
73
|
+
checkStringArray( 'test.json', 'test', 'test' )
|
|
74
|
+
).toThrow(
|
|
75
|
+
new ValidationError(
|
|
76
|
+
'Invalid test.json: "test" must be an array.'
|
|
77
|
+
)
|
|
78
|
+
);
|
|
79
|
+
|
|
80
|
+
expect( () =>
|
|
81
|
+
checkStringArray( 'test.json', 'test', { test: 'test' } )
|
|
82
|
+
).toThrow(
|
|
83
|
+
new ValidationError(
|
|
84
|
+
'Invalid test.json: "test" must be an array.'
|
|
85
|
+
)
|
|
86
|
+
);
|
|
87
|
+
} );
|
|
88
|
+
|
|
89
|
+
it( 'throws when array contains non-strings', () => {
|
|
90
|
+
expect( () =>
|
|
91
|
+
checkStringArray( 'test.json', 'test', [ 12 ] )
|
|
92
|
+
).toThrow(
|
|
93
|
+
new ValidationError(
|
|
94
|
+
'Invalid test.json: "test" must be an array of strings.'
|
|
95
|
+
)
|
|
96
|
+
);
|
|
97
|
+
|
|
98
|
+
expect( () =>
|
|
99
|
+
checkStringArray( 'test.json', 'test', [ 'test', 12 ] )
|
|
100
|
+
).toThrow(
|
|
101
|
+
new ValidationError(
|
|
102
|
+
'Invalid test.json: "test" must be an array of strings.'
|
|
103
|
+
)
|
|
104
|
+
);
|
|
105
|
+
} );
|
|
106
|
+
|
|
107
|
+
it( 'passes for string arrays', () => {
|
|
108
|
+
expect( () =>
|
|
109
|
+
checkStringArray( 'test.json', 'test', [] )
|
|
110
|
+
).not.toThrow();
|
|
111
|
+
expect( () =>
|
|
112
|
+
checkStringArray( 'test.json', 'test', [ 'test' ] )
|
|
113
|
+
).not.toThrow();
|
|
114
|
+
} );
|
|
115
|
+
} );
|
|
116
|
+
|
|
117
|
+
describe( 'checkObjectWithValues', () => {
|
|
118
|
+
it( 'throws when not an object', () => {
|
|
119
|
+
expect( () =>
|
|
120
|
+
checkObjectWithValues( 'test.json', 'test', 'test', [] )
|
|
121
|
+
).toThrow(
|
|
122
|
+
new ValidationError(
|
|
123
|
+
'Invalid test.json: "test" must be an object.'
|
|
124
|
+
)
|
|
125
|
+
);
|
|
126
|
+
|
|
127
|
+
expect( () =>
|
|
128
|
+
checkObjectWithValues( 'test.json', 'test', [ 'test' ], [] )
|
|
129
|
+
).toThrow(
|
|
130
|
+
new ValidationError(
|
|
131
|
+
'Invalid test.json: "test" must be an object.'
|
|
132
|
+
)
|
|
133
|
+
);
|
|
134
|
+
} );
|
|
135
|
+
|
|
136
|
+
it( 'throws when no allowed types are given', () => {
|
|
137
|
+
expect( () =>
|
|
138
|
+
checkObjectWithValues(
|
|
139
|
+
'test.json',
|
|
140
|
+
'test',
|
|
141
|
+
{ test: 'test' },
|
|
142
|
+
[]
|
|
143
|
+
)
|
|
144
|
+
).toThrow(
|
|
145
|
+
new ValidationError(
|
|
146
|
+
'Invalid test.json: "test.test" must be a .'
|
|
147
|
+
)
|
|
148
|
+
);
|
|
149
|
+
} );
|
|
150
|
+
|
|
151
|
+
it( 'throws when type is not allowed', () => {
|
|
152
|
+
expect( () =>
|
|
153
|
+
checkObjectWithValues( 'test.json', 'test', { test: 'test' }, [
|
|
154
|
+
'number',
|
|
155
|
+
] )
|
|
156
|
+
).toThrow(
|
|
157
|
+
new ValidationError(
|
|
158
|
+
'Invalid test.json: "test.test" must be a number.'
|
|
159
|
+
)
|
|
160
|
+
);
|
|
161
|
+
|
|
162
|
+
expect( () =>
|
|
163
|
+
checkObjectWithValues( 'test.json', 'test', { test: 1 }, [
|
|
164
|
+
'string',
|
|
165
|
+
] )
|
|
166
|
+
).toThrow(
|
|
167
|
+
new ValidationError(
|
|
168
|
+
'Invalid test.json: "test.test" must be a string.'
|
|
169
|
+
)
|
|
170
|
+
);
|
|
171
|
+
|
|
172
|
+
expect( () =>
|
|
173
|
+
checkObjectWithValues(
|
|
174
|
+
'test.json',
|
|
175
|
+
'test',
|
|
176
|
+
{ test: [ 'test' ] },
|
|
177
|
+
[ 'object', 'string' ]
|
|
178
|
+
)
|
|
179
|
+
).toThrow(
|
|
180
|
+
new ValidationError(
|
|
181
|
+
'Invalid test.json: "test.test" must be a object or string.'
|
|
182
|
+
)
|
|
183
|
+
);
|
|
184
|
+
} );
|
|
185
|
+
|
|
186
|
+
it( 'passes when type is allowed', () => {
|
|
187
|
+
expect( () =>
|
|
188
|
+
checkObjectWithValues( 'test.json', 'test', { test: 'test' }, [
|
|
189
|
+
'string',
|
|
190
|
+
] )
|
|
191
|
+
).not.toThrow();
|
|
192
|
+
expect( () =>
|
|
193
|
+
checkObjectWithValues( 'test.json', 'test', { test: 1 }, [
|
|
194
|
+
'number',
|
|
195
|
+
] )
|
|
196
|
+
).not.toThrow();
|
|
197
|
+
expect( () =>
|
|
198
|
+
checkObjectWithValues(
|
|
199
|
+
'test.json',
|
|
200
|
+
'test',
|
|
201
|
+
{ test: { nested: 'test' } },
|
|
202
|
+
[ 'object' ]
|
|
203
|
+
)
|
|
204
|
+
).not.toThrow();
|
|
205
|
+
expect( () =>
|
|
206
|
+
checkObjectWithValues(
|
|
207
|
+
'test.json',
|
|
208
|
+
'test',
|
|
209
|
+
{ test: [ 'test' ] },
|
|
210
|
+
[ 'array' ]
|
|
211
|
+
)
|
|
212
|
+
).not.toThrow();
|
|
213
|
+
} );
|
|
214
|
+
} );
|
|
215
|
+
|
|
216
|
+
describe( 'checkVersion', () => {
|
|
217
|
+
it( 'throws for invalid input', () => {
|
|
218
|
+
expect( () => checkVersion( 'test.json', 'test', 'test' ) ).toThrow(
|
|
219
|
+
new ValidationError(
|
|
220
|
+
'Invalid test.json: "test" must be a string of the format "X", "X.X", or "X.X.X".'
|
|
221
|
+
)
|
|
222
|
+
);
|
|
223
|
+
|
|
224
|
+
expect( () => checkVersion( 'test.json', 'test', 123 ) ).toThrow(
|
|
225
|
+
new ValidationError(
|
|
226
|
+
'Invalid test.json: "test" must be a string.'
|
|
227
|
+
)
|
|
228
|
+
);
|
|
229
|
+
} );
|
|
230
|
+
|
|
231
|
+
it( 'passes for different version formats', () => {
|
|
232
|
+
expect( () =>
|
|
233
|
+
checkVersion( 'test.json', 'test', '1' )
|
|
234
|
+
).not.toThrow();
|
|
235
|
+
expect( () =>
|
|
236
|
+
checkVersion( 'test.json', 'test', '1.1' )
|
|
237
|
+
).not.toThrow();
|
|
238
|
+
expect( () =>
|
|
239
|
+
checkVersion( 'test.json', 'test', '1.1.1' )
|
|
240
|
+
).not.toThrow();
|
|
241
|
+
expect( () =>
|
|
242
|
+
checkVersion( 'test.json', 'test', '15.7.2' )
|
|
243
|
+
).not.toThrow();
|
|
244
|
+
expect( () =>
|
|
245
|
+
checkVersion( 'test.json', 'test', '26634543' )
|
|
246
|
+
).not.toThrow();
|
|
247
|
+
} );
|
|
248
|
+
} );
|
|
249
|
+
|
|
250
|
+
describe( 'checkValidURL', () => {
|
|
251
|
+
it( 'throws for invaid URLs', () => {
|
|
252
|
+
expect( () =>
|
|
253
|
+
checkValidURL( 'test.json', 'test', 'localhost' )
|
|
254
|
+
).toThrow(
|
|
255
|
+
new ValidationError(
|
|
256
|
+
'Invalid test.json: "test" must be a valid URL.'
|
|
257
|
+
)
|
|
258
|
+
);
|
|
259
|
+
|
|
260
|
+
expect( () => checkValidURL( 'test.json', 'test', '' ) ).toThrow(
|
|
261
|
+
new ValidationError(
|
|
262
|
+
'Invalid test.json: "test" must be a valid URL.'
|
|
263
|
+
)
|
|
264
|
+
);
|
|
265
|
+
|
|
266
|
+
expect( () => checkValidURL( 'test.json', 'test', 123 ) ).toThrow(
|
|
267
|
+
new ValidationError(
|
|
268
|
+
'Invalid test.json: "test" must be a valid URL.'
|
|
269
|
+
)
|
|
270
|
+
);
|
|
271
|
+
} );
|
|
272
|
+
|
|
273
|
+
it( 'passes for valid URLs', () => {
|
|
274
|
+
expect( () =>
|
|
275
|
+
checkValidURL( 'test.json', 'test', 'http://test.com' )
|
|
276
|
+
).not.toThrow();
|
|
277
|
+
expect( () =>
|
|
278
|
+
checkValidURL( 'test.json', 'test', 'https://test.com' )
|
|
279
|
+
).not.toThrow();
|
|
280
|
+
expect( () =>
|
|
281
|
+
checkValidURL( 'test.json', 'test', 'http://test' )
|
|
282
|
+
).not.toThrow();
|
|
283
|
+
expect( () =>
|
|
284
|
+
checkValidURL(
|
|
285
|
+
'test.json',
|
|
286
|
+
'test',
|
|
287
|
+
'http://test/test?test=test'
|
|
288
|
+
)
|
|
289
|
+
).not.toThrow();
|
|
290
|
+
expect( () =>
|
|
291
|
+
checkValidURL( 'test.json', 'test', 'http://test.co.uk' )
|
|
292
|
+
).not.toThrow();
|
|
293
|
+
expect( () =>
|
|
294
|
+
checkValidURL( 'test.json', 'test', 'https://test.co.uk:8888' )
|
|
295
|
+
).not.toThrow();
|
|
296
|
+
expect( () =>
|
|
297
|
+
checkValidURL(
|
|
298
|
+
'test.json',
|
|
299
|
+
'test',
|
|
300
|
+
'http://test.co.uk:8888/test?test=test#test'
|
|
301
|
+
)
|
|
302
|
+
).not.toThrow();
|
|
303
|
+
} );
|
|
304
|
+
} );
|
|
305
|
+
} );
|
|
@@ -1,8 +1,7 @@
|
|
|
1
1
|
'use strict';
|
|
2
2
|
|
|
3
3
|
/**
|
|
4
|
-
* @typedef {import('./
|
|
5
|
-
* @typedef {import('./config').WPSource} WPSource
|
|
4
|
+
* @typedef {import('./parse-source-string').WPSource} WPSource
|
|
6
5
|
*/
|
|
7
6
|
|
|
8
7
|
/**
|
|
@@ -12,105 +11,145 @@
|
|
|
12
11
|
class ValidationError extends Error {}
|
|
13
12
|
|
|
14
13
|
/**
|
|
15
|
-
* Validates
|
|
16
|
-
* do not match the required format.
|
|
14
|
+
* Validates that the value is a string.
|
|
17
15
|
*
|
|
18
|
-
* @param {
|
|
19
|
-
* @param {
|
|
20
|
-
* @
|
|
16
|
+
* @param {string} configFile The configuration file we're validating.
|
|
17
|
+
* @param {string} configKey The configuration key we're validating.
|
|
18
|
+
* @param {number} value The value to check.
|
|
21
19
|
*/
|
|
22
|
-
function
|
|
23
|
-
|
|
24
|
-
if ( config.core !== null && typeof config.core !== 'string' ) {
|
|
20
|
+
function checkString( configFile, configKey, value ) {
|
|
21
|
+
if ( typeof value !== 'string' ) {
|
|
25
22
|
throw new ValidationError(
|
|
26
|
-
`Invalid
|
|
23
|
+
`Invalid ${ configFile }: "${ configKey }" must be a string.`
|
|
27
24
|
);
|
|
28
25
|
}
|
|
26
|
+
}
|
|
29
27
|
|
|
30
|
-
|
|
31
|
-
|
|
32
|
-
|
|
33
|
-
|
|
28
|
+
/**
|
|
29
|
+
* Validates the port and throws if it isn't valid.
|
|
30
|
+
*
|
|
31
|
+
* @param {string} configFile The configuration file we're validating.
|
|
32
|
+
* @param {string} configKey The configuration key we're validating.
|
|
33
|
+
* @param {number} port The port to check.
|
|
34
|
+
*/
|
|
35
|
+
function checkPort( configFile, configKey, port ) {
|
|
36
|
+
if ( ! Number.isInteger( port ) ) {
|
|
34
37
|
throw new ValidationError(
|
|
35
|
-
`Invalid
|
|
38
|
+
`Invalid ${ configFile }: "${ configKey }" must be an integer.`
|
|
36
39
|
);
|
|
37
40
|
}
|
|
38
41
|
|
|
39
|
-
if (
|
|
40
|
-
! Array.isArray( config.themes ) ||
|
|
41
|
-
config.themes.some( ( theme ) => typeof theme !== 'string' )
|
|
42
|
-
) {
|
|
42
|
+
if ( port < 0 || port > 65535 ) {
|
|
43
43
|
throw new ValidationError(
|
|
44
|
-
`Invalid
|
|
44
|
+
`Invalid ${ configFile }: "${ configKey }" must be a valid port.`
|
|
45
45
|
);
|
|
46
46
|
}
|
|
47
|
+
}
|
|
47
48
|
|
|
48
|
-
|
|
49
|
+
/**
|
|
50
|
+
* Validates the array and throws if it isn't valid.
|
|
51
|
+
*
|
|
52
|
+
* @param {string} configFile The config file we're validating.
|
|
53
|
+
* @param {string} configKey The configuration key we're validating.
|
|
54
|
+
* @param {string[]} array The array that we're checking.
|
|
55
|
+
*/
|
|
56
|
+
function checkStringArray( configFile, configKey, array ) {
|
|
57
|
+
if ( ! Array.isArray( array ) ) {
|
|
49
58
|
throw new ValidationError(
|
|
50
|
-
`Invalid
|
|
59
|
+
`Invalid ${ configFile }: "${ configKey }" must be an array.`
|
|
51
60
|
);
|
|
52
61
|
}
|
|
53
62
|
|
|
54
|
-
if ( typeof
|
|
63
|
+
if ( array.some( ( value ) => typeof value !== 'string' ) ) {
|
|
55
64
|
throw new ValidationError(
|
|
56
|
-
`Invalid
|
|
65
|
+
`Invalid ${ configFile }: "${ configKey }" must be an array of strings.`
|
|
57
66
|
);
|
|
58
67
|
}
|
|
68
|
+
}
|
|
59
69
|
|
|
60
|
-
|
|
70
|
+
/**
|
|
71
|
+
* Validates the object and throws if it isn't valid.
|
|
72
|
+
*
|
|
73
|
+
* @param {string} configFile The config file we're validating.
|
|
74
|
+
* @param {string} configKey The configuration key we're validating.
|
|
75
|
+
* @param {string[]} obj The object that we're checking.
|
|
76
|
+
* @param {string[]} allowTypes The types that are allowed.
|
|
77
|
+
*/
|
|
78
|
+
function checkObjectWithValues( configFile, configKey, obj, allowTypes ) {
|
|
79
|
+
if ( allowTypes === undefined ) {
|
|
80
|
+
allowTypes = [];
|
|
81
|
+
}
|
|
82
|
+
|
|
83
|
+
if ( typeof obj !== 'object' || Array.isArray( obj ) ) {
|
|
61
84
|
throw new ValidationError(
|
|
62
|
-
`Invalid
|
|
85
|
+
`Invalid ${ configFile }: "${ configKey }" must be an object.`
|
|
63
86
|
);
|
|
64
87
|
}
|
|
65
88
|
|
|
66
|
-
for ( const
|
|
67
|
-
if ( !
|
|
89
|
+
for ( const key in obj ) {
|
|
90
|
+
if ( ! obj[ key ] && ! allowTypes.includes( 'empty' ) ) {
|
|
68
91
|
throw new ValidationError(
|
|
69
|
-
`Invalid
|
|
92
|
+
`Invalid ${ configFile }: "${ configKey }.${ key }" must not be empty.`
|
|
93
|
+
);
|
|
94
|
+
}
|
|
95
|
+
|
|
96
|
+
// Identify arrays uniquely.
|
|
97
|
+
const type = Array.isArray( obj[ key ] ) ? 'array' : typeof obj[ key ];
|
|
98
|
+
|
|
99
|
+
if ( ! allowTypes.includes( type ) ) {
|
|
100
|
+
throw new ValidationError(
|
|
101
|
+
`Invalid ${ configFile }: "${ configKey }.${ key }" must be a ${ allowTypes.join(
|
|
102
|
+
' or '
|
|
103
|
+
) }.`
|
|
70
104
|
);
|
|
71
105
|
}
|
|
72
106
|
}
|
|
107
|
+
}
|
|
73
108
|
|
|
74
|
-
|
|
75
|
-
|
|
76
|
-
|
|
77
|
-
|
|
78
|
-
|
|
79
|
-
|
|
80
|
-
|
|
109
|
+
/**
|
|
110
|
+
* Validates the version and throws if it isn't valid.
|
|
111
|
+
*
|
|
112
|
+
* @param {string} configFile The config file we're validating.
|
|
113
|
+
* @param {string} configKey The configuration key we're validating.
|
|
114
|
+
* @param {string} version The version that we're checking.
|
|
115
|
+
*/
|
|
116
|
+
function checkVersion( configFile, configKey, version ) {
|
|
117
|
+
if ( typeof version !== 'string' ) {
|
|
81
118
|
throw new ValidationError(
|
|
82
|
-
`Invalid
|
|
119
|
+
`Invalid ${ configFile }: "${ configKey }" must be a string.`
|
|
83
120
|
);
|
|
84
121
|
}
|
|
85
122
|
|
|
86
|
-
|
|
87
|
-
|
|
88
|
-
|
|
89
|
-
|
|
123
|
+
if ( ! version.match( /[0-9]+(?:\.[0-9]+)*/ ) ) {
|
|
124
|
+
throw new ValidationError(
|
|
125
|
+
`Invalid ${ configFile }: "${ configKey }" must be a string of the format "X", "X.X", or "X.X.X".`
|
|
126
|
+
);
|
|
127
|
+
}
|
|
90
128
|
}
|
|
91
129
|
|
|
92
130
|
/**
|
|
93
|
-
* Validates the
|
|
131
|
+
* Validates the url and throws if it isn't valid.
|
|
94
132
|
*
|
|
95
|
-
* @param {string}
|
|
96
|
-
* @param {
|
|
97
|
-
* @param {string}
|
|
133
|
+
* @param {string} configFile The config file we're validating.
|
|
134
|
+
* @param {string} configKey The configuration key we're validating.
|
|
135
|
+
* @param {string} url The URL that we're checking.
|
|
98
136
|
*/
|
|
99
|
-
function checkValidURL(
|
|
100
|
-
if ( config[ configKey ] === undefined ) {
|
|
101
|
-
return;
|
|
102
|
-
}
|
|
103
|
-
|
|
137
|
+
function checkValidURL( configFile, configKey, url ) {
|
|
104
138
|
try {
|
|
105
|
-
new URL(
|
|
139
|
+
new URL( url );
|
|
106
140
|
} catch {
|
|
107
141
|
throw new ValidationError(
|
|
108
|
-
`Invalid
|
|
142
|
+
`Invalid ${ configFile }: "${ configKey }" must be a valid URL.`
|
|
109
143
|
);
|
|
110
144
|
}
|
|
111
145
|
}
|
|
112
146
|
|
|
113
147
|
module.exports = {
|
|
114
|
-
validateConfig,
|
|
115
148
|
ValidationError,
|
|
149
|
+
checkString,
|
|
150
|
+
checkPort,
|
|
151
|
+
checkStringArray,
|
|
152
|
+
checkObjectWithValues,
|
|
153
|
+
checkVersion,
|
|
154
|
+
checkValidURL,
|
|
116
155
|
};
|
package/lib/env.js
CHANGED
|
@@ -3,9 +3,11 @@
|
|
|
3
3
|
* Internal dependencies
|
|
4
4
|
*/
|
|
5
5
|
const { ValidationError } = require( './config' );
|
|
6
|
+
const { AfterSetupError } = require( './execute-after-setup' );
|
|
6
7
|
const commands = require( './commands' );
|
|
7
8
|
|
|
8
9
|
module.exports = {
|
|
9
10
|
...commands,
|
|
10
11
|
ValidationError,
|
|
12
|
+
AfterSetupError,
|
|
11
13
|
};
|
|
@@ -0,0 +1,51 @@
|
|
|
1
|
+
'use strict';
|
|
2
|
+
/**
|
|
3
|
+
* External dependencies
|
|
4
|
+
*/
|
|
5
|
+
const { execSync } = require( 'child_process' );
|
|
6
|
+
|
|
7
|
+
/**
|
|
8
|
+
* @typedef {import('./config').WPConfig} WPConfig
|
|
9
|
+
*/
|
|
10
|
+
|
|
11
|
+
/**
|
|
12
|
+
* Error subtype which indicates that the afterSetup command failed.
|
|
13
|
+
*/
|
|
14
|
+
class AfterSetupError extends Error {}
|
|
15
|
+
|
|
16
|
+
/**
|
|
17
|
+
* Executes any defined afterSetup command.
|
|
18
|
+
*
|
|
19
|
+
* @param {WPConfig} config The config object to use.
|
|
20
|
+
* @param {Object} spinner A CLI spinner which indciates progress.
|
|
21
|
+
*/
|
|
22
|
+
function executeAfterSetup( config, spinner ) {
|
|
23
|
+
if ( ! config.afterSetup ) {
|
|
24
|
+
return;
|
|
25
|
+
}
|
|
26
|
+
|
|
27
|
+
spinner.text = 'Executing Script: afterSetup';
|
|
28
|
+
|
|
29
|
+
try {
|
|
30
|
+
let output = execSync( config.afterSetup, {
|
|
31
|
+
encoding: 'utf-8',
|
|
32
|
+
stdio: 'pipe',
|
|
33
|
+
env: process.env,
|
|
34
|
+
} );
|
|
35
|
+
|
|
36
|
+
// Remove any trailing whitespace for nicer output.
|
|
37
|
+
output = output.trimRight();
|
|
38
|
+
|
|
39
|
+
// We don't need to bother with any output if there isn't any.
|
|
40
|
+
if ( output ) {
|
|
41
|
+
spinner.info( `After Setup:\n${ output }` );
|
|
42
|
+
}
|
|
43
|
+
} catch ( error ) {
|
|
44
|
+
throw new AfterSetupError( `After Setup:\n${ error.stderr }` );
|
|
45
|
+
}
|
|
46
|
+
}
|
|
47
|
+
|
|
48
|
+
module.exports = {
|
|
49
|
+
AfterSetupError,
|
|
50
|
+
executeAfterSetup,
|
|
51
|
+
};
|
|
@@ -0,0 +1,31 @@
|
|
|
1
|
+
'use strict';
|
|
2
|
+
/**
|
|
3
|
+
* External dependencies
|
|
4
|
+
*/
|
|
5
|
+
const os = require( 'os' );
|
|
6
|
+
|
|
7
|
+
/**
|
|
8
|
+
* Gets information about the host user.
|
|
9
|
+
*
|
|
10
|
+
* @return {Object} The host user's name, uid, and gid.
|
|
11
|
+
*/
|
|
12
|
+
module.exports = function getHostUser() {
|
|
13
|
+
const hostUser = os.userInfo();
|
|
14
|
+
|
|
15
|
+
// On Windows the uid and gid will be -1. Since there isn't a great way to handle this,
|
|
16
|
+
// we're just going to say that the host user is root. On Windows you'll likely be
|
|
17
|
+
// using WSL to run commands inside the container, which has a uid and gid. If
|
|
18
|
+
// you aren't, you'll be mounting directories from Windows, to a Linux
|
|
19
|
+
// VM (Docker Desktop uses one), to the guest OS. I assume that
|
|
20
|
+
// when dealing with this configuration that file ownership
|
|
21
|
+
// has the same kind of magic handling that macOS uses.
|
|
22
|
+
const uid = ( hostUser.uid === -1 ? 0 : hostUser.uid ).toString();
|
|
23
|
+
const gid = ( hostUser.gid === -1 ? 0 : hostUser.gid ).toString();
|
|
24
|
+
|
|
25
|
+
return {
|
|
26
|
+
name: hostUser.username,
|
|
27
|
+
uid,
|
|
28
|
+
gid,
|
|
29
|
+
fullUser: uid + ':' + gid,
|
|
30
|
+
};
|
|
31
|
+
};
|