1
1
import process from 'process'
2
+ import { Transform } from 'stream'
3
+ import { stripVTControlCharacters } from 'util'
2
4
3
5
import execa from 'execa'
4
- // @ts -expect-error TS(7016) FIXME: Could not find a declaration file for module 'stri... Remove this comment to see the full error message
5
- import stripAnsiCc from 'strip-ansi-control-characters'
6
6
7
7
import { stopSpinner , type Spinner } from '../lib/spinner.js'
8
+
8
9
import { chalk , log , NETLIFYDEVERR , NETLIFYDEVWARN } from './command-helpers.js'
9
10
import { processOnExit } from './dev.js'
10
11
11
- /**
12
- * @type {(() => Promise<void>)[] } - array of functions to run before the process exits
13
- */
14
- // @ts -expect-error TS(7034) FIXME: Variable 'cleanupWork' implicitly has type 'any[]'... Remove this comment to see the full error message
15
- const cleanupWork = [ ]
12
+ const isErrnoException = ( value : unknown ) : value is NodeJS . ErrnoException =>
13
+ value instanceof Error && Object . hasOwn ( value , 'code' )
14
+
15
+ const createStripAnsiControlCharsStream = ( ) : Transform =>
16
+ new Transform ( {
17
+ transform ( chunk , _encoding , callback ) {
18
+ callback ( null , stripVTControlCharacters ( typeof chunk === 'string' ? chunk : ( chunk as unknown ) ?. toString ( ) ?? '' ) )
19
+ } ,
20
+ } )
21
+
22
+ const cleanupWork : ( ( ) => Promise < void > ) [ ] = [ ]
16
23
17
24
let cleanupStarted = false
18
25
19
- /**
20
- * @param {object } input
21
- * @param {number= } input.exitCode The exit code to return when exiting the process after cleanup
22
- */
23
26
const cleanupBeforeExit = async ( { exitCode } : { exitCode ?: number | undefined } = { } ) => {
24
27
// If cleanup has started, then wherever started it will be responsible for exiting
25
28
if ( ! cleanupStarted ) {
26
29
cleanupStarted = true
27
30
try {
28
- // @ts -expect-error TS(7005) FIXME: Variable 'cleanupWork' implicitly has an 'any[]' t... Remove this comment to see the full error message
29
31
await Promise . all ( cleanupWork . map ( ( cleanup ) => cleanup ( ) ) )
30
32
} finally {
33
+ // eslint-disable-next-line n/no-process-exit
31
34
process . exit ( exitCode )
32
35
}
33
36
}
@@ -63,7 +66,7 @@ export const runCommand = (
63
66
// In this case, we want to manually control when to clear and when to render a frame, so we turn this off.
64
67
stopSpinner ( { error : false , spinner } )
65
68
}
66
- const pipeDataWithSpinner = ( writeStream : NodeJS . WriteStream , chunk : any ) => {
69
+ const pipeDataWithSpinner = ( writeStream : NodeJS . WriteStream , chunk : string | Uint8Array ) => {
67
70
if ( spinner ?. isSpinning ) {
68
71
spinner . clear ( )
69
72
}
@@ -72,15 +75,19 @@ export const runCommand = (
72
75
} )
73
76
}
74
77
75
- // @ts -expect-error TS(2531) FIXME: Object is possibly 'null'.
76
- commandProcess . stdout . pipe ( stripAnsiCc . stream ( ) ) . on ( 'data' , pipeDataWithSpinner . bind ( null , process . stdout ) )
77
- // @ts -expect-error TS(2531) FIXME: Object is possibly 'null'.
78
- commandProcess . stderr . pipe ( stripAnsiCc . stream ( ) ) . on ( 'data' , pipeDataWithSpinner . bind ( null , process . stderr ) )
79
- // @ts -expect-error TS(2345) FIXME: Argument of type 'Writable | null' is not assignab... Remove this comment to see the full error message
80
- process . stdin . pipe ( commandProcess . stdin )
78
+ commandProcess . stdout
79
+ ?. pipe ( createStripAnsiControlCharsStream ( ) )
80
+ . on ( 'data' , pipeDataWithSpinner . bind ( null , process . stdout ) )
81
+ commandProcess . stderr
82
+ ?. pipe ( createStripAnsiControlCharsStream ( ) )
83
+ . on ( 'data' , pipeDataWithSpinner . bind ( null , process . stderr ) )
84
+ if ( commandProcess . stdin != null ) {
85
+ process . stdin . pipe ( commandProcess . stdin )
86
+ }
81
87
82
88
// we can't try->await->catch since we don't want to block on the framework server which
83
89
// is a long running process
90
+ // eslint-disable-next-line @typescript-eslint/no-floating-promises
84
91
commandProcess . then ( async ( ) => {
85
92
const result = await commandProcess
86
93
const [ commandWithoutArgs ] = command . split ( ' ' )
@@ -92,9 +99,10 @@ export const runCommand = (
92
99
)
93
100
} else {
94
101
const errorMessage = result . failed
95
- ? // @ts -expect-error TS(2339) FIXME: Property 'shortMessage' does not exist on type 'Ex... Remove this comment to see the full error message
96
- `${ NETLIFYDEVERR } ${ result . shortMessage } `
97
- : `${ NETLIFYDEVWARN } "${ command } " exited with code ${ result . exitCode } `
102
+ ? // @ts -expect-error FIXME(serhalp): We use `reject: false` which means the resolved value is either the resolved value
103
+ // or the rejected value, but the types aren't smart enough to know this.
104
+ `${ NETLIFYDEVERR } ${ result . shortMessage as string } `
105
+ : `${ NETLIFYDEVWARN } "${ command } " exited with code ${ result . exitCode . toString ( ) } `
98
106
99
107
log ( `${ errorMessage } . Shutting down Netlify Dev server` )
100
108
}
@@ -108,18 +116,10 @@ export const runCommand = (
108
116
return commandProcess
109
117
}
110
118
111
- /**
112
- *
113
- * @param {object } config
114
- * @param {string } config.command
115
- * @param {* } config.error
116
- * @returns
117
- */
118
- // @ts -expect-error TS(7031) FIXME: Binding element 'command' implicitly has an 'any' ... Remove this comment to see the full error message
119
- const isNonExistingCommandError = ( { command, error : commandError } ) => {
119
+ const isNonExistingCommandError = ( { command, error : commandError } : { command : string ; error : unknown } ) => {
120
120
// `ENOENT` is only returned for non Windows systems
121
121
// See https://github.com/sindresorhus/execa/pull/447
122
- if ( commandError . code === 'ENOENT' ) {
122
+ if ( isErrnoException ( commandError ) && commandError . code === 'ENOENT' ) {
123
123
return true
124
124
}
125
125
@@ -130,6 +130,7 @@ const isNonExistingCommandError = ({ command, error: commandError }) => {
130
130
131
131
// this only works on English versions of Windows
132
132
return (
133
+ commandError instanceof Error &&
133
134
typeof commandError . message === 'string' &&
134
135
commandError . message . includes ( 'is not recognized as an internal or external command' )
135
136
)
0 commit comments