Skip to content

Commit c860e46

Browse files
committed
fix: interactive inputs with existing config/cli options
1 parent bb0248f commit c860e46

2 files changed

Lines changed: 54 additions & 11 deletions

File tree

src/cmd.ts

Lines changed: 14 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -10,7 +10,7 @@ import { log } from "./logger"
1010
import { MassargCommand } from "massarg/command"
1111
import { getUniqueTmpPath as generateUniqueTmpPath } from "./file"
1212
import { colorize } from "./colors"
13-
import { promptForMissingConfig, resolveInputs } from "./prompts"
13+
import { promptBeforeConfig, promptAfterConfig, resolveInputs } from "./prompts"
1414
import { initScaffold } from "./init"
1515

1616
export async function parseCliArgs(args = process.argv.slice(2)) {
@@ -33,8 +33,10 @@ export async function parseCliArgs(args = process.argv.slice(2)) {
3333
log(config, LogLevel.debug, `Simple Scaffold v${pkg.version}`)
3434
config.tmpDir = generateUniqueTmpPath()
3535
try {
36-
// Auto-detect config file in cwd if not explicitly provided
37-
if (!config.config && !config.git) {
36+
// Auto-detect config file in cwd — but only if the user didn't
37+
// explicitly provide templates/output (which signals a one-time run)
38+
const isOneTimeRun = config.templates?.length > 0 || config.output
39+
if (!config.config && !config.git && !isOneTimeRun) {
3840
try {
3941
config.config = await findConfigFile(process.cwd())
4042
log(config, LogLevel.debug, `Auto-detected config file: ${config.config}`)
@@ -43,19 +45,24 @@ export async function parseCliArgs(args = process.argv.slice(2)) {
4345
}
4446
}
4547

46-
// Load config early so we can prompt for template key
48+
// Load config map early so we can prompt for name and template key
4749
const hasConfigSource = Boolean(config.config || config.git)
4850
let configMap: ScaffoldConfigMap | undefined
4951
if (hasConfigSource) {
5052
configMap = await getConfigFile(config)
5153
}
5254

53-
// Prompt for missing values interactively
54-
config = await promptForMissingConfig(config, configMap)
55+
// Phase 1: prompt for name + key (needed before parseConfigFile)
56+
config = await promptBeforeConfig(config, configMap)
5557

58+
// Parse and merge the config file
5659
log(config, LogLevel.debug, "Parsing config file...", config)
5760
const parsed = await parseConfigFile(config)
58-
const resolved = await resolveInputs(parsed)
61+
62+
// Phase 2: prompt for anything still missing after config merge
63+
const prompted = await promptAfterConfig(parsed)
64+
65+
const resolved = await resolveInputs(prompted)
5966
await Scaffold(resolved)
6067
} catch (e) {
6168
const message = "message" in (e as object) ? (e as Error).message : e?.toString()

src/prompts.ts

Lines changed: 40 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -156,10 +156,10 @@ export function isInteractive(): boolean {
156156
}
157157

158158
/**
159-
* Fills in missing config values by prompting the user interactively.
160-
* Only prompts when running in a TTY — in non-interactive mode, returns config as-is.
159+
* Prompts for name and template key before the config file is parsed.
160+
* These are needed by parseConfigFile to know which template to load.
161161
*/
162-
export async function promptForMissingConfig(
162+
export async function promptBeforeConfig(
163163
config: ScaffoldCmdConfig,
164164
configMap?: ScaffoldConfigMap,
165165
): Promise<ScaffoldCmdConfig> {
@@ -178,7 +178,19 @@ export async function promptForMissingConfig(
178178
}
179179
}
180180

181-
if (!config.output) {
181+
return config
182+
}
183+
184+
/**
185+
* Prompts for any values still missing after the config file has been parsed.
186+
* Only prompts in interactive mode.
187+
*/
188+
export async function promptAfterConfig(config: ScaffoldConfig): Promise<ScaffoldConfig> {
189+
if (!isInteractive()) {
190+
return config
191+
}
192+
193+
if (!config.output || (typeof config.output === "string" && !config.output)) {
182194
config.output = await promptForOutput()
183195
}
184196

@@ -189,6 +201,30 @@ export async function promptForMissingConfig(
189201
return config
190202
}
191203

204+
/**
205+
* @deprecated Use {@link promptBeforeConfig} and {@link promptAfterConfig} instead.
206+
*/
207+
export async function promptForMissingConfig(
208+
config: ScaffoldCmdConfig,
209+
configMap?: ScaffoldConfigMap,
210+
): Promise<ScaffoldCmdConfig> {
211+
const afterPre = await promptBeforeConfig(config, configMap)
212+
213+
if (!isInteractive()) {
214+
return afterPre
215+
}
216+
217+
if (!afterPre.output) {
218+
afterPre.output = await promptForOutput()
219+
}
220+
221+
if (!afterPre.templates || afterPre.templates.length === 0) {
222+
afterPre.templates = await promptForTemplates()
223+
}
224+
225+
return afterPre
226+
}
227+
192228
/**
193229
* Prompts for any required inputs defined in the scaffold config and merges them into data.
194230
* Only prompts in interactive mode; in non-interactive mode, only applies defaults.

0 commit comments

Comments
 (0)