From bd322ebeb8dd51f7c14e27dff459fa70aa0406c8 Mon Sep 17 00:00:00 2001 From: Luan Nico Date: Thu, 17 Apr 2025 18:02:02 -0400 Subject: [PATCH 1/2] feat: Add validation to non-interactive mode and better error messages --- lib/commands/create_command.dart | 13 +++++++++++-- lib/utils.dart | 33 ++++++++++++++++++++++++-------- 2 files changed, 36 insertions(+), 10 deletions(-) diff --git a/lib/commands/create_command.dart b/lib/commands/create_command.dart index 6f817fd..ed3a002 100644 --- a/lib/commands/create_command.dart +++ b/lib/commands/create_command.dart @@ -24,7 +24,12 @@ Future createCommand(ArgResults command) async { 'Choose a name for your project: ', desc: 'Note: this must be a valid dart identifier (no dashes). ' 'For example: my_game', - validate: (it) => !it.contains('-') && it != 'test', + validate: (it) => switch(it) { + _ when it.isEmpty => 'Name cannot be empty', + _ when it.contains('-') => 'Name cannot contain dashes', + _ when it == 'test' => 'Name cannot be "test" as it conflicts with the Dart package', + _ => null, + }, ); final org = getString( @@ -35,7 +40,11 @@ Future createCommand(ArgResults command) async { desc: 'Note: this is a dot separated list of "packages", ' 'normally in reverse domain notation. ' 'For example: org.flame_engine.games', - validate: (it) => !it.contains('-'), + validate: (it) => switch(it) { + _ when it.isEmpty => 'Org cannot be empty', + _ when it.contains('-') => 'Org cannot contain dashes', + _ => null, + }, ); final versions = FlameVersionManager.singleton.versions; diff --git a/lib/utils.dart b/lib/utils.dart index 0b6e621..3ab2d06 100644 --- a/lib/utils.dart +++ b/lib/utils.dart @@ -17,7 +17,7 @@ String getString( String message, { required bool isInteractive, String? desc, - bool Function(String)? validate, + String? Function(String)? validate, }) { var value = results[name] as String?; if (!isInteractive) { @@ -25,12 +25,31 @@ String getString( print('Missing parameter $name is required.'); exit(1); } + final error = validate?.call(value); + if (error != null) { + print('Invalid value $value provided: $error'); + exit(1); + } } while (value == null || value.isEmpty) { if (desc != null) { stdout.write(ansi.darkGray.wrap('\n$desc\u{1B}[1A\r')); } - value = prompts.get(message, validate: validate); + value = prompts.get( + message, + validate: (e) { + final error = validate?.call(e); + if (error != null) { + // clear the line + stdout.write('\n\r\u{1B}[K'); + stdout.write(ansi.red.wrap('$error\u{1B}[1A\r')); + return false; + } else { + stdout.write('\n\r\u{1B}[K'); + return true; + } + }, + ); if (desc != null) { stdout.write('\r\u{1B}[K'); } @@ -77,14 +96,14 @@ String getOption( } List _unwrap(dynamic value) { - return switch(value) { + return switch (value) { null => [], String _ => [value], List _ => value, List _ => value.map((e) => e.toString()).toList(), _ => throw ArgumentError( - 'Invalid type for value (${value.runtimeType}): $value', - ), + 'Invalid type for value (${value.runtimeType}): $value', + ), }; } @@ -118,9 +137,7 @@ List getMultiOption( if (desc != null) { stdout.write(ansi.darkGray.wrap('\n$desc\u{1B}[1A\r')); } - final selectedOptions = value.isEmpty - ? startingOptions - : value; + final selectedOptions = value.isEmpty ? startingOptions : value; value = cbx(message, options, selectedOptions); if (desc != null) { stdout.write('\r\u{1B}[K'); From cf7a1dc4b9a0b4b395f93c1a60160538717336f0 Mon Sep 17 00:00:00 2001 From: Luan Nico Date: Thu, 17 Apr 2025 18:05:52 -0400 Subject: [PATCH 2/2] Formatting --- lib/commands/create_command.dart | 7 ++++--- lib/commands/version_command.dart | 2 +- 2 files changed, 5 insertions(+), 4 deletions(-) diff --git a/lib/commands/create_command.dart b/lib/commands/create_command.dart index ed3a002..5eb6851 100644 --- a/lib/commands/create_command.dart +++ b/lib/commands/create_command.dart @@ -24,10 +24,11 @@ Future createCommand(ArgResults command) async { 'Choose a name for your project: ', desc: 'Note: this must be a valid dart identifier (no dashes). ' 'For example: my_game', - validate: (it) => switch(it) { + validate: (it) => switch (it) { _ when it.isEmpty => 'Name cannot be empty', _ when it.contains('-') => 'Name cannot contain dashes', - _ when it == 'test' => 'Name cannot be "test" as it conflicts with the Dart package', + _ when it == 'test' => 'Name cannot be "test", ' + 'as it conflicts with the Dart package', _ => null, }, ); @@ -40,7 +41,7 @@ Future createCommand(ArgResults command) async { desc: 'Note: this is a dot separated list of "packages", ' 'normally in reverse domain notation. ' 'For example: org.flame_engine.games', - validate: (it) => switch(it) { + validate: (it) => switch (it) { _ when it.isEmpty => 'Org cannot be empty', _ when it.contains('-') => 'Org cannot contain dashes', _ => null, diff --git a/lib/commands/version_command.dart b/lib/commands/version_command.dart index f6f0185..3d0a6e9 100644 --- a/lib/commands/version_command.dart +++ b/lib/commands/version_command.dart @@ -8,4 +8,4 @@ Future versionCommand() async { await runExecutableArguments('dart', ['--version'], verbose: true); print(''); await runExecutableArguments('flutter', ['--version'], verbose: true); -} \ No newline at end of file +}