pubspec_parse: Added support for `executables` field in `pubspec.yaml` (#1952)
Co-authored-by: Kevin Moore <kevmoo@users.noreply.github.com>
diff --git a/pkgs/pubspec_parse/CHANGELOG.md b/pkgs/pubspec_parse/CHANGELOG.md
index 124b5e4..5aeb498 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 cdfc8ff..eb77908 100644
--- a/pkgs/pubspec_parse/lib/src/pubspec.dart
+++ b/pkgs/pubspec_parse/lib/src/pubspec.dart
@@ -93,6 +93,10 @@
/// and other settings.
final Map<String, dynamic>? flutter;
+ /// Optional field to specify executables
+ @JsonKey(fromJson: _executablesMap)
+ final Map<String, String?> executables;
+
/// If this package is a Pub Workspace, this field lists the sub-packages.
final List<String>? workspace;
@@ -129,12 +133,14 @@
Map<String, Dependency>? devDependencies,
Map<String, Dependency>? dependencyOverrides,
this.flutter,
+ Map<String, String?>? 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 @@
return MapEntry(key, constraint);
}) ??
{};
+
+Map<String, String?> _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 f0fb79e..58e015a 100644
--- a/pkgs/pubspec_parse/lib/src/pubspec.g.dart
+++ b/pkgs/pubspec_parse/lib/src/pubspec.g.dart
@@ -54,6 +54,8 @@
(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 6bf96bb..73a1117 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 5570b60..e0698af 100644
--- a/pkgs/pubspec_parse/test/parse_test.dart
+++ b/pkgs/pubspec_parse/test/parse_test.dart
@@ -34,6 +34,7 @@
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 @@
'pkg2',
],
'resolution': 'workspace',
+ 'executables': {
+ 'my_script': 'bin/my_script.dart',
+ 'my_script2': 'bin/my_script2.dart',
+ },
},
skipTryPub: true,
);
@@ -96,6 +101,11 @@
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 @@
});
});
+ 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(