Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

pubspec_parse: Added support for executables field in pubspec.yaml #1952

Merged
merged 10 commits into from
Jan 7, 2025
4 changes: 2 additions & 2 deletions pkgs/pubspec_parse/CHANGELOG.md
Original file line number Diff line number Diff line change
@@ -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.

Expand Down
24 changes: 24 additions & 0 deletions pkgs/pubspec_parse/lib/src/pubspec.dart
Original file line number Diff line number Diff line change
Expand Up @@ -93,6 +93,10 @@ class Pubspec {
/// 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;

Expand Down Expand Up @@ -129,12 +133,14 @@ class Pubspec {
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.');
Expand Down Expand Up @@ -232,3 +238,21 @@ Map<String, VersionConstraint?> _environmentMap(Map? source) =>
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.',
);
}
}) ??
{};
2 changes: 2 additions & 0 deletions pkgs/pubspec_parse/lib/src/pubspec.g.dart

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

2 changes: 1 addition & 1 deletion pkgs/pubspec_parse/pubspec.yaml
Original file line number Diff line number Diff line change
@@ -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.
Expand Down
62 changes: 62 additions & 0 deletions pkgs/pubspec_parse/test/parse_test.dart
Original file line number Diff line number Diff line change
Expand Up @@ -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 {
Expand Down Expand Up @@ -64,6 +65,10 @@ void main() {
'pkg2',
],
'resolution': 'workspace',
'executables': {
'my_script': 'bin/my_script.dart',
'my_script2': 'bin/my_script2.dart',
},
},
skipTryPub: true,
);
Expand Down Expand Up @@ -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');
Expand Down Expand Up @@ -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(
Expand Down
Loading