1
+ import EventEmitter from 'node:events' ;
1
2
import { createRequire } from 'node:module' ;
2
3
import { basename , isAbsolute , join , relative , resolve } from 'node:path' ;
3
4
import process from 'node:process' ;
@@ -34,15 +35,15 @@ import { type ConflicterOptions } from '@yeoman/conflicter';
34
35
import { defaults , pick } from 'lodash-es' ;
35
36
import { ComposedStore } from './composed-store.js' ;
36
37
import Store from './store.js' ;
37
- import Environment from './environment.js' ;
38
38
import type YeomanCommand from './util/command.js' ;
39
39
import { asNamespace , defaultLookups } from './util/namespace.js' ;
40
40
import { type LookupOptions , lookupGenerators } from './generator-lookup.js' ;
41
41
import { UNKNOWN_NAMESPACE , UNKNOWN_RESOLVED , defaultQueues } from './constants.js' ;
42
42
import { resolveModulePath } from './util/resolve.js' ;
43
43
import { commitSharedFsTask } from './commit.js' ;
44
- // eslint-disable-next-line import/order
45
44
import { packageManagerInstallTask } from './package-manager.js' ;
45
+ // eslint-disable-next-line import/order
46
+ import { splitArgsFromString } from './util/util.js' ;
46
47
47
48
const require = createRequire ( import . meta. url ) ;
48
49
@@ -61,42 +62,6 @@ export type EnvironmentOptions = BaseEnvironmentOptions &
61
62
nodePackageManager ?: string ;
62
63
} ;
63
64
64
- /**
65
- * Two-step argument splitting function that first splits arguments in quotes,
66
- * and then splits up the remaining arguments if they are not part of a quote.
67
- */
68
- function splitArgsFromString ( argsString : string | string [ ] ) : string [ ] {
69
- if ( Array . isArray ( argsString ) ) {
70
- return argsString ;
71
- }
72
-
73
- let result : string [ ] = [ ] ;
74
- if ( ! argsString ) {
75
- return result ;
76
- }
77
-
78
- const quoteSeparatedArgs = argsString . split ( / ( " [ ^ " ] * " ) / ) . filter ( Boolean ) ;
79
- for ( const arg of quoteSeparatedArgs ) {
80
- if ( arg . includes ( '"' ) ) {
81
- result . push ( arg . replace ( / " / g, '' ) ) ;
82
- } else {
83
- result = result . concat ( arg . trim ( ) . split ( ' ' ) ) ;
84
- }
85
- }
86
-
87
- return result ;
88
- }
89
-
90
- const getComposeOptions = ( args ?: any , options ?: any , composeOptions ?: any ) : ComposeOptions => {
91
- if ( typeof composeOptions === 'object' ) {
92
- composeOptions . generatorArgs = args ;
93
- composeOptions . generatorOptions = options ;
94
- return composeOptions ;
95
- }
96
-
97
- return composeOptions ;
98
- } ;
99
-
100
65
const getInstantiateOptions = ( args ?: any , options ?: any ) : InstantiateOptions => {
101
66
if ( Array . isArray ( args ) || typeof args === 'string' ) {
102
67
return { generatorArgs : splitArgsFromString ( args ) , generatorOptions : options } ;
@@ -116,7 +81,42 @@ const getInstantiateOptions = (args?: any, options?: any): InstantiateOptions =>
116
81
return { generatorOptions : options } ;
117
82
} ;
118
83
119
- export default class EnvironmentBase extends Environment implements BaseEnvironment {
84
+ const getComposeOptions = ( ...varargs : any [ ] ) : ComposeOptions => {
85
+ if ( varargs . filter ( Boolean ) . length === 0 ) return { } ;
86
+
87
+ const [ args , options , composeOptions ] = varargs ;
88
+ if ( typeof args === 'boolean' ) {
89
+ return { schedule : args } ;
90
+ }
91
+
92
+ let generatorArgs ;
93
+ let generatorOptions ;
94
+ if ( args !== undefined ) {
95
+ if ( typeof args === 'object' ) {
96
+ if ( 'generatorOptions' in args || 'generatorArgs' in args || 'schedule' in args ) {
97
+ return args ;
98
+ }
99
+
100
+ generatorOptions = args ;
101
+ } else {
102
+ generatorArgs = Array . isArray ( args ) ? args : splitArgsFromString ( String ( args ) ) ;
103
+ }
104
+ }
105
+
106
+ if ( typeof options === 'boolean' ) {
107
+ return { generatorArgs, generatorOptions, schedule : options } ;
108
+ }
109
+
110
+ generatorOptions = generatorOptions ?? options ;
111
+
112
+ if ( typeof composeOptions === 'boolean' ) {
113
+ return { generatorArgs, generatorOptions, schedule : composeOptions } ;
114
+ }
115
+
116
+ return composeOptions ;
117
+ } ;
118
+
119
+ export default class EnvironmentBase extends EventEmitter implements BaseEnvironment {
120
120
cwd : string ;
121
121
adapter : QueuedAdapter ;
122
122
sharedFs : MemFs < MemFsEditorFile > ;
@@ -137,12 +137,7 @@ export default class EnvironmentBase extends Environment implements BaseEnvironm
137
137
protected _rootGenerator ?: BaseGenerator ;
138
138
protected compatibilityMode ?: false | 'v4' ;
139
139
140
- constructor ( options ?: EnvironmentOptions ) ;
141
- constructor ( options : EnvironmentOptions = { } , adapterCompat ?: InputOutputAdapter ) {
142
- if ( adapterCompat ) {
143
- options . adapter = adapterCompat ;
144
- }
145
-
140
+ constructor ( options : EnvironmentOptions = { } ) {
146
141
super ( ) ;
147
142
148
143
this . setMaxListeners ( 100 ) ;
@@ -203,11 +198,6 @@ export default class EnvironmentBase extends Environment implements BaseEnvironm
203
198
this . experimental = experimental || process . argv . includes ( '--experimental' ) ;
204
199
205
200
this . alias ( / ^ ( [ ^ : ] + ) $ / , '$1:app' ) ;
206
-
207
- this . loadSharedOptions ( this . options ) ;
208
- if ( this . sharedOptions . skipLocalCache === undefined ) {
209
- this . sharedOptions . skipLocalCache = true ;
210
- }
211
201
}
212
202
213
203
async applyTransforms ( transformStreams : Transform [ ] , options : ApplyTransformsOptions = { } ) : Promise < void > {
@@ -383,6 +373,25 @@ export default class EnvironmentBase extends Environment implements BaseEnvironm
383
373
return generator as unknown as G ;
384
374
}
385
375
376
+ /**
377
+ * @protected
378
+ * Compose with the generator.
379
+ *
380
+ * @param {String } namespaceOrPath
381
+ * @return {Generator } The instantiated generator or the singleton instance.
382
+ */
383
+ async composeWith < G extends BaseGenerator = BaseGenerator > (
384
+ generator : string | GetGeneratorConstructor < G > ,
385
+ composeOptions ?: ComposeOptions < G > ,
386
+ ) : Promise < G > ;
387
+ async composeWith < G extends BaseGenerator = BaseGenerator > ( generator : string | GetGeneratorConstructor < G > , ...args : any [ ] ) : Promise < G > {
388
+ const options = getComposeOptions ( ...args ) as ComposeOptions < G > ;
389
+ const { schedule = true , ...instantiateOptions } = options ;
390
+
391
+ const generatorInstance = await this . create ( generator , instantiateOptions ) ;
392
+ return this . queueGenerator ( generatorInstance , { schedule } ) ;
393
+ }
394
+
386
395
/**
387
396
* Given a String `filepath`, tries to figure out the relative namespace.
388
397
*
0 commit comments