@@ -4,8 +4,10 @@ import {ArgOutput, FlagOutput, Input} from '@oclif/core/lib/interfaces/parser.js
44import Command from '@shopify/cli-kit/node/base-command'
55import { AdminSession , ensureAuthenticatedThemes } from '@shopify/cli-kit/node/session'
66import { loadEnvironment } from '@shopify/cli-kit/node/environments'
7- import { renderWarning } from '@shopify/cli-kit/node/ui'
7+ import { renderWarning , renderConcurrent } from '@shopify/cli-kit/node/ui'
88import { AbortError } from '@shopify/cli-kit/node/error'
9+ import { AbortController } from '@shopify/cli-kit/node/abort'
10+ import type { Writable } from 'stream'
911
1012export interface FlagValues {
1113 [ key : string ] : boolean | string | string [ ] | number | undefined
@@ -36,7 +38,11 @@ export default abstract class ThemeCommand extends Command {
3638 return configurationFileName
3739 }
3840
39- async command ( _flags : FlagValues , _session : AdminSession ) : Promise < void > { }
41+ async command (
42+ _flags : FlagValues ,
43+ _session : AdminSession ,
44+ _context ?: { stdout ?: Writable ; stderr ?: Writable } ,
45+ ) : Promise < void > { }
4046
4147 async run <
4248 TFlags extends FlagOutput & { path ?: string ; verbose ?: boolean } ,
@@ -50,50 +56,73 @@ export default abstract class ThemeCommand extends Command {
5056 const requiredFlags = klass . multiEnvironmentsFlags
5157 const { flags} = await this . parse ( klass )
5258
53- // Single environment
54- if ( ! flags . environment ) {
59+ // No environment provided
60+ if ( ! flags . environment ?. length ) {
5561 const session = await this . ensureAuthenticated ( flags )
62+
5663 await this . command ( flags , session )
64+
5765 return
5866 }
5967
60- // Synchronously authenticate all environments
61- const sessions : { [ storeFqdn : string ] : AdminSession } = { }
6268 // OCLIF parses flags.environment as an array when using the --environment & -e flag but
6369 // as a string when using the direct environment variable SHOPIFY_FLAG_ENVIRONMENT
6470 // This handles both cases
6571 const environments = Array . isArray ( flags . environment ) ? flags . environment : [ flags . environment ]
6672
73+ // If only one environment is specified, treat it as single environment mode
74+ if ( environments . length === 1 ) {
75+ const session = await this . ensureAuthenticated ( flags )
76+ await this . command ( flags , session )
77+ return
78+ }
79+
80+ // Multiple environments
81+ const sessions : { [ storeFqdn : string ] : AdminSession } = { }
82+
6783 // Authenticate on all environments sequentially to avoid race conditions,
6884 // with authentication happening in parallel.
6985 for ( const environmentName of environments ) {
7086 // eslint-disable-next-line no-await-in-loop
71- const environmentConfig = await loadEnvironment ( environmentName , 'shopify.theme.toml' , { from : flags . path } )
87+ const environmentConfig = await loadEnvironment ( environmentName , 'shopify.theme.toml' , {
88+ from : flags . path ,
89+ silent : true ,
90+ } )
7291 // eslint-disable-next-line no-await-in-loop
7392 sessions [ environmentName ] = await this . ensureAuthenticated ( environmentConfig as FlagValues )
7493 }
7594
76- // Concurrently run commands
77- await Promise . all (
78- environments . map ( async ( environment : string ) => {
79- const environmentConfig = await loadEnvironment ( environment , 'shopify.theme.toml' , { from : flags . path } )
80- const environmentFlags = {
81- ...flags ,
82- ...environmentConfig ,
83- environment : [ environment ] ,
84- }
85-
86- if ( ! this . validConfig ( environmentConfig as FlagValues , requiredFlags , environment ) ) return
87-
88- const session = sessions [ environment ]
89-
90- if ( ! session ) {
91- throw new AbortError ( `No session found for environment ${ environment } ` )
92- }
93-
94- return this . command ( environmentFlags , session )
95- } ) ,
96- )
95+ // Use renderConcurrent for multi-environment execution
96+ const abortController = new AbortController ( )
97+
98+ await renderConcurrent ( {
99+ processes : environments . map ( ( environment : string ) => ( {
100+ prefix : environment ,
101+ action : async ( stdout : Writable , stderr : Writable , _signal ) => {
102+ const environmentConfig = await loadEnvironment ( environment , 'shopify.theme.toml' , {
103+ from : flags . path ,
104+ silent : true ,
105+ } )
106+ const environmentFlags = {
107+ ...flags ,
108+ ...environmentConfig ,
109+ environment : [ environment ] ,
110+ }
111+
112+ if ( ! this . validConfig ( environmentConfig as FlagValues , requiredFlags , environment ) ) return
113+
114+ const session = sessions [ environment ]
115+
116+ if ( ! session ) {
117+ throw new AbortError ( `No session found for environment ${ environment } ` )
118+ }
119+
120+ await this . command ( environmentFlags , session , { stdout, stderr} )
121+ } ,
122+ } ) ) ,
123+ abortSignal : abortController . signal ,
124+ showTimestamps : true ,
125+ } )
97126 }
98127
99128 private async ensureAuthenticated ( flags : FlagValues ) {
0 commit comments