diff --git a/packages/flutter_app/lib/features/post/view/post_page.dart b/packages/flutter_app/lib/features/post/view/post_page.dart deleted file mode 100644 index cba9d6df..00000000 --- a/packages/flutter_app/lib/features/post/view/post_page.dart +++ /dev/null @@ -1,15 +0,0 @@ -import 'package:flutter/material.dart'; - -class PostPage extends StatelessWidget { - const PostPage({super.key}); - - @override - Widget build(BuildContext context) { - return Scaffold( - appBar: AppBar( - title: const Text('Post'), - ), - body: const Center(child: Text('Post Page')), - ); - } -} diff --git a/packages/flutter_app/lib/features/pub_dev_packages/query/pub_dev_package_details_provider.dart b/packages/flutter_app/lib/features/pub_dev_packages/query/pub_dev_package_details_provider.dart new file mode 100644 index 00000000..63de5d05 --- /dev/null +++ b/packages/flutter_app/lib/features/pub_dev_packages/query/pub_dev_package_details_provider.dart @@ -0,0 +1,18 @@ +import 'package:hooks_riverpod/hooks_riverpod.dart'; +import 'package:pub_dev_api_client/pub_dev_api_client.dart'; +import 'package:riverpod_annotation/riverpod_annotation.dart'; + +import '../../../package_adaptor/pub_dev_api_client_provider.dart'; + +part 'pub_dev_package_details_provider.g.dart'; + +/// Provider for pub.dev package details by package name. +@riverpod +Future pubDevPackageDetails( + Ref ref, { + required String packageName, +}) async { + final client = ref.watch(pubDevApiClientProvider); + final response = await client.getPackageDetails(packageName: packageName); + return response; +} diff --git a/packages/flutter_app/lib/features/pub_dev_packages/query/pub_dev_package_details_provider.g.dart b/packages/flutter_app/lib/features/pub_dev_packages/query/pub_dev_package_details_provider.g.dart new file mode 100644 index 00000000..17c5c236 --- /dev/null +++ b/packages/flutter_app/lib/features/pub_dev_packages/query/pub_dev_package_details_provider.g.dart @@ -0,0 +1,184 @@ +// GENERATED CODE - DO NOT MODIFY BY HAND + +// ignore_for_file: duplicate_ignore, type=lint, implicit_dynamic_parameter, implicit_dynamic_type, implicit_dynamic_method, strict_raw_type + +part of 'pub_dev_package_details_provider.dart'; + +// ************************************************************************** +// RiverpodGenerator +// ************************************************************************** + +String _$pubDevPackageDetailsHash() => + r'009b9b652b9792197a424bd7825542bdcae202a6'; + +/// Copied from Dart SDK +class _SystemHash { + _SystemHash._(); + + static int combine(int hash, int value) { + // ignore: parameter_assignments + hash = 0x1fffffff & (hash + value); + // ignore: parameter_assignments + hash = 0x1fffffff & (hash + ((0x0007ffff & hash) << 10)); + return hash ^ (hash >> 6); + } + + static int finish(int hash) { + // ignore: parameter_assignments + hash = 0x1fffffff & (hash + ((0x03ffffff & hash) << 3)); + // ignore: parameter_assignments + hash = hash ^ (hash >> 11); + return 0x1fffffff & (hash + ((0x00003fff & hash) << 15)); + } +} + +/// Provider for pub.dev package details by package name. +/// +/// Copied from [pubDevPackageDetails]. +@ProviderFor(pubDevPackageDetails) +const pubDevPackageDetailsProvider = PubDevPackageDetailsFamily(); + +/// Provider for pub.dev package details by package name. +/// +/// Copied from [pubDevPackageDetails]. +class PubDevPackageDetailsFamily + extends Family> { + /// Provider for pub.dev package details by package name. + /// + /// Copied from [pubDevPackageDetails]. + const PubDevPackageDetailsFamily(); + + /// Provider for pub.dev package details by package name. + /// + /// Copied from [pubDevPackageDetails]. + PubDevPackageDetailsProvider call({ + required String packageName, + }) { + return PubDevPackageDetailsProvider( + packageName: packageName, + ); + } + + @override + PubDevPackageDetailsProvider getProviderOverride( + covariant PubDevPackageDetailsProvider provider, + ) { + return call( + packageName: provider.packageName, + ); + } + + static const Iterable? _dependencies = null; + + @override + Iterable? get dependencies => _dependencies; + + static const Iterable? _allTransitiveDependencies = null; + + @override + Iterable? get allTransitiveDependencies => + _allTransitiveDependencies; + + @override + String? get name => r'pubDevPackageDetailsProvider'; +} + +/// Provider for pub.dev package details by package name. +/// +/// Copied from [pubDevPackageDetails]. +class PubDevPackageDetailsProvider + extends AutoDisposeFutureProvider { + /// Provider for pub.dev package details by package name. + /// + /// Copied from [pubDevPackageDetails]. + PubDevPackageDetailsProvider({ + required String packageName, + }) : this._internal( + (ref) => pubDevPackageDetails( + ref as PubDevPackageDetailsRef, + packageName: packageName, + ), + from: pubDevPackageDetailsProvider, + name: r'pubDevPackageDetailsProvider', + debugGetCreateSourceHash: + const bool.fromEnvironment('dart.vm.product') + ? null + : _$pubDevPackageDetailsHash, + dependencies: PubDevPackageDetailsFamily._dependencies, + allTransitiveDependencies: + PubDevPackageDetailsFamily._allTransitiveDependencies, + packageName: packageName, + ); + + PubDevPackageDetailsProvider._internal( + super._createNotifier, { + required super.name, + required super.dependencies, + required super.allTransitiveDependencies, + required super.debugGetCreateSourceHash, + required super.from, + required this.packageName, + }) : super.internal(); + + final String packageName; + + @override + Override overrideWith( + FutureOr Function( + PubDevPackageDetailsRef provider) + create, + ) { + return ProviderOverride( + origin: this, + override: PubDevPackageDetailsProvider._internal( + (ref) => create(ref as PubDevPackageDetailsRef), + from: from, + name: null, + dependencies: null, + allTransitiveDependencies: null, + debugGetCreateSourceHash: null, + packageName: packageName, + ), + ); + } + + @override + AutoDisposeFutureProviderElement + createElement() { + return _PubDevPackageDetailsProviderElement(this); + } + + @override + bool operator ==(Object other) { + return other is PubDevPackageDetailsProvider && + other.packageName == packageName; + } + + @override + int get hashCode { + var hash = _SystemHash.combine(0, runtimeType.hashCode); + hash = _SystemHash.combine(hash, packageName.hashCode); + + return _SystemHash.finish(hash); + } +} + +@Deprecated('Will be removed in 3.0. Use Ref instead') +// ignore: unused_element +mixin PubDevPackageDetailsRef + on AutoDisposeFutureProviderRef { + /// The parameter `packageName` of this provider. + String get packageName; +} + +class _PubDevPackageDetailsProviderElement + extends AutoDisposeFutureProviderElement + with PubDevPackageDetailsRef { + _PubDevPackageDetailsProviderElement(super.provider); + + @override + String get packageName => + (origin as PubDevPackageDetailsProvider).packageName; +} +// ignore_for_file: type=lint +// ignore_for_file: subtype_of_sealed_class, invalid_use_of_internal_member, invalid_use_of_visible_for_testing_member, deprecated_member_use_from_same_package diff --git a/packages/flutter_app/lib/features/pub_dev_packages/query/pub_dev_packages_page_state_provider.dart b/packages/flutter_app/lib/features/pub_dev_packages/query/pub_dev_packages_page_state_provider.dart new file mode 100644 index 00000000..0a70a681 --- /dev/null +++ b/packages/flutter_app/lib/features/pub_dev_packages/query/pub_dev_packages_page_state_provider.dart @@ -0,0 +1,56 @@ +import 'package:pub_dev_api_client/pub_dev_api_client.dart'; +import 'package:riverpod_annotation/riverpod_annotation.dart'; + +import '../../../package_adaptor/pub_dev_api_client_provider.dart'; + +part 'pub_dev_packages_page_state_provider.g.dart'; + +/// Provider for the search word of pub.dev packages. +@Riverpod(keepAlive: true) +class PubDevPackageSearchWordState extends _$PubDevPackageSearchWordState { + @override + String build() => ''; + + /// Update the search word. + // ignore: use_setters_to_change_properties + void update(String word) { + state = word; + } + + /// Clear the search word. + void clear() { + state = ''; + } +} + +@Riverpod(keepAlive: true) +class PubDevPackagesPageState extends _$PubDevPackagesPageState { + @override + Future build() async { + final searchWord = ref.watch(pubDevPackageSearchWordStateProvider); + final client = ref.watch(pubDevApiClientProvider); + final response = await client.getSearchedPackages(searchWord: searchWord); + return response; + } + + Future loadNext(int nextPage) async { + state = const AsyncLoading() + .copyWithPrevious(state); + + final searchWord = ref.read(pubDevPackageSearchWordStateProvider); + final client = ref.read(pubDevApiClientProvider); + final response = await client.getSearchedPackages( + searchWord: searchWord, + page: nextPage, + ); + final currentPackages = state.requireValue.packages; + final newPackages = [...currentPackages, ...response.packages]; + + state = AsyncData( + GetSearchedPackagesResponseBody( + packages: newPackages, + nextPageUrl: response.nextPageUrl, + ), + ); + } +} diff --git a/packages/flutter_app/lib/features/pub_dev_packages/query/pub_dev_packages_page_state_provider.g.dart b/packages/flutter_app/lib/features/pub_dev_packages/query/pub_dev_packages_page_state_provider.g.dart new file mode 100644 index 00000000..82654ec1 --- /dev/null +++ b/packages/flutter_app/lib/features/pub_dev_packages/query/pub_dev_packages_page_state_provider.g.dart @@ -0,0 +1,49 @@ +// GENERATED CODE - DO NOT MODIFY BY HAND + +// ignore_for_file: duplicate_ignore, type=lint, implicit_dynamic_parameter, implicit_dynamic_type, implicit_dynamic_method, strict_raw_type + +part of 'pub_dev_packages_page_state_provider.dart'; + +// ************************************************************************** +// RiverpodGenerator +// ************************************************************************** + +String _$pubDevPackageSearchWordStateHash() => + r'4503635ef8a15e7279a81f805139a09dbafd0320'; + +/// Provider for the search word of pub.dev packages. +/// +/// Copied from [PubDevPackageSearchWordState]. +@ProviderFor(PubDevPackageSearchWordState) +final pubDevPackageSearchWordStateProvider = + NotifierProvider.internal( + PubDevPackageSearchWordState.new, + name: r'pubDevPackageSearchWordStateProvider', + debugGetCreateSourceHash: const bool.fromEnvironment('dart.vm.product') + ? null + : _$pubDevPackageSearchWordStateHash, + dependencies: null, + allTransitiveDependencies: null, +); + +typedef _$PubDevPackageSearchWordState = Notifier; +String _$pubDevPackagesPageStateHash() => + r'fa605b47791791857c2a92b0e3f8a0ca0e8ecc38'; + +/// See also [PubDevPackagesPageState]. +@ProviderFor(PubDevPackagesPageState) +final pubDevPackagesPageStateProvider = AsyncNotifierProvider< + PubDevPackagesPageState, GetSearchedPackagesResponseBody>.internal( + PubDevPackagesPageState.new, + name: r'pubDevPackagesPageStateProvider', + debugGetCreateSourceHash: const bool.fromEnvironment('dart.vm.product') + ? null + : _$pubDevPackagesPageStateHash, + dependencies: null, + allTransitiveDependencies: null, +); + +typedef _$PubDevPackagesPageState + = AsyncNotifier; +// ignore_for_file: type=lint +// ignore_for_file: subtype_of_sealed_class, invalid_use_of_internal_member, invalid_use_of_visible_for_testing_member, deprecated_member_use_from_same_package diff --git a/packages/flutter_app/lib/features/pub_dev_packages/query/query.dart b/packages/flutter_app/lib/features/pub_dev_packages/query/query.dart new file mode 100644 index 00000000..4b060687 --- /dev/null +++ b/packages/flutter_app/lib/features/pub_dev_packages/query/query.dart @@ -0,0 +1,2 @@ +export 'pub_dev_package_details_provider.dart'; +export 'pub_dev_packages_page_state_provider.dart'; diff --git a/packages/flutter_app/lib/features/pub_dev_packages/view/pub_dev_packages_page.dart b/packages/flutter_app/lib/features/pub_dev_packages/view/pub_dev_packages_page.dart new file mode 100644 index 00000000..5aba215b --- /dev/null +++ b/packages/flutter_app/lib/features/pub_dev_packages/view/pub_dev_packages_page.dart @@ -0,0 +1,208 @@ +import 'dart:async'; + +import 'package:convenient_widgets/convenient_widgets.dart'; +import 'package:flutter/material.dart'; +import 'package:gap/gap.dart'; +import 'package:hooks_riverpod/hooks_riverpod.dart'; +import 'package:url_launcher/url_launcher.dart'; + +import '../../../gen/strings.g.dart'; +import '../query/query.dart'; + +/// Pub.dev packages page. +class PubDevPackagesPage extends ConsumerWidget { + const PubDevPackagesPage({super.key}); + + @override + Widget build(BuildContext context, WidgetRef ref) { + final t = Translations.of(context); + final asyncValue = ref.watch(pubDevPackagesPageStateProvider); + + return UnfocusOnTap( + child: Scaffold( + appBar: AppBar( + title: Text(t.pubDevPackagesPage.appBar.title), + ), + body: asyncValue.when( + loading: () => + const Center(child: CircularProgressIndicator.adaptive()), + error: (error, stackTrace) => Center(child: Text('$error')), + data: (packagesState) { + final packages = packagesState.packages; + final nextPage = packagesState.nextPage; + + if (packages.isEmpty) { + return Center(child: Text(t.pubDevPackagesPage.body.emptyLabel)); + } + + return NotificationListener( + onNotification: (notification) { + if (notification.metrics.extentAfter == 0 && nextPage != null) { + unawaited( + ref + .read(pubDevPackagesPageStateProvider.notifier) + .loadNext(nextPage), + ); + return true; + } + return false; + }, + child: CustomScrollView( + slivers: [ + SliverAppBar( + floating: true, + title: TextFormField( + controller: TextEditingController( + text: ref.watch(pubDevPackageSearchWordStateProvider), + ), + decoration: InputDecoration( + hintText: t.pubDevPackagesPage.searchBar.hintText, + prefixIcon: const Icon(Icons.search), + suffixIcon: IconButton( + onPressed: () => ref + .read( + pubDevPackageSearchWordStateProvider.notifier, + ) + .clear(), + icon: const Icon(Icons.clear), + ), + ), + onFieldSubmitted: ref + .read(pubDevPackageSearchWordStateProvider.notifier) + .update, + ), + ), + SliverList( + delegate: SliverChildBuilderDelegate( + // Add 1 for the loading indicator. + childCount: packages.length + 1, + (context, index) { + if (index == packages.length) { + return asyncValue.isRefreshing + ? const Center( + child: Padding( + padding: EdgeInsets.symmetric(vertical: 20), + child: CircularProgressIndicator.adaptive(), + ), + ) + : const Gap(40); + } + + final package = packages[index]; + final name = package.name; + + return Padding( + padding: const EdgeInsets.symmetric( + vertical: 4, + horizontal: 8, + ), + child: _PackageCard(packageName: name), + ); + }, + ), + ), + ], + ), + ); + }, + ), + ), + ); + } +} + +class _PackageCard extends StatelessWidget { + const _PackageCard({ + required this.packageName, + }); + + final String packageName; + + @override + Widget build(BuildContext context) { + final t = Translations.of(context); + return Card( + elevation: 0.5, + child: ListTile( + title: Text(packageName), + onTap: () async { + await showDialog( + context: context, + builder: (_) => Consumer( + builder: (context, ref, child) { + final asyncValue = ref.watch( + pubDevPackageDetailsProvider(packageName: packageName), + ); + + return AlertDialog( + scrollable: true, + title: Row( + children: [ + Expanded(child: Text(packageName)), + IconButton( + icon: const Icon(Icons.open_in_new), + onPressed: () { + final url = + Uri.https('pub.dev', '/packages/$packageName'); + launchUrl(url); + }, + ), + ], + ), + content: asyncValue.when( + loading: () => const Center( + child: CircularProgressIndicator.adaptive(), + ), + error: (error, stackTrace) => Text('$error'), + data: (packageDetails) { + final latestDetail = packageDetails.latest; + return Column( + mainAxisSize: MainAxisSize.min, + crossAxisAlignment: CrossAxisAlignment.start, + children: [ + Wrap( + children: [ + Text( + t.pubDevPackagesPage.dialog.content.version, + style: const TextStyle( + fontWeight: FontWeight.bold, + ), + ), + const SizedBox(width: 8), + Text(latestDetail.pubspec.version), + ], + ), + const Gap(20), + Wrap( + children: [ + Text( + t.pubDevPackagesPage.dialog.content.description, + style: const TextStyle( + fontWeight: FontWeight.bold, + ), + ), + const SizedBox(width: 8), + Text(latestDetail.pubspec.description), + ], + ), + ], + ); + }, + ), + actionsAlignment: MainAxisAlignment.center, + actions: [ + ElevatedButton( + onPressed: Navigator.of(context).pop, + child: + Text(t.pubDevPackagesPage.dialog.button.close.label), + ), + ], + ); + }, + ), + ); + }, + ), + ); + } +} diff --git a/packages/flutter_app/lib/gen/strings.g.dart b/packages/flutter_app/lib/gen/strings.g.dart index 53d08660..7d8d165e 100644 --- a/packages/flutter_app/lib/gen/strings.g.dart +++ b/packages/flutter_app/lib/gen/strings.g.dart @@ -4,9 +4,9 @@ /// To regenerate, run: `dart run slang` /// /// Locales: 2 -/// Strings: 54 (27 per locale) +/// Strings: 58 (29 per locale) /// -/// Built on 2024-11-25 at 07:00 UTC +/// Built on 2024-12-03 at 01:33 UTC // coverage:ignore-file // ignore_for_file: type=lint, unused_import diff --git a/packages/flutter_app/lib/gen/strings_en.g.dart b/packages/flutter_app/lib/gen/strings_en.g.dart index 358b33d8..1274a4bf 100644 --- a/packages/flutter_app/lib/gen/strings_en.g.dart +++ b/packages/flutter_app/lib/gen/strings_en.g.dart @@ -39,11 +39,10 @@ class TranslationsEn implements Translations { @override late final _TranslationsAuthorEn author = _TranslationsAuthorEn._(_root); @override late final _TranslationsButtonEn button = _TranslationsButtonEn._(_root); @override late final _TranslationsHomePageEn homePage = _TranslationsHomePageEn._(_root); + @override late final _TranslationsPubDevPackagesPageEn pubDevPackagesPage = _TranslationsPubDevPackagesPageEn._(_root); @override late final _TranslationsNotFoundPageEn notFoundPage = _TranslationsNotFoundPageEn._(_root); - @override late final _TranslationsPinkieMewPageEn pinkieMewPage = _TranslationsPinkieMewPageEn._(_root); @override late final _TranslationsSettingsPageEn settingsPage = _TranslationsSettingsPageEn._(_root); @override late final _TranslationsThemeEn theme = _TranslationsThemeEn._(_root); - @override late final _TranslationsTopLevelTabEn topLevelTab = _TranslationsTopLevelTabEn._(_root); } // Path: accountPage @@ -98,6 +97,19 @@ class _TranslationsHomePageEn implements TranslationsHomePageJa { @override late final _TranslationsHomePageListEn list = _TranslationsHomePageListEn._(_root); } +// Path: pubDevPackagesPage +class _TranslationsPubDevPackagesPageEn implements TranslationsPubDevPackagesPageJa { + _TranslationsPubDevPackagesPageEn._(this._root); + + final TranslationsEn _root; // ignore: unused_field + + // Translations + @override late final _TranslationsPubDevPackagesPageAppBarEn appBar = _TranslationsPubDevPackagesPageAppBarEn._(_root); + @override late final _TranslationsPubDevPackagesPageSearchBarEn searchBar = _TranslationsPubDevPackagesPageSearchBarEn._(_root); + @override late final _TranslationsPubDevPackagesPageBodyEn body = _TranslationsPubDevPackagesPageBodyEn._(_root); + @override late final _TranslationsPubDevPackagesPageDialogEn dialog = _TranslationsPubDevPackagesPageDialogEn._(_root); +} + // Path: notFoundPage class _TranslationsNotFoundPageEn implements TranslationsNotFoundPageJa { _TranslationsNotFoundPageEn._(this._root); @@ -111,16 +123,6 @@ class _TranslationsNotFoundPageEn implements TranslationsNotFoundPageJa { @override late final _TranslationsNotFoundPageBackButtonEn backButton = _TranslationsNotFoundPageBackButtonEn._(_root); } -// Path: pinkieMewPage -class _TranslationsPinkieMewPageEn implements TranslationsPinkieMewPageJa { - _TranslationsPinkieMewPageEn._(this._root); - - final TranslationsEn _root; // ignore: unused_field - - // Translations - @override String get title => 'Pinkie and Mew'; -} - // Path: settingsPage class _TranslationsSettingsPageEn implements TranslationsSettingsPageJa { _TranslationsSettingsPageEn._(this._root); @@ -143,18 +145,6 @@ class _TranslationsThemeEn implements TranslationsThemeJa { @override late final _TranslationsThemeSelectionEn selection = _TranslationsThemeSelectionEn._(_root); } -// Path: topLevelTab -class _TranslationsTopLevelTabEn implements TranslationsTopLevelTabJa { - _TranslationsTopLevelTabEn._(this._root); - - final TranslationsEn _root; // ignore: unused_field - - // Translations - @override late final _TranslationsTopLevelTabHomeEn home = _TranslationsTopLevelTabHomeEn._(_root); - @override late final _TranslationsTopLevelTabRiverpodEn riverpod = _TranslationsTopLevelTabRiverpodEn._(_root); - @override late final _TranslationsTopLevelTabSettingsEn settings = _TranslationsTopLevelTabSettingsEn._(_root); -} - // Path: accountPage.appBar class _TranslationsAccountPageAppBarEn implements TranslationsAccountPageAppBarJa { _TranslationsAccountPageAppBarEn._(this._root); @@ -206,6 +196,47 @@ class _TranslationsHomePageListEn implements TranslationsHomePageListJa { @override String get doubleCount => 'The doubled count value :'; } +// Path: pubDevPackagesPage.appBar +class _TranslationsPubDevPackagesPageAppBarEn implements TranslationsPubDevPackagesPageAppBarJa { + _TranslationsPubDevPackagesPageAppBarEn._(this._root); + + final TranslationsEn _root; // ignore: unused_field + + // Translations + @override String get title => 'Pub.dev Packages'; +} + +// Path: pubDevPackagesPage.searchBar +class _TranslationsPubDevPackagesPageSearchBarEn implements TranslationsPubDevPackagesPageSearchBarJa { + _TranslationsPubDevPackagesPageSearchBarEn._(this._root); + + final TranslationsEn _root; // ignore: unused_field + + // Translations + @override String get hintText => 'Search packages'; +} + +// Path: pubDevPackagesPage.body +class _TranslationsPubDevPackagesPageBodyEn implements TranslationsPubDevPackagesPageBodyJa { + _TranslationsPubDevPackagesPageBodyEn._(this._root); + + final TranslationsEn _root; // ignore: unused_field + + // Translations + @override String get emptyLabel => 'No packages found.'; +} + +// Path: pubDevPackagesPage.dialog +class _TranslationsPubDevPackagesPageDialogEn implements TranslationsPubDevPackagesPageDialogJa { + _TranslationsPubDevPackagesPageDialogEn._(this._root); + + final TranslationsEn _root; // ignore: unused_field + + // Translations + @override late final _TranslationsPubDevPackagesPageDialogContentEn content = _TranslationsPubDevPackagesPageDialogContentEn._(_root); + @override late final _TranslationsPubDevPackagesPageDialogButtonEn button = _TranslationsPubDevPackagesPageDialogButtonEn._(_root); +} + // Path: notFoundPage.header class _TranslationsNotFoundPageHeaderEn implements TranslationsNotFoundPageHeaderJa { _TranslationsNotFoundPageHeaderEn._(this._root); @@ -268,44 +299,35 @@ class _TranslationsThemeSelectionEn implements TranslationsThemeSelectionJa { @override late final _TranslationsThemeSelectionPageEn page = _TranslationsThemeSelectionPageEn._(_root); } -// Path: topLevelTab.home -class _TranslationsTopLevelTabHomeEn implements TranslationsTopLevelTabHomeJa { - _TranslationsTopLevelTabHomeEn._(this._root); - - final TranslationsEn _root; // ignore: unused_field - - // Translations - @override String get label => 'Home'; -} - -// Path: topLevelTab.riverpod -class _TranslationsTopLevelTabRiverpodEn implements TranslationsTopLevelTabRiverpodJa { - _TranslationsTopLevelTabRiverpodEn._(this._root); +// Path: homePage.list.appInfo +class _TranslationsHomePageListAppInfoEn implements TranslationsHomePageListAppInfoJa { + _TranslationsHomePageListAppInfoEn._(this._root); final TranslationsEn _root; // ignore: unused_field // Translations - @override late final _TranslationsTopLevelTabRiverpodExampleEn example = _TranslationsTopLevelTabRiverpodExampleEn._(_root); + @override String get label => 'App Info'; } -// Path: topLevelTab.settings -class _TranslationsTopLevelTabSettingsEn implements TranslationsTopLevelTabSettingsJa { - _TranslationsTopLevelTabSettingsEn._(this._root); +// Path: pubDevPackagesPage.dialog.content +class _TranslationsPubDevPackagesPageDialogContentEn implements TranslationsPubDevPackagesPageDialogContentJa { + _TranslationsPubDevPackagesPageDialogContentEn._(this._root); final TranslationsEn _root; // ignore: unused_field // Translations - @override String get label => 'Settings'; + @override String get version => 'Latest version :'; + @override String get description => 'Description :'; } -// Path: homePage.list.appInfo -class _TranslationsHomePageListAppInfoEn implements TranslationsHomePageListAppInfoJa { - _TranslationsHomePageListAppInfoEn._(this._root); +// Path: pubDevPackagesPage.dialog.button +class _TranslationsPubDevPackagesPageDialogButtonEn implements TranslationsPubDevPackagesPageDialogButtonJa { + _TranslationsPubDevPackagesPageDialogButtonEn._(this._root); final TranslationsEn _root; // ignore: unused_field // Translations - @override String get label => 'App Info'; + @override late final _TranslationsPubDevPackagesPageDialogButtonCloseEn close = _TranslationsPubDevPackagesPageDialogButtonCloseEn._(_root); } // Path: settingsPage.list.themeSelector @@ -362,14 +384,14 @@ class _TranslationsThemeSelectionPageEn implements TranslationsThemeSelectionPag @override late final _TranslationsThemeSelectionPageAppBarEn appBar = _TranslationsThemeSelectionPageAppBarEn._(_root); } -// Path: topLevelTab.riverpod.example -class _TranslationsTopLevelTabRiverpodExampleEn implements TranslationsTopLevelTabRiverpodExampleJa { - _TranslationsTopLevelTabRiverpodExampleEn._(this._root); +// Path: pubDevPackagesPage.dialog.button.close +class _TranslationsPubDevPackagesPageDialogButtonCloseEn implements TranslationsPubDevPackagesPageDialogButtonCloseJa { + _TranslationsPubDevPackagesPageDialogButtonCloseEn._(this._root); final TranslationsEn _root; // ignore: unused_field // Translations - @override String get label => 'Riverpod'; + @override String get label => 'Close'; } // Path: theme.selection.page.appBar @@ -396,11 +418,16 @@ extension on TranslationsEn { case 'homePage.appBar.title': return 'Home'; case 'homePage.list.appInfo.label': return 'App Info'; case 'homePage.list.doubleCount': return 'The doubled count value :'; + case 'pubDevPackagesPage.appBar.title': return 'Pub.dev Packages'; + case 'pubDevPackagesPage.searchBar.hintText': return 'Search packages'; + case 'pubDevPackagesPage.body.emptyLabel': return 'No packages found.'; + case 'pubDevPackagesPage.dialog.content.version': return 'Latest version :'; + case 'pubDevPackagesPage.dialog.content.description': return 'Description :'; + case 'pubDevPackagesPage.dialog.button.close.label': return 'Close'; case 'notFoundPage.title': return '404 Not Found'; case 'notFoundPage.header.label': return 'Sorry...'; case 'notFoundPage.description': return 'is not found.'; case 'notFoundPage.backButton.label': return 'is not found.'; - case 'pinkieMewPage.title': return 'Pinkie and Mew'; case 'settingsPage.appBar.title': return 'Settings'; case 'settingsPage.list.themeSelector.label': return 'Theme Selector'; case 'settingsPage.list.account.label': return 'Account'; @@ -411,9 +438,6 @@ extension on TranslationsEn { case 'theme.mode.subtitle.light': return 'Light'; case 'theme.mode.subtitle.dark': return 'Dark'; case 'theme.selection.page.appBar.title': return 'Theme Selector'; - case 'topLevelTab.home.label': return 'Home'; - case 'topLevelTab.riverpod.example.label': return 'Riverpod'; - case 'topLevelTab.settings.label': return 'Settings'; default: return null; } } diff --git a/packages/flutter_app/lib/gen/strings_ja.g.dart b/packages/flutter_app/lib/gen/strings_ja.g.dart index a9854518..d4e255d0 100644 --- a/packages/flutter_app/lib/gen/strings_ja.g.dart +++ b/packages/flutter_app/lib/gen/strings_ja.g.dart @@ -43,11 +43,10 @@ class Translations implements BaseTranslations { late final TranslationsAuthorJa author = TranslationsAuthorJa._(_root); late final TranslationsButtonJa button = TranslationsButtonJa._(_root); late final TranslationsHomePageJa homePage = TranslationsHomePageJa._(_root); + late final TranslationsPubDevPackagesPageJa pubDevPackagesPage = TranslationsPubDevPackagesPageJa._(_root); late final TranslationsNotFoundPageJa notFoundPage = TranslationsNotFoundPageJa._(_root); - late final TranslationsPinkieMewPageJa pinkieMewPage = TranslationsPinkieMewPageJa._(_root); late final TranslationsSettingsPageJa settingsPage = TranslationsSettingsPageJa._(_root); late final TranslationsThemeJa theme = TranslationsThemeJa._(_root); - late final TranslationsTopLevelTabJa topLevelTab = TranslationsTopLevelTabJa._(_root); } // Path: accountPage @@ -102,6 +101,19 @@ class TranslationsHomePageJa { late final TranslationsHomePageListJa list = TranslationsHomePageListJa._(_root); } +// Path: pubDevPackagesPage +class TranslationsPubDevPackagesPageJa { + TranslationsPubDevPackagesPageJa._(this._root); + + final Translations _root; // ignore: unused_field + + // Translations + late final TranslationsPubDevPackagesPageAppBarJa appBar = TranslationsPubDevPackagesPageAppBarJa._(_root); + late final TranslationsPubDevPackagesPageSearchBarJa searchBar = TranslationsPubDevPackagesPageSearchBarJa._(_root); + late final TranslationsPubDevPackagesPageBodyJa body = TranslationsPubDevPackagesPageBodyJa._(_root); + late final TranslationsPubDevPackagesPageDialogJa dialog = TranslationsPubDevPackagesPageDialogJa._(_root); +} + // Path: notFoundPage class TranslationsNotFoundPageJa { TranslationsNotFoundPageJa._(this._root); @@ -115,16 +127,6 @@ class TranslationsNotFoundPageJa { late final TranslationsNotFoundPageBackButtonJa backButton = TranslationsNotFoundPageBackButtonJa._(_root); } -// Path: pinkieMewPage -class TranslationsPinkieMewPageJa { - TranslationsPinkieMewPageJa._(this._root); - - final Translations _root; // ignore: unused_field - - // Translations - String get title => 'Pinkie and Mew'; -} - // Path: settingsPage class TranslationsSettingsPageJa { TranslationsSettingsPageJa._(this._root); @@ -147,18 +149,6 @@ class TranslationsThemeJa { late final TranslationsThemeSelectionJa selection = TranslationsThemeSelectionJa._(_root); } -// Path: topLevelTab -class TranslationsTopLevelTabJa { - TranslationsTopLevelTabJa._(this._root); - - final Translations _root; // ignore: unused_field - - // Translations - late final TranslationsTopLevelTabHomeJa home = TranslationsTopLevelTabHomeJa._(_root); - late final TranslationsTopLevelTabRiverpodJa riverpod = TranslationsTopLevelTabRiverpodJa._(_root); - late final TranslationsTopLevelTabSettingsJa settings = TranslationsTopLevelTabSettingsJa._(_root); -} - // Path: accountPage.appBar class TranslationsAccountPageAppBarJa { TranslationsAccountPageAppBarJa._(this._root); @@ -210,6 +200,47 @@ class TranslationsHomePageListJa { String get doubleCount => '2倍されたカウント値:'; } +// Path: pubDevPackagesPage.appBar +class TranslationsPubDevPackagesPageAppBarJa { + TranslationsPubDevPackagesPageAppBarJa._(this._root); + + final Translations _root; // ignore: unused_field + + // Translations + String get title => 'Pub.dev パッケージ'; +} + +// Path: pubDevPackagesPage.searchBar +class TranslationsPubDevPackagesPageSearchBarJa { + TranslationsPubDevPackagesPageSearchBarJa._(this._root); + + final Translations _root; // ignore: unused_field + + // Translations + String get hintText => 'パッケージを検索'; +} + +// Path: pubDevPackagesPage.body +class TranslationsPubDevPackagesPageBodyJa { + TranslationsPubDevPackagesPageBodyJa._(this._root); + + final Translations _root; // ignore: unused_field + + // Translations + String get emptyLabel => 'パッケージが見つかりませんでした。'; +} + +// Path: pubDevPackagesPage.dialog +class TranslationsPubDevPackagesPageDialogJa { + TranslationsPubDevPackagesPageDialogJa._(this._root); + + final Translations _root; // ignore: unused_field + + // Translations + late final TranslationsPubDevPackagesPageDialogContentJa content = TranslationsPubDevPackagesPageDialogContentJa._(_root); + late final TranslationsPubDevPackagesPageDialogButtonJa button = TranslationsPubDevPackagesPageDialogButtonJa._(_root); +} + // Path: notFoundPage.header class TranslationsNotFoundPageHeaderJa { TranslationsNotFoundPageHeaderJa._(this._root); @@ -272,44 +303,35 @@ class TranslationsThemeSelectionJa { late final TranslationsThemeSelectionPageJa page = TranslationsThemeSelectionPageJa._(_root); } -// Path: topLevelTab.home -class TranslationsTopLevelTabHomeJa { - TranslationsTopLevelTabHomeJa._(this._root); - - final Translations _root; // ignore: unused_field - - // Translations - String get label => 'Home'; -} - -// Path: topLevelTab.riverpod -class TranslationsTopLevelTabRiverpodJa { - TranslationsTopLevelTabRiverpodJa._(this._root); +// Path: homePage.list.appInfo +class TranslationsHomePageListAppInfoJa { + TranslationsHomePageListAppInfoJa._(this._root); final Translations _root; // ignore: unused_field // Translations - late final TranslationsTopLevelTabRiverpodExampleJa example = TranslationsTopLevelTabRiverpodExampleJa._(_root); + String get label => 'アプリ情報'; } -// Path: topLevelTab.settings -class TranslationsTopLevelTabSettingsJa { - TranslationsTopLevelTabSettingsJa._(this._root); +// Path: pubDevPackagesPage.dialog.content +class TranslationsPubDevPackagesPageDialogContentJa { + TranslationsPubDevPackagesPageDialogContentJa._(this._root); final Translations _root; // ignore: unused_field // Translations - String get label => 'Settings'; + String get version => '最新バージョン :'; + String get description => '説明 :'; } -// Path: homePage.list.appInfo -class TranslationsHomePageListAppInfoJa { - TranslationsHomePageListAppInfoJa._(this._root); +// Path: pubDevPackagesPage.dialog.button +class TranslationsPubDevPackagesPageDialogButtonJa { + TranslationsPubDevPackagesPageDialogButtonJa._(this._root); final Translations _root; // ignore: unused_field // Translations - String get label => 'アプリ情報'; + late final TranslationsPubDevPackagesPageDialogButtonCloseJa close = TranslationsPubDevPackagesPageDialogButtonCloseJa._(_root); } // Path: settingsPage.list.themeSelector @@ -366,14 +388,14 @@ class TranslationsThemeSelectionPageJa { late final TranslationsThemeSelectionPageAppBarJa appBar = TranslationsThemeSelectionPageAppBarJa._(_root); } -// Path: topLevelTab.riverpod.example -class TranslationsTopLevelTabRiverpodExampleJa { - TranslationsTopLevelTabRiverpodExampleJa._(this._root); +// Path: pubDevPackagesPage.dialog.button.close +class TranslationsPubDevPackagesPageDialogButtonCloseJa { + TranslationsPubDevPackagesPageDialogButtonCloseJa._(this._root); final Translations _root; // ignore: unused_field // Translations - String get label => 'Riverpod'; + String get label => 'とじる'; } // Path: theme.selection.page.appBar @@ -400,11 +422,16 @@ extension on Translations { case 'homePage.appBar.title': return 'Home'; case 'homePage.list.appInfo.label': return 'アプリ情報'; case 'homePage.list.doubleCount': return '2倍されたカウント値:'; + case 'pubDevPackagesPage.appBar.title': return 'Pub.dev パッケージ'; + case 'pubDevPackagesPage.searchBar.hintText': return 'パッケージを検索'; + case 'pubDevPackagesPage.body.emptyLabel': return 'パッケージが見つかりませんでした。'; + case 'pubDevPackagesPage.dialog.content.version': return '最新バージョン :'; + case 'pubDevPackagesPage.dialog.content.description': return '説明 :'; + case 'pubDevPackagesPage.dialog.button.close.label': return 'とじる'; case 'notFoundPage.title': return '404 Not Found'; case 'notFoundPage.header.label': return 'ごめんなさい🙏'; case 'notFoundPage.description': return 'is not found.'; case 'notFoundPage.backButton.label': return 'is not found.'; - case 'pinkieMewPage.title': return 'Pinkie and Mew'; case 'settingsPage.appBar.title': return '設定'; case 'settingsPage.list.themeSelector.label': return 'テーマ選択'; case 'settingsPage.list.account.label': return 'アカウント'; @@ -415,9 +442,6 @@ extension on Translations { case 'theme.mode.subtitle.light': return '明るいテーマ'; case 'theme.mode.subtitle.dark': return '暗いテーマ'; case 'theme.selection.page.appBar.title': return 'テーマ選択'; - case 'topLevelTab.home.label': return 'Home'; - case 'topLevelTab.riverpod.example.label': return 'Riverpod'; - case 'topLevelTab.settings.label': return 'Settings'; default: return null; } } diff --git a/packages/flutter_app/lib/i18n/app_en.yaml b/packages/flutter_app/lib/i18n/app_en.yaml index 289fb227..f9993e41 100644 --- a/packages/flutter_app/lib/i18n/app_en.yaml +++ b/packages/flutter_app/lib/i18n/app_en.yaml @@ -19,6 +19,20 @@ homePage: appInfo: label: "App Info" doubleCount: "The doubled count value :" +pubDevPackagesPage: + appBar: + title: "Pub.dev Packages" + searchBar: + hintText: "Search packages" + body: + emptyLabel: "No packages found." + dialog: + content: + version: "Latest version :" + description: "Description :" + button: + close: + label: "Close" notFoundPage: title: "404 Not Found" header: @@ -26,8 +40,6 @@ notFoundPage: description: "is not found." backButton: label: "is not found." -pinkieMewPage: - title: "Pinkie and Mew" settingsPage: appBar: title: "Settings" @@ -50,11 +62,3 @@ theme: page: appBar: title: "Theme Selector" -topLevelTab: - home: - label: "Home" - riverpod: - example: - label: "Riverpod" - settings: - label: "Settings" diff --git a/packages/flutter_app/lib/i18n/app_ja.yaml b/packages/flutter_app/lib/i18n/app_ja.yaml index 3d19f162..ed2dad97 100644 --- a/packages/flutter_app/lib/i18n/app_ja.yaml +++ b/packages/flutter_app/lib/i18n/app_ja.yaml @@ -19,6 +19,20 @@ homePage: appInfo: label: "アプリ情報" doubleCount: "2倍されたカウント値:" +pubDevPackagesPage: + appBar: + title: "Pub.dev パッケージ" + searchBar: + hintText: "パッケージを検索" + body: + emptyLabel: "パッケージが見つかりませんでした。" + dialog: + content: + version: "最新バージョン :" + description: "説明 :" + button: + close: + label: "とじる" notFoundPage: title: "404 Not Found" header: @@ -26,8 +40,6 @@ notFoundPage: description: "is not found." backButton: label: "is not found." -pinkieMewPage: - title: "Pinkie and Mew" settingsPage: appBar: title: "設定" @@ -50,11 +62,3 @@ theme: page: appBar: title: "テーマ選択" -topLevelTab: - home: - label: "Home" - riverpod: - example: - label: "Riverpod" - settings: - label: "Settings" diff --git a/packages/flutter_app/lib/package_adaptor/pub_dev_api_client_provider.dart b/packages/flutter_app/lib/package_adaptor/pub_dev_api_client_provider.dart new file mode 100644 index 00000000..4d07d09f --- /dev/null +++ b/packages/flutter_app/lib/package_adaptor/pub_dev_api_client_provider.dart @@ -0,0 +1,13 @@ +import 'package:hooks_riverpod/hooks_riverpod.dart'; +import 'package:pub_dev_api_client/pub_dev_api_client.dart'; +import 'package:riverpod_annotation/riverpod_annotation.dart'; + +part 'pub_dev_api_client_provider.g.dart'; + +@Riverpod(keepAlive: true) +PubDevApiClient pubDevApiClient(Ref ref) { + return PubDevApiClient.fromParameters( + baseUrl: 'https://pub.dev/api', + timeoutDuration: const Duration(seconds: 30), + ); +} diff --git a/packages/flutter_app/lib/package_adaptor/pub_dev_api_client_provider.g.dart b/packages/flutter_app/lib/package_adaptor/pub_dev_api_client_provider.g.dart new file mode 100644 index 00000000..c4efbe61 --- /dev/null +++ b/packages/flutter_app/lib/package_adaptor/pub_dev_api_client_provider.g.dart @@ -0,0 +1,29 @@ +// GENERATED CODE - DO NOT MODIFY BY HAND + +// ignore_for_file: duplicate_ignore, type=lint, implicit_dynamic_parameter, implicit_dynamic_type, implicit_dynamic_method, strict_raw_type + +part of 'pub_dev_api_client_provider.dart'; + +// ************************************************************************** +// RiverpodGenerator +// ************************************************************************** + +String _$pubDevApiClientHash() => r'a480dd2c3d62f33421097013c21c92a9c2ef2fac'; + +/// See also [pubDevApiClient]. +@ProviderFor(pubDevApiClient) +final pubDevApiClientProvider = Provider.internal( + pubDevApiClient, + name: r'pubDevApiClientProvider', + debugGetCreateSourceHash: const bool.fromEnvironment('dart.vm.product') + ? null + : _$pubDevApiClientHash, + dependencies: null, + allTransitiveDependencies: null, +); + +@Deprecated('Will be removed in 3.0. Use Ref instead') +// ignore: unused_element +typedef PubDevApiClientRef = ProviderRef; +// ignore_for_file: type=lint +// ignore_for_file: subtype_of_sealed_class, invalid_use_of_internal_member, invalid_use_of_visible_for_testing_member, deprecated_member_use_from_same_package diff --git a/packages/flutter_app/lib/router/app_routes.dart b/packages/flutter_app/lib/router/app_routes.dart index f6bf9834..4617b065 100644 --- a/packages/flutter_app/lib/router/app_routes.dart +++ b/packages/flutter_app/lib/router/app_routes.dart @@ -81,11 +81,11 @@ class InitializationRoute extends GoRouteData { ), ], ), - TypedStatefulShellBranch( + TypedStatefulShellBranch( routes: [ - TypedGoRoute( - name: PostRouteData.name, - path: PostRouteData.path, + TypedGoRoute( + name: PubDevPackagesRouteData.name, + path: PubDevPackagesRouteData.path, ), ], ), diff --git a/packages/flutter_app/lib/router/app_routes.g.dart b/packages/flutter_app/lib/router/app_routes.g.dart index c6e4ae0c..82901af0 100644 --- a/packages/flutter_app/lib/router/app_routes.g.dart +++ b/packages/flutter_app/lib/router/app_routes.g.dart @@ -112,9 +112,9 @@ RouteBase get $mainShellRouteData => StatefulShellRouteData.$route( StatefulShellBranchData.$branch( routes: [ GoRouteData.$route( - path: '/post', - name: '/post', - factory: $PostRouteDataExtension._fromState, + path: '/pub_dev_packages', + name: '/pub_dev_packages', + factory: $PubDevPackagesRouteDataExtension._fromState, ), ], ), @@ -355,11 +355,12 @@ extension $ExploreRouteDataExtension on ExploreRouteData { void replace(BuildContext context) => context.replace(location); } -extension $PostRouteDataExtension on PostRouteData { - static PostRouteData _fromState(GoRouterState state) => const PostRouteData(); +extension $PubDevPackagesRouteDataExtension on PubDevPackagesRouteData { + static PubDevPackagesRouteData _fromState(GoRouterState state) => + const PubDevPackagesRouteData(); String get location => GoRouteData.$location( - '/post', + '/pub_dev_packages', ); void go(BuildContext context) => context.go(location); diff --git a/packages/flutter_app/lib/router/branches/branches.dart b/packages/flutter_app/lib/router/branches/branches.dart index e608d703..5bda19fe 100644 --- a/packages/flutter_app/lib/router/branches/branches.dart +++ b/packages/flutter_app/lib/router/branches/branches.dart @@ -1,5 +1,5 @@ export 'dashboard_routes.dart'; export 'explore_routes.dart'; export 'home_routes.dart'; -export 'post_routes.dart'; +export 'pub_dev_packages_routes.dart'; export 'settings_routers.dart'; diff --git a/packages/flutter_app/lib/router/branches/post_routes.dart b/packages/flutter_app/lib/router/branches/post_routes.dart deleted file mode 100644 index 6c3b5b36..00000000 --- a/packages/flutter_app/lib/router/branches/post_routes.dart +++ /dev/null @@ -1,20 +0,0 @@ -import 'package:flutter/material.dart'; -import 'package:go_router/go_router.dart'; - -import '../../features/post/view/post_page.dart'; - -class PostShellBranchData extends StatefulShellBranchData { - const PostShellBranchData(); -} - -class PostRouteData extends GoRouteData { - const PostRouteData(); - - static const String name = '/post'; - static const String path = '/post'; - - @override - Widget build(BuildContext context, GoRouterState state) { - return const PostPage(); - } -} diff --git a/packages/flutter_app/lib/router/branches/pub_dev_packages_routes.dart b/packages/flutter_app/lib/router/branches/pub_dev_packages_routes.dart new file mode 100644 index 00000000..925d4509 --- /dev/null +++ b/packages/flutter_app/lib/router/branches/pub_dev_packages_routes.dart @@ -0,0 +1,20 @@ +import 'package:flutter/material.dart'; +import 'package:go_router/go_router.dart'; + +import '../../features/pub_dev_packages/view/pub_dev_packages_page.dart'; + +class PubDevPackagesShellBranchData extends StatefulShellBranchData { + const PubDevPackagesShellBranchData(); +} + +class PubDevPackagesRouteData extends GoRouteData { + const PubDevPackagesRouteData(); + + static const String name = '/pub_dev_packages'; + static const String path = '/pub_dev_packages'; + + @override + Widget build(BuildContext context, GoRouterState state) { + return const PubDevPackagesPage(); + } +} diff --git a/packages/flutter_app/pubspec.lock b/packages/flutter_app/pubspec.lock index ab80087e..76c84e4e 100644 --- a/packages/flutter_app/pubspec.lock +++ b/packages/flutter_app/pubspec.lock @@ -429,6 +429,22 @@ packages: url: "https://pub.dev" source: hosted version: "7.0.2" + dio: + dependency: transitive + description: + name: dio + sha256: "5598aa796bbf4699afd5c67c0f5f6e2ed542afc956884b9cd58c306966efc260" + url: "https://pub.dev" + source: hosted + version: "5.7.0" + dio_web_adapter: + dependency: transitive + description: + name: dio_web_adapter + sha256: "33259a9276d6cea88774a0000cfae0d861003497755969c92faa223108620dc8" + url: "https://pub.dev" + source: hosted + version: "2.0.0" fake_async: dependency: transitive description: @@ -1185,6 +1201,14 @@ packages: url: "https://pub.dev" source: hosted version: "1.0.6" + mock_web_server: + dependency: transitive + description: + name: mock_web_server + sha256: d6ec0d2a644c2ff5ef86da4360743e33f65c0fcf780555b913107502ac51a98e + url: "https://pub.dev" + source: hosted + version: "5.0.0-nullsafety.1" mockito: dependency: "direct dev" description: @@ -1329,6 +1353,13 @@ packages: url: "https://pub.dev" source: hosted version: "1.5.1" + pub_dev_api_client: + dependency: "direct main" + description: + path: "../pub_dev_api_client" + relative: true + source: path + version: "1.0.0+1" pub_semver: dependency: transitive description: @@ -1345,6 +1376,14 @@ packages: url: "https://pub.dev" source: hosted version: "1.3.0" + retrofit: + dependency: transitive + description: + name: retrofit + sha256: "3c9885ef3dbc5dc4b3fb0a40c972ab52e4dad04d52dac9bba24dfa76cf100451" + url: "https://pub.dev" + source: hosted + version: "4.4.1" riverpod: dependency: transitive description: diff --git a/packages/flutter_app/pubspec.yaml b/packages/flutter_app/pubspec.yaml index 5524acb4..a1d770e7 100644 --- a/packages/flutter_app/pubspec.yaml +++ b/packages/flutter_app/pubspec.yaml @@ -43,6 +43,8 @@ dependencies: json_annotation: ^4.8.1 linked_scroll_controller: ^0.2.0 package_info_plus: ^8.0.2 + pub_dev_api_client: + path: ../pub_dev_api_client riverpod_annotation: ^2.6.1 shared_preferences: ^2.3.3 simple_logger: ^1.9.0+1 diff --git a/packages/pub_dev_api_client/.gitignore b/packages/pub_dev_api_client/.gitignore new file mode 100644 index 00000000..29a3a501 --- /dev/null +++ b/packages/pub_dev_api_client/.gitignore @@ -0,0 +1,43 @@ +# Miscellaneous +*.class +*.log +*.pyc +*.swp +.DS_Store +.atom/ +.buildlog/ +.history +.svn/ +migrate_working_dir/ + +# IntelliJ related +*.iml +*.ipr +*.iws +.idea/ + +# The .vscode folder contains launch configuration and tasks you configure in +# VS Code which you may wish to be included in version control, so this line +# is commented out by default. +#.vscode/ + +# Flutter/Dart/Pub related +**/doc/api/ +**/ios/Flutter/.last_build_id +.dart_tool/ +.flutter-plugins +.flutter-plugins-dependencies +.pub-cache/ +.pub/ +/build/ + +# Symbolication related +app.*.symbols + +# Obfuscation related +app.*.map.json + +# Android Studio will place build artifacts here +/android/app/debug +/android/app/profile +/android/app/release diff --git a/packages/pub_dev_api_client/.metadata b/packages/pub_dev_api_client/.metadata new file mode 100644 index 00000000..d044da85 --- /dev/null +++ b/packages/pub_dev_api_client/.metadata @@ -0,0 +1,45 @@ +# This file tracks properties of this Flutter project. +# Used by Flutter tool to assess capabilities and perform upgrades etc. +# +# This file should be version controlled and should not be manually edited. + +version: + revision: "dec2ee5c1f98f8e84a7d5380c05eb8a3d0a81668" + channel: "stable" + +project_type: app + +# Tracks metadata for the flutter migrate command +migration: + platforms: + - platform: root + create_revision: dec2ee5c1f98f8e84a7d5380c05eb8a3d0a81668 + base_revision: dec2ee5c1f98f8e84a7d5380c05eb8a3d0a81668 + - platform: android + create_revision: dec2ee5c1f98f8e84a7d5380c05eb8a3d0a81668 + base_revision: dec2ee5c1f98f8e84a7d5380c05eb8a3d0a81668 + - platform: ios + create_revision: dec2ee5c1f98f8e84a7d5380c05eb8a3d0a81668 + base_revision: dec2ee5c1f98f8e84a7d5380c05eb8a3d0a81668 + - platform: linux + create_revision: dec2ee5c1f98f8e84a7d5380c05eb8a3d0a81668 + base_revision: dec2ee5c1f98f8e84a7d5380c05eb8a3d0a81668 + - platform: macos + create_revision: dec2ee5c1f98f8e84a7d5380c05eb8a3d0a81668 + base_revision: dec2ee5c1f98f8e84a7d5380c05eb8a3d0a81668 + - platform: web + create_revision: dec2ee5c1f98f8e84a7d5380c05eb8a3d0a81668 + base_revision: dec2ee5c1f98f8e84a7d5380c05eb8a3d0a81668 + - platform: windows + create_revision: dec2ee5c1f98f8e84a7d5380c05eb8a3d0a81668 + base_revision: dec2ee5c1f98f8e84a7d5380c05eb8a3d0a81668 + + # User provided section + + # List of Local paths (relative to this file) that should be + # ignored by the migrate tool. + # + # Files that are not part of the templates will be ignored by default. + unmanaged_files: + - 'lib/main.dart' + - 'ios/Runner.xcodeproj/project.pbxproj' diff --git a/packages/pub_dev_api_client/analysis_options.yaml b/packages/pub_dev_api_client/analysis_options.yaml new file mode 100644 index 00000000..4464c37c --- /dev/null +++ b/packages/pub_dev_api_client/analysis_options.yaml @@ -0,0 +1,7 @@ +include: package:altive_lints/altive_lints.yaml +analyzer: + plugins: + - custom_lint + exclude: + - "**/*.g.dart" + - "**/*.freezed.dart" diff --git a/packages/pub_dev_api_client/lib/pub_dev_api_client.dart b/packages/pub_dev_api_client/lib/pub_dev_api_client.dart new file mode 100644 index 00000000..a47ed36c --- /dev/null +++ b/packages/pub_dev_api_client/lib/pub_dev_api_client.dart @@ -0,0 +1,5 @@ +/// Library that provides a client for the Pub.dev API. +library; + +export 'src/models/models.dart'; +export 'src/pub_dev_api_client.dart'; diff --git a/packages/pub_dev_api_client/lib/src/models/get_package_details_response_body.dart b/packages/pub_dev_api_client/lib/src/models/get_package_details_response_body.dart new file mode 100644 index 00000000..a4eb1ef9 --- /dev/null +++ b/packages/pub_dev_api_client/lib/src/models/get_package_details_response_body.dart @@ -0,0 +1,21 @@ +import 'package:flutter/foundation.dart'; +import 'package:freezed_annotation/freezed_annotation.dart'; + +import 'models.dart'; + +part 'get_package_details_response_body.freezed.dart'; +part 'get_package_details_response_body.g.dart'; + +/// Response body for the package details endpoint. +@freezed +class GetPackageDetailsResponseBody with _$GetPackageDetailsResponseBody { + /// Default constructor. + const factory GetPackageDetailsResponseBody({ + required String name, + required LatestPackageRelease latest, + }) = _GetPackageDetailsResponseBody; + + /// Create an instance from JSON. + factory GetPackageDetailsResponseBody.fromJson(Map json) => + _$GetPackageDetailsResponseBodyFromJson(json); +} diff --git a/packages/pub_dev_api_client/lib/src/models/get_package_details_response_body.freezed.dart b/packages/pub_dev_api_client/lib/src/models/get_package_details_response_body.freezed.dart new file mode 100644 index 00000000..42cce2b6 --- /dev/null +++ b/packages/pub_dev_api_client/lib/src/models/get_package_details_response_body.freezed.dart @@ -0,0 +1,222 @@ +// coverage:ignore-file +// GENERATED CODE - DO NOT MODIFY BY HAND +// ignore_for_file: type=lint +// ignore_for_file: unused_element, deprecated_member_use, deprecated_member_use_from_same_package, use_function_type_syntax_for_parameters, unnecessary_const, avoid_init_to_null, invalid_override_different_default_values_named, prefer_expression_function_bodies, annotate_overrides, invalid_annotation_target, unnecessary_question_mark + +part of 'get_package_details_response_body.dart'; + +// ************************************************************************** +// FreezedGenerator +// ************************************************************************** + +T _$identity(T value) => value; + +final _privateConstructorUsedError = UnsupportedError( + 'It seems like you constructed your class using `MyClass._()`. This constructor is only meant to be used by freezed and you are not supposed to need it nor use it.\nPlease check the documentation here for more information: https://github.com/rrousselGit/freezed#adding-getters-and-methods-to-our-models'); + +GetPackageDetailsResponseBody _$GetPackageDetailsResponseBodyFromJson( + Map json) { + return _GetPackageDetailsResponseBody.fromJson(json); +} + +/// @nodoc +mixin _$GetPackageDetailsResponseBody { + String get name => throw _privateConstructorUsedError; + LatestPackageRelease get latest => throw _privateConstructorUsedError; + + /// Serializes this GetPackageDetailsResponseBody to a JSON map. + Map toJson() => throw _privateConstructorUsedError; + + /// Create a copy of GetPackageDetailsResponseBody + /// with the given fields replaced by the non-null parameter values. + @JsonKey(includeFromJson: false, includeToJson: false) + $GetPackageDetailsResponseBodyCopyWith + get copyWith => throw _privateConstructorUsedError; +} + +/// @nodoc +abstract class $GetPackageDetailsResponseBodyCopyWith<$Res> { + factory $GetPackageDetailsResponseBodyCopyWith( + GetPackageDetailsResponseBody value, + $Res Function(GetPackageDetailsResponseBody) then) = + _$GetPackageDetailsResponseBodyCopyWithImpl<$Res, + GetPackageDetailsResponseBody>; + @useResult + $Res call({String name, LatestPackageRelease latest}); + + $LatestPackageReleaseCopyWith<$Res> get latest; +} + +/// @nodoc +class _$GetPackageDetailsResponseBodyCopyWithImpl<$Res, + $Val extends GetPackageDetailsResponseBody> + implements $GetPackageDetailsResponseBodyCopyWith<$Res> { + _$GetPackageDetailsResponseBodyCopyWithImpl(this._value, this._then); + + // ignore: unused_field + final $Val _value; + // ignore: unused_field + final $Res Function($Val) _then; + + /// Create a copy of GetPackageDetailsResponseBody + /// with the given fields replaced by the non-null parameter values. + @pragma('vm:prefer-inline') + @override + $Res call({ + Object? name = null, + Object? latest = null, + }) { + return _then(_value.copyWith( + name: null == name + ? _value.name + : name // ignore: cast_nullable_to_non_nullable + as String, + latest: null == latest + ? _value.latest + : latest // ignore: cast_nullable_to_non_nullable + as LatestPackageRelease, + ) as $Val); + } + + /// Create a copy of GetPackageDetailsResponseBody + /// with the given fields replaced by the non-null parameter values. + @override + @pragma('vm:prefer-inline') + $LatestPackageReleaseCopyWith<$Res> get latest { + return $LatestPackageReleaseCopyWith<$Res>(_value.latest, (value) { + return _then(_value.copyWith(latest: value) as $Val); + }); + } +} + +/// @nodoc +abstract class _$$GetPackageDetailsResponseBodyImplCopyWith<$Res> + implements $GetPackageDetailsResponseBodyCopyWith<$Res> { + factory _$$GetPackageDetailsResponseBodyImplCopyWith( + _$GetPackageDetailsResponseBodyImpl value, + $Res Function(_$GetPackageDetailsResponseBodyImpl) then) = + __$$GetPackageDetailsResponseBodyImplCopyWithImpl<$Res>; + @override + @useResult + $Res call({String name, LatestPackageRelease latest}); + + @override + $LatestPackageReleaseCopyWith<$Res> get latest; +} + +/// @nodoc +class __$$GetPackageDetailsResponseBodyImplCopyWithImpl<$Res> + extends _$GetPackageDetailsResponseBodyCopyWithImpl<$Res, + _$GetPackageDetailsResponseBodyImpl> + implements _$$GetPackageDetailsResponseBodyImplCopyWith<$Res> { + __$$GetPackageDetailsResponseBodyImplCopyWithImpl( + _$GetPackageDetailsResponseBodyImpl _value, + $Res Function(_$GetPackageDetailsResponseBodyImpl) _then) + : super(_value, _then); + + /// Create a copy of GetPackageDetailsResponseBody + /// with the given fields replaced by the non-null parameter values. + @pragma('vm:prefer-inline') + @override + $Res call({ + Object? name = null, + Object? latest = null, + }) { + return _then(_$GetPackageDetailsResponseBodyImpl( + name: null == name + ? _value.name + : name // ignore: cast_nullable_to_non_nullable + as String, + latest: null == latest + ? _value.latest + : latest // ignore: cast_nullable_to_non_nullable + as LatestPackageRelease, + )); + } +} + +/// @nodoc +@JsonSerializable() +class _$GetPackageDetailsResponseBodyImpl + with DiagnosticableTreeMixin + implements _GetPackageDetailsResponseBody { + const _$GetPackageDetailsResponseBodyImpl( + {required this.name, required this.latest}); + + factory _$GetPackageDetailsResponseBodyImpl.fromJson( + Map json) => + _$$GetPackageDetailsResponseBodyImplFromJson(json); + + @override + final String name; + @override + final LatestPackageRelease latest; + + @override + String toString({DiagnosticLevel minLevel = DiagnosticLevel.info}) { + return 'GetPackageDetailsResponseBody(name: $name, latest: $latest)'; + } + + @override + void debugFillProperties(DiagnosticPropertiesBuilder properties) { + super.debugFillProperties(properties); + properties + ..add(DiagnosticsProperty('type', 'GetPackageDetailsResponseBody')) + ..add(DiagnosticsProperty('name', name)) + ..add(DiagnosticsProperty('latest', latest)); + } + + @override + bool operator ==(Object other) { + return identical(this, other) || + (other.runtimeType == runtimeType && + other is _$GetPackageDetailsResponseBodyImpl && + (identical(other.name, name) || other.name == name) && + (identical(other.latest, latest) || other.latest == latest)); + } + + @JsonKey(includeFromJson: false, includeToJson: false) + @override + int get hashCode => Object.hash(runtimeType, name, latest); + + /// Create a copy of GetPackageDetailsResponseBody + /// with the given fields replaced by the non-null parameter values. + @JsonKey(includeFromJson: false, includeToJson: false) + @override + @pragma('vm:prefer-inline') + _$$GetPackageDetailsResponseBodyImplCopyWith< + _$GetPackageDetailsResponseBodyImpl> + get copyWith => __$$GetPackageDetailsResponseBodyImplCopyWithImpl< + _$GetPackageDetailsResponseBodyImpl>(this, _$identity); + + @override + Map toJson() { + return _$$GetPackageDetailsResponseBodyImplToJson( + this, + ); + } +} + +abstract class _GetPackageDetailsResponseBody + implements GetPackageDetailsResponseBody { + const factory _GetPackageDetailsResponseBody( + {required final String name, + required final LatestPackageRelease latest}) = + _$GetPackageDetailsResponseBodyImpl; + + factory _GetPackageDetailsResponseBody.fromJson(Map json) = + _$GetPackageDetailsResponseBodyImpl.fromJson; + + @override + String get name; + @override + LatestPackageRelease get latest; + + /// Create a copy of GetPackageDetailsResponseBody + /// with the given fields replaced by the non-null parameter values. + @override + @JsonKey(includeFromJson: false, includeToJson: false) + _$$GetPackageDetailsResponseBodyImplCopyWith< + _$GetPackageDetailsResponseBodyImpl> + get copyWith => throw _privateConstructorUsedError; +} diff --git a/packages/pub_dev_api_client/lib/src/models/get_package_details_response_body.g.dart b/packages/pub_dev_api_client/lib/src/models/get_package_details_response_body.g.dart new file mode 100644 index 00000000..c346ea52 --- /dev/null +++ b/packages/pub_dev_api_client/lib/src/models/get_package_details_response_body.g.dart @@ -0,0 +1,22 @@ +// GENERATED CODE - DO NOT MODIFY BY HAND + +part of 'get_package_details_response_body.dart'; + +// ************************************************************************** +// JsonSerializableGenerator +// ************************************************************************** + +_$GetPackageDetailsResponseBodyImpl + _$$GetPackageDetailsResponseBodyImplFromJson(Map json) => + _$GetPackageDetailsResponseBodyImpl( + name: json['name'] as String, + latest: LatestPackageRelease.fromJson( + json['latest'] as Map), + ); + +Map _$$GetPackageDetailsResponseBodyImplToJson( + _$GetPackageDetailsResponseBodyImpl instance) => + { + 'name': instance.name, + 'latest': instance.latest, + }; diff --git a/packages/pub_dev_api_client/lib/src/models/get_searched_packages_response_body.dart b/packages/pub_dev_api_client/lib/src/models/get_searched_packages_response_body.dart new file mode 100644 index 00000000..38dae4a0 --- /dev/null +++ b/packages/pub_dev_api_client/lib/src/models/get_searched_packages_response_body.dart @@ -0,0 +1,41 @@ +import 'package:flutter/foundation.dart'; +import 'package:freezed_annotation/freezed_annotation.dart'; + +import 'package_name.dart'; + +part 'get_searched_packages_response_body.freezed.dart'; +part 'get_searched_packages_response_body.g.dart'; + +/// Response body for the search API. +@freezed +class GetSearchedPackagesResponseBody with _$GetSearchedPackagesResponseBody { + /// Default constructor. + const factory GetSearchedPackagesResponseBody({ + required List packages, + + // e.g. "https://pub.dev/api/search?page=2" + @JsonKey(name: 'next') String? nextPageUrl, + }) = _GetSearchedPackagesResponseBody; + + const GetSearchedPackagesResponseBody._(); + + /// Create an instance from JSON. + factory GetSearchedPackagesResponseBody.fromJson(Map json) => + _$GetSearchedPackagesResponseBodyFromJson(json); + + /// Get the next page number. + int? get nextPage { + final url = nextPageUrl; + if (url == null) { + return null; + } + + final uri = Uri.parse(url); + final page = uri.queryParameters['page']; + if (page == null) { + return null; + } + + return int.tryParse(page); + } +} diff --git a/packages/pub_dev_api_client/lib/src/models/get_searched_packages_response_body.freezed.dart b/packages/pub_dev_api_client/lib/src/models/get_searched_packages_response_body.freezed.dart new file mode 100644 index 00000000..7009ce9f --- /dev/null +++ b/packages/pub_dev_api_client/lib/src/models/get_searched_packages_response_body.freezed.dart @@ -0,0 +1,225 @@ +// coverage:ignore-file +// GENERATED CODE - DO NOT MODIFY BY HAND +// ignore_for_file: type=lint +// ignore_for_file: unused_element, deprecated_member_use, deprecated_member_use_from_same_package, use_function_type_syntax_for_parameters, unnecessary_const, avoid_init_to_null, invalid_override_different_default_values_named, prefer_expression_function_bodies, annotate_overrides, invalid_annotation_target, unnecessary_question_mark + +part of 'get_searched_packages_response_body.dart'; + +// ************************************************************************** +// FreezedGenerator +// ************************************************************************** + +T _$identity(T value) => value; + +final _privateConstructorUsedError = UnsupportedError( + 'It seems like you constructed your class using `MyClass._()`. This constructor is only meant to be used by freezed and you are not supposed to need it nor use it.\nPlease check the documentation here for more information: https://github.com/rrousselGit/freezed#adding-getters-and-methods-to-our-models'); + +GetSearchedPackagesResponseBody _$GetSearchedPackagesResponseBodyFromJson( + Map json) { + return _GetSearchedPackagesResponseBody.fromJson(json); +} + +/// @nodoc +mixin _$GetSearchedPackagesResponseBody { + List get packages => + throw _privateConstructorUsedError; // e.g. "https://pub.dev/api/search?page=2" + @JsonKey(name: 'next') + String? get nextPageUrl => throw _privateConstructorUsedError; + + /// Serializes this GetSearchedPackagesResponseBody to a JSON map. + Map toJson() => throw _privateConstructorUsedError; + + /// Create a copy of GetSearchedPackagesResponseBody + /// with the given fields replaced by the non-null parameter values. + @JsonKey(includeFromJson: false, includeToJson: false) + $GetSearchedPackagesResponseBodyCopyWith + get copyWith => throw _privateConstructorUsedError; +} + +/// @nodoc +abstract class $GetSearchedPackagesResponseBodyCopyWith<$Res> { + factory $GetSearchedPackagesResponseBodyCopyWith( + GetSearchedPackagesResponseBody value, + $Res Function(GetSearchedPackagesResponseBody) then) = + _$GetSearchedPackagesResponseBodyCopyWithImpl<$Res, + GetSearchedPackagesResponseBody>; + @useResult + $Res call( + {List packages, @JsonKey(name: 'next') String? nextPageUrl}); +} + +/// @nodoc +class _$GetSearchedPackagesResponseBodyCopyWithImpl<$Res, + $Val extends GetSearchedPackagesResponseBody> + implements $GetSearchedPackagesResponseBodyCopyWith<$Res> { + _$GetSearchedPackagesResponseBodyCopyWithImpl(this._value, this._then); + + // ignore: unused_field + final $Val _value; + // ignore: unused_field + final $Res Function($Val) _then; + + /// Create a copy of GetSearchedPackagesResponseBody + /// with the given fields replaced by the non-null parameter values. + @pragma('vm:prefer-inline') + @override + $Res call({ + Object? packages = null, + Object? nextPageUrl = freezed, + }) { + return _then(_value.copyWith( + packages: null == packages + ? _value.packages + : packages // ignore: cast_nullable_to_non_nullable + as List, + nextPageUrl: freezed == nextPageUrl + ? _value.nextPageUrl + : nextPageUrl // ignore: cast_nullable_to_non_nullable + as String?, + ) as $Val); + } +} + +/// @nodoc +abstract class _$$GetSearchedPackagesResponseBodyImplCopyWith<$Res> + implements $GetSearchedPackagesResponseBodyCopyWith<$Res> { + factory _$$GetSearchedPackagesResponseBodyImplCopyWith( + _$GetSearchedPackagesResponseBodyImpl value, + $Res Function(_$GetSearchedPackagesResponseBodyImpl) then) = + __$$GetSearchedPackagesResponseBodyImplCopyWithImpl<$Res>; + @override + @useResult + $Res call( + {List packages, @JsonKey(name: 'next') String? nextPageUrl}); +} + +/// @nodoc +class __$$GetSearchedPackagesResponseBodyImplCopyWithImpl<$Res> + extends _$GetSearchedPackagesResponseBodyCopyWithImpl<$Res, + _$GetSearchedPackagesResponseBodyImpl> + implements _$$GetSearchedPackagesResponseBodyImplCopyWith<$Res> { + __$$GetSearchedPackagesResponseBodyImplCopyWithImpl( + _$GetSearchedPackagesResponseBodyImpl _value, + $Res Function(_$GetSearchedPackagesResponseBodyImpl) _then) + : super(_value, _then); + + /// Create a copy of GetSearchedPackagesResponseBody + /// with the given fields replaced by the non-null parameter values. + @pragma('vm:prefer-inline') + @override + $Res call({ + Object? packages = null, + Object? nextPageUrl = freezed, + }) { + return _then(_$GetSearchedPackagesResponseBodyImpl( + packages: null == packages + ? _value._packages + : packages // ignore: cast_nullable_to_non_nullable + as List, + nextPageUrl: freezed == nextPageUrl + ? _value.nextPageUrl + : nextPageUrl // ignore: cast_nullable_to_non_nullable + as String?, + )); + } +} + +/// @nodoc +@JsonSerializable() +class _$GetSearchedPackagesResponseBodyImpl + extends _GetSearchedPackagesResponseBody with DiagnosticableTreeMixin { + const _$GetSearchedPackagesResponseBodyImpl( + {required final List packages, + @JsonKey(name: 'next') this.nextPageUrl}) + : _packages = packages, + super._(); + + factory _$GetSearchedPackagesResponseBodyImpl.fromJson( + Map json) => + _$$GetSearchedPackagesResponseBodyImplFromJson(json); + + final List _packages; + @override + List get packages { + if (_packages is EqualUnmodifiableListView) return _packages; + // ignore: implicit_dynamic_type + return EqualUnmodifiableListView(_packages); + } + +// e.g. "https://pub.dev/api/search?page=2" + @override + @JsonKey(name: 'next') + final String? nextPageUrl; + + @override + String toString({DiagnosticLevel minLevel = DiagnosticLevel.info}) { + return 'GetSearchedPackagesResponseBody(packages: $packages, nextPageUrl: $nextPageUrl)'; + } + + @override + void debugFillProperties(DiagnosticPropertiesBuilder properties) { + super.debugFillProperties(properties); + properties + ..add(DiagnosticsProperty('type', 'GetSearchedPackagesResponseBody')) + ..add(DiagnosticsProperty('packages', packages)) + ..add(DiagnosticsProperty('nextPageUrl', nextPageUrl)); + } + + @override + bool operator ==(Object other) { + return identical(this, other) || + (other.runtimeType == runtimeType && + other is _$GetSearchedPackagesResponseBodyImpl && + const DeepCollectionEquality().equals(other._packages, _packages) && + (identical(other.nextPageUrl, nextPageUrl) || + other.nextPageUrl == nextPageUrl)); + } + + @JsonKey(includeFromJson: false, includeToJson: false) + @override + int get hashCode => Object.hash( + runtimeType, const DeepCollectionEquality().hash(_packages), nextPageUrl); + + /// Create a copy of GetSearchedPackagesResponseBody + /// with the given fields replaced by the non-null parameter values. + @JsonKey(includeFromJson: false, includeToJson: false) + @override + @pragma('vm:prefer-inline') + _$$GetSearchedPackagesResponseBodyImplCopyWith< + _$GetSearchedPackagesResponseBodyImpl> + get copyWith => __$$GetSearchedPackagesResponseBodyImplCopyWithImpl< + _$GetSearchedPackagesResponseBodyImpl>(this, _$identity); + + @override + Map toJson() { + return _$$GetSearchedPackagesResponseBodyImplToJson( + this, + ); + } +} + +abstract class _GetSearchedPackagesResponseBody + extends GetSearchedPackagesResponseBody { + const factory _GetSearchedPackagesResponseBody( + {required final List packages, + @JsonKey(name: 'next') final String? nextPageUrl}) = + _$GetSearchedPackagesResponseBodyImpl; + const _GetSearchedPackagesResponseBody._() : super._(); + + factory _GetSearchedPackagesResponseBody.fromJson(Map json) = + _$GetSearchedPackagesResponseBodyImpl.fromJson; + + @override + List get packages; // e.g. "https://pub.dev/api/search?page=2" + @override + @JsonKey(name: 'next') + String? get nextPageUrl; + + /// Create a copy of GetSearchedPackagesResponseBody + /// with the given fields replaced by the non-null parameter values. + @override + @JsonKey(includeFromJson: false, includeToJson: false) + _$$GetSearchedPackagesResponseBodyImplCopyWith< + _$GetSearchedPackagesResponseBodyImpl> + get copyWith => throw _privateConstructorUsedError; +} diff --git a/packages/pub_dev_api_client/lib/src/models/get_searched_packages_response_body.g.dart b/packages/pub_dev_api_client/lib/src/models/get_searched_packages_response_body.g.dart new file mode 100644 index 00000000..bc6af610 --- /dev/null +++ b/packages/pub_dev_api_client/lib/src/models/get_searched_packages_response_body.g.dart @@ -0,0 +1,23 @@ +// GENERATED CODE - DO NOT MODIFY BY HAND + +part of 'get_searched_packages_response_body.dart'; + +// ************************************************************************** +// JsonSerializableGenerator +// ************************************************************************** + +_$GetSearchedPackagesResponseBodyImpl + _$$GetSearchedPackagesResponseBodyImplFromJson(Map json) => + _$GetSearchedPackagesResponseBodyImpl( + packages: (json['packages'] as List) + .map((e) => PackageName.fromJson(e as Map)) + .toList(), + nextPageUrl: json['next'] as String?, + ); + +Map _$$GetSearchedPackagesResponseBodyImplToJson( + _$GetSearchedPackagesResponseBodyImpl instance) => + { + 'packages': instance.packages, + 'next': instance.nextPageUrl, + }; diff --git a/packages/pub_dev_api_client/lib/src/models/latest_package_release.dart b/packages/pub_dev_api_client/lib/src/models/latest_package_release.dart new file mode 100644 index 00000000..29e81b7f --- /dev/null +++ b/packages/pub_dev_api_client/lib/src/models/latest_package_release.dart @@ -0,0 +1,20 @@ +import 'package:flutter/foundation.dart'; +import 'package:freezed_annotation/freezed_annotation.dart'; + +import 'package_pubspec.dart'; + +part 'latest_package_release.freezed.dart'; +part 'latest_package_release.g.dart'; + +/// Package details for the latest release. +@freezed +class LatestPackageRelease with _$LatestPackageRelease { + /// Default constructor. + const factory LatestPackageRelease({ + required PackagePubspec pubspec, + }) = _LatestPackageRelease; + + /// Create an instance from JSON. + factory LatestPackageRelease.fromJson(Map json) => + _$LatestPackageReleaseFromJson(json); +} diff --git a/packages/pub_dev_api_client/lib/src/models/latest_package_release.freezed.dart b/packages/pub_dev_api_client/lib/src/models/latest_package_release.freezed.dart new file mode 100644 index 00000000..f14cc4c9 --- /dev/null +++ b/packages/pub_dev_api_client/lib/src/models/latest_package_release.freezed.dart @@ -0,0 +1,193 @@ +// coverage:ignore-file +// GENERATED CODE - DO NOT MODIFY BY HAND +// ignore_for_file: type=lint +// ignore_for_file: unused_element, deprecated_member_use, deprecated_member_use_from_same_package, use_function_type_syntax_for_parameters, unnecessary_const, avoid_init_to_null, invalid_override_different_default_values_named, prefer_expression_function_bodies, annotate_overrides, invalid_annotation_target, unnecessary_question_mark + +part of 'latest_package_release.dart'; + +// ************************************************************************** +// FreezedGenerator +// ************************************************************************** + +T _$identity(T value) => value; + +final _privateConstructorUsedError = UnsupportedError( + 'It seems like you constructed your class using `MyClass._()`. This constructor is only meant to be used by freezed and you are not supposed to need it nor use it.\nPlease check the documentation here for more information: https://github.com/rrousselGit/freezed#adding-getters-and-methods-to-our-models'); + +LatestPackageRelease _$LatestPackageReleaseFromJson(Map json) { + return _LatestPackageRelease.fromJson(json); +} + +/// @nodoc +mixin _$LatestPackageRelease { + PackagePubspec get pubspec => throw _privateConstructorUsedError; + + /// Serializes this LatestPackageRelease to a JSON map. + Map toJson() => throw _privateConstructorUsedError; + + /// Create a copy of LatestPackageRelease + /// with the given fields replaced by the non-null parameter values. + @JsonKey(includeFromJson: false, includeToJson: false) + $LatestPackageReleaseCopyWith get copyWith => + throw _privateConstructorUsedError; +} + +/// @nodoc +abstract class $LatestPackageReleaseCopyWith<$Res> { + factory $LatestPackageReleaseCopyWith(LatestPackageRelease value, + $Res Function(LatestPackageRelease) then) = + _$LatestPackageReleaseCopyWithImpl<$Res, LatestPackageRelease>; + @useResult + $Res call({PackagePubspec pubspec}); + + $PackagePubspecCopyWith<$Res> get pubspec; +} + +/// @nodoc +class _$LatestPackageReleaseCopyWithImpl<$Res, + $Val extends LatestPackageRelease> + implements $LatestPackageReleaseCopyWith<$Res> { + _$LatestPackageReleaseCopyWithImpl(this._value, this._then); + + // ignore: unused_field + final $Val _value; + // ignore: unused_field + final $Res Function($Val) _then; + + /// Create a copy of LatestPackageRelease + /// with the given fields replaced by the non-null parameter values. + @pragma('vm:prefer-inline') + @override + $Res call({ + Object? pubspec = null, + }) { + return _then(_value.copyWith( + pubspec: null == pubspec + ? _value.pubspec + : pubspec // ignore: cast_nullable_to_non_nullable + as PackagePubspec, + ) as $Val); + } + + /// Create a copy of LatestPackageRelease + /// with the given fields replaced by the non-null parameter values. + @override + @pragma('vm:prefer-inline') + $PackagePubspecCopyWith<$Res> get pubspec { + return $PackagePubspecCopyWith<$Res>(_value.pubspec, (value) { + return _then(_value.copyWith(pubspec: value) as $Val); + }); + } +} + +/// @nodoc +abstract class _$$LatestPackageReleaseImplCopyWith<$Res> + implements $LatestPackageReleaseCopyWith<$Res> { + factory _$$LatestPackageReleaseImplCopyWith(_$LatestPackageReleaseImpl value, + $Res Function(_$LatestPackageReleaseImpl) then) = + __$$LatestPackageReleaseImplCopyWithImpl<$Res>; + @override + @useResult + $Res call({PackagePubspec pubspec}); + + @override + $PackagePubspecCopyWith<$Res> get pubspec; +} + +/// @nodoc +class __$$LatestPackageReleaseImplCopyWithImpl<$Res> + extends _$LatestPackageReleaseCopyWithImpl<$Res, _$LatestPackageReleaseImpl> + implements _$$LatestPackageReleaseImplCopyWith<$Res> { + __$$LatestPackageReleaseImplCopyWithImpl(_$LatestPackageReleaseImpl _value, + $Res Function(_$LatestPackageReleaseImpl) _then) + : super(_value, _then); + + /// Create a copy of LatestPackageRelease + /// with the given fields replaced by the non-null parameter values. + @pragma('vm:prefer-inline') + @override + $Res call({ + Object? pubspec = null, + }) { + return _then(_$LatestPackageReleaseImpl( + pubspec: null == pubspec + ? _value.pubspec + : pubspec // ignore: cast_nullable_to_non_nullable + as PackagePubspec, + )); + } +} + +/// @nodoc +@JsonSerializable() +class _$LatestPackageReleaseImpl + with DiagnosticableTreeMixin + implements _LatestPackageRelease { + const _$LatestPackageReleaseImpl({required this.pubspec}); + + factory _$LatestPackageReleaseImpl.fromJson(Map json) => + _$$LatestPackageReleaseImplFromJson(json); + + @override + final PackagePubspec pubspec; + + @override + String toString({DiagnosticLevel minLevel = DiagnosticLevel.info}) { + return 'LatestPackageRelease(pubspec: $pubspec)'; + } + + @override + void debugFillProperties(DiagnosticPropertiesBuilder properties) { + super.debugFillProperties(properties); + properties + ..add(DiagnosticsProperty('type', 'LatestPackageRelease')) + ..add(DiagnosticsProperty('pubspec', pubspec)); + } + + @override + bool operator ==(Object other) { + return identical(this, other) || + (other.runtimeType == runtimeType && + other is _$LatestPackageReleaseImpl && + (identical(other.pubspec, pubspec) || other.pubspec == pubspec)); + } + + @JsonKey(includeFromJson: false, includeToJson: false) + @override + int get hashCode => Object.hash(runtimeType, pubspec); + + /// Create a copy of LatestPackageRelease + /// with the given fields replaced by the non-null parameter values. + @JsonKey(includeFromJson: false, includeToJson: false) + @override + @pragma('vm:prefer-inline') + _$$LatestPackageReleaseImplCopyWith<_$LatestPackageReleaseImpl> + get copyWith => + __$$LatestPackageReleaseImplCopyWithImpl<_$LatestPackageReleaseImpl>( + this, _$identity); + + @override + Map toJson() { + return _$$LatestPackageReleaseImplToJson( + this, + ); + } +} + +abstract class _LatestPackageRelease implements LatestPackageRelease { + const factory _LatestPackageRelease({required final PackagePubspec pubspec}) = + _$LatestPackageReleaseImpl; + + factory _LatestPackageRelease.fromJson(Map json) = + _$LatestPackageReleaseImpl.fromJson; + + @override + PackagePubspec get pubspec; + + /// Create a copy of LatestPackageRelease + /// with the given fields replaced by the non-null parameter values. + @override + @JsonKey(includeFromJson: false, includeToJson: false) + _$$LatestPackageReleaseImplCopyWith<_$LatestPackageReleaseImpl> + get copyWith => throw _privateConstructorUsedError; +} diff --git a/packages/pub_dev_api_client/lib/src/models/latest_package_release.g.dart b/packages/pub_dev_api_client/lib/src/models/latest_package_release.g.dart new file mode 100644 index 00000000..ee4cb25d --- /dev/null +++ b/packages/pub_dev_api_client/lib/src/models/latest_package_release.g.dart @@ -0,0 +1,19 @@ +// GENERATED CODE - DO NOT MODIFY BY HAND + +part of 'latest_package_release.dart'; + +// ************************************************************************** +// JsonSerializableGenerator +// ************************************************************************** + +_$LatestPackageReleaseImpl _$$LatestPackageReleaseImplFromJson( + Map json) => + _$LatestPackageReleaseImpl( + pubspec: PackagePubspec.fromJson(json['pubspec'] as Map), + ); + +Map _$$LatestPackageReleaseImplToJson( + _$LatestPackageReleaseImpl instance) => + { + 'pubspec': instance.pubspec, + }; diff --git a/packages/pub_dev_api_client/lib/src/models/models.dart b/packages/pub_dev_api_client/lib/src/models/models.dart new file mode 100644 index 00000000..69d1f42d --- /dev/null +++ b/packages/pub_dev_api_client/lib/src/models/models.dart @@ -0,0 +1,4 @@ +export 'get_package_details_response_body.dart'; +export 'get_searched_packages_response_body.dart'; +export 'latest_package_release.dart'; +export 'package_name.dart'; diff --git a/packages/pub_dev_api_client/lib/src/models/package_name.dart b/packages/pub_dev_api_client/lib/src/models/package_name.dart new file mode 100644 index 00000000..9f3b23e3 --- /dev/null +++ b/packages/pub_dev_api_client/lib/src/models/package_name.dart @@ -0,0 +1,18 @@ +import 'package:flutter/foundation.dart'; +import 'package:freezed_annotation/freezed_annotation.dart'; + +part 'package_name.freezed.dart'; +part 'package_name.g.dart'; + +/// Package name. +@freezed +class PackageName with _$PackageName { + /// Default constructor. + const factory PackageName({ + @JsonKey(name: 'package') required String name, + }) = _PackageName; + + /// Create an instance from JSON. + factory PackageName.fromJson(Map json) => + _$PackageNameFromJson(json); +} diff --git a/packages/pub_dev_api_client/lib/src/models/package_name.freezed.dart b/packages/pub_dev_api_client/lib/src/models/package_name.freezed.dart new file mode 100644 index 00000000..3c515ea6 --- /dev/null +++ b/packages/pub_dev_api_client/lib/src/models/package_name.freezed.dart @@ -0,0 +1,177 @@ +// coverage:ignore-file +// GENERATED CODE - DO NOT MODIFY BY HAND +// ignore_for_file: type=lint +// ignore_for_file: unused_element, deprecated_member_use, deprecated_member_use_from_same_package, use_function_type_syntax_for_parameters, unnecessary_const, avoid_init_to_null, invalid_override_different_default_values_named, prefer_expression_function_bodies, annotate_overrides, invalid_annotation_target, unnecessary_question_mark + +part of 'package_name.dart'; + +// ************************************************************************** +// FreezedGenerator +// ************************************************************************** + +T _$identity(T value) => value; + +final _privateConstructorUsedError = UnsupportedError( + 'It seems like you constructed your class using `MyClass._()`. This constructor is only meant to be used by freezed and you are not supposed to need it nor use it.\nPlease check the documentation here for more information: https://github.com/rrousselGit/freezed#adding-getters-and-methods-to-our-models'); + +PackageName _$PackageNameFromJson(Map json) { + return _PackageName.fromJson(json); +} + +/// @nodoc +mixin _$PackageName { + @JsonKey(name: 'package') + String get name => throw _privateConstructorUsedError; + + /// Serializes this PackageName to a JSON map. + Map toJson() => throw _privateConstructorUsedError; + + /// Create a copy of PackageName + /// with the given fields replaced by the non-null parameter values. + @JsonKey(includeFromJson: false, includeToJson: false) + $PackageNameCopyWith get copyWith => + throw _privateConstructorUsedError; +} + +/// @nodoc +abstract class $PackageNameCopyWith<$Res> { + factory $PackageNameCopyWith( + PackageName value, $Res Function(PackageName) then) = + _$PackageNameCopyWithImpl<$Res, PackageName>; + @useResult + $Res call({@JsonKey(name: 'package') String name}); +} + +/// @nodoc +class _$PackageNameCopyWithImpl<$Res, $Val extends PackageName> + implements $PackageNameCopyWith<$Res> { + _$PackageNameCopyWithImpl(this._value, this._then); + + // ignore: unused_field + final $Val _value; + // ignore: unused_field + final $Res Function($Val) _then; + + /// Create a copy of PackageName + /// with the given fields replaced by the non-null parameter values. + @pragma('vm:prefer-inline') + @override + $Res call({ + Object? name = null, + }) { + return _then(_value.copyWith( + name: null == name + ? _value.name + : name // ignore: cast_nullable_to_non_nullable + as String, + ) as $Val); + } +} + +/// @nodoc +abstract class _$$PackageNameImplCopyWith<$Res> + implements $PackageNameCopyWith<$Res> { + factory _$$PackageNameImplCopyWith( + _$PackageNameImpl value, $Res Function(_$PackageNameImpl) then) = + __$$PackageNameImplCopyWithImpl<$Res>; + @override + @useResult + $Res call({@JsonKey(name: 'package') String name}); +} + +/// @nodoc +class __$$PackageNameImplCopyWithImpl<$Res> + extends _$PackageNameCopyWithImpl<$Res, _$PackageNameImpl> + implements _$$PackageNameImplCopyWith<$Res> { + __$$PackageNameImplCopyWithImpl( + _$PackageNameImpl _value, $Res Function(_$PackageNameImpl) _then) + : super(_value, _then); + + /// Create a copy of PackageName + /// with the given fields replaced by the non-null parameter values. + @pragma('vm:prefer-inline') + @override + $Res call({ + Object? name = null, + }) { + return _then(_$PackageNameImpl( + name: null == name + ? _value.name + : name // ignore: cast_nullable_to_non_nullable + as String, + )); + } +} + +/// @nodoc +@JsonSerializable() +class _$PackageNameImpl with DiagnosticableTreeMixin implements _PackageName { + const _$PackageNameImpl({@JsonKey(name: 'package') required this.name}); + + factory _$PackageNameImpl.fromJson(Map json) => + _$$PackageNameImplFromJson(json); + + @override + @JsonKey(name: 'package') + final String name; + + @override + String toString({DiagnosticLevel minLevel = DiagnosticLevel.info}) { + return 'PackageName(name: $name)'; + } + + @override + void debugFillProperties(DiagnosticPropertiesBuilder properties) { + super.debugFillProperties(properties); + properties + ..add(DiagnosticsProperty('type', 'PackageName')) + ..add(DiagnosticsProperty('name', name)); + } + + @override + bool operator ==(Object other) { + return identical(this, other) || + (other.runtimeType == runtimeType && + other is _$PackageNameImpl && + (identical(other.name, name) || other.name == name)); + } + + @JsonKey(includeFromJson: false, includeToJson: false) + @override + int get hashCode => Object.hash(runtimeType, name); + + /// Create a copy of PackageName + /// with the given fields replaced by the non-null parameter values. + @JsonKey(includeFromJson: false, includeToJson: false) + @override + @pragma('vm:prefer-inline') + _$$PackageNameImplCopyWith<_$PackageNameImpl> get copyWith => + __$$PackageNameImplCopyWithImpl<_$PackageNameImpl>(this, _$identity); + + @override + Map toJson() { + return _$$PackageNameImplToJson( + this, + ); + } +} + +abstract class _PackageName implements PackageName { + const factory _PackageName( + {@JsonKey(name: 'package') required final String name}) = + _$PackageNameImpl; + + factory _PackageName.fromJson(Map json) = + _$PackageNameImpl.fromJson; + + @override + @JsonKey(name: 'package') + String get name; + + /// Create a copy of PackageName + /// with the given fields replaced by the non-null parameter values. + @override + @JsonKey(includeFromJson: false, includeToJson: false) + _$$PackageNameImplCopyWith<_$PackageNameImpl> get copyWith => + throw _privateConstructorUsedError; +} diff --git a/packages/pub_dev_api_client/lib/src/models/package_name.g.dart b/packages/pub_dev_api_client/lib/src/models/package_name.g.dart new file mode 100644 index 00000000..a47c3757 --- /dev/null +++ b/packages/pub_dev_api_client/lib/src/models/package_name.g.dart @@ -0,0 +1,17 @@ +// GENERATED CODE - DO NOT MODIFY BY HAND + +part of 'package_name.dart'; + +// ************************************************************************** +// JsonSerializableGenerator +// ************************************************************************** + +_$PackageNameImpl _$$PackageNameImplFromJson(Map json) => + _$PackageNameImpl( + name: json['package'] as String, + ); + +Map _$$PackageNameImplToJson(_$PackageNameImpl instance) => + { + 'package': instance.name, + }; diff --git a/packages/pub_dev_api_client/lib/src/models/package_pubspec.dart b/packages/pub_dev_api_client/lib/src/models/package_pubspec.dart new file mode 100644 index 00000000..2b7e14c2 --- /dev/null +++ b/packages/pub_dev_api_client/lib/src/models/package_pubspec.dart @@ -0,0 +1,20 @@ +import 'package:flutter/foundation.dart'; +import 'package:freezed_annotation/freezed_annotation.dart'; + +part 'package_pubspec.freezed.dart'; +part 'package_pubspec.g.dart'; + +/// Information about a package's pubspec.yaml. +@freezed +class PackagePubspec with _$PackagePubspec { + /// Default constructor. + const factory PackagePubspec({ + required String name, + required String version, + required String description, + }) = _PackagePubspec; + + /// Create an instance from JSON. + factory PackagePubspec.fromJson(Map json) => + _$PackagePubspecFromJson(json); +} diff --git a/packages/pub_dev_api_client/lib/src/models/package_pubspec.freezed.dart b/packages/pub_dev_api_client/lib/src/models/package_pubspec.freezed.dart new file mode 100644 index 00000000..419e1cb3 --- /dev/null +++ b/packages/pub_dev_api_client/lib/src/models/package_pubspec.freezed.dart @@ -0,0 +1,214 @@ +// coverage:ignore-file +// GENERATED CODE - DO NOT MODIFY BY HAND +// ignore_for_file: type=lint +// ignore_for_file: unused_element, deprecated_member_use, deprecated_member_use_from_same_package, use_function_type_syntax_for_parameters, unnecessary_const, avoid_init_to_null, invalid_override_different_default_values_named, prefer_expression_function_bodies, annotate_overrides, invalid_annotation_target, unnecessary_question_mark + +part of 'package_pubspec.dart'; + +// ************************************************************************** +// FreezedGenerator +// ************************************************************************** + +T _$identity(T value) => value; + +final _privateConstructorUsedError = UnsupportedError( + 'It seems like you constructed your class using `MyClass._()`. This constructor is only meant to be used by freezed and you are not supposed to need it nor use it.\nPlease check the documentation here for more information: https://github.com/rrousselGit/freezed#adding-getters-and-methods-to-our-models'); + +PackagePubspec _$PackagePubspecFromJson(Map json) { + return _PackagePubspec.fromJson(json); +} + +/// @nodoc +mixin _$PackagePubspec { + String get name => throw _privateConstructorUsedError; + String get version => throw _privateConstructorUsedError; + String get description => throw _privateConstructorUsedError; + + /// Serializes this PackagePubspec to a JSON map. + Map toJson() => throw _privateConstructorUsedError; + + /// Create a copy of PackagePubspec + /// with the given fields replaced by the non-null parameter values. + @JsonKey(includeFromJson: false, includeToJson: false) + $PackagePubspecCopyWith get copyWith => + throw _privateConstructorUsedError; +} + +/// @nodoc +abstract class $PackagePubspecCopyWith<$Res> { + factory $PackagePubspecCopyWith( + PackagePubspec value, $Res Function(PackagePubspec) then) = + _$PackagePubspecCopyWithImpl<$Res, PackagePubspec>; + @useResult + $Res call({String name, String version, String description}); +} + +/// @nodoc +class _$PackagePubspecCopyWithImpl<$Res, $Val extends PackagePubspec> + implements $PackagePubspecCopyWith<$Res> { + _$PackagePubspecCopyWithImpl(this._value, this._then); + + // ignore: unused_field + final $Val _value; + // ignore: unused_field + final $Res Function($Val) _then; + + /// Create a copy of PackagePubspec + /// with the given fields replaced by the non-null parameter values. + @pragma('vm:prefer-inline') + @override + $Res call({ + Object? name = null, + Object? version = null, + Object? description = null, + }) { + return _then(_value.copyWith( + name: null == name + ? _value.name + : name // ignore: cast_nullable_to_non_nullable + as String, + version: null == version + ? _value.version + : version // ignore: cast_nullable_to_non_nullable + as String, + description: null == description + ? _value.description + : description // ignore: cast_nullable_to_non_nullable + as String, + ) as $Val); + } +} + +/// @nodoc +abstract class _$$PackagePubspecImplCopyWith<$Res> + implements $PackagePubspecCopyWith<$Res> { + factory _$$PackagePubspecImplCopyWith(_$PackagePubspecImpl value, + $Res Function(_$PackagePubspecImpl) then) = + __$$PackagePubspecImplCopyWithImpl<$Res>; + @override + @useResult + $Res call({String name, String version, String description}); +} + +/// @nodoc +class __$$PackagePubspecImplCopyWithImpl<$Res> + extends _$PackagePubspecCopyWithImpl<$Res, _$PackagePubspecImpl> + implements _$$PackagePubspecImplCopyWith<$Res> { + __$$PackagePubspecImplCopyWithImpl( + _$PackagePubspecImpl _value, $Res Function(_$PackagePubspecImpl) _then) + : super(_value, _then); + + /// Create a copy of PackagePubspec + /// with the given fields replaced by the non-null parameter values. + @pragma('vm:prefer-inline') + @override + $Res call({ + Object? name = null, + Object? version = null, + Object? description = null, + }) { + return _then(_$PackagePubspecImpl( + name: null == name + ? _value.name + : name // ignore: cast_nullable_to_non_nullable + as String, + version: null == version + ? _value.version + : version // ignore: cast_nullable_to_non_nullable + as String, + description: null == description + ? _value.description + : description // ignore: cast_nullable_to_non_nullable + as String, + )); + } +} + +/// @nodoc +@JsonSerializable() +class _$PackagePubspecImpl + with DiagnosticableTreeMixin + implements _PackagePubspec { + const _$PackagePubspecImpl( + {required this.name, required this.version, required this.description}); + + factory _$PackagePubspecImpl.fromJson(Map json) => + _$$PackagePubspecImplFromJson(json); + + @override + final String name; + @override + final String version; + @override + final String description; + + @override + String toString({DiagnosticLevel minLevel = DiagnosticLevel.info}) { + return 'PackagePubspec(name: $name, version: $version, description: $description)'; + } + + @override + void debugFillProperties(DiagnosticPropertiesBuilder properties) { + super.debugFillProperties(properties); + properties + ..add(DiagnosticsProperty('type', 'PackagePubspec')) + ..add(DiagnosticsProperty('name', name)) + ..add(DiagnosticsProperty('version', version)) + ..add(DiagnosticsProperty('description', description)); + } + + @override + bool operator ==(Object other) { + return identical(this, other) || + (other.runtimeType == runtimeType && + other is _$PackagePubspecImpl && + (identical(other.name, name) || other.name == name) && + (identical(other.version, version) || other.version == version) && + (identical(other.description, description) || + other.description == description)); + } + + @JsonKey(includeFromJson: false, includeToJson: false) + @override + int get hashCode => Object.hash(runtimeType, name, version, description); + + /// Create a copy of PackagePubspec + /// with the given fields replaced by the non-null parameter values. + @JsonKey(includeFromJson: false, includeToJson: false) + @override + @pragma('vm:prefer-inline') + _$$PackagePubspecImplCopyWith<_$PackagePubspecImpl> get copyWith => + __$$PackagePubspecImplCopyWithImpl<_$PackagePubspecImpl>( + this, _$identity); + + @override + Map toJson() { + return _$$PackagePubspecImplToJson( + this, + ); + } +} + +abstract class _PackagePubspec implements PackagePubspec { + const factory _PackagePubspec( + {required final String name, + required final String version, + required final String description}) = _$PackagePubspecImpl; + + factory _PackagePubspec.fromJson(Map json) = + _$PackagePubspecImpl.fromJson; + + @override + String get name; + @override + String get version; + @override + String get description; + + /// Create a copy of PackagePubspec + /// with the given fields replaced by the non-null parameter values. + @override + @JsonKey(includeFromJson: false, includeToJson: false) + _$$PackagePubspecImplCopyWith<_$PackagePubspecImpl> get copyWith => + throw _privateConstructorUsedError; +} diff --git a/packages/pub_dev_api_client/lib/src/models/package_pubspec.g.dart b/packages/pub_dev_api_client/lib/src/models/package_pubspec.g.dart new file mode 100644 index 00000000..f075e08b --- /dev/null +++ b/packages/pub_dev_api_client/lib/src/models/package_pubspec.g.dart @@ -0,0 +1,22 @@ +// GENERATED CODE - DO NOT MODIFY BY HAND + +part of 'package_pubspec.dart'; + +// ************************************************************************** +// JsonSerializableGenerator +// ************************************************************************** + +_$PackagePubspecImpl _$$PackagePubspecImplFromJson(Map json) => + _$PackagePubspecImpl( + name: json['name'] as String, + version: json['version'] as String, + description: json['description'] as String, + ); + +Map _$$PackagePubspecImplToJson( + _$PackagePubspecImpl instance) => + { + 'name': instance.name, + 'version': instance.version, + 'description': instance.description, + }; diff --git a/packages/pub_dev_api_client/lib/src/pub_dev_api_client.dart b/packages/pub_dev_api_client/lib/src/pub_dev_api_client.dart new file mode 100644 index 00000000..ed11bd38 --- /dev/null +++ b/packages/pub_dev_api_client/lib/src/pub_dev_api_client.dart @@ -0,0 +1,52 @@ +import 'package:dio/dio.dart'; +import 'package:retrofit/retrofit.dart' hide Headers; + +import 'models/models.dart'; + +part 'pub_dev_api_client.g.dart'; + +/// Client for the Pub.dev API. +@RestApi() +abstract class PubDevApiClient { + /// Internal constructor. + factory PubDevApiClient.internal( + Dio dio, { + String baseUrl, + }) = _PubDevApiClient; + + /// Create a client from parameters. + factory PubDevApiClient.fromParameters({ + required String baseUrl, + required Duration timeoutDuration, + }) { + return _PubDevApiClient( + Dio( + BaseOptions( + baseUrl: baseUrl, + connectTimeout: timeoutDuration, + sendTimeout: timeoutDuration, + receiveTimeout: timeoutDuration, + contentType: Headers.jsonContentType, + ), + )..interceptors.add( + LogInterceptor( + responseBody: true, + ), + ), + ); + } + + /// Get packages by search word. + @GET('/search') + Future getSearchedPackages({ + @Query('q') String? searchWord, + @Query('sort') String? sort = 'top', + @Query('page') int? page, + }); + + /// Get particular package details. + @GET('/packages/{name}') + Future getPackageDetails({ + @Path('name') required String packageName, + }); +} diff --git a/packages/pub_dev_api_client/lib/src/pub_dev_api_client.g.dart b/packages/pub_dev_api_client/lib/src/pub_dev_api_client.g.dart new file mode 100644 index 00000000..502ae3ff --- /dev/null +++ b/packages/pub_dev_api_client/lib/src/pub_dev_api_client.g.dart @@ -0,0 +1,129 @@ +// GENERATED CODE - DO NOT MODIFY BY HAND + +part of 'pub_dev_api_client.dart'; + +// ************************************************************************** +// RetrofitGenerator +// ************************************************************************** + +// ignore_for_file: unnecessary_brace_in_string_interps,no_leading_underscores_for_local_identifiers,unused_element,unnecessary_string_interpolations + +class _PubDevApiClient implements PubDevApiClient { + _PubDevApiClient( + this._dio, { + this.baseUrl, + this.errorLogger, + }); + + final Dio _dio; + + String? baseUrl; + + final ParseErrorLogger? errorLogger; + + @override + Future getSearchedPackages({ + String? searchWord, + String? sort = 'top', + int? page, + }) async { + final _extra = {}; + final queryParameters = { + r'q': searchWord, + r'sort': sort, + r'page': page, + }; + queryParameters.removeWhere((k, v) => v == null); + final _headers = {}; + const Map? _data = null; + final _options = _setStreamType(Options( + method: 'GET', + headers: _headers, + extra: _extra, + ) + .compose( + _dio.options, + '/search', + queryParameters: queryParameters, + data: _data, + ) + .copyWith( + baseUrl: _combineBaseUrls( + _dio.options.baseUrl, + baseUrl, + ))); + final _result = await _dio.fetch>(_options); + late GetSearchedPackagesResponseBody _value; + try { + _value = GetSearchedPackagesResponseBody.fromJson(_result.data!); + } on Object catch (e, s) { + errorLogger?.logError(e, s, _options); + rethrow; + } + return _value; + } + + @override + Future getPackageDetails( + {required String packageName}) async { + final _extra = {}; + final queryParameters = {}; + final _headers = {}; + const Map? _data = null; + final _options = _setStreamType(Options( + method: 'GET', + headers: _headers, + extra: _extra, + ) + .compose( + _dio.options, + '/packages/${packageName}', + queryParameters: queryParameters, + data: _data, + ) + .copyWith( + baseUrl: _combineBaseUrls( + _dio.options.baseUrl, + baseUrl, + ))); + final _result = await _dio.fetch>(_options); + late GetPackageDetailsResponseBody _value; + try { + _value = GetPackageDetailsResponseBody.fromJson(_result.data!); + } on Object catch (e, s) { + errorLogger?.logError(e, s, _options); + rethrow; + } + return _value; + } + + RequestOptions _setStreamType(RequestOptions requestOptions) { + if (T != dynamic && + !(requestOptions.responseType == ResponseType.bytes || + requestOptions.responseType == ResponseType.stream)) { + if (T == String) { + requestOptions.responseType = ResponseType.plain; + } else { + requestOptions.responseType = ResponseType.json; + } + } + return requestOptions; + } + + String _combineBaseUrls( + String dioBaseUrl, + String? baseUrl, + ) { + if (baseUrl == null || baseUrl.trim().isEmpty) { + return dioBaseUrl; + } + + final url = Uri.parse(baseUrl); + + if (url.isAbsolute) { + return url.toString(); + } + + return Uri.parse(dioBaseUrl).resolveUri(url).toString(); + } +} diff --git a/packages/pub_dev_api_client/pubspec.lock b/packages/pub_dev_api_client/pubspec.lock new file mode 100644 index 00000000..e07c03ac --- /dev/null +++ b/packages/pub_dev_api_client/pubspec.lock @@ -0,0 +1,756 @@ +# Generated by pub +# See https://dart.dev/tools/pub/glossary#lockfile +packages: + _fe_analyzer_shared: + dependency: transitive + description: + name: _fe_analyzer_shared + sha256: f256b0c0ba6c7577c15e2e4e114755640a875e885099367bf6e012b19314c834 + url: "https://pub.dev" + source: hosted + version: "72.0.0" + _macros: + dependency: transitive + description: dart + source: sdk + version: "0.3.2" + altive_lints: + dependency: "direct dev" + description: + name: altive_lints + sha256: e9cace896453be6f97b9b41e3d02bd7f7c8c96c3fbe5e900a4d47d6f8d5c99d0 + url: "https://pub.dev" + source: hosted + version: "1.16.0" + analyzer: + dependency: transitive + description: + name: analyzer + sha256: b652861553cd3990d8ed361f7979dc6d7053a9ac8843fa73820ab68ce5410139 + url: "https://pub.dev" + source: hosted + version: "6.7.0" + analyzer_plugin: + dependency: transitive + description: + name: analyzer_plugin + sha256: "9661b30b13a685efaee9f02e5d01ed9f2b423bd889d28a304d02d704aee69161" + url: "https://pub.dev" + source: hosted + version: "0.11.3" + args: + dependency: transitive + description: + name: args + sha256: bf9f5caeea8d8fe6721a9c358dd8a5c1947b27f1cfaa18b39c301273594919e6 + url: "https://pub.dev" + source: hosted + version: "2.6.0" + async: + dependency: transitive + description: + name: async + sha256: "947bfcf187f74dbc5e146c9eb9c0f10c9f8b30743e341481c1e2ed3ecc18c20c" + url: "https://pub.dev" + source: hosted + version: "2.11.0" + boolean_selector: + dependency: transitive + description: + name: boolean_selector + sha256: "6cfb5af12253eaf2b368f07bacc5a80d1301a071c73360d746b7f2e32d762c66" + url: "https://pub.dev" + source: hosted + version: "2.1.1" + build: + dependency: transitive + description: + name: build + sha256: "80184af8b6cb3e5c1c4ec6d8544d27711700bc3e6d2efad04238c7b5290889f0" + url: "https://pub.dev" + source: hosted + version: "2.4.1" + build_config: + dependency: transitive + description: + name: build_config + sha256: bf80fcfb46a29945b423bd9aad884590fb1dc69b330a4d4700cac476af1708d1 + url: "https://pub.dev" + source: hosted + version: "1.1.1" + build_daemon: + dependency: transitive + description: + name: build_daemon + sha256: "79b2aef6ac2ed00046867ed354c88778c9c0f029df8a20fe10b5436826721ef9" + url: "https://pub.dev" + source: hosted + version: "4.0.2" + build_resolvers: + dependency: transitive + description: + name: build_resolvers + sha256: "339086358431fa15d7eca8b6a36e5d783728cf025e559b834f4609a1fcfb7b0a" + url: "https://pub.dev" + source: hosted + version: "2.4.2" + build_runner: + dependency: "direct dev" + description: + name: build_runner + sha256: "028819cfb90051c6b5440c7e574d1896f8037e3c96cf17aaeb054c9311cfbf4d" + url: "https://pub.dev" + source: hosted + version: "2.4.13" + build_runner_core: + dependency: transitive + description: + name: build_runner_core + sha256: f8126682b87a7282a339b871298cc12009cb67109cfa1614d6436fb0289193e0 + url: "https://pub.dev" + source: hosted + version: "7.3.2" + built_collection: + dependency: transitive + description: + name: built_collection + sha256: "376e3dd27b51ea877c28d525560790aee2e6fbb5f20e2f85d5081027d94e2100" + url: "https://pub.dev" + source: hosted + version: "5.1.1" + built_value: + dependency: transitive + description: + name: built_value + sha256: c7913a9737ee4007efedaffc968c049fd0f3d0e49109e778edc10de9426005cb + url: "https://pub.dev" + source: hosted + version: "8.9.2" + characters: + dependency: transitive + description: + name: characters + sha256: "04a925763edad70e8443c99234dc3328f442e811f1d8fd1a72f1c8ad0f69a605" + url: "https://pub.dev" + source: hosted + version: "1.3.0" + checked_yaml: + dependency: transitive + description: + name: checked_yaml + sha256: feb6bed21949061731a7a75fc5d2aa727cf160b91af9a3e464c5e3a32e28b5ff + url: "https://pub.dev" + source: hosted + version: "2.0.3" + ci: + dependency: transitive + description: + name: ci + sha256: "145d095ce05cddac4d797a158bc4cf3b6016d1fe63d8c3d2fbd7212590adca13" + url: "https://pub.dev" + source: hosted + version: "0.1.0" + cli_util: + dependency: transitive + description: + name: cli_util + sha256: ff6785f7e9e3c38ac98b2fb035701789de90154024a75b6cb926445e83197d1c + url: "https://pub.dev" + source: hosted + version: "0.4.2" + code_builder: + dependency: transitive + description: + name: code_builder + sha256: "0ec10bf4a89e4c613960bf1e8b42c64127021740fb21640c29c909826a5eea3e" + url: "https://pub.dev" + source: hosted + version: "4.10.1" + collection: + dependency: transitive + description: + name: collection + sha256: ee67cb0715911d28db6bf4af1026078bd6f0128b07a5f66fb2ed94ec6783c09a + url: "https://pub.dev" + source: hosted + version: "1.18.0" + convert: + dependency: transitive + description: + name: convert + sha256: b30acd5944035672bc15c6b7a8b47d773e41e2f17de064350988c5d02adb1c68 + url: "https://pub.dev" + source: hosted + version: "3.1.2" + coverage: + dependency: transitive + description: + name: coverage + sha256: "4b03e11f6d5b8f6e5bb5e9f7889a56fe6c5cbe942da5378ea4d4d7f73ef9dfe5" + url: "https://pub.dev" + source: hosted + version: "1.11.0" + crypto: + dependency: transitive + description: + name: crypto + sha256: "1e445881f28f22d6140f181e07737b22f1e099a5e1ff94b0af2f9e4a463f4855" + url: "https://pub.dev" + source: hosted + version: "3.0.6" + custom_lint: + dependency: "direct dev" + description: + name: custom_lint + sha256: "3486c470bb93313a9417f926c7dd694a2e349220992d7b9d14534dc49c15bba9" + url: "https://pub.dev" + source: hosted + version: "0.7.0" + custom_lint_builder: + dependency: transitive + description: + name: custom_lint_builder + sha256: "42cdc41994eeeddab0d7a722c7093ec52bd0761921eeb2cbdbf33d192a234759" + url: "https://pub.dev" + source: hosted + version: "0.7.0" + custom_lint_core: + dependency: transitive + description: + name: custom_lint_core + sha256: "02450c3e45e2a6e8b26c4d16687596ab3c4644dd5792e3313aa9ceba5a49b7f5" + url: "https://pub.dev" + source: hosted + version: "0.7.0" + custom_lint_visitor: + dependency: transitive + description: + name: custom_lint_visitor + sha256: "8aeb3b6ae2bb765e7716b93d1d10e8356d04e0ff6d7592de6ee04e0dd7d6587d" + url: "https://pub.dev" + source: hosted + version: "1.0.0+6.7.0" + dart_style: + dependency: transitive + description: + name: dart_style + sha256: "7856d364b589d1f08986e140938578ed36ed948581fbc3bc9aef1805039ac5ab" + url: "https://pub.dev" + source: hosted + version: "2.3.7" + dio: + dependency: "direct main" + description: + name: dio + sha256: "5598aa796bbf4699afd5c67c0f5f6e2ed542afc956884b9cd58c306966efc260" + url: "https://pub.dev" + source: hosted + version: "5.7.0" + dio_web_adapter: + dependency: transitive + description: + name: dio_web_adapter + sha256: "33259a9276d6cea88774a0000cfae0d861003497755969c92faa223108620dc8" + url: "https://pub.dev" + source: hosted + version: "2.0.0" + file: + dependency: transitive + description: + name: file + sha256: a3b4f84adafef897088c160faf7dfffb7696046cb13ae90b508c2cbc95d3b8d4 + url: "https://pub.dev" + source: hosted + version: "7.0.1" + fixnum: + dependency: transitive + description: + name: fixnum + sha256: b6dc7065e46c974bc7c5f143080a6764ec7a4be6da1285ececdc37be96de53be + url: "https://pub.dev" + source: hosted + version: "1.1.1" + flutter: + dependency: "direct main" + description: flutter + source: sdk + version: "0.0.0" + freezed: + dependency: "direct dev" + description: + name: freezed + sha256: "44c19278dd9d89292cf46e97dc0c1e52ce03275f40a97c5a348e802a924bf40e" + url: "https://pub.dev" + source: hosted + version: "2.5.7" + freezed_annotation: + dependency: "direct main" + description: + name: freezed_annotation + sha256: c2e2d632dd9b8a2b7751117abcfc2b4888ecfe181bd9fca7170d9ef02e595fe2 + url: "https://pub.dev" + source: hosted + version: "2.4.4" + frontend_server_client: + dependency: transitive + description: + name: frontend_server_client + sha256: f64a0333a82f30b0cca061bc3d143813a486dc086b574bfb233b7c1372427694 + url: "https://pub.dev" + source: hosted + version: "4.0.0" + glob: + dependency: transitive + description: + name: glob + sha256: "0e7014b3b7d4dac1ca4d6114f82bf1782ee86745b9b42a92c9289c23d8a0ab63" + url: "https://pub.dev" + source: hosted + version: "2.1.2" + graphs: + dependency: transitive + description: + name: graphs + sha256: "741bbf84165310a68ff28fe9e727332eef1407342fca52759cb21ad8177bb8d0" + url: "https://pub.dev" + source: hosted + version: "2.3.2" + hotreloader: + dependency: transitive + description: + name: hotreloader + sha256: ed56fdc1f3a8ac924e717257621d09e9ec20e308ab6352a73a50a1d7a4d9158e + url: "https://pub.dev" + source: hosted + version: "4.2.0" + http_multi_server: + dependency: transitive + description: + name: http_multi_server + sha256: "97486f20f9c2f7be8f514851703d0119c3596d14ea63227af6f7a481ef2b2f8b" + url: "https://pub.dev" + source: hosted + version: "3.2.1" + http_parser: + dependency: transitive + description: + name: http_parser + sha256: "2aa08ce0341cc9b354a498388e30986515406668dbcc4f7c950c3e715496693b" + url: "https://pub.dev" + source: hosted + version: "4.0.2" + io: + dependency: transitive + description: + name: io + sha256: "2ec25704aba361659e10e3e5f5d672068d332fc8ac516421d483a11e5cbd061e" + url: "https://pub.dev" + source: hosted + version: "1.0.4" + js: + dependency: transitive + description: + name: js + sha256: c1b2e9b5ea78c45e1a0788d29606ba27dc5f71f019f32ca5140f61ef071838cf + url: "https://pub.dev" + source: hosted + version: "0.7.1" + json_annotation: + dependency: transitive + description: + name: json_annotation + sha256: "1ce844379ca14835a50d2f019a3099f419082cfdd231cd86a142af94dd5c6bb1" + url: "https://pub.dev" + source: hosted + version: "4.9.0" + json_serializable: + dependency: "direct dev" + description: + name: json_serializable + sha256: c2fcb3920cf2b6ae6845954186420fca40bc0a8abcc84903b7801f17d7050d7c + url: "https://pub.dev" + source: hosted + version: "6.9.0" + logging: + dependency: transitive + description: + name: logging + sha256: c8245ada5f1717ed44271ed1c26b8ce85ca3228fd2ffdb75468ab01979309d61 + url: "https://pub.dev" + source: hosted + version: "1.3.0" + macros: + dependency: transitive + description: + name: macros + sha256: "0acaed5d6b7eab89f63350bccd82119e6c602df0f391260d0e32b5e23db79536" + url: "https://pub.dev" + source: hosted + version: "0.1.2-main.4" + matcher: + dependency: transitive + description: + name: matcher + sha256: d2323aa2060500f906aa31a895b4030b6da3ebdcc5619d14ce1aada65cd161cb + url: "https://pub.dev" + source: hosted + version: "0.12.16+1" + material_color_utilities: + dependency: transitive + description: + name: material_color_utilities + sha256: f7142bb1154231d7ea5f96bc7bde4bda2a0945d2806bb11670e30b850d56bdec + url: "https://pub.dev" + source: hosted + version: "0.11.1" + meta: + dependency: transitive + description: + name: meta + sha256: bdb68674043280c3428e9ec998512fb681678676b3c54e773629ffe74419f8c7 + url: "https://pub.dev" + source: hosted + version: "1.15.0" + mime: + dependency: transitive + description: + name: mime + sha256: "41a20518f0cb1256669420fdba0cd90d21561e560ac240f26ef8322e45bb7ed6" + url: "https://pub.dev" + source: hosted + version: "2.0.0" + mock_web_server: + dependency: "direct main" + description: + name: mock_web_server + sha256: d6ec0d2a644c2ff5ef86da4360743e33f65c0fcf780555b913107502ac51a98e + url: "https://pub.dev" + source: hosted + version: "5.0.0-nullsafety.1" + mockito: + dependency: "direct main" + description: + name: mockito + sha256: "6841eed20a7befac0ce07df8116c8b8233ed1f4486a7647c7fc5a02ae6163917" + url: "https://pub.dev" + source: hosted + version: "5.4.4" + node_preamble: + dependency: transitive + description: + name: node_preamble + sha256: "6e7eac89047ab8a8d26cf16127b5ed26de65209847630400f9aefd7cd5c730db" + url: "https://pub.dev" + source: hosted + version: "2.0.2" + package_config: + dependency: transitive + description: + name: package_config + sha256: "1c5b77ccc91e4823a5af61ee74e6b972db1ef98c2ff5a18d3161c982a55448bd" + url: "https://pub.dev" + source: hosted + version: "2.1.0" + path: + dependency: transitive + description: + name: path + sha256: "087ce49c3f0dc39180befefc60fdb4acd8f8620e5682fe2476afd0b3688bb4af" + url: "https://pub.dev" + source: hosted + version: "1.9.0" + pool: + dependency: transitive + description: + name: pool + sha256: "20fe868b6314b322ea036ba325e6fc0711a22948856475e2c2b6306e8ab39c2a" + url: "https://pub.dev" + source: hosted + version: "1.5.1" + protobuf: + dependency: transitive + description: + name: protobuf + sha256: "68645b24e0716782e58948f8467fd42a880f255096a821f9e7d0ec625b00c84d" + url: "https://pub.dev" + source: hosted + version: "3.1.0" + pub_semver: + dependency: transitive + description: + name: pub_semver + sha256: "40d3ab1bbd474c4c2328c91e3a7df8c6dd629b79ece4c4bd04bee496a224fb0c" + url: "https://pub.dev" + source: hosted + version: "2.1.4" + pubspec_parse: + dependency: transitive + description: + name: pubspec_parse + sha256: c799b721d79eb6ee6fa56f00c04b472dcd44a30d258fac2174a6ec57302678f8 + url: "https://pub.dev" + source: hosted + version: "1.3.0" + retrofit: + dependency: "direct main" + description: + name: retrofit + sha256: "3c9885ef3dbc5dc4b3fb0a40c972ab52e4dad04d52dac9bba24dfa76cf100451" + url: "https://pub.dev" + source: hosted + version: "4.4.1" + retrofit_generator: + dependency: "direct dev" + description: + name: retrofit_generator + sha256: f76fdb2b66854690d5a332e7364d7561fc9dc2b3c924d7956ab8070495e21f6a + url: "https://pub.dev" + source: hosted + version: "9.1.5" + rxdart: + dependency: transitive + description: + name: rxdart + sha256: "5c3004a4a8dbb94bd4bf5412a4def4acdaa12e12f269737a5751369e12d1a962" + url: "https://pub.dev" + source: hosted + version: "0.28.0" + shelf: + dependency: transitive + description: + name: shelf + sha256: ad29c505aee705f41a4d8963641f91ac4cee3c8fad5947e033390a7bd8180fa4 + url: "https://pub.dev" + source: hosted + version: "1.4.1" + shelf_packages_handler: + dependency: transitive + description: + name: shelf_packages_handler + sha256: "89f967eca29607c933ba9571d838be31d67f53f6e4ee15147d5dc2934fee1b1e" + url: "https://pub.dev" + source: hosted + version: "3.0.2" + shelf_static: + dependency: transitive + description: + name: shelf_static + sha256: c87c3875f91262785dade62d135760c2c69cb217ac759485334c5857ad89f6e3 + url: "https://pub.dev" + source: hosted + version: "1.1.3" + shelf_web_socket: + dependency: transitive + description: + name: shelf_web_socket + sha256: cc36c297b52866d203dbf9332263c94becc2fe0ceaa9681d07b6ef9807023b67 + url: "https://pub.dev" + source: hosted + version: "2.0.1" + sky_engine: + dependency: transitive + description: flutter + source: sdk + version: "0.0.99" + source_gen: + dependency: transitive + description: + name: source_gen + sha256: "14658ba5f669685cd3d63701d01b31ea748310f7ab854e471962670abcf57832" + url: "https://pub.dev" + source: hosted + version: "1.5.0" + source_helper: + dependency: transitive + description: + name: source_helper + sha256: "6adebc0006c37dd63fe05bca0a929b99f06402fc95aa35bf36d67f5c06de01fd" + url: "https://pub.dev" + source: hosted + version: "1.3.4" + source_map_stack_trace: + dependency: transitive + description: + name: source_map_stack_trace + sha256: c0713a43e323c3302c2abe2a1cc89aa057a387101ebd280371d6a6c9fa68516b + url: "https://pub.dev" + source: hosted + version: "2.1.2" + source_maps: + dependency: transitive + description: + name: source_maps + sha256: "708b3f6b97248e5781f493b765c3337db11c5d2c81c3094f10904bfa8004c703" + url: "https://pub.dev" + source: hosted + version: "0.10.12" + source_span: + dependency: transitive + description: + name: source_span + sha256: "53e943d4206a5e30df338fd4c6e7a077e02254531b138a15aec3bd143c1a8b3c" + url: "https://pub.dev" + source: hosted + version: "1.10.0" + sprintf: + dependency: transitive + description: + name: sprintf + sha256: "1fc9ffe69d4df602376b52949af107d8f5703b77cda567c4d7d86a0693120f23" + url: "https://pub.dev" + source: hosted + version: "7.0.0" + stack_trace: + dependency: transitive + description: + name: stack_trace + sha256: "73713990125a6d93122541237550ee3352a2d84baad52d375a4cad2eb9b7ce0b" + url: "https://pub.dev" + source: hosted + version: "1.11.1" + stream_channel: + dependency: transitive + description: + name: stream_channel + sha256: ba2aa5d8cc609d96bbb2899c28934f9e1af5cddbd60a827822ea467161eb54e7 + url: "https://pub.dev" + source: hosted + version: "2.1.2" + stream_transform: + dependency: transitive + description: + name: stream_transform + sha256: "14a00e794c7c11aa145a170587321aedce29769c08d7f58b1d141da75e3b1c6f" + url: "https://pub.dev" + source: hosted + version: "2.1.0" + string_scanner: + dependency: transitive + description: + name: string_scanner + sha256: "556692adab6cfa87322a115640c11f13cb77b3f076ddcc5d6ae3c20242bedcde" + url: "https://pub.dev" + source: hosted + version: "1.2.0" + term_glyph: + dependency: transitive + description: + name: term_glyph + sha256: a29248a84fbb7c79282b40b8c72a1209db169a2e0542bce341da992fe1bc7e84 + url: "https://pub.dev" + source: hosted + version: "1.2.1" + test: + dependency: "direct dev" + description: + name: test + sha256: f2a018e2baa6fce7c8daa55b8bdf4b3d7d165f82caac269e4cbe5edd666c0e4c + url: "https://pub.dev" + source: hosted + version: "1.25.9" + test_api: + dependency: transitive + description: + name: test_api + sha256: fb31f383e2ee25fbbfe06b40fe21e1e458d14080e3c67e7ba0acfde4df4e0bbd + url: "https://pub.dev" + source: hosted + version: "0.7.4" + test_core: + dependency: transitive + description: + name: test_core + sha256: "60ff490bb383858015df7b7a0d883301a426edf9033989f55f091d91efb9dfaf" + url: "https://pub.dev" + source: hosted + version: "0.6.6" + timing: + dependency: transitive + description: + name: timing + sha256: "70a3b636575d4163c477e6de42f247a23b315ae20e86442bebe32d3cabf61c32" + url: "https://pub.dev" + source: hosted + version: "1.0.1" + typed_data: + dependency: transitive + description: + name: typed_data + sha256: f9049c039ebfeb4cf7a7104a675823cd72dba8297f264b6637062516699fa006 + url: "https://pub.dev" + source: hosted + version: "1.4.0" + uuid: + dependency: transitive + description: + name: uuid + sha256: a5be9ef6618a7ac1e964353ef476418026db906c4facdedaa299b7a2e71690ff + url: "https://pub.dev" + source: hosted + version: "4.5.1" + vector_math: + dependency: transitive + description: + name: vector_math + sha256: "80b3257d1492ce4d091729e3a67a60407d227c27241d6927be0130c98e741803" + url: "https://pub.dev" + source: hosted + version: "2.1.4" + vm_service: + dependency: transitive + description: + name: vm_service + sha256: "5c5f338a667b4c644744b661f309fb8080bb94b18a7e91ef1dbd343bed00ed6d" + url: "https://pub.dev" + source: hosted + version: "14.2.5" + watcher: + dependency: transitive + description: + name: watcher + sha256: "3d2ad6751b3c16cf07c7fca317a1413b3f26530319181b37e3b9039b84fc01d8" + url: "https://pub.dev" + source: hosted + version: "1.1.0" + web: + dependency: transitive + description: + name: web + sha256: cd3543bd5798f6ad290ea73d210f423502e71900302dde696f8bff84bf89a1cb + url: "https://pub.dev" + source: hosted + version: "1.1.0" + web_socket: + dependency: transitive + description: + name: web_socket + sha256: "3c12d96c0c9a4eec095246debcea7b86c0324f22df69893d538fcc6f1b8cce83" + url: "https://pub.dev" + source: hosted + version: "0.1.6" + web_socket_channel: + dependency: transitive + description: + name: web_socket_channel + sha256: "9f187088ed104edd8662ca07af4b124465893caf063ba29758f97af57e61da8f" + url: "https://pub.dev" + source: hosted + version: "3.0.1" + webkit_inspection_protocol: + dependency: transitive + description: + name: webkit_inspection_protocol + sha256: "87d3f2333bb240704cd3f1c6b5b7acd8a10e7f0bc28c28dcf14e782014f4a572" + url: "https://pub.dev" + source: hosted + version: "1.2.1" + yaml: + dependency: transitive + description: + name: yaml + sha256: "75769501ea3489fca56601ff33454fe45507ea3bfb014161abc3b43ae25989d5" + url: "https://pub.dev" + source: hosted + version: "3.1.2" +sdks: + dart: ">=3.5.3 <4.0.0" diff --git a/packages/pub_dev_api_client/pubspec.yaml b/packages/pub_dev_api_client/pubspec.yaml new file mode 100644 index 00000000..cb05375e --- /dev/null +++ b/packages/pub_dev_api_client/pubspec.yaml @@ -0,0 +1,26 @@ +name: pub_dev_api_client +description: Pub.dev API client package +version: 1.0.0+1 + +environment: + sdk: ^3.5.3 + +dependencies: + dio: ^5.7.0 + flutter: + sdk: flutter + freezed_annotation: ^2.4.4 + mock_web_server: ^5.0.0-nullsafety.1 + mockito: ^5.4.4 + retrofit: ^4.4.1 + +dev_dependencies: + altive_lints: ^1.16.0 + build_runner: ^2.4.13 + custom_lint: ^0.7.0 + freezed: ^2.5.7 + json_serializable: ^6.9.0 + retrofit_generator: ^9.1.5 + test: ^1.25.8 + + diff --git a/packages/pub_dev_api_client/test/src/pub_dev_api_client_test.dart b/packages/pub_dev_api_client/test/src/pub_dev_api_client_test.dart new file mode 100644 index 00000000..d9681957 --- /dev/null +++ b/packages/pub_dev_api_client/test/src/pub_dev_api_client_test.dart @@ -0,0 +1,128 @@ +import 'dart:convert'; + +import 'package:mock_web_server/mock_web_server.dart'; +import 'package:pub_dev_api_client/pub_dev_api_client.dart'; +import 'package:pub_dev_api_client/src/models/package_pubspec.dart'; +import 'package:test/test.dart'; + +void main() { + PubDevApiClient createClient({required String baseUrl}) { + final client = PubDevApiClient.fromParameters( + baseUrl: baseUrl, + timeoutDuration: const Duration(milliseconds: 30000), + ); + return client; + } + + Future createMockWebServer( + Map? response, + ) async { + final server = MockWebServer(); + addTearDown(server.shutdown); + await server.start(); + server.enqueue( + body: jsonEncode(response), + headers: {'content-type': 'application/json'}, + ); + return server; + } + + group('fromParameters', () { + test( + 'Ensure that RestApiClient can be instantiated ' + 'using the fromParameters constructor', () { + final client = PubDevApiClient.fromParameters( + baseUrl: 'https://example.com/api-base-url', + timeoutDuration: const Duration(seconds: 30), + ); + + expect(client, isA()); + }); + }); + + group('getSearchedPackages', () { + const mockResponse = GetSearchedPackagesResponseBody( + packages: [ + PackageName(name: 'package1'), + PackageName(name: 'package2'), + ], + ); + + test( + 'Verify that the request is sent to the correct endpoint' + ' when the method is called', () async { + final mockServer = await createMockWebServer(mockResponse.toJson()); + + final client = createClient(baseUrl: mockServer.url); + + await client.getSearchedPackages(); + + final request = mockServer.takeRequest(); + + expect(request.uri.path, '/search'); + }); + + test( + 'Verify that the correct query parameters are included in the request' + ' when it is sent', () async { + final mockServer = await createMockWebServer(mockResponse.toJson()); + + final client = createClient(baseUrl: mockServer.url); + + await client.getSearchedPackages(searchWord: 'word', page: 2); + + final request = mockServer.takeRequest(); + + expect(request.uri.queryParameters['q'], 'word'); + expect(request.uri.queryParameters['sort'], 'top'); + expect(request.uri.queryParameters['page'], '2'); + }); + + test( + 'Verify that the parsed response object is correctly returned' + ' when the request is sent', () async { + final mockServer = await createMockWebServer(mockResponse.toJson()); + final client = createClient(baseUrl: mockServer.url); + final response = await client.getSearchedPackages(); + + expect(response, mockResponse); + }); + }); + + group('getPackageDetails', () { + const mockResponse = GetPackageDetailsResponseBody( + name: 'package1', + latest: LatestPackageRelease( + pubspec: PackagePubspec( + name: 'package1', + version: '1.0.0', + description: 'description description description', + ), + ), + ); + + test( + 'Verify that the request is sent to the correct endpoint' + ' when the method is called', () async { + final mockServer = await createMockWebServer(mockResponse.toJson()); + + final client = createClient(baseUrl: mockServer.url); + + await client.getPackageDetails(packageName: 'package1'); + + final request = mockServer.takeRequest(); + + expect(request.uri.path, '/packages/package1'); + }); + + test( + 'Verify that the parsed response object is correctly returned' + ' when the request is sent', () async { + final mockServer = await createMockWebServer(mockResponse.toJson()); + final client = createClient(baseUrl: mockServer.url); + final response = await client.getPackageDetails(packageName: 'package1'); + + expect(response, mockResponse); + }); + }); +}