@@ -23,22 +23,7 @@ export async function scaffoldMonorepo(projectNameArg, options) {
2323 validate : v => v && / ^ [ a - z A - Z 0 - 9 . _ - ] + $ / . test ( v ) ? true : 'Use alphanumerics, dash, underscore, dot'
2424 } ) ;
2525 }
26- if ( ! options . services ) {
27- interactiveQuestions . push ( {
28- type : 'multiselect' ,
29- name : 'services' ,
30- message : 'Select services to include:' ,
31- choices : [
32- { title : 'Node.js (Express)' , value : 'node' } ,
33- { title : 'Python (FastAPI)' , value : 'python' } ,
34- { title : 'Go (Fiber-like)' , value : 'go' } ,
35- { title : 'Java (Spring Boot)' , value : 'java' } ,
36- { title : 'Frontend (Next.js)' , value : 'frontend' }
37- ] ,
38- instructions : false ,
39- min : 1
40- } ) ;
41- }
26+
4227 if ( ! options . preset ) {
4328 interactiveQuestions . push ( {
4429 type : 'select' ,
@@ -97,9 +82,6 @@ export async function scaffoldMonorepo(projectNameArg, options) {
9782 case 'projectName' :
9883 answers . projectName = projectNameArg || 'app' ;
9984 break ;
100- case 'services' :
101- answers . services = [ 'node' ] ;
102- break ;
10385 case 'preset' :
10486 answers . preset = '' ;
10587 break ;
@@ -131,11 +113,7 @@ export async function scaffoldMonorepo(projectNameArg, options) {
131113 console . error ( chalk . red ( 'Project name is required.' ) ) ;
132114 process . exit ( 1 ) ;
133115 }
134- options . services = options . services || ( answers . services ? answers . services . join ( ',' ) : undefined ) ;
135- if ( ! options . services ) {
136- console . error ( chalk . red ( 'At least one service must be selected.' ) ) ;
137- process . exit ( 1 ) ;
138- }
116+ // Note: options.services will be handled in the dynamic flow below if not provided via CLI
139117 options . preset = options . preset || answers . preset || '' ;
140118 options . packageManager = options . packageManager || answers . packageManager || 'npm' ;
141119 if ( options . git === undefined ) options . git = answers . git ;
@@ -187,17 +165,21 @@ export async function scaffoldMonorepo(projectNameArg, options) {
187165 services . push ( { type, name, port } ) ;
188166 }
189167 } else {
190- // New dynamic interactive flow: ask how many services, then collect each.
191- const countAns = await prompts ( {
192- type : 'number' ,
193- name : 'svcCount' ,
194- message : 'How many services do you want to create?' ,
195- initial : 1 ,
196- min : 1 ,
197- validate : v => Number . isInteger ( v ) && v > 0 && v <= 50 ? true : 'Enter a positive integer (max 50)'
198- } ) ;
199- const svcCount = countAns . svcCount || 1 ;
200- for ( let i = 0 ; i < svcCount ; i ++ ) {
168+ // Dynamic interactive flow: ask how many services, then collect each.
169+ // In non-interactive mode, default to a single node service
170+ if ( nonInteractive ) {
171+ services . push ( { type : 'node' , name : 'node' , port : defaultPorts . node } ) ;
172+ } else {
173+ const countAns = await prompts ( {
174+ type : 'number' ,
175+ name : 'svcCount' ,
176+ message : 'How many services do you want to create?' ,
177+ initial : 1 ,
178+ min : 1 ,
179+ validate : v => Number . isInteger ( v ) && v > 0 && v <= 50 ? true : 'Enter a positive integer (max 50)'
180+ } ) ;
181+ const svcCount = countAns . svcCount || 1 ;
182+ for ( let i = 0 ; i < svcCount ; i ++ ) {
201183 const typeAns = await prompts ( {
202184 type : 'select' ,
203185 name : 'svcType' ,
@@ -238,41 +220,6 @@ export async function scaffoldMonorepo(projectNameArg, options) {
238220 }
239221 }
240222 services . push ( { type : svcType , name : svcName , port : svcPort } ) ;
241- }
242- }
243-
244- // Always allow customization of name & port in interactive mode (not nonInteractive)
245- if ( ! nonInteractive ) {
246- for ( let i = 0 ; i < services . length ; i ++ ) {
247- const svc = services [ i ] ;
248- const rename = await prompts ( {
249- type : 'text' ,
250- name : 'newName' ,
251- message : `Name for ${ svc . type } service (leave blank to keep '${ svc . name } '):` ,
252- validate : v => ! v || ( / ^ [ a - z A - Z 0 - 9 . _ - ] + $ / . test ( v ) ? true : 'Use alphanumerics, dash, underscore, dot' )
253- } ) ;
254- if ( rename . newName && rename . newName !== svc . name ) {
255- if ( reservedNames . has ( rename . newName ) ) {
256- console . log ( chalk . red ( `Name '${ rename . newName } ' is reserved. Keeping '${ svc . name } '.` ) ) ;
257- } else if ( services . find ( s => s !== svc && s . name === rename . newName ) ) {
258- console . log ( chalk . red ( `Name '${ rename . newName } ' already used. Keeping '${ svc . name } '.` ) ) ;
259- } else {
260- svc . name = rename . newName ;
261- }
262- }
263- const portResp = await prompts ( {
264- type : 'text' ,
265- name : 'newPort' ,
266- message : `Port for ${ svc . name } (${ svc . type } ) (default ${ svc . port } ):` ,
267- validate : v => ! v || ( / ^ \d + $ / . test ( v ) && + v > 0 && + v <= 65535 ) ? true : 'Enter a valid port 1-65535'
268- } ) ;
269- if ( portResp . newPort ) {
270- const newPort = Number ( portResp . newPort ) ;
271- if ( services . find ( s => s !== svc && s . port === newPort ) ) {
272- console . log ( chalk . red ( `Port ${ newPort } already used; keeping ${ svc . port } .` ) ) ;
273- } else {
274- svc . port = newPort ;
275- }
276223 }
277224 }
278225 }
0 commit comments