diff --git a/CHANGELOG.md b/CHANGELOG.md index bc5431b..9118de2 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -4,9 +4,10 @@ - Support multiple `--headers` flags and more robust header value parsing. For example: `--headers="header1=value1;header2=value2"` or `--headers="header1=value1" --headers="header2=value2"` -- Add `--list-files` flag to show a directory listing when no `index.html` is +- Added `--list-files` flag to show a directory listing when no `index.html` is present. -- Add clickable link to serve output. +- Added `--version` flag. +- Added clickable link to serve output. - Require `sdk: ^3.10.0`. ## 4.1.0 diff --git a/README.md b/README.md index 4efeb48..44c3a79 100644 --- a/README.md +++ b/README.md @@ -54,17 +54,18 @@ See the Dart documentation of [SecurityContext.usePrivateKey](https://api.dart.d ```console $ dhttpd --help --p, --port= The port to listen on. Provide `0` to use a random port. - (defaults to "8080") - --path= The path to serve. If not set, the current directory is used. - --headers= HTTP headers to apply to each response. Can be used multiple times. Format: header=value;header2=value +--headers= HTTP headers to apply to each response. Can be used multiple times. Format: header=value;header2=value --host= The hostname to listen on. (defaults to "localhost") +-l, --list-files List the files in the directory if no index.html is present. + --path= The path to serve. If not set, the current directory is used. +-p, --port= The port to listen on. Provide `0` to use a random port. + (defaults to "8080") --sslcert= The SSL certificate to use. Also requires sslkey --sslkey= The key of the SSL certificate to use. Also requires sslcert --sslkeypassword= The password for the key of the SSL certificate to use. -h, --help Displays the help. --l, --list-files List the files in the directory if no index.html is present. + --version Prints the version of dhttpd. ``` [path]: https://dart.dev/tools/pub/cmd/pub-global#running-a-script-from-your-path diff --git a/bin/dhttpd.dart b/bin/dhttpd.dart index ba6820a..23d2ead 100644 --- a/bin/dhttpd.dart +++ b/bin/dhttpd.dart @@ -3,6 +3,7 @@ import 'dart:io'; import 'package:dhttpd/dhttpd.dart'; import 'package:dhttpd/src/options.dart'; import 'package:dhttpd/src/utils.dart'; +import 'package:dhttpd/src/version.dart'; Future main(List args) async { final Options options; @@ -22,6 +23,11 @@ Future main(List args) async { return; } + if (options.version) { + print(packageVersion); + return; + } + final httpd = await Dhttpd.start( path: options.path, port: options.port, diff --git a/lib/src/options.dart b/lib/src/options.dart index 3fe00b9..61bf126 100644 --- a/lib/src/options.dart +++ b/lib/src/options.dart @@ -9,22 +9,6 @@ const String defaultHost = 'localhost'; @CliOptions() class Options { - @CliOption( - abbr: 'p', - valueHelp: 'port', - defaultsTo: defaultPort, - help: 'The port to listen on. Provide `0` to use a random port.', - ) - final int port; - - @CliOption( - valueHelp: 'path', - help: - 'The path to serve.' - ' If not set, the current directory is used.', - ) - final String? path; - @CliOption( valueHelp: 'headers', help: @@ -41,6 +25,29 @@ class Options { ) final String host; + @CliOption( + abbr: 'l', + negatable: false, + help: 'List the files in the directory if no index.html is present.', + ) + final bool listFiles; + + @CliOption( + valueHelp: 'path', + help: + 'The path to serve.' + ' If not set, the current directory is used.', + ) + final String? path; + + @CliOption( + abbr: 'p', + valueHelp: 'port', + defaultsTo: defaultPort, + help: 'The port to listen on. Provide `0` to use a random port.', + ) + final int port; + @CliOption( valueHelp: 'sslcert', help: 'The SSL certificate to use. Also requires sslkey', @@ -62,22 +69,19 @@ class Options { @CliOption(abbr: 'h', negatable: false, help: 'Displays the help.') final bool help; - @CliOption( - abbr: 'l', - negatable: false, - help: 'List the files in the directory if no index.html is present.', - ) - final bool listFiles; + @CliOption(negatable: false, help: 'Prints the version of dhttpd.') + final bool version; Options({ - required this.port, - this.path, required this.headers, required this.host, + this.listFiles = false, + this.path, + required this.port, this.sslcert, this.sslkey, this.sslkeypassword, required this.help, - this.listFiles = false, + this.version = false, }); } diff --git a/lib/src/options.g.dart b/lib/src/options.g.dart index 37792d6..9da5d72 100644 --- a/lib/src/options.g.dart +++ b/lib/src/options.g.dart @@ -17,32 +17,21 @@ T _$badNumberFormat( ); Options _$parseOptionsResult(ArgResults result) => Options( + headers: result['headers'] as List, + host: result['host'] as String, + listFiles: result['list-files'] as bool, + path: result['path'] as String?, port: int.tryParse(result['port'] as String) ?? _$badNumberFormat(result['port'] as String, 'int', 'port'), - path: result['path'] as String?, - headers: result['headers'] as List, - host: result['host'] as String, sslcert: result['sslcert'] as String?, sslkey: result['sslkey'] as String?, sslkeypassword: result['sslkeypassword'] as String?, help: result['help'] as bool, - listFiles: result['list-files'] as bool, + version: result['version'] as bool, ); ArgParser _$populateOptionsParser(ArgParser parser) => parser - ..addOption( - 'port', - abbr: 'p', - help: 'The port to listen on. Provide `0` to use a random port.', - valueHelp: 'port', - defaultsTo: '8080', - ) - ..addOption( - 'path', - help: 'The path to serve. If not set, the current directory is used.', - valueHelp: 'path', - ) ..addMultiOption( 'headers', help: @@ -55,6 +44,24 @@ ArgParser _$populateOptionsParser(ArgParser parser) => parser valueHelp: 'host', defaultsTo: 'localhost', ) + ..addFlag( + 'list-files', + abbr: 'l', + help: 'List the files in the directory if no index.html is present.', + negatable: false, + ) + ..addOption( + 'path', + help: 'The path to serve. If not set, the current directory is used.', + valueHelp: 'path', + ) + ..addOption( + 'port', + abbr: 'p', + help: 'The port to listen on. Provide `0` to use a random port.', + valueHelp: 'port', + defaultsTo: '8080', + ) ..addOption( 'sslcert', help: 'The SSL certificate to use. Also requires sslkey', @@ -71,12 +78,7 @@ ArgParser _$populateOptionsParser(ArgParser parser) => parser valueHelp: 'sslkeypassword', ) ..addFlag('help', abbr: 'h', help: 'Displays the help.', negatable: false) - ..addFlag( - 'list-files', - abbr: 'l', - help: 'List the files in the directory if no index.html is present.', - negatable: false, - ); + ..addFlag('version', help: 'Prints the version of dhttpd.', negatable: false); final _$parserForOptions = _$populateOptionsParser(ArgParser()); diff --git a/lib/src/version.dart b/lib/src/version.dart new file mode 100644 index 0000000..c8bf6ec --- /dev/null +++ b/lib/src/version.dart @@ -0,0 +1,2 @@ +// Generated code. Do not modify. +const packageVersion = '4.2.0'; diff --git a/pubspec.yaml b/pubspec.yaml index 38b059d..84ae533 100644 --- a/pubspec.yaml +++ b/pubspec.yaml @@ -17,6 +17,7 @@ dev_dependencies: build_cli: ^2.1.2 build_runner: ^2.0.0 build_verify: ^3.0.0 + build_version: ^2.1.1 dart_flutter_team_lints: ^3.0.0 http: ^1.1.0 path: ^1.8.0 diff --git a/test/command_test.dart b/test/command_test.dart index a71af2c..6f1ff85 100644 --- a/test/command_test.dart +++ b/test/command_test.dart @@ -3,18 +3,27 @@ import 'dart:async'; import 'dart:io'; +import 'package:dhttpd/src/version.dart'; import 'package:http/http.dart' as http; import 'package:test/test.dart'; import 'package:test_descriptor/test_descriptor.dart' as d; import 'package:test_process/test_process.dart'; void main() { + test('prints version', _versionCheck); test('prints help', () => _readmeCheck(['--help'])); test('serves on specified port', _outputCheck); test('handles custom headers', _headersCheck); test('rejects invalid headers', _invalidHeadersCheck); } +Future _versionCheck() async { + final process = await _runApp(['--version']); + final output = (await process.stdoutStream().join('\n')).trim(); + await process.shouldExit(0); + expect(output, packageVersion); +} + Future _readmeCheck(List args) async { final process = await _runApp(args); final output = (await process.stdoutStream().join('\n')).trim(); @@ -34,17 +43,18 @@ $output expect(expected, r'''```console $ dhttpd --help --p, --port= The port to listen on. Provide `0` to use a random port. - (defaults to "8080") - --path= The path to serve. If not set, the current directory is used. - --headers= HTTP headers to apply to each response. Can be used multiple times. Format: header=value;header2=value +--headers= HTTP headers to apply to each response. Can be used multiple times. Format: header=value;header2=value --host= The hostname to listen on. (defaults to "localhost") +-l, --list-files List the files in the directory if no index.html is present. + --path= The path to serve. If not set, the current directory is used. +-p, --port= The port to listen on. Provide `0` to use a random port. + (defaults to "8080") --sslcert= The SSL certificate to use. Also requires sslkey --sslkey= The key of the SSL certificate to use. Also requires sslcert --sslkeypassword= The password for the key of the SSL certificate to use. -h, --help Displays the help. --l, --list-files List the files in the directory if no index.html is present. + --version Prints the version of dhttpd. ```'''); expect(readme.readAsStringSync(), contains(expected));