diff --git a/.gitignore b/.gitignore new file mode 100644 index 0000000..996f812 --- /dev/null +++ b/.gitignore @@ -0,0 +1,6 @@ +.dart_tool/ + +.idea/ +*.iml + +pubspec.lock diff --git a/README.md b/README.md index ecde512..e4213b8 100644 --- a/README.md +++ b/README.md @@ -21,3 +21,13 @@ reporting. ## Contributing Guidelines To contribute to cli_tools, see the [contribution guidelines](CONTRIBUTING.md). + +### Development workflow + +This repo uses [melos](https://melos.invertase.dev/) to aid in development, +test, and publishing. + +After cloning the repo, run `melos bootstrap` (or `melos bs`) to initialize it +(this will also run `dart pub get`). + +Run `melos test` to run all the tests. diff --git a/melos.yaml b/melos.yaml new file mode 100644 index 0000000..9f54402 --- /dev/null +++ b/melos.yaml @@ -0,0 +1,19 @@ +name: cli_tools_repo + +packages: + - packages/** + +ide: + intellij: + enabled: false + +command: + version: + workspaceChangelog: false + +scripts: + test: + description: "Run all tests" + run: dart test + exec: + concurrency: 1 diff --git a/packages/cli_tools/.gitignore b/packages/cli_tools/.gitignore index 3a85790..2db9f72 100644 --- a/packages/cli_tools/.gitignore +++ b/packages/cli_tools/.gitignore @@ -1,3 +1,5 @@ # https://dart.dev/guides/libraries/private-files # Created by `dart pub` .dart_tool/ + +pubspec.lock diff --git a/packages/cli_tools/CHANGELOG.md b/packages/cli_tools/CHANGELOG.md index a4b9608..a128d85 100644 --- a/packages/cli_tools/CHANGELOG.md +++ b/packages/cli_tools/CHANGELOG.md @@ -1,4 +1,6 @@ -# Changelog +## 0.7.1 + + - **CHORE**(cli_tools): Bumped `config` dependency. ## 0.7.0 - refactor!: Moved out the `config` library from the `cli_tools` package and into its own package, to be published as `config` on pub.dev. diff --git a/packages/cli_tools/analysis_options.yaml b/packages/cli_tools/analysis_options.yaml index 65336e6..3ce6aff 100644 --- a/packages/cli_tools/analysis_options.yaml +++ b/packages/cli_tools/analysis_options.yaml @@ -1,5 +1,12 @@ include: package:serverpod_lints/cli.yaml analyzer: + language: + strict-raw-types: false errors: - unnecessary_final: false + inference_failure_on_instance_creation: ignore + inference_failure_on_function_invocation: ignore + +linter: + rules: + prefer_relative_imports: true diff --git a/packages/cli_tools/example/main.dart b/packages/cli_tools/example/main.dart index f968a7c..7b44ac4 100644 --- a/packages/cli_tools/example/main.dart +++ b/packages/cli_tools/example/main.dart @@ -1,8 +1,8 @@ import 'package:cli_tools/cli_tools.dart'; import 'package:config/config.dart'; -Future main(List args) async { - var commandRunner = BetterCommandRunner( +Future main(final List args) async { + final commandRunner = BetterCommandRunner( 'example', 'Example CLI command', globalOptions: [ @@ -29,7 +29,7 @@ Future main(List args) async { } else { logLevel = LogLevel.info; } - var logger = StdOutLogger(logLevel); + final logger = StdOutLogger(logLevel); logger.info('An info message'); logger.error('An error message'); @@ -97,12 +97,12 @@ class TimeSeriesCommand extends BetterCommand { String get description => 'Generate a series of time stamps'; @override - void runWithConfig(Configuration commandConfig) { + void runWithConfig(final Configuration commandConfig) { var start = DateTime.now(); - var until = commandConfig.value(TimeSeriesOption.until); + final until = commandConfig.value(TimeSeriesOption.until); // exactly one of these options is set - var length = commandConfig.optionalValue(TimeSeriesOption.length); + final length = commandConfig.optionalValue(TimeSeriesOption.length); var interval = commandConfig.optionalValue(TimeSeriesOption.interval); interval ??= (until.difference(start) ~/ length!); if (interval < const Duration(milliseconds: 1)) { diff --git a/packages/cli_tools/example/simple_command_example.dart b/packages/cli_tools/example/simple_command_example.dart index d61b547..95b4fe2 100644 --- a/packages/cli_tools/example/simple_command_example.dart +++ b/packages/cli_tools/example/simple_command_example.dart @@ -13,8 +13,8 @@ import 'package:config/config.dart'; /// ```sh /// INTERVAL=1s dart run example/simple_command_example.dart show /// ``` -Future main(List args) async { - var commandRunner = BetterCommandRunner( +Future main(final List args) async { + final commandRunner = BetterCommandRunner( 'example', 'Example CLI command', ); @@ -56,8 +56,8 @@ class ShowCommand extends BetterCommand { String get description => 'Show the configured interval'; @override - void runWithConfig(Configuration commandConfig) { - var interval = commandConfig.value(ShowOption.interval); + void runWithConfig(final Configuration commandConfig) { + final interval = commandConfig.value(ShowOption.interval); print('interval: $interval'); } } diff --git a/packages/cli_tools/lib/logger.dart b/packages/cli_tools/lib/logger.dart index 81944b3..daccec2 100644 --- a/packages/cli_tools/lib/logger.dart +++ b/packages/cli_tools/lib/logger.dart @@ -1,4 +1,4 @@ +export 'src/logger/helpers/ansi_style.dart'; export 'src/logger/logger.dart'; export 'src/logger/loggers/std_out_logger.dart'; export 'src/logger/loggers/void_logger.dart'; -export 'src/logger/helpers/ansi_style.dart'; diff --git a/packages/cli_tools/lib/package_version.dart b/packages/cli_tools/lib/package_version.dart index 8d0ffe7..a8ca08b 100644 --- a/packages/cli_tools/lib/package_version.dart +++ b/packages/cli_tools/lib/package_version.dart @@ -1,3 +1,3 @@ export 'src/package_version/package_version.dart'; -export 'src/package_version/pub_api_client_exceptions.dart'; export 'src/package_version/pub_api_client.dart'; +export 'src/package_version/pub_api_client_exceptions.dart'; diff --git a/packages/cli_tools/lib/src/analytics/analytics.dart b/packages/cli_tools/lib/src/analytics/analytics.dart index 9ebe489..4802252 100644 --- a/packages/cli_tools/lib/src/analytics/analytics.dart +++ b/packages/cli_tools/lib/src/analytics/analytics.dart @@ -10,7 +10,7 @@ abstract interface class Analytics { void cleanUp(); /// Track an event. - void track({required String event}); + void track({required final String event}); } /// Analytics service for MixPanel. @@ -21,9 +21,9 @@ class MixPanelAnalytics implements Analytics { final String _version; MixPanelAnalytics({ - required String uniqueUserId, - required String projectToken, - required String version, + required final String uniqueUserId, + required final String projectToken, + required final String version, }) : _uniqueUserId = uniqueUserId, _projectToken = projectToken, _version = version; @@ -32,8 +32,8 @@ class MixPanelAnalytics implements Analytics { void cleanUp() {} @override - void track({required String event}) { - var payload = jsonEncode({ + void track({required final String event}) { + final payload = jsonEncode({ 'event': event, 'properties': { 'distinct_id': _uniqueUserId, @@ -60,7 +60,7 @@ class MixPanelAnalytics implements Analytics { } } - Future _quietPost(String payload) async { + Future _quietPost(final String payload) async { try { await http.post( Uri.parse(_endpoint), diff --git a/packages/cli_tools/lib/src/better_command_runner/better_command.dart b/packages/cli_tools/lib/src/better_command_runner/better_command.dart index 641c963..0385a61 100644 --- a/packages/cli_tools/lib/src/better_command_runner/better_command.dart +++ b/packages/cli_tools/lib/src/better_command_runner/better_command.dart @@ -57,10 +57,10 @@ abstract class BetterCommand extends Command { /// } /// ``` BetterCommand({ - MessageOutput? messageOutput = _defaultMessageOutput, - int? wrapTextColumn, + final MessageOutput? messageOutput = _defaultMessageOutput, + final int? wrapTextColumn, this.options = const [], - Map? env, + final Map? env, }) : _messageOutput = messageOutput, _argParser = ArgParser(usageLineLength: wrapTextColumn), envVariables = env ?? Platform.environment { @@ -71,7 +71,7 @@ abstract class BetterCommand extends Command { if (_messageOutput != _defaultMessageOutput) { return _messageOutput; } - if (runner case BetterCommandRunner runner) { + if (runner case final BetterCommandRunner runner) { return runner.messageOutput; } return _messageOutput; @@ -120,7 +120,7 @@ abstract class BetterCommand extends Command { /// /// This method can be overridden to change the configuration resolution /// behavior. - Configuration resolveConfiguration(ArgResults? argResults) { + Configuration resolveConfiguration(final ArgResults? argResults) { return Configuration.resolveNoExcept( options: options, argResults: argResults, diff --git a/packages/cli_tools/lib/src/better_command_runner/better_command_runner.dart b/packages/cli_tools/lib/src/better_command_runner/better_command_runner.dart index 7c8242c..0397b3e 100644 --- a/packages/cli_tools/lib/src/better_command_runner/better_command_runner.dart +++ b/packages/cli_tools/lib/src/better_command_runner/better_command_runner.dart @@ -22,13 +22,13 @@ final class MessageOutput { /// Logs a usage exception. /// If the function has not been provided then nothing will happen. - void logUsageException(UsageException exception) { + void logUsageException(final UsageException exception) { usageExceptionLogger?.call(exception); } /// Logs a usage message. /// If the function has not been provided then nothing will happen. - void logUsage(String usage) { + void logUsage(final String usage) { usageLogger?.call(usage); } } @@ -84,7 +84,7 @@ class BetterCommandRunner /// Sets the global configuration, by default called by [parse]. /// It must be set before [runCommand] is called. - set globalConfiguration(Configuration configuration) { + set globalConfiguration(final Configuration configuration) { _globalConfiguration = configuration; } @@ -140,13 +140,14 @@ class BetterCommandRunner super.executableName, super.description, { super.suggestionDistanceLimit, - MessageOutput? messageOutput = const MessageOutput(usageLogger: print), - SetLogLevel? setLogLevel, - OnBeforeRunCommand? onBeforeRunCommand, - OnAnalyticsEvent? onAnalyticsEvent, - int? wrapTextColumn, - List? globalOptions, - Map? env, + final MessageOutput? messageOutput = + const MessageOutput(usageLogger: print), + final SetLogLevel? setLogLevel, + final OnBeforeRunCommand? onBeforeRunCommand, + final OnAnalyticsEvent? onAnalyticsEvent, + final int? wrapTextColumn, + final List? globalOptions, + final Map? env, }) : _messageOutput = messageOutput, _setLogLevel = setLogLevel, _onBeforeRunCommand = onBeforeRunCommand, @@ -176,8 +177,8 @@ class BetterCommandRunner MessageOutput? get messageOutput => _messageOutput; /// Adds a list of commands to the command runner. - void addCommands(List> commands) { - for (var command in commands) { + void addCommands(final List> commands) { + for (final command in commands) { addCommand(command); } } @@ -195,9 +196,9 @@ class BetterCommandRunner /// If this method is overridden, the overriding method must ensure that /// the global configuration is set, see [globalConfiguration]. @override - Future run(Iterable args) { + Future run(final Iterable args) { return Future.sync(() { - var argResults = parse(args); + final argResults = parse(args); globalConfiguration = resolveConfiguration(argResults); try { @@ -219,7 +220,7 @@ class BetterCommandRunner /// Parses the command line arguments and returns the result. @override - ArgResults parse(Iterable args) { + ArgResults parse(final Iterable args) { try { return super.parse(args); } on UsageException catch (e) { @@ -247,7 +248,7 @@ class BetterCommandRunner /// /// This returns the return value of [Command.run]. @override - Future runCommand(ArgResults topLevelResults) async { + Future runCommand(final ArgResults topLevelResults) async { _setLogLevel?.call( parsedLogLevel: _determineLogLevel(globalConfiguration), commandName: topLevelResults.command?.name, @@ -261,7 +262,7 @@ class BetterCommandRunner unawaited( Future(() async { - var command = topLevelResults.command; + final command = topLevelResults.command; if (command != null) { // Command name can only be null for top level results. // But since we are taking the name of a command from the top level @@ -280,7 +281,7 @@ class BetterCommandRunner // commands that are invalid. // Note that there are other scenarios that also trigger a [UsageException] // so the try/catch statement can't be fully compensated for handled here. - var noUnexpectedArgs = topLevelResults.rest.isEmpty; + final noUnexpectedArgs = topLevelResults.rest.isEmpty; if (noUnexpectedArgs) { _onAnalyticsEvent?.call(BetterCommandRunnerAnalyticsEvents.help); } @@ -302,7 +303,7 @@ class BetterCommandRunner /// /// This method can be overridden to change the configuration resolution /// behavior. - Configuration resolveConfiguration(ArgResults? argResults) { + Configuration resolveConfiguration(final ArgResults? argResults) { return Configuration.resolveNoExcept( options: _globalOptions, argResults: argResults, @@ -311,7 +312,7 @@ class BetterCommandRunner ); } - static CommandRunnerLogLevel _determineLogLevel(Configuration config) { + static CommandRunnerLogLevel _determineLogLevel(final Configuration config) { if (config.findValueOf(argName: BetterCommandRunnerFlags.verbose) == true) { return CommandRunnerLogLevel.verbose; } else if (config.findValueOf(argName: BetterCommandRunnerFlags.quiet) == diff --git a/packages/cli_tools/lib/src/documentation_generator/documentation_generator.dart b/packages/cli_tools/lib/src/documentation_generator/documentation_generator.dart index 1613b5e..e0143ed 100644 --- a/packages/cli_tools/lib/src/documentation_generator/documentation_generator.dart +++ b/packages/cli_tools/lib/src/documentation_generator/documentation_generator.dart @@ -6,12 +6,12 @@ class CommandDocumentationGenerator { CommandDocumentationGenerator(this.commandRunner); Map generateMarkdown() { - var commands = commandRunner.commands.values; + final commands = commandRunner.commands.values; - var files = {}; + final files = {}; - for (var command in commands) { - StringBuffer markdown = StringBuffer(); + for (final command in commands) { + final StringBuffer markdown = StringBuffer(); markdown.writeln('## Usage\n'); if (command.argParser.options.isNotEmpty) { @@ -21,9 +21,9 @@ class CommandDocumentationGenerator { } if (command.subcommands.isNotEmpty) { - var numberOfSubcommands = command.subcommands.length; + final numberOfSubcommands = command.subcommands.length; markdown.writeln('### Sub commands\n'); - for (var (i, subcommand) in command.subcommands.entries.indexed) { + for (final (i, subcommand) in command.subcommands.entries.indexed) { markdown.writeln('#### `${subcommand.key}`\n'); markdown.writeln('```console'); markdown.writeln(subcommand.value.usage); diff --git a/packages/cli_tools/lib/src/local_storage_manager/local_storage_manager.dart b/packages/cli_tools/lib/src/local_storage_manager/local_storage_manager.dart index ba50494..4b56512 100644 --- a/packages/cli_tools/lib/src/local_storage_manager/local_storage_manager.dart +++ b/packages/cli_tools/lib/src/local_storage_manager/local_storage_manager.dart @@ -1,9 +1,10 @@ import 'dart:convert'; import 'dart:io'; -import 'package:cli_tools/src/local_storage_manager/local_storage_manager_exceptions.dart'; import 'package:path/path.dart' as p; +import 'local_storage_manager_exceptions.dart'; + /// An abstract class that provides methods for storing, fetching and removing /// json files from local storage. /// @@ -11,7 +12,7 @@ import 'package:path/path.dart' as p; abstract base class LocalStorageManager { /// Fetches the home directory of the current user. static Directory get homeDirectory { - var envVars = Platform.environment; + final envVars = Platform.environment; if (Platform.isWindows) { return Directory(envVars['UserProfile']!); @@ -29,10 +30,10 @@ abstract base class LocalStorageManager { /// /// Throws a [DeleteException] if an error occurs during file deletion. static Future removeFile({ - required String fileName, - required String localStoragePath, + required final String fileName, + required final String localStoragePath, }) async { - var file = File(p.join(localStoragePath, fileName)); + final file = File(p.join(localStoragePath, fileName)); if (!file.existsSync()) return; @@ -54,11 +55,11 @@ abstract base class LocalStorageManager { /// Throws a [SerializationException] if an error occurs during serialization. /// Throws a [WriteException] if an error occurs during file writing. static Future storeJsonFile({ - required String fileName, - required Map json, - required String localStoragePath, + required final String fileName, + required final Map json, + required final String localStoragePath, }) async { - var file = File(p.join(localStoragePath, fileName)); + final file = File(p.join(localStoragePath, fileName)); if (!file.existsSync()) { try { @@ -93,11 +94,11 @@ abstract base class LocalStorageManager { /// Throws a [ReadException] if an error occurs during file reading. /// Throws a [DeserializationException] if an error occurs during deserialization. static Future tryFetchAndDeserializeJsonFile({ - required String fileName, - required String localStoragePath, - required T Function(Map json) fromJson, + required final String fileName, + required final String localStoragePath, + required final T Function(Map json) fromJson, }) async { - var file = File(p.join(localStoragePath, fileName)); + final file = File(p.join(localStoragePath, fileName)); if (!file.existsSync()) return null; @@ -109,7 +110,7 @@ abstract base class LocalStorageManager { } try { - return fromJson(jsonDecode(fileContent)); + return fromJson(jsonDecode(fileContent) as Map); } catch (e, stackTrace) { throw DeserializationException(file, e, stackTrace); } diff --git a/packages/cli_tools/lib/src/logger/helpers/ansi_style.dart b/packages/cli_tools/lib/src/logger/helpers/ansi_style.dart index f5f171f..c4e526a 100644 --- a/packages/cli_tools/lib/src/logger/helpers/ansi_style.dart +++ b/packages/cli_tools/lib/src/logger/helpers/ansi_style.dart @@ -30,7 +30,7 @@ enum AnsiStyle { /// Wraps text with ansi escape code for style if stdout has terminal and /// supports ansi escapes. - String wrap(String text) { + String wrap(final String text) { if (!ansiSupported) { return text; } diff --git a/packages/cli_tools/lib/src/logger/helpers/progress.dart b/packages/cli_tools/lib/src/logger/helpers/progress.dart index bd38805..5b5561a 100644 --- a/packages/cli_tools/lib/src/logger/helpers/progress.dart +++ b/packages/cli_tools/lib/src/logger/helpers/progress.dart @@ -17,7 +17,7 @@ import 'dart:async'; import 'dart:io'; -import 'package:cli_tools/src/logger/helpers/ansi_style.dart'; +import 'ansi_style.dart'; /// {@template progress_options} /// An object containing configuration for a [Progress] instance. @@ -63,7 +63,7 @@ class Progress { Progress( this._message, this._stdout, { - ProgressOptions options = const ProgressOptions(), + final ProgressOptions options = const ProgressOptions(), }) : _stopwatch = Stopwatch(), _options = options { _stopwatch @@ -75,9 +75,10 @@ class Progress { // Do not animate if the log level is lower than info since other logs // might interrupt the animation if (!_stdout.hasTerminal) { - var frames = _options.animation.frames; - var char = frames.isEmpty ? '' : frames.first; - var prefix = char.isEmpty ? char : '${AnsiStyle.lightGreen.wrap(char)} '; + final frames = _options.animation.frames; + final char = frames.isEmpty ? '' : frames.first; + final prefix = + char.isEmpty ? char : '${AnsiStyle.lightGreen.wrap(char)} '; _write('$prefix$_message...\n'); return; } @@ -104,7 +105,7 @@ class Progress { /// /// * [fail], to end the progress and mark it as failed. /// * [cancel], to cancel the progress entirely and remove the written line. - void complete([String? update]) { + void complete([final String? update]) { _stopwatch.stop(); _write( '''$_clearLine${AnsiStyle.lightGreen.wrap('✓')} ${update ?? _message} $_time\n''', @@ -118,7 +119,7 @@ class Progress { /// /// * [complete], to end the progress and mark it as a successful completion. /// * [cancel], to cancel the progress entirely and remove the written line. - void fail([String? update]) { + void fail([final String? update]) { _timer?.cancel(); _write( '$_clearLine${AnsiStyle.red.wrap('✗')} ${update ?? _message} $_time\n', @@ -127,7 +128,7 @@ class Progress { } /// Update the progress message. - void update(String update) { + void update(final String update) { if (_timer != null) _write(_clearLine); _message = update; _onTick(_timer); @@ -150,24 +151,24 @@ class Progress { '\r'; // bring cursor to the start of the current line } - void _onTick(Timer? _) { + void _onTick(final Timer? _) { _index++; - var frames = _options.animation.frames; - var char = frames.isEmpty ? '' : frames[_index % frames.length]; - var prefix = char.isEmpty ? char : '${AnsiStyle.lightGreen.wrap(char)} '; + final frames = _options.animation.frames; + final char = frames.isEmpty ? '' : frames[_index % frames.length]; + final prefix = char.isEmpty ? char : '${AnsiStyle.lightGreen.wrap(char)} '; _write('$_clearLine$prefix$_message... $_time'); } - void _write(String object) { + void _write(final String object) { _stdout.write(object); } String get _time { - var elapsedTime = _stopwatch.elapsed.inMilliseconds; - var displayInMilliseconds = elapsedTime < 100; - var time = displayInMilliseconds ? elapsedTime : elapsedTime / 1000; - var formattedTime = + final elapsedTime = _stopwatch.elapsed.inMilliseconds; + final displayInMilliseconds = elapsedTime < 100; + final time = displayInMilliseconds ? elapsedTime : elapsedTime / 1000; + final formattedTime = displayInMilliseconds ? '${time}ms' : '${time.toStringAsFixed(1)}s'; return AnsiStyle.darkGray.wrap('($formattedTime)'); } diff --git a/packages/cli_tools/lib/src/logger/logger.dart b/packages/cli_tools/lib/src/logger/logger.dart index dcce1d4..44a54d2 100644 --- a/packages/cli_tools/lib/src/logger/logger.dart +++ b/packages/cli_tools/lib/src/logger/logger.dart @@ -13,36 +13,39 @@ abstract class Logger { /// Display debug [message] to the user. /// Commands should use this for information that is important for /// debugging purposes. - void debug(String message, {bool newParagraph, LogType type}); + void debug(final String message, + {final bool newParagraph, final LogType type}); /// Display a normal [message] to the user. /// Command should use this as the standard communication channel for /// success, progress or information messages. - void info(String message, {bool newParagraph, LogType type}); + void info(final String message, + {final bool newParagraph, final LogType type}); /// Display a warning [message] to the user. /// Commands should use this if they have important but not critical /// information for the user. - void warning(String message, {bool newParagraph, LogType type}); + void warning(final String message, + {final bool newParagraph, final LogType type}); /// Display an error [message] to the user. /// Commands should use this if they want to inform a user that an error /// has occurred. void error( - String message, { - bool newParagraph, - StackTrace? stackTrace, - LogType type, + final String message, { + final bool newParagraph, + final StackTrace? stackTrace, + final LogType type, }); /// Display a [message] to the user with a specified [level]. /// /// This is for logging messages with a dynamically specified log level. void log( - String message, - LogLevel level, { - bool newParagraph, - LogType type, + final String message, + final LogLevel level, { + final bool newParagraph, + final LogType type, }); /// Display a progress message on [LogLevel.info] while running [runner] @@ -51,9 +54,9 @@ abstract class Logger { /// Uses return value from [runner] to print set progress success status. /// Returns return value from [runner]. Future progress( - String message, - Future Function() runner, { - bool newParagraph, + final String message, + final Future Function() runner, { + final bool newParagraph, }); /// Directly write a [message] to the output. @@ -63,10 +66,10 @@ abstract class Logger { /// If [newParagraph] is set to true, output is written as a new paragraph. /// [LogLevel] can be set to control the log level of the message. void write( - String message, - LogLevel logLevel, { - bool newParagraph = false, - bool newLine = true, + final String message, + final LogLevel logLevel, { + final bool newParagraph = false, + final bool newLine = true, }); /// Returns a [Future] that completes once all logging is complete. @@ -100,7 +103,7 @@ class RawLogType extends LogType { /// If [title] is set the box will have a title row. class BoxLogType extends LogType { final String? title; - const BoxLogType({this.title, bool newParagraph = true}); + const BoxLogType({this.title, final bool newParagraph = true}); } /// Abstract style console formatting. diff --git a/packages/cli_tools/lib/src/logger/loggers/std_out_logger.dart b/packages/cli_tools/lib/src/logger/loggers/std_out_logger.dart index bbd07b9..60fbe48 100644 --- a/packages/cli_tools/lib/src/logger/loggers/std_out_logger.dart +++ b/packages/cli_tools/lib/src/logger/loggers/std_out_logger.dart @@ -1,18 +1,19 @@ import 'dart:io'; import 'dart:math' as math; -import 'package:cli_tools/src/logger/logger.dart'; -import 'package:cli_tools/src/logger/helpers/ansi_style.dart'; -import 'package:cli_tools/src/logger/helpers/progress.dart'; import 'package:super_string/super_string.dart'; +import '../helpers/ansi_style.dart'; +import '../helpers/progress.dart'; +import '../logger.dart'; + /// Logger that logs using the [Stdout] library. /// Errors and Warnings are printed on [stderr] and other messages are logged /// on [stdout]. class StdOutLogger extends Logger { static const int _defaultColumnWrap = 80; - static String _levelPrefix(LogLevel level) { + static String _levelPrefix(final LogLevel level) { return switch (level) { LogLevel.debug => 'DEBUG: ', LogLevel.info => '', @@ -38,7 +39,7 @@ class StdOutLogger extends Logger { /// If null (the default), messages are written to [stdout] for all log levels. StdOutLogger( super.logLevel, { - Map? replacements, + final Map? replacements, this.logToStderrLevelThreshold, }) : _replacements = replacements; @@ -47,39 +48,39 @@ class StdOutLogger extends Logger { @override void debug( - String message, { - bool newParagraph = false, - LogType type = TextLogType.normal, + final String message, { + final bool newParagraph = false, + final LogType type = TextLogType.normal, }) { log(message, LogLevel.debug, newParagraph: newParagraph, type: type); } @override void info( - String message, { - bool newParagraph = false, - LogType type = TextLogType.normal, + final String message, { + final bool newParagraph = false, + final LogType type = TextLogType.normal, }) { log(message, LogLevel.info, newParagraph: newParagraph, type: type); } @override void warning( - String message, { - bool newParagraph = false, - LogType type = TextLogType.normal, + final String message, { + final bool newParagraph = false, + final LogType type = TextLogType.normal, }) { log(message, LogLevel.warning, newParagraph: newParagraph, type: type); } @override void error( - String message, { - bool newParagraph = false, - StackTrace? stackTrace, - LogType type = TextLogType.normal, + final String message, { + final bool newParagraph = false, + final StackTrace? stackTrace, + final LogType type = TextLogType.normal, }) { - var msg = + final msg = stackTrace != null ? '$message\n${stackTrace.toString()}' : message; log(msg, LogLevel.error, newParagraph: newParagraph, type: type); @@ -87,13 +88,13 @@ class StdOutLogger extends Logger { @override void log( - String message, - LogLevel level, { - bool newParagraph = false, - LogType type = TextLogType.normal, + final String message, + final LogLevel level, { + final bool newParagraph = false, + final LogType type = TextLogType.normal, }) { if (ansiSupported) { - var ansiMessage = switch (level) { + final ansiMessage = switch (level) { LogLevel.debug => AnsiStyle.darkGray.wrap(message), LogLevel.info => message, LogLevel.warning => AnsiStyle.yellow.wrap(message), @@ -103,7 +104,7 @@ class StdOutLogger extends Logger { _log(ansiMessage, level, newParagraph, type); } else { - var prefix = _levelPrefix(level); + final prefix = _levelPrefix(level); _log(message, level, newParagraph, type, prefix: prefix); } @@ -111,9 +112,9 @@ class StdOutLogger extends Logger { @override Future progress( - String message, - Future Function() runner, { - bool newParagraph = false, + final String message, + final Future Function() runner, { + final bool newParagraph = false, }) async { if (logLevel.index > LogLevel.info.index) { return await runner(); @@ -127,9 +128,9 @@ class StdOutLogger extends Logger { write('', LogLevel.info, newParagraph: false, newLine: true); } - var progress = Progress(message, stdout); + final progress = Progress(message, stdout); trackedAnimationInProgress = progress; - bool success = await runner(); + final bool success = await runner(); trackedAnimationInProgress = null; success ? progress.complete() : progress.fail(); return success; @@ -141,16 +142,16 @@ class StdOutLogger extends Logger { await stdout.flush(); } - bool shouldLog(LogLevel logLevel) { + bool shouldLog(final LogLevel logLevel) { return logLevel.index >= this.logLevel.index; } void _log( String message, - LogLevel logLevel, - bool newParagraph, - LogType type, { - String prefix = '', + final LogLevel logLevel, + final bool newParagraph, + final LogType type, { + final String prefix = '', }) { if (message == '') return; if (!shouldLog(logLevel)) return; @@ -201,21 +202,22 @@ class StdOutLogger extends Logger { @override void write( String message, - LogLevel logLevel, { - newParagraph = false, - newLine = true, + final LogLevel logLevel, { + final newParagraph = false, + final newLine = true, }) { message = switch (_replacements) { null => message, - Map replacements => replacements.entries.fold( + final Map replacements => replacements.entries.fold( message, - (String acc, entry) => acc.replaceAll(entry.key, entry.value), + (final String acc, final entry) => + acc.replaceAll(entry.key, entry.value), ), }; _stopAnimationInProgress(); - var output = '${newParagraph ? '\n' : ''}$message${newLine ? '\n' : ''}'; - var threshold = logToStderrLevelThreshold; + final output = '${newParagraph ? '\n' : ''}$message${newLine ? '\n' : ''}'; + final threshold = logToStderrLevelThreshold; if (threshold != null && logLevel.index >= threshold.index) { stderr.write(output); } else { @@ -236,11 +238,11 @@ class StdOutLogger extends Logger { } /// wrap text based on column width -String _wrapText(String text, int columnWidth) { - var textLines = text.split('\n'); - List outLines = []; +String _wrapText(final String text, final int columnWidth) { + final textLines = text.split('\n'); + final List outLines = []; for (var line in textLines) { - var leadingTrimChar = _tryGetLeadingTrimmableChar(line); + final leadingTrimChar = _tryGetLeadingTrimmableChar(line); // wordWrap(...) uses trim as part of its implementation which removes all // leading trimmable characters. // In order to preserve them we temporarily replace the first char with a @@ -260,7 +262,7 @@ String _wrapText(String text, int columnWidth) { return outLines.join('\n'); } -String? _tryGetLeadingTrimmableChar(String text) { +String? _tryGetLeadingTrimmableChar(final String text) { if (text.isNotEmpty && text.first.trim().isEmpty) { return text.first; } @@ -278,23 +280,23 @@ String? _tryGetLeadingTrimmableChar(String text) { /// /// When [title] is provided, the box will have a title above it. String _formatAsBox({ - required String message, - String? title, - required int wrapColumn, + required final String message, + final String? title, + required final int wrapColumn, }) { const int kPaddingLeftRight = 1; const int kEdges = 2; - var maxTextWidthPerLine = wrapColumn - kEdges - kPaddingLeftRight * 2; - var lines = _wrapText(message, maxTextWidthPerLine).split('\n'); - var lineWidth = lines.map((String line) => line.length).toList(); - var maxColumnSize = lineWidth.reduce( - (int currLen, int maxLen) => math.max(currLen, maxLen), + final maxTextWidthPerLine = wrapColumn - kEdges - kPaddingLeftRight * 2; + final lines = _wrapText(message, maxTextWidthPerLine).split('\n'); + final lineWidth = lines.map((final String line) => line.length).toList(); + final maxColumnSize = lineWidth.reduce( + (final int currLen, final int maxLen) => math.max(currLen, maxLen), ); - var textWidth = math.min(maxColumnSize, maxTextWidthPerLine); - var textWithPaddingWidth = textWidth + kPaddingLeftRight * 2; + final textWidth = math.min(maxColumnSize, maxTextWidthPerLine); + final textWithPaddingWidth = textWidth + kPaddingLeftRight * 2; - var buffer = StringBuffer(); + final buffer = StringBuffer(); // Write `┌─ [title] ─┐`. buffer.write('┌'); @@ -313,7 +315,7 @@ String _formatAsBox({ buffer.write('│'); buffer.write(' ' * kPaddingLeftRight); buffer.write(lines[lineIdx]); - var remainingSpacesToEnd = textWidth - lineWidth[lineIdx]; + final remainingSpacesToEnd = textWidth - lineWidth[lineIdx]; buffer.write(' ' * (remainingSpacesToEnd + kPaddingLeftRight)); buffer.write('│'); buffer.write('\n'); diff --git a/packages/cli_tools/lib/src/logger/loggers/void_logger.dart b/packages/cli_tools/lib/src/logger/loggers/void_logger.dart index 13c1ff6..e915e3f 100644 --- a/packages/cli_tools/lib/src/logger/loggers/void_logger.dart +++ b/packages/cli_tools/lib/src/logger/loggers/void_logger.dart @@ -1,4 +1,4 @@ -import 'package:cli_tools/src/logger/logger.dart'; +import '../logger.dart'; /// Logger that logs no output. /// @@ -11,39 +11,39 @@ class VoidLogger extends Logger { @override void debug( - String message, { - bool newParagraph = false, - LogType type = const RawLogType(), + final String message, { + final bool newParagraph = false, + final LogType type = const RawLogType(), }) {} @override void info( - String message, { - bool newParagraph = false, - LogType type = const RawLogType(), + final String message, { + final bool newParagraph = false, + final LogType type = const RawLogType(), }) {} @override void warning( - String message, { - bool newParagraph = false, - LogType type = const RawLogType(), + final String message, { + final bool newParagraph = false, + final LogType type = const RawLogType(), }) {} @override void error( - String message, { - bool newParagraph = false, - StackTrace? stackTrace, - LogType type = const RawLogType(), + final String message, { + final bool newParagraph = false, + final StackTrace? stackTrace, + final LogType type = const RawLogType(), }) {} @override void log( - String message, - LogLevel level, { - bool newParagraph = false, - LogType type = const RawLogType(), + final String message, + final LogLevel level, { + final bool newParagraph = false, + final LogType type = const RawLogType(), }) {} @override @@ -53,18 +53,18 @@ class VoidLogger extends Logger { @override Future progress( - String message, - Future Function() runner, { - bool newParagraph = true, + final String message, + final Future Function() runner, { + final bool newParagraph = true, }) async { return await runner(); } @override void write( - String message, - LogLevel logLevel, { - bool newParagraph = false, - bool newLine = true, + final String message, + final LogLevel logLevel, { + final bool newParagraph = false, + final bool newLine = true, }) {} } diff --git a/packages/cli_tools/lib/src/package_version/package_version.dart b/packages/cli_tools/lib/src/package_version/package_version.dart index 7f43183..51b8de7 100644 --- a/packages/cli_tools/lib/src/package_version/package_version.dart +++ b/packages/cli_tools/lib/src/package_version/package_version.dart @@ -19,18 +19,19 @@ abstract class PackageVersion { /// [PackageVersionConstants.badConnectionRetryTimeout] is enforced before /// attempting to fetch the latest version again. static Future fetchLatestPackageVersion({ - required Future Function(PackageVersionData versionArtefact) + required final Future Function(PackageVersionData versionArtefact) storePackageVersionData, - required Future Function() loadPackageVersionData, - required Future Function() fetchLatestPackageVersion, + required final Future Function() + loadPackageVersionData, + required final Future Function() fetchLatestPackageVersion, }) async { - var storedVersionData = await loadPackageVersionData(); + final storedVersionData = await loadPackageVersionData(); if (storedVersionData != null && _validVersion(storedVersionData)) { return storedVersionData.version; } - var latestPackageVersion = await fetchLatestPackageVersion(); + final latestPackageVersion = await fetchLatestPackageVersion(); await _storePubDevVersion( latestPackageVersion, @@ -40,13 +41,13 @@ abstract class PackageVersion { return latestPackageVersion; } - static bool _validVersion(PackageVersionData versionData) { + static bool _validVersion(final PackageVersionData versionData) { return versionData.validUntil.isAfter(DateTime.now()); } static Future _storePubDevVersion( - Version? version, { - required Future Function(PackageVersionData versionArtefact) + final Version? version, { + required final Future Function(PackageVersionData versionArtefact) storePackageVersionData, }) async { PackageVersionData versionArtefact; @@ -74,10 +75,10 @@ class PackageVersionData { PackageVersionData(this.version, this.validUntil); - factory PackageVersionData.fromJson(Map json) => + factory PackageVersionData.fromJson(final Map json) => PackageVersionData( - Version.parse(json['version']), - DateTime.fromMillisecondsSinceEpoch(json['valid_until']), + Version.parse(json['version'] as String), + DateTime.fromMillisecondsSinceEpoch(json['valid_until'] as int), ); Map toJson() => { diff --git a/packages/cli_tools/lib/src/package_version/pub_api_client.dart b/packages/cli_tools/lib/src/package_version/pub_api_client.dart index 8e947f4..8d97124 100644 --- a/packages/cli_tools/lib/src/package_version/pub_api_client.dart +++ b/packages/cli_tools/lib/src/package_version/pub_api_client.dart @@ -1,18 +1,19 @@ import 'dart:async'; -import 'package:cli_tools/src/package_version/pub_api_client_exceptions.dart'; import 'package:http/http.dart' as http; import 'package:pub_api_client/pub_api_client.dart'; import 'package:pub_semver/pub_semver.dart'; +import 'pub_api_client_exceptions.dart'; + /// A client for the pub.dev API. class PubApiClient { final PubClient _pubClient; final Duration _requestTimeout; PubApiClient({ - http.Client? httpClient, - requestTimeout = const Duration(seconds: 2), + final http.Client? httpClient, + final Duration requestTimeout = const Duration(seconds: 2), }) : _pubClient = PubClient(client: httpClient), _requestTimeout = requestTimeout; @@ -24,10 +25,10 @@ class PubApiClient { /// /// Throws a [VersionFetchException] if the request fails. /// Throws a [VersionParseException] if the version can not be parsed. - Future tryFetchLatestStableVersion(String packageName) async { + Future tryFetchLatestStableVersion(final String packageName) async { String? latestStableVersion; try { - var packageVersions = await _pubClient + final packageVersions = await _pubClient .packageVersions(packageName) .timeout(_requestTimeout); latestStableVersion = _tryGetLatestStableVersion(packageVersions); @@ -53,8 +54,8 @@ class PubApiClient { } } - String? _tryGetLatestStableVersion(List packageVersions) { - for (var version in packageVersions) { + String? _tryGetLatestStableVersion(final List packageVersions) { + for (final version in packageVersions) { if (!version.contains('-') && !version.contains('+')) { return version; } @@ -65,7 +66,7 @@ class PubApiClient { /// Required because of an issue with the pub_api_client package. /// Issue: https://github.com/leoafarias/pub_api_client/issues/35 - String _formatPubClientException(Object exception) { + String _formatPubClientException(final Object exception) { try { return exception.toString(); } catch (_) { diff --git a/packages/cli_tools/lib/src/prompts/confirm.dart b/packages/cli_tools/lib/src/prompts/confirm.dart index 69cb487..7e0a55b 100644 --- a/packages/cli_tools/lib/src/prompts/confirm.dart +++ b/packages/cli_tools/lib/src/prompts/confirm.dart @@ -1,16 +1,16 @@ import 'dart:io'; -import 'package:cli_tools/cli_tools.dart'; +import '../logger/logger.dart'; /// Prompts the user to confirm an action. /// Returns `true` if the user confirms, `false` otherwise. /// If [defaultValue] is provided, the user can skip the prompt by pressing Enter. Future confirm( - String message, { - bool? defaultValue, - required Logger logger, + final String message, { + final bool? defaultValue, + required final Logger logger, }) async { - var prompt = defaultValue == null + final prompt = defaultValue == null ? '[y/n]' : defaultValue ? '[Y/n]' @@ -23,7 +23,7 @@ Future confirm( newLine: false, newParagraph: false, ); - var input = stdin.readLineSync()?.trim().toLowerCase(); + final input = stdin.readLineSync()?.trim().toLowerCase(); if (input == null || input.isEmpty) { if (defaultValue != null) { diff --git a/packages/cli_tools/lib/src/prompts/input.dart b/packages/cli_tools/lib/src/prompts/input.dart index f2de3af..c5a847b 100644 --- a/packages/cli_tools/lib/src/prompts/input.dart +++ b/packages/cli_tools/lib/src/prompts/input.dart @@ -1,15 +1,15 @@ import 'dart:io'; -import 'package:cli_tools/cli_tools.dart'; +import '../logger/logger.dart'; /// Prompts the user for input. /// If [defaultValue] is provided, the user can skip the prompt by pressing Enter. Future input( - String message, { - String? defaultValue, - required Logger logger, + final String message, { + final String? defaultValue, + required final Logger logger, }) async { - var defaultDescription = defaultValue == null ? '' : ' ($defaultValue)'; + final defaultDescription = defaultValue == null ? '' : ' ($defaultValue)'; logger.write( '$message$defaultDescription: ', @@ -17,8 +17,8 @@ Future input( newLine: false, newParagraph: false, ); - var input = stdin.readLineSync()?.trim(); - var missingInput = input == null || input.isEmpty; + final input = stdin.readLineSync()?.trim(); + final missingInput = input == null || input.isEmpty; if (missingInput) { return defaultValue ?? ''; } diff --git a/packages/cli_tools/lib/src/prompts/select.dart b/packages/cli_tools/lib/src/prompts/select.dart index 4015df2..00793a4 100644 --- a/packages/cli_tools/lib/src/prompts/select.dart +++ b/packages/cli_tools/lib/src/prompts/select.dart @@ -1,7 +1,7 @@ import 'dart:io'; -import 'package:cli_tools/cli_tools.dart'; - +import '../../better_command_runner.dart' show ExitException; +import '../logger/logger.dart'; import 'key_codes.dart'; /// Object that represents an option in a select prompt. @@ -15,9 +15,9 @@ class Option { /// Prompts the user to select an option from a list of [options]. Future