@@ -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' ,
@@ -87,9 +72,6 @@ export async function scaffoldMonorepo(projectNameArg, options) {
8772 case 'projectName' :
8873 answers . projectName = projectNameArg || 'app' ;
8974 break ;
90- case 'services' :
91- answers . services = [ 'node' ] ;
92- break ;
9375 case 'preset' :
9476 answers . preset = '' ;
9577 break ;
@@ -118,11 +100,7 @@ export async function scaffoldMonorepo(projectNameArg, options) {
118100 console . error ( chalk . red ( 'Project name is required.' ) ) ;
119101 process . exit ( 1 ) ;
120102 }
121- options . services = options . services || ( answers . services ? answers . services . join ( ',' ) : undefined ) ;
122- if ( ! options . services ) {
123- console . error ( chalk . red ( 'At least one service must be selected.' ) ) ;
124- process . exit ( 1 ) ;
125- }
103+ // Note: options.services will be handled in the dynamic flow below if not provided via CLI
126104 options . preset = options . preset || answers . preset || '' ;
127105 options . packageManager = options . packageManager || answers . packageManager || 'npm' ;
128106 if ( options . git === undefined ) options . git = answers . git ;
@@ -173,17 +151,21 @@ export async function scaffoldMonorepo(projectNameArg, options) {
173151 services . push ( { type, name, port } ) ;
174152 }
175153 } else {
176- // New dynamic interactive flow: ask how many services, then collect each.
177- const countAns = await prompts ( {
178- type : 'number' ,
179- name : 'svcCount' ,
180- message : 'How many services do you want to create?' ,
181- initial : 1 ,
182- min : 1 ,
183- validate : v => Number . isInteger ( v ) && v > 0 && v <= 50 ? true : 'Enter a positive integer (max 50)'
184- } ) ;
185- const svcCount = countAns . svcCount || 1 ;
186- for ( let i = 0 ; i < svcCount ; i ++ ) {
154+ // Dynamic interactive flow: ask how many services, then collect each.
155+ // In non-interactive mode, default to a single node service
156+ if ( nonInteractive ) {
157+ services . push ( { type : 'node' , name : 'node' , port : defaultPorts . node } ) ;
158+ } else {
159+ const countAns = await prompts ( {
160+ type : 'number' ,
161+ name : 'svcCount' ,
162+ message : 'How many services do you want to create?' ,
163+ initial : 1 ,
164+ min : 1 ,
165+ validate : v => Number . isInteger ( v ) && v > 0 && v <= 50 ? true : 'Enter a positive integer (max 50)'
166+ } ) ;
167+ const svcCount = countAns . svcCount || 1 ;
168+ for ( let i = 0 ; i < svcCount ; i ++ ) {
187169 const typeAns = await prompts ( {
188170 type : 'select' ,
189171 name : 'svcType' ,
@@ -224,41 +206,6 @@ export async function scaffoldMonorepo(projectNameArg, options) {
224206 }
225207 }
226208 services . push ( { type : svcType , name : svcName , port : svcPort } ) ;
227- }
228- }
229-
230- // Always allow customization of name & port in interactive mode (not nonInteractive)
231- if ( ! nonInteractive ) {
232- for ( let i = 0 ; i < services . length ; i ++ ) {
233- const svc = services [ i ] ;
234- const rename = await prompts ( {
235- type : 'text' ,
236- name : 'newName' ,
237- message : `Name for ${ svc . type } service (leave blank to keep '${ svc . name } '):` ,
238- validate : v => ! v || ( / ^ [ a - z A - Z 0 - 9 . _ - ] + $ / . test ( v ) ? true : 'Use alphanumerics, dash, underscore, dot' )
239- } ) ;
240- if ( rename . newName && rename . newName !== svc . name ) {
241- if ( reservedNames . has ( rename . newName ) ) {
242- console . log ( chalk . red ( `Name '${ rename . newName } ' is reserved. Keeping '${ svc . name } '.` ) ) ;
243- } else if ( services . find ( s => s !== svc && s . name === rename . newName ) ) {
244- console . log ( chalk . red ( `Name '${ rename . newName } ' already used. Keeping '${ svc . name } '.` ) ) ;
245- } else {
246- svc . name = rename . newName ;
247- }
248- }
249- const portResp = await prompts ( {
250- type : 'text' ,
251- name : 'newPort' ,
252- message : `Port for ${ svc . name } (${ svc . type } ) (default ${ svc . port } ):` ,
253- validate : v => ! v || ( / ^ \d + $ / . test ( v ) && + v > 0 && + v <= 65535 ) ? true : 'Enter a valid port 1-65535'
254- } ) ;
255- if ( portResp . newPort ) {
256- const newPort = Number ( portResp . newPort ) ;
257- if ( services . find ( s => s !== svc && s . port === newPort ) ) {
258- console . log ( chalk . red ( `Port ${ newPort } already used; keeping ${ svc . port } .` ) ) ;
259- } else {
260- svc . port = newPort ;
261- }
262209 }
263210 }
264211 }
0 commit comments