1
1
import { Json } from '@app-config/utils' ;
2
- import { ParsingExtension , parseRawString , guessFileType } from '@app-config/core' ;
2
+ import { ParsingExtension , parseRawString , guessFileType , AppConfigError } from '@app-config/core' ;
3
+ import { forKey , validateOptions } from '@app-config/extension-utils' ;
3
4
import { exec } from 'child_process' ;
4
5
import { promisify } from 'util' ;
5
6
@@ -12,83 +13,72 @@ export interface Options {
12
13
trimWhitespace : boolean ;
13
14
}
14
15
15
- class ExecError extends Error {
16
+ class ExecError extends AppConfigError {
16
17
name = 'ExecError' ;
17
18
}
18
19
19
- function parseOptions ( parsed : Json ) : Options {
20
- if ( typeof parsed === 'string' ) {
21
- return { command : parsed , failOnStderr : false , parseOutput : false , trimWhitespace : true } ;
22
- }
23
-
24
- if ( parsed && typeof parsed === 'object' && ! Array . isArray ( parsed ) ) {
25
- const { command, failOnStderr = false , parseOutput = false , trimWhitespace = true } = parsed ;
26
-
27
- if ( typeof command !== 'string' ) {
28
- throw new ExecError ( '$exec requires a "command" option' ) ;
29
- }
30
-
31
- if ( typeof failOnStderr !== 'boolean' ) {
32
- throw new ExecError ( '$exec "failOnStderr" option must be a boolean' ) ;
33
- }
34
-
35
- if ( typeof parseOutput !== 'boolean' ) {
36
- throw new ExecError ( '$exec "parseString" option must be a boolean' ) ;
37
- }
38
-
39
- if ( typeof trimWhitespace !== 'boolean' ) {
40
- throw new ExecError ( '$exec "trimWhitespace" option must be a boolean' ) ;
41
- }
42
-
43
- return { command, failOnStderr, parseOutput, trimWhitespace } ;
44
- }
45
-
46
- throw new ExecError ( '$exec must be a string, or object with options' ) ;
47
- }
48
-
49
20
function execParsingExtension ( ) : ParsingExtension {
50
- return ( value , [ _ , objectKey ] ) => {
51
- if ( objectKey !== '$exec' ) {
52
- return false ;
53
- }
21
+ return forKey (
22
+ '$exec' ,
23
+ validateOptions (
24
+ ( SchemaBuilder ) =>
25
+ SchemaBuilder . oneOf (
26
+ SchemaBuilder . stringSchema ( ) ,
27
+ SchemaBuilder . emptySchema ( )
28
+ . addString ( 'command' )
29
+ . addBoolean ( 'failOnStderr' , { } , false )
30
+ . addBoolean ( 'parseOutput' , { } , false )
31
+ . addBoolean ( 'trimWhitespace' , { } , false ) ,
32
+ ) ,
33
+ ( value ) => async ( parse ) => {
34
+ let options ;
35
+
36
+ if ( typeof value === 'string' ) {
37
+ options = { command : value } ;
38
+ } else {
39
+ options = value ;
40
+ }
54
41
55
- return async ( parse ) => {
56
- const parsed = await parse ( value ) . then ( ( v ) => v . toJSON ( ) ) ;
42
+ const {
43
+ command,
44
+ failOnStderr = false ,
45
+ parseOutput = false ,
46
+ trimWhitespace = true ,
47
+ } = options ;
57
48
58
- const { command, failOnStderr, parseOutput, trimWhitespace } = parseOptions ( parsed ) ;
49
+ try {
50
+ const { stdout, stderr } = await execAsync ( command ) ;
59
51
60
- try {
61
- const { stdout, stderr } = await execAsync ( command ) ;
52
+ if ( failOnStderr && stderr ) {
53
+ throw new ExecError ( `$exec command "${ command } " produced stderr: ${ stderr } ` ) ;
54
+ }
62
55
63
- if ( failOnStderr && stderr ) {
64
- throw new ExecError ( `$exec command "${ command } " produced stderr: ${ stderr } ` ) ;
65
- }
56
+ let result : Json = stdout ;
66
57
67
- let result : Json = stdout ;
58
+ if ( trimWhitespace ) {
59
+ result = stdout . trim ( ) ;
60
+ }
68
61
69
- if ( trimWhitespace ) {
70
- result = stdout . trim ( ) ;
71
- }
62
+ if ( parseOutput ) {
63
+ const fileType = await guessFileType ( stdout ) ;
64
+ result = await parseRawString ( stdout , fileType ) ;
65
+ }
72
66
73
- if ( parseOutput ) {
74
- const fileType = await guessFileType ( stdout ) ;
75
- result = await parseRawString ( stdout , fileType ) ;
76
- }
67
+ return parse ( result , { shouldFlatten : true } ) ;
68
+ } catch ( err : unknown ) {
69
+ if ( ! isError ( err ) ) {
70
+ throw err ;
71
+ }
77
72
78
- return parse ( result , { shouldFlatten : true } ) ;
79
- } catch ( err : unknown ) {
80
- if ( ! isError ( err ) ) {
81
- throw err ;
82
- }
73
+ if ( err instanceof ExecError ) {
74
+ throw err ;
75
+ }
83
76
84
- if ( err instanceof ExecError ) {
85
- throw err ;
77
+ throw new ExecError ( `$exec command "${ command } " failed with error:\n${ err . message } ` ) ;
86
78
}
87
-
88
- throw new ExecError ( `$exec command "${ command } " failed with error:\n${ err . message } ` ) ;
89
- }
90
- } ;
91
- } ;
79
+ } ,
80
+ ) ,
81
+ ) ;
92
82
}
93
83
94
84
/**
0 commit comments