diff --git a/pkgs/pubspec_parse/CHANGELOG.md b/pkgs/pubspec_parse/CHANGELOG.md index 124b5e4eb..5aeb49802 100644 --- a/pkgs/pubspec_parse/CHANGELOG.md +++ b/pkgs/pubspec_parse/CHANGELOG.md @@ -1,6 +1,6 @@ -## 1.5.0-wip +## 1.5.0 -- Add `Pubspec.workspace` and `Pubspec.resolution` fields. +- Added fields to `Pubspec`: `executables`, `resolution`, `workspace`. - Require Dart 3.6 - Update dependencies. diff --git a/pkgs/pubspec_parse/lib/src/pubspec.dart b/pkgs/pubspec_parse/lib/src/pubspec.dart index cdfc8ff78..eb779089a 100644 --- a/pkgs/pubspec_parse/lib/src/pubspec.dart +++ b/pkgs/pubspec_parse/lib/src/pubspec.dart @@ -93,6 +93,10 @@ class Pubspec { /// and other settings. final Map? flutter; + /// Optional field to specify executables + @JsonKey(fromJson: _executablesMap) + final Map executables; + /// If this package is a Pub Workspace, this field lists the sub-packages. final List? workspace; @@ -129,12 +133,14 @@ class Pubspec { Map? devDependencies, Map? dependencyOverrides, this.flutter, + Map? executables, }) : // ignore: deprecated_member_use_from_same_package authors = _normalizeAuthors(author, authors), environment = environment ?? const {}, dependencies = dependencies ?? const {}, devDependencies = devDependencies ?? const {}, + executables = executables ?? const {}, dependencyOverrides = dependencyOverrides ?? const {} { if (name.isEmpty) { throw ArgumentError.value(name, 'name', '"name" cannot be empty.'); @@ -232,3 +238,21 @@ Map _environmentMap(Map? source) => return MapEntry(key, constraint); }) ?? {}; + +Map _executablesMap(Map? source) => + source?.map((k, value) { + final key = k as String; + if (value == null) { + return MapEntry(key, null); + } else if (value is String) { + return MapEntry(key, value); + } else { + throw CheckedFromJsonException( + source, + key, + 'String', + '`$value` is not a String.', + ); + } + }) ?? + {}; diff --git a/pkgs/pubspec_parse/lib/src/pubspec.g.dart b/pkgs/pubspec_parse/lib/src/pubspec.g.dart index f0fb79e6b..58e015a5e 100644 --- a/pkgs/pubspec_parse/lib/src/pubspec.g.dart +++ b/pkgs/pubspec_parse/lib/src/pubspec.g.dart @@ -54,6 +54,8 @@ Pubspec _$PubspecFromJson(Map json) => $checkedCreate( (v) => (v as Map?)?.map( (k, e) => MapEntry(k as String, e), )), + executables: + $checkedConvert('executables', (v) => _executablesMap(v as Map?)), ); return val; }, diff --git a/pkgs/pubspec_parse/pubspec.yaml b/pkgs/pubspec_parse/pubspec.yaml index 6bf96bb87..73a11171e 100644 --- a/pkgs/pubspec_parse/pubspec.yaml +++ b/pkgs/pubspec_parse/pubspec.yaml @@ -1,5 +1,5 @@ name: pubspec_parse -version: 1.5.0-wip +version: 1.5.0 description: >- Simple package for parsing pubspec.yaml files with a type-safe API and rich error reporting. diff --git a/pkgs/pubspec_parse/test/parse_test.dart b/pkgs/pubspec_parse/test/parse_test.dart index 5570b60a0..e0698af16 100644 --- a/pkgs/pubspec_parse/test/parse_test.dart +++ b/pkgs/pubspec_parse/test/parse_test.dart @@ -34,6 +34,7 @@ void main() { expect(value.screenshots, isEmpty); expect(value.workspace, isNull); expect(value.resolution, isNull); + expect(value.executables, isEmpty); }); test('all fields set', () async { @@ -64,6 +65,10 @@ void main() { 'pkg2', ], 'resolution': 'workspace', + 'executables': { + 'my_script': 'bin/my_script.dart', + 'my_script2': 'bin/my_script2.dart', + }, }, skipTryPub: true, ); @@ -96,6 +101,11 @@ void main() { expect(value.screenshots, hasLength(1)); expect(value.screenshots!.first.description, 'my screenshot'); expect(value.screenshots!.first.path, 'path/to/screenshot'); + expect(value.executables, hasLength(2)); + expect(value.executables.keys, contains('my_script')); + expect(value.executables.keys, contains('my_script2')); + expect(value.executables['my_script'], 'bin/my_script.dart'); + expect(value.executables['my_script2'], 'bin/my_script2.dart'); expect(value.workspace, hasLength(2)); expect(value.workspace!.first, 'pkg1'); expect(value.workspace!.last, 'pkg2'); @@ -222,6 +232,58 @@ line 3, column 16: Unsupported value for "publish_to". Must be an http or https }); }); + group('executables', () { + test('one executable', () async { + final value = await parse({ + ...defaultPubspec, + 'executables': {'my_script': 'bin/my_script.dart'}, + }); + expect(value.executables, hasLength(1)); + expect(value.executables.keys, contains('my_script')); + expect(value.executables['my_script'], 'bin/my_script.dart'); + }); + + test('many executables', () async { + final value = await parse({ + ...defaultPubspec, + 'executables': { + 'my_script': 'bin/my_script.dart', + 'my_script2': 'bin/my_script2.dart', + }, + }); + expect(value.executables, hasLength(2)); + expect(value.executables.keys, contains('my_script')); + expect(value.executables.keys, contains('my_script2')); + expect(value.executables['my_script'], 'bin/my_script.dart'); + expect(value.executables['my_script2'], 'bin/my_script2.dart'); + }); + + test('invalid value', () async { + expectParseThrowsContaining( + { + ...defaultPubspec, + 'executables': { + 'script': 32, + }, + }, + 'Unsupported value for "script". `32` is not a String.', + skipTryPub: true, + ); + }); + + test('invalid executable - lenient', () async { + final value = await parse( + { + ...defaultPubspec, + 'executables': 'Invalid value', + }, + lenient: true, + ); + expect(value.name, 'sample'); + expect(value.executables, isEmpty); + }); + }); + group('invalid', () { test('null', () { expectParseThrows(