@@ -10,6 +10,7 @@ import {AbortSignal} from '@shopify/cli-kit/node/abort'
1010import { joinPath } from '@shopify/cli-kit/node/path'
1111import { fileExists , mkdir , rmdir } from '@shopify/cli-kit/node/fs'
1212import { useConcurrentOutputContext } from '@shopify/cli-kit/node/ui/components'
13+ import { groupBy } from '@shopify/cli-kit/common/collection'
1314import { formatMessagesSync , Message } from 'esbuild'
1415import { isUnitTest } from '@shopify/cli-kit/node/context/local'
1516import EventEmitter from 'events'
@@ -234,8 +235,20 @@ export class AppEventWatcher extends EventEmitter {
234235 * buildForBundle method.
235236 */
236237 private async buildExtensions ( extensionEvents : ExtensionEvent [ ] ) {
237- const promises = extensionEvents . map ( async ( extEvent ) => {
238- const ext = extEvent . extension
238+ // Group events by extension to handle multiple events for the same extension
239+ const groupedByUid = groupBy ( extensionEvents , ( event ) => event . extension . uid )
240+ const groupedExtensionEvents : { extension : ExtensionInstance ; events : ExtensionEvent [ ] } [ ] = [ ]
241+
242+ for ( const events of Object . values ( groupedByUid ) ) {
243+ if ( events . length > 0 && events [ 0 ] ) {
244+ groupedExtensionEvents . push ( {
245+ extension : events [ 0 ] . extension ,
246+ events,
247+ } )
248+ }
249+ }
250+
251+ const promises = groupedExtensionEvents . map ( async ( { extension : ext , events} ) => {
239252 return useConcurrentOutputContext ( { outputPrefix : ext . handle , stripAnsi : false } , async ( ) => {
240253 try {
241254 if ( this . esbuildManager . contexts ?. [ ext . uid ] ?. length ) {
@@ -244,7 +257,11 @@ export class AppEventWatcher extends EventEmitter {
244257 } else {
245258 await this . buildExtension ( ext )
246259 }
247- extEvent . buildResult = { status : 'ok' , uid : ext . uid }
260+ // Update all events for this extension with success result
261+ const buildResult = { status : 'ok' as const , uid : ext . uid }
262+ events . forEach ( ( event ) => {
263+ event . buildResult = buildResult
264+ } )
248265 // eslint-disable-next-line no-catch-all/no-catch-all, @typescript-eslint/no-explicit-any
249266 } catch ( error : any ) {
250267 // If there is an `errors` array, it's an esbuild error, format it and log it
@@ -267,12 +284,16 @@ export class AppEventWatcher extends EventEmitter {
267284 this . options . stderr . write ( error . message )
268285 }
269286
270- extEvent . buildResult = {
271- status : 'error' ,
287+ // Update all events for this extension with error result
288+ const buildResult = {
289+ status : 'error' as const ,
272290 error : errorMessage ,
273291 file : errorFile ,
274292 uid : ext . uid ,
275293 }
294+ events . forEach ( ( event ) => {
295+ event . buildResult = buildResult
296+ } )
276297 }
277298 } )
278299 } )
0 commit comments