@@ -24,7 +24,10 @@ import { color } from "../../color";
2424import { memoize } from "../decorators" ;
2525
2626class Hook implements IHook {
27- constructor ( public name : string , public fullPath : string ) { }
27+ constructor (
28+ public name : string ,
29+ public fullPath : string ,
30+ ) { }
2831}
2932
3033export class HooksService implements IHooksService {
@@ -45,7 +48,7 @@ export class HooksService implements IHooksService {
4548 private $projectHelper : IProjectHelper ,
4649 private $options : IOptions ,
4750 private $performanceService : IPerformanceService ,
48- private $projectConfigService : IProjectConfigService
51+ private $projectConfigService : IProjectConfigService ,
4952 ) { }
5053
5154 public get hookArgsName ( ) : string {
@@ -69,12 +72,12 @@ export class HooksService implements IHooksService {
6972
7073 if ( projectDir ) {
7174 this . hooksDirectories . push (
72- path . join ( projectDir , HooksService . HOOKS_DIRECTORY_NAME )
75+ path . join ( projectDir , HooksService . HOOKS_DIRECTORY_NAME ) ,
7376 ) ;
7477 }
7578
7679 this . $logger . trace (
77- "Hooks directories: " + util . inspect ( this . hooksDirectories )
80+ "Hooks directories: " + util . inspect ( this . hooksDirectories ) ,
7881 ) ;
7982
8083 const customHooks = this . $projectConfigService . getValue ( "hooks" , [ ] ) ;
@@ -91,7 +94,7 @@ export class HooksService implements IHooksService {
9194
9295 public executeBeforeHooks (
9396 commandName : string ,
94- hookArguments ?: IDictionary < any >
97+ hookArguments ?: IDictionary < any > ,
9598 ) : Promise < void > {
9699 const beforeHookName = `before-${ HooksService . formatHookName ( commandName ) } ` ;
97100 const traceMessage = `BeforeHookName for command ${ commandName } is ${ beforeHookName } ` ;
@@ -100,7 +103,7 @@ export class HooksService implements IHooksService {
100103
101104 public executeAfterHooks (
102105 commandName : string ,
103- hookArguments ?: IDictionary < any >
106+ hookArguments ?: IDictionary < any > ,
104107 ) : Promise < void > {
105108 const afterHookName = `after-${ HooksService . formatHookName ( commandName ) } ` ;
106109 const traceMessage = `AfterHookName for command ${ commandName } is ${ afterHookName } ` ;
@@ -110,7 +113,7 @@ export class HooksService implements IHooksService {
110113 private async executeHooks (
111114 hookName : string ,
112115 traceMessage : string ,
113- hookArguments ?: IDictionary < any >
116+ hookArguments ?: IDictionary < any > ,
114117 ) : Promise < any > {
115118 if ( this . $config . DISABLE_HOOKS || ! this . $options . hooks ) {
116119 return ;
@@ -135,8 +138,8 @@ export class HooksService implements IHooksService {
135138 await this . executeHooksInDirectory (
136139 hooksDirectory ,
137140 hookName ,
138- hookArguments
139- )
141+ hookArguments ,
142+ ) ,
140143 ) ;
141144 }
142145
@@ -148,8 +151,8 @@ export class HooksService implements IHooksService {
148151 this . $projectHelper . projectDir ,
149152 hookName ,
150153 hook ,
151- hookArguments
152- )
154+ hookArguments ,
155+ ) ,
153156 ) ;
154157 }
155158 } catch ( err ) {
@@ -160,11 +163,16 @@ export class HooksService implements IHooksService {
160163 return _ . flatten ( results ) ;
161164 }
162165
166+ private isESModule ( hook : IHook ) : boolean {
167+ const ext = path . extname ( hook . fullPath ) . toLowerCase ( ) ;
168+ return ext === ".mjs" ;
169+ }
170+
163171 private async executeHook (
164172 directoryPath : string ,
165173 hookName : string ,
166174 hook : IHook ,
167- hookArguments ?: IDictionary < any >
175+ hookArguments ?: IDictionary < any > ,
168176 ) : Promise < any > {
169177 hookArguments = hookArguments || { } ;
170178
@@ -173,15 +181,22 @@ export class HooksService implements IHooksService {
173181 const relativePath = path . relative ( directoryPath , hook . fullPath ) ;
174182 const trackId = relativePath . replace (
175183 new RegExp ( "\\" + path . sep , "g" ) ,
176- AnalyticsEventLabelDelimiter
184+ AnalyticsEventLabelDelimiter ,
177185 ) ;
186+ const isESM = this . isESModule ( hook ) ;
178187 let command = this . getSheBangInterpreter ( hook ) ;
179188 let inProc = false ;
180189 if ( ! command ) {
181190 command = hook . fullPath ;
182- if ( path . extname ( hook . fullPath ) . toLowerCase ( ) === ".js" ) {
191+ if (
192+ [ ".mjs" , ".cjs" , ".js" ] . includes (
193+ path . extname ( hook . fullPath ) . toLowerCase ( ) ,
194+ )
195+ ) {
183196 command = process . argv [ 0 ] ;
184- inProc = this . shouldExecuteInProcess ( this . $fs . readText ( hook . fullPath ) ) ;
197+ inProc = isESM
198+ ? true
199+ : this . shouldExecuteInProcess ( this . $fs . readText ( hook . fullPath ) ) ;
185200 }
186201 }
187202
@@ -190,24 +205,30 @@ export class HooksService implements IHooksService {
190205 this . $logger . trace (
191206 "Executing %s hook at location %s in-process" ,
192207 hookName ,
193- hook . fullPath
208+ hook . fullPath ,
194209 ) ;
195- const hookEntryPoint = require ( hook . fullPath ) ;
210+ let hookEntryPoint ;
211+ if ( isESM ) {
212+ const { default : hookFn } = await import ( hook . fullPath ) ;
213+ hookEntryPoint = hookFn ;
214+ } else {
215+ hookEntryPoint = require ( hook . fullPath ) ;
216+ }
196217
197218 this . $logger . trace ( `Validating ${ hookName } arguments.` ) ;
198219
199220 const invalidArguments = this . validateHookArguments (
200221 hookEntryPoint ,
201- hook . fullPath
222+ hook . fullPath ,
202223 ) ;
203224
204225 if ( invalidArguments . length ) {
205226 this . $logger . warn (
206227 `${
207228 hook . fullPath
208229 } will NOT be executed because it has invalid arguments - ${ color . grey (
209- invalidArguments . join ( ", " )
210- ) } .`
230+ invalidArguments . join ( ", " ) ,
231+ ) } .`,
211232 ) ;
212233 return ;
213234 }
@@ -220,14 +241,13 @@ export class HooksService implements IHooksService {
220241 const projectDataHookArg =
221242 hookArguments [ "hookArgs" ] && hookArguments [ "hookArgs" ] [ "projectData" ] ;
222243 if ( projectDataHookArg ) {
223- hookArguments [ "projectData" ] = hookArguments [
224- "$projectData"
225- ] = projectDataHookArg ;
244+ hookArguments [ "projectData" ] = hookArguments [ "$projectData" ] =
245+ projectDataHookArg ;
226246 }
227247
228248 const maybePromise = this . $injector . resolve (
229249 hookEntryPoint ,
230- hookArguments
250+ hookArguments ,
231251 ) ;
232252 if ( maybePromise ) {
233253 this . $logger . trace ( "Hook promises to signal completion" ) ;
@@ -255,15 +275,15 @@ export class HooksService implements IHooksService {
255275 "Executing %s hook at location %s with environment " ,
256276 hookName ,
257277 hook . fullPath ,
258- environment
278+ environment ,
259279 ) ;
260280
261281 const output = await this . $childProcess . spawnFromEvent (
262282 command ,
263283 [ hook . fullPath ] ,
264284 "close" ,
265285 environment ,
266- { throwError : false }
286+ { throwError : false } ,
267287 ) ;
268288 result = output ;
269289
@@ -275,7 +295,7 @@ export class HooksService implements IHooksService {
275295 "Finished executing %s hook at location %s with environment " ,
276296 hookName ,
277297 hook . fullPath ,
278- environment
298+ environment ,
279299 ) ;
280300 }
281301 const endTime = this . $performanceService . now ( ) ;
@@ -289,7 +309,7 @@ export class HooksService implements IHooksService {
289309 private async executeHooksInDirectory (
290310 directoryPath : string ,
291311 hookName : string ,
292- hookArguments ?: IDictionary < any >
312+ hookArguments ?: IDictionary < any > ,
293313 ) : Promise < any [ ] > {
294314 hookArguments = hookArguments || { } ;
295315 const results : any [ ] = [ ] ;
@@ -301,7 +321,7 @@ export class HooksService implements IHooksService {
301321 directoryPath ,
302322 hookName ,
303323 hook ,
304- hookArguments
324+ hookArguments ,
305325 ) ;
306326
307327 if ( result ) {
@@ -316,14 +336,14 @@ export class HooksService implements IHooksService {
316336 const hooks : IHook [ ] = [ ] ;
317337 const customHooks : INsConfigHooks [ ] = this . $projectConfigService . getValue (
318338 "hooks" ,
319- [ ]
339+ [ ] ,
320340 ) ;
321341
322342 for ( const cHook of customHooks ) {
323343 if ( cHook . type === hookName ) {
324344 const fullPath = path . join (
325345 this . $projectHelper . projectDir ,
326- cHook . script
346+ cHook . script ,
327347 ) ;
328348 const isFile = this . $fs . getFsStats ( fullPath ) . isFile ( ) ;
329349
@@ -332,8 +352,8 @@ export class HooksService implements IHooksService {
332352 hooks . push (
333353 new Hook (
334354 this . getBaseFilename ( fileNameParts [ fileNameParts . length - 1 ] ) ,
335- fullPath
336- )
355+ fullPath ,
356+ ) ,
337357 ) ;
338358 }
339359 }
@@ -346,10 +366,10 @@ export class HooksService implements IHooksService {
346366 const allBaseHooks = this . getHooksInDirectory ( directoryPath ) ;
347367 const baseHooks = _ . filter (
348368 allBaseHooks ,
349- ( hook ) => hook . name . toLowerCase ( ) === hookName . toLowerCase ( )
369+ ( hook ) => hook . name . toLowerCase ( ) === hookName . toLowerCase ( ) ,
350370 ) ;
351371 const moreHooks = this . getHooksInDirectory (
352- path . join ( directoryPath , hookName )
372+ path . join ( directoryPath , hookName ) ,
353373 ) ;
354374 return baseHooks . concat ( moreHooks ) ;
355375 }
@@ -385,13 +405,11 @@ export class HooksService implements IHooksService {
385405 const clientName = this . $staticConfig . CLIENT_NAME . toUpperCase ( ) ;
386406
387407 const environment : IStringDictionary = { } ;
388- environment [ util . format ( "%s-COMMANDLINE" , clientName ) ] = process . argv . join (
389- " "
390- ) ;
408+ environment [ util . format ( "%s-COMMANDLINE" , clientName ) ] =
409+ process . argv . join ( " " ) ;
391410 environment [ util . format ( "%s-HOOK_FULL_PATH" , clientName ) ] = hookFullPath ;
392- environment [
393- util . format ( "%s-VERSION" , clientName )
394- ] = this . $staticConfig . version ;
411+ environment [ util . format ( "%s-VERSION" , clientName ) ] =
412+ this . $staticConfig . version ;
395413
396414 return {
397415 cwd : this . $projectHelper . projectDir ,
@@ -463,7 +481,7 @@ export class HooksService implements IHooksService {
463481
464482 private validateHookArguments (
465483 hookConstructor : any ,
466- hookFullPath : string
484+ hookFullPath : string ,
467485 ) : string [ ] {
468486 const invalidArguments : string [ ] = [ ] ;
469487
@@ -477,7 +495,7 @@ export class HooksService implements IHooksService {
477495 }
478496 } catch ( err ) {
479497 this . $logger . trace (
480- `Cannot resolve ${ argument } of hook ${ hookFullPath } , reason: ${ err } `
498+ `Cannot resolve ${ argument } of hook ${ hookFullPath } , reason: ${ err } ` ,
481499 ) ;
482500 invalidArguments . push ( argument ) ;
483501 }
0 commit comments