feat(cli): add Command.withConditionalBehavior for predicate based wrapping of commands
Type
- [ ] Refactor
- [x] Feature
- [ ] Bug Fix
- [ ] Optimization
- [ ] Documentation Update
Description
This PR introduces a composable combinator approach for adding conditional behaviors to commands based on CLI arguments.
Rather than adding separate runWith* methods for each conditional behavior (which would lead to API explosion with runWithWizard, runWithHelp, runWithValidation, etc.), this PR provides a single, extensible combinator pattern that follows functional composition principles.
Command.withConditionalBehavior(predicate, behavior)
A combinator that wraps a command to conditionally trigger a behavior based on the provided predicate function:
const command = Command.make("greet", {
name: Options.text("name")
}, ({ name }) => Effect.log(`Hello, ${name}!`))
.pipe(
Command.withConditionalBehavior(
(args) => args.length <= 1, // Trigger when no args provided
"wizard" // Run wizard mode
)
)
const cli = Command.run(command, {
name: "MyApp",
version: "1.0.0"
})
Parameters:
- predicate: (args: ReadonlyArray
) => boolean - Function that determines when to trigger the behavior - behavior: "wizard" | CustomBehaviorFunction - Either the built-in "wizard" mode or a custom function
Wizard mode on bare command:
Command.make("deploy", config).pipe(
Command.withConditionalBehavior(
(args) => args.length <= 1,
"wizard"
)
)
Command.make("migrate", config).pipe(
Command.withConditionalBehavior(
(args) => args.includes("--interactive"),
(cmd, args) => Effect.gen(function* () {
// Custom prompting logic
const confirmed = yield* promptForConfirmation()
return confirmed ? args : Effect.fail(new UserCancelled())
})
)
)
Related
- Related Issue #5699
- Closes #5699
🦋 Changeset detected
Latest commit: 7e629458108e53088b3621befd61df18673ae710
The changes in this PR will be included in the next version bump.
This PR includes changesets to release 1 package
| Name | Type |
|---|---|
| @effect/cli | Minor |
Not sure what this means? Click here to learn what changesets are.
Click here if you're a maintainer who wants to add another changeset to this PR
@ryanbas21 - thanks for the PR!
I'm not sure about having a separate run method with all the specifics around wizard mode. Because then you could make the argument that we should expose similar utilities for showing help documentation based on certain conditions, prompting on certain conditions, etc.
I think it would be nicer if a combinator could be exposed that would allow you to wrap a command and show the wizard mode based on a predicate.
@ryanbas21 - thanks for the PR!
I'm not sure about having a separate
runmethod with all the specifics around wizard mode. Because then you could make the argument that we should expose similar utilities for showing help documentation based on certain conditions, prompting on certain conditions, etc.I think it would be nicer if a combinator could be exposed that would allow you to wrap a command and show the wizard mode based on a predicate.
@IMax153 good feedback. Re-implemented it in this way. Let me know what you think?