Skip to content

Commit 070355e

Browse files
pubspec_parse: Added support for executables field in pubspec.yaml (#1952)
Co-authored-by: Kevin Moore <[email protected]>
1 parent 5265a85 commit 070355e

File tree

5 files changed

+91
-3
lines changed

5 files changed

+91
-3
lines changed

pkgs/pubspec_parse/CHANGELOG.md

+2-2
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,6 @@
1-
## 1.5.0-wip
1+
## 1.5.0
22

3-
- Add `Pubspec.workspace` and `Pubspec.resolution` fields.
3+
- Added fields to `Pubspec`: `executables`, `resolution`, `workspace`.
44
- Require Dart 3.6
55
- Update dependencies.
66

pkgs/pubspec_parse/lib/src/pubspec.dart

+24
Original file line numberDiff line numberDiff line change
@@ -93,6 +93,10 @@ class Pubspec {
9393
/// and other settings.
9494
final Map<String, dynamic>? flutter;
9595

96+
/// Optional field to specify executables
97+
@JsonKey(fromJson: _executablesMap)
98+
final Map<String, String?> executables;
99+
96100
/// If this package is a Pub Workspace, this field lists the sub-packages.
97101
final List<String>? workspace;
98102

@@ -129,12 +133,14 @@ class Pubspec {
129133
Map<String, Dependency>? devDependencies,
130134
Map<String, Dependency>? dependencyOverrides,
131135
this.flutter,
136+
Map<String, String?>? executables,
132137
}) :
133138
// ignore: deprecated_member_use_from_same_package
134139
authors = _normalizeAuthors(author, authors),
135140
environment = environment ?? const {},
136141
dependencies = dependencies ?? const {},
137142
devDependencies = devDependencies ?? const {},
143+
executables = executables ?? const {},
138144
dependencyOverrides = dependencyOverrides ?? const {} {
139145
if (name.isEmpty) {
140146
throw ArgumentError.value(name, 'name', '"name" cannot be empty.');
@@ -232,3 +238,21 @@ Map<String, VersionConstraint?> _environmentMap(Map? source) =>
232238
return MapEntry(key, constraint);
233239
}) ??
234240
{};
241+
242+
Map<String, String?> _executablesMap(Map? source) =>
243+
source?.map((k, value) {
244+
final key = k as String;
245+
if (value == null) {
246+
return MapEntry(key, null);
247+
} else if (value is String) {
248+
return MapEntry(key, value);
249+
} else {
250+
throw CheckedFromJsonException(
251+
source,
252+
key,
253+
'String',
254+
'`$value` is not a String.',
255+
);
256+
}
257+
}) ??
258+
{};

pkgs/pubspec_parse/lib/src/pubspec.g.dart

+2
Some generated files are not rendered by default. Learn more about customizing how changed files appear on GitHub.

pkgs/pubspec_parse/pubspec.yaml

+1-1
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,5 @@
11
name: pubspec_parse
2-
version: 1.5.0-wip
2+
version: 1.5.0
33
description: >-
44
Simple package for parsing pubspec.yaml files with a type-safe API and rich
55
error reporting.

pkgs/pubspec_parse/test/parse_test.dart

+62
Original file line numberDiff line numberDiff line change
@@ -34,6 +34,7 @@ void main() {
3434
expect(value.screenshots, isEmpty);
3535
expect(value.workspace, isNull);
3636
expect(value.resolution, isNull);
37+
expect(value.executables, isEmpty);
3738
});
3839

3940
test('all fields set', () async {
@@ -64,6 +65,10 @@ void main() {
6465
'pkg2',
6566
],
6667
'resolution': 'workspace',
68+
'executables': {
69+
'my_script': 'bin/my_script.dart',
70+
'my_script2': 'bin/my_script2.dart',
71+
},
6772
},
6873
skipTryPub: true,
6974
);
@@ -96,6 +101,11 @@ void main() {
96101
expect(value.screenshots, hasLength(1));
97102
expect(value.screenshots!.first.description, 'my screenshot');
98103
expect(value.screenshots!.first.path, 'path/to/screenshot');
104+
expect(value.executables, hasLength(2));
105+
expect(value.executables.keys, contains('my_script'));
106+
expect(value.executables.keys, contains('my_script2'));
107+
expect(value.executables['my_script'], 'bin/my_script.dart');
108+
expect(value.executables['my_script2'], 'bin/my_script2.dart');
99109
expect(value.workspace, hasLength(2));
100110
expect(value.workspace!.first, 'pkg1');
101111
expect(value.workspace!.last, 'pkg2');
@@ -222,6 +232,58 @@ line 3, column 16: Unsupported value for "publish_to". Must be an http or https
222232
});
223233
});
224234

235+
group('executables', () {
236+
test('one executable', () async {
237+
final value = await parse({
238+
...defaultPubspec,
239+
'executables': {'my_script': 'bin/my_script.dart'},
240+
});
241+
expect(value.executables, hasLength(1));
242+
expect(value.executables.keys, contains('my_script'));
243+
expect(value.executables['my_script'], 'bin/my_script.dart');
244+
});
245+
246+
test('many executables', () async {
247+
final value = await parse({
248+
...defaultPubspec,
249+
'executables': {
250+
'my_script': 'bin/my_script.dart',
251+
'my_script2': 'bin/my_script2.dart',
252+
},
253+
});
254+
expect(value.executables, hasLength(2));
255+
expect(value.executables.keys, contains('my_script'));
256+
expect(value.executables.keys, contains('my_script2'));
257+
expect(value.executables['my_script'], 'bin/my_script.dart');
258+
expect(value.executables['my_script2'], 'bin/my_script2.dart');
259+
});
260+
261+
test('invalid value', () async {
262+
expectParseThrowsContaining(
263+
{
264+
...defaultPubspec,
265+
'executables': {
266+
'script': 32,
267+
},
268+
},
269+
'Unsupported value for "script". `32` is not a String.',
270+
skipTryPub: true,
271+
);
272+
});
273+
274+
test('invalid executable - lenient', () async {
275+
final value = await parse(
276+
{
277+
...defaultPubspec,
278+
'executables': 'Invalid value',
279+
},
280+
lenient: true,
281+
);
282+
expect(value.name, 'sample');
283+
expect(value.executables, isEmpty);
284+
});
285+
});
286+
225287
group('invalid', () {
226288
test('null', () {
227289
expectParseThrows(

0 commit comments

Comments
 (0)