11import { isString } from "remeda" ;
22
3- import { createPromiseWithResolvers } from "@/common" ;
3+ import { concatTemplateStrings , createPromiseWithResolvers } from "@/common" ;
44
55import { isAbortError } from "./error" ;
6- import { defaultOptions , getProcessOptions , getSpawnCommand } from "./params" ;
6+ import {
7+ defaultOptions ,
8+ isCommandStringParams ,
9+ isCommandTemplateParams ,
10+ isFactoryParams ,
11+ isSpawnParams ,
12+ parseCommandString ,
13+ } from "./params" ;
714import { spawnProcess } from "./spawn" ;
815
916import type {
1017 BaseExec ,
1118 BaseProcessInstance ,
1219 BaseProcessOptions ,
20+ ExecCommandStringParams ,
21+ ExecCommandTemplateParams ,
1322 ExecParams ,
1423 KillSignal ,
1524} from "./types" ;
1625import type { Nullable } from "@/types" ;
1726import type { ChildProcess } from "node:child_process" ;
1827import type { Readable } from "node:stream" ;
1928
20- export abstract class BaseProcess implements BaseProcessInstance {
21- protected static execImpl ( self : BaseProcess , params : ExecParams ) : BaseExec {
22- const exec = ( ...params : ExecParams ) : any => {
29+ export abstract class BaseProcess < P , I > implements BaseProcessInstance < P , I > {
30+ protected static execImpl < P , I > ( self : BaseProcess < P , I > , params : ExecParams ) {
31+ const execCommandTemplateOrString = (
32+ ...params : ExecCommandTemplateParams | ExecCommandStringParams
33+ ) => {
34+ const input = isCommandTemplateParams ( params )
35+ ? concatTemplateStrings ( params [ 0 ] , params . slice ( 1 ) )
36+ : params [ 0 ] ;
37+
2338 let cmd ;
2439 try {
25- cmd = getSpawnCommand ( params ) ;
40+ cmd = parseCommandString ( input ) ;
2641 } catch ( error ) {
2742 self . thrownError = error as Error ;
2843 }
@@ -31,16 +46,23 @@ export abstract class BaseProcess implements BaseProcessInstance {
3146 return cmd ? self . spawn ( cmd . command , cmd . args ) : self ;
3247 } ;
3348
34- // Factory case
35- const options = getProcessOptions ( params ) ;
36- if ( options ) {
37- self . options = { ...self . options , ...options } ;
49+ if ( isCommandTemplateParams ( params ) || isCommandStringParams ( params ) ) {
50+ return execCommandTemplateOrString ( ... params ) ;
51+ } else if ( isSpawnParams ( params ) ) {
52+ self . options = { ...self . options , ...params [ 2 ] } ;
3853
39- return exec ;
40- }
54+ return self . spawn ( params [ 0 ] , params [ 1 ] || [ ] ) ;
55+ } else if ( isFactoryParams ( params ) ) {
56+ self . options = { ...self . options , ...params [ 0 ] } ;
4157
42- // Command string or template case
43- return exec ( ...params ) ;
58+ return execCommandTemplateOrString ;
59+ } else {
60+ self . thrownError = new Error (
61+ `Invalid parameters passed to exec: ${ JSON . stringify ( params ) } ` ,
62+ ) ;
63+
64+ return self ;
65+ }
4466 }
4567
4668 protected _process : ChildProcess | undefined ;
@@ -82,12 +104,12 @@ export abstract class BaseProcess implements BaseProcessInstance {
82104 createPromiseWithResolvers < void > ( ) ) ;
83105 }
84106
85- exec : any = ( ...params : ExecParams ) => {
107+ exec : BaseExec < BaseProcessInstance < P , I > > = ( ...params : ExecParams ) : any => {
86108 return BaseProcess . execImpl ( this , params ) ;
87109 } ;
88110
89- pipe : any = ( ...params : ExecParams ) => {
90- const self = this . construct ( ) ;
111+ pipe : BaseExec < BaseProcessInstance < P , I > > = ( ...params : ExecParams ) : any => {
112+ const self = this . child ( ) ;
91113
92114 return BaseProcess . execImpl ( self , params ) ;
93115 } ;
@@ -96,8 +118,8 @@ export abstract class BaseProcess implements BaseProcessInstance {
96118 return this . process ?. kill ( signal ) === true ;
97119 }
98120
99- then < TResult1 = any , TResult2 = never > (
100- onfulfilled ?: ( ( value : any ) => TResult1 | PromiseLike < TResult1 > ) | null ,
121+ then < TResult1 = P , TResult2 = never > (
122+ onfulfilled ?: ( ( value : P ) => TResult1 | PromiseLike < TResult1 > ) | null ,
101123 onrejected ?: ( ( reason : unknown ) => TResult2 | PromiseLike < TResult2 > ) | null ,
102124 ) : Promise < TResult1 | TResult2 > {
103125 return this . thenImpl ( ) . then ( onfulfilled , onrejected ) ;
@@ -148,9 +170,9 @@ export abstract class BaseProcess implements BaseProcessInstance {
148170 this . process ?. removeAllListeners ( ) ;
149171 }
150172
151- abstract [ Symbol . asyncIterator ] ( ) : AsyncIterator < any > ;
173+ abstract [ Symbol . asyncIterator ] ( ) : AsyncIterator < I > ;
152174
153- protected abstract thenImpl ( ) : Promise < any > ;
175+ protected abstract thenImpl ( ) : Promise < P > ;
154176
155- protected abstract construct ( ) : BaseProcess ;
177+ protected abstract child ( ) : BaseProcess < P , I > ;
156178}
0 commit comments