Skip to content

Commit

Permalink
Add missing fields in pubspec package as extension methods
Browse files Browse the repository at this point in the history
  • Loading branch information
jxstxn1 committed Mar 6, 2024
1 parent ceb15e1 commit af0fde0
Show file tree
Hide file tree
Showing 3 changed files with 154 additions and 0 deletions.
72 changes: 72 additions & 0 deletions lib/src/models/pubspec_extensions.dart
Original file line number Diff line number Diff line change
@@ -0,0 +1,72 @@
import 'package:pubspec/pubspec.dart';
import 'package:yaml/yaml.dart';

/// {@template pubspec_extensions}
/// Extensions on [PubSpec] to provide additional functionality.
///
/// Following the pubspec file definition on dart.dev
/// https://dart.dev/tools/pub/pubspec
/// {@endtemplate}
extension PubspecExtensions on PubSpec {
/// Optional. URL pointing to the package's source code repository.
String? repository() => unParsedYaml?['repository'];

/// Optional. URL pointing to an issue tracker for the package.
String? issueTracker() => unParsedYaml?['issue_tracker'];

/// Optional. List of URLs where users can sponsor development of the package.
YamlList? funding() => unParsedYaml?['funding'];

/// Optional. Specify files to ignore when conducting a pre-publishing search
/// for potential leaks of secrets.
YamlList? falseSecrets() => unParsedYaml?['false_secrets'];

/// Optional. Specify a list of screenshot files to display on pub.dev
List<Screenshot>? screenshots() {
final screenShotList = unParsedYaml?['screenshots'];
if (screenShotList == null) {
return null;
}
final List<Screenshot> screenshots = [];
for (final screenShot in screenShotList) {
screenshots.add(Screenshot.fromJson(screenShot));
}
return screenshots;
}

/// Optional field to list the topics that this packages belongs to.
YamlList? topics() => unParsedYaml?['topics'];

/// Optional. List of ignored security advisories.
YamlList? ignoredAdvisories() => unParsedYaml?['ignored_advisories'];
}

/// {@template screenshot}
/// A screenshot of the package to display on pub.dev.
/// {@endtemplate}
class Screenshot {
const Screenshot(this.path, this.description);

final String path;
final String description;

factory Screenshot.fromJson(Map json) => Screenshot(
json['path'] as String,
json['description'] as String,
);

@override
String toString() => 'Screenshot(path: $path, description: $description)';

@override
bool operator ==(Object other) {
if (identical(this, other)) return true;

return other is Screenshot &&
other.path == path &&
other.description == description;
}

@override
int get hashCode => path.hashCode ^ description.hashCode;
}
1 change: 1 addition & 0 deletions pubspec.yaml
Original file line number Diff line number Diff line change
Expand Up @@ -12,6 +12,7 @@ dependencies:
oauth2: ^2.0.2
path: ^1.8.3
pubspec: ^2.3.0
yaml: ^3.1.2

dev_dependencies:
build_runner: ^2.4.6
Expand Down
81 changes: 81 additions & 0 deletions test/pubspec_extensions_test.dart
Original file line number Diff line number Diff line change
@@ -0,0 +1,81 @@
import 'package:pub_api_client/src/models/pubspec_extensions.dart';
import 'package:pubspec/pubspec.dart';
import 'package:test/test.dart';
import 'package:yaml/yaml.dart';

void main() {
test('Should be able to parse repository field', () async {
final pubspec = await PubSpec.loadFile('test/example_pubspec.yaml');
expect(pubspec.repository(), 'https://foo.bar/repo');
});

test('Should be able to parse issue tracker field', () async {
final pubspec = await PubSpec.loadFile('test/example_pubspec.yaml');
expect(pubspec.issueTracker(), 'https://foo.bar/issues');
});

test('Should be able to parse funding field', () async {
final pubspec = await PubSpec.loadFile('test/example_pubspec.yaml');
final sponsors = pubspec.funding();
expect(sponsors, isA<YamlList>());
expect(sponsors, hasLength(2));
expect(sponsors?[0], 'https://foo.bar/sponsor1');
expect(sponsors?[1], 'https://foo.bar/sponsor2');
});

test('Should be able to parse false secrets field', () async {
final pubspec = await PubSpec.loadFile('test/example_pubspec.yaml');
final falseSecrets = pubspec.falseSecrets();
expect(falseSecrets, isA<YamlList>());
expect(falseSecrets, hasLength(2));
expect(falseSecrets?[0], '/lib/foo/bar.dart');
expect(falseSecrets?[1], '/lib/bar/foo.dart');
});

test('Should be able to parse screenshots field', () async {
final screenshots = pubspec.screenshots();

expect(screenshots, isA<List<Screenshot>>());
expect(screenshots, hasLength(1));

final firstScreenShot = screenshots?[0];
expect(firstScreenShot, isA<Screenshot>());
expect(firstScreenShot?.description, 'foo-bar screenshot');
expect(firstScreenShot?.path, 'screenshots/foo-bar.png');
});

test('Should be able to parse topics field', () async {
final pubspec = await PubSpec.loadFile('test/example_pubspec.yaml');
final topics = pubspec.topics();
expect(topics, isA<YamlList>());
expect(topics, hasLength(2));
expect(topics?[0], 'bar');
expect(topics?[1], 'foo');
});

test('Should be able to parse ignoredAdvisories field', () async {
final pubspec = await PubSpec.loadFile('test/example_pubspec.yaml');
final ignoredAdvisories = pubspec.ignoredAdvisories();
expect(ignoredAdvisories, isA<YamlList>());
expect(ignoredAdvisories, hasLength(2));
expect(ignoredAdvisories?[0], 'foo-bar');
expect(ignoredAdvisories?[1], 'bar-foo');
});
}

const pubspec = PubSpec(
unParsedYaml: {
'repository': 'https://foo.bar/repo',
'issue_tracker': 'https://foo.bar/issues',
'funding': ['https://foo.bar/sponsor1', 'https://foo.bar/sponsor2'],
'false_secrets': ['/lib/foo/bar.dart', '/lib/bar/foo.dart'],
'topics': ['bar', 'foo'],
'ignored_advisories': ['foo-bar', 'bar-foo'],
'screenshots': [
{
'description': 'foo-bar screenshot',
'path': 'screenshots/foo-bar.png',
}
],
},
);

0 comments on commit af0fde0

Please sign in to comment.