-
-
Notifications
You must be signed in to change notification settings - Fork 99
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
feat: support conditional prompting for variables #1251
Comments
brick.yaml
I would like the new feature too. I have try a little change of the source code to add a new option like example like this vars:
injectable_enable:
type: boolean
default: true
prompt: 是否声明为injectable?
injectable:
type: enum
depend-on: injectable_enable
default: "lazySingleton"
prompt: 使用哪种类型的injectable(仅在声明为injectable时生效)?
values:
- "singleton"
- "lazySingleton" so when the source code I change like follow in mason some change like this /// add new code to change constructor
...
/// An optional description of the variable.
final String? description;
// add new code here
/// An optional dependency of the variable.
final String? dependOn;
/// An optional default value for the variable.
@JsonKey(name: 'default')
final Object? defaultValue;
... in mason_cli ...
for (final entry in _brick.vars.entries) {
final variable = entry.key;
final properties = entry.value;
// add new code
if (properties.dependOn != null &&
const [null, '', false].contains(vars[properties.dependOn])) {
continue;
}
...
}
... It is a easy way, but I do not know there is other design defect. I found that yeoman support function condition, I do not know if we need it. |
Thanks for the issue! I think we need to have a more detailed proposal. The snippet from @Farley-Chen seems like a good start; however, it's unclear how this would work with non-boolean variable values (e.g. I only want to ask for variable B if the value of variable A is "foo"). There are lots of cases to consider and initially it seems to me that we'd need to support scripting within the yaml to satisfy all the requirements (similar to GitHub workflow syntax) however; I don't love having scripting directly in yaml since you lose the ability to execute, test, lint, etc. |
This is a feature, I'd definitely love to see in Mason. The proposal of @Farley-Chen is a good starting point, but has the drawback, that the My ProposalMy proposal is to introduce the This business logic allows and enables the implementation of a complete control flow of all the variables defined in the ExampleRelevant part of vars:
has_authentication:
type: boolean
description: If app should support authentication or not.
default: true
prompt: Do you want support for authentication?
web_client_id:
type: string
description: Web client id string in order to allow authentication with Google provider.
default: YOUR_WEBCLIENT_ID
pre_prompt: isWebClientIdNeeded # This is the name of the Dart function that checks the value of the previous has_authentication variable. If it is false, this variable shall not be prompted for value.
prompt: Paste here the web client id from Google Firebase Console. The import 'package:mason/mason.dart';
bool isWebClientIdNeeded(HookContext context) {
if (context.vars['has_authentication']) {
// prompt for web_client_id
return true;
}
// skip prompting web_client_id
return false;
} ComparisonIn the following, I compare my proposal with the existing solution, where brick developers are forced to define conditional variables in hooks, instead of the My proposed solution:
Existing solution, in which conditional variables have to be moved from the
Potential errors of brick developers, when using my proposal
|
Hi @ka-zo ! Thanks for chiming in. Your proposal reminds me to how Visual Studio Code extension utilise custom when clauses. I do believe the conditional logic should be in a programming language and not a markup language such as YAML. As @felangel stated, programming languages already provide testing out of the box. Hence, I like fact that your proposal used Dart to define the conditional logic. Decision treeI would like to bring attention to decision trees. I think it would be very nice if, as a consumer of a brick, I could know the decision tree associated with a variable. In other words, knowing at a glance when will variable "xyz" be prompted for, or what other variables are needed when variable "abc" is provided. If we still want to have the vars:
animals:
type: enum
values: ["none", "dogs", "cats"]
default: "none"
prompt: What animal do you want to adopt?
with:
dogs:
type: number
when: # How we allow specifying this condition is to be defined. (animals == dogs)
prompt: How many dogs would you like to adopt?
with:
names:
type: list
when: # How we allow specifying this condition is to be defined. (dogs > 0)
prompt: What should their names be? I haven't had much time to compose an actual proposal. Just wanted to emphasize that I would value and appreciate a solution that provides something that looks like a decision tree to the user of a brick, so that they can conceptualize what variables could be prompted, and when, at a glance. P.S. I feel that the ability of specifying custom |
Hi @alestiago , Good point. I like your suggestion a lot, it provides an immediate overview of the dependencies for brick developers. What do you think about combining your proposal with mine: decision tree + Dart code based decisions? Dart code based business logic for the decisions allow implementing even complex decision processes, furthermore the My example would look like this, after combining it with your proposal: The relevant part of the vars:
has_authentication:
type: boolean
description: If app should support authentication or not.
default: true
prompt: Do you want support for authentication?
with:
web_client_id:
type: string
when: hasAuthentication # This is the name of the Dart function that checks the value of the previous has_authentication variable. If it is false, this variable shall not be prompted for value.
description: Web client id string in order to allow authentication with Google provider.
default: YOUR_WEBCLIENT_ID
prompt: Paste here the web client id from Google Firebase Console. The conditions could be stored in the import 'package:mason/mason.dart';
bool hasAuthentication(HookContext context) {
if (context.vars['has_authentication']) {
// prompt for web_client_id
return true;
}
// skip prompting web_client_id
return false;
} The The signature of the dart function implementing the conditional logic can still be the same: This would allow even more complex decisions, like creating many conditional variables on the same level, each corresponding to a specific number range of the parent node of type number. Walking through the decision tree, and prompting (or not prompting) each variable could be done in the order the variables are located in the Any child variable, whose parent variable does not get prompted, shall not be prompted either. |
Apologies for the delay! I need to think some more about this and do some more research to see if there are any existing standards in place (GitHub workflows conditional steps/jobs comes to mind) but overall the main problems I see with the current proposal are:
FragileWhat I mean by that is, the string "hasAuthentication" has to match in the brick.yaml and in the hooks. Additional OverheadIn addition, based on the proposal, we'd need to add a new optional file (which needs to be compiled) when you have conditional vars which would result in longer wait times when installing a brick for the first time, and longer execution times when running a brick (on each run). SummaryFor those reasons, I'd prefer to hold off on implementing the proposed solution. Ideally we can arrive at a solution that doesn't have all the same short-comings especially since conditional variable prompting is already possible today and this proposal is focusing on making conditional variables part of the brick.yaml instead of relying on hooks to do the prompting programmatically. |
Description
As a mason user, I would sometimes like to prompt for variables conditionally depending on the previous answers.
Conditional prompting can be achieved directly through the
pre_gen.dart
hook. However, if the prompting logic is moved to the pre generation hook thebrick.yaml
will no longer need to declare the variables.Requirements
Additional context
The text was updated successfully, but these errors were encountered: