[libmetacpan-client-perl] 01/05: New upstream version 2.021000

Damyan Ivanov dmn at moszumanska.debian.org
Fri Dec 1 20:39:58 UTC 2017


This is an automated email from the git hooks/post-receive script.

dmn pushed a commit to branch master
in repository libmetacpan-client-perl.

commit c9a12ca1b1081c4f8dbe935cf78e5b4320e480e3
Author: Damyan Ivanov <dmn at debian.org>
Date:   Fri Dec 1 20:15:47 2017 +0000

    New upstream version 2.021000
---
 Changes                                          |  81 +++++++++-
 MANIFEST                                         |  12 +-
 META.json                                        | 100 +++++++++----
 META.yml                                         |  77 +++++++---
 Makefile.PL                                      |   8 +-
 README                                           | 111 ++++++++++++--
 cpanfile                                         |  12 +-
 dist.ini                                         |   6 +-
 examples/autocomplete_suggest.pl                 |  13 ++
 examples/changes.pl                              |   9 ++
 examples/contributors.pl                         |  19 +++
 examples/metacpan_url.pl                         |  24 +++
 examples/package.pl                              |  18 +++
 examples/permission.pl                           |  18 +++
 lib/MetaCPAN/Client.pm                           | 166 ++++++++++++++++++---
 lib/MetaCPAN/Client/Author.pm                    | 181 ++++++++++++++++++-----
 lib/MetaCPAN/Client/Distribution.pm              |  48 +++++-
 lib/MetaCPAN/Client/DownloadURL.pm               |  16 +-
 lib/MetaCPAN/Client/Favorite.pm                  |  17 ++-
 lib/MetaCPAN/Client/File.pm                      | 133 +++++++++++++++--
 lib/MetaCPAN/Client/Mirror.pm                    |  26 +++-
 lib/MetaCPAN/Client/Module.pm                    |  36 ++++-
 lib/MetaCPAN/Client/{Rating.pm => Package.pm}    |  51 ++++---
 lib/MetaCPAN/Client/{Rating.pm => Permission.pm} |  43 ++----
 lib/MetaCPAN/Client/Pod.pm                       |   4 +-
 lib/MetaCPAN/Client/Rating.pm                    |  10 +-
 lib/MetaCPAN/Client/Release.pm                   | 142 ++++++++++++++++--
 lib/MetaCPAN/Client/Request.pm                   | 145 ++++++++----------
 lib/MetaCPAN/Client/ResultSet.pm                 |   8 +-
 lib/MetaCPAN/Client/Role/Entity.pm               |  10 +-
 lib/MetaCPAN/Client/Role/HasUA.pm                | 124 ++++++++++++++++
 lib/MetaCPAN/Client/Scroll.pm                    |  71 ++++-----
 lib/MetaCPAN/Client/Types.pm                     |   9 +-
 t/00-report-prereqs.dd                           |  12 +-
 t/api/_get.t                                     |   1 +
 t/api/_get_or_search.t                           |   1 +
 t/api/_search.t                                  |   1 +
 t/api/author.t                                   |   1 +
 t/api/distribution.t                             |   1 +
 t/api/download_url.t                             |   1 +
 t/api/favorite.t                                 |   1 +
 t/api/file.t                                     |   1 +
 t/api/module.t                                   |   1 +
 t/api/package.t                                  |  22 +++
 t/api/permission.t                               |  19 +++
 t/api/pod.t                                      |   1 +
 t/api/rating.t                                   |   1 +
 t/api/release.t                                  |   1 +
 t/scroll.t                                       |   9 +-
 t/ua_trap.t                                      |   6 +-
 xt/author/00-compile.t                           |   5 +-
 xt/author/critic.t                               |  12 --
 52 files changed, 1447 insertions(+), 398 deletions(-)

diff --git a/Changes b/Changes
index c212e5b..0308789 100644
--- a/Changes
+++ b/Changes
@@ -1,5 +1,82 @@
 Revision history for MetaCPAN-Client (previously MetaCPAN-API)
 
+2.021000    18.11.17
+            * Scroller fix for page skipping (Thomas Sibley)
+            * Sorting in scrolled searches (Thomas Sibley)
+            * Type check cleanup (Thomas Sibley)
+
+2.020000    17.11.17
+            * Added support for /search/autocomplete/suggest (Mickey)
+
+2.019000    16.11.17
+            * Added 'package' type support for scrolled searches (Mickey)
+
+2.018000    16.10.17
+            * Fix fetch URL (Mickey, GH#92)
+            * Removed critic author test (Mickey)
+
+2.017000    25.6.17
+            * reverse_dependencies: update link to new API endpoint (Mickey, GH#89)
+
+2.016000    7.6.17
+            * Support CSV field list in 'all' requests (Mickey, GH#87)
+
+2.015000    14.5.17
+            * Added 'main_module' field to the Release object (Mickey)
+            * Updated doc (Matthew Horsfall, GH#85)
+
+2.014000    12.5.17
+            * Fixed single-value case for expected arrayref (Mickey, GH#84)
+            * Added support for new release/contributors endpoint (Mickey)
+
+2.013001    12.5.17
+            * Updated endpoint name following API change (Mickey)
+
+2.013000    9.5.17
+            * Added support for new 'packages' type (Mickey)
+
+2.012000    27.4.17
+            * Fixed 'email' field handling in Author objects (Mickey, GH#83)
+
+2.011000    18.4.17
+            * Added support for scroller time/size params (Mickey)
+            * Removed warning of scroller deletion failure (Mickey, GH#81)
+
+2.010000    3.4.17
+            * Added support for new 'permission' type (Mickey)
+
+2.009001    29.3.17
+            * Use Test::Needs to force a minimum
+              WWW::Mechanize::Cached version (Olaf Alders, GH#76)
+
+2.009000    24.3.17
+            * Bump WWW::Mechanize::Cached version to 1.50 (Olaf Alders, GH#76)
+            * Require LWP::Protocol::https in tests (Mickey, GH#79)
+            * Added 'changes' method for Release objects (Mickey, GH#57)
+            * Cleaner URLs - removed redundant slashes and 'v1' (Mickey)
+            * Created a role for user-agent handling for reuse (Mickey)
+
+2.008001    23.3.17
+            * Fixed a test (Mickey)
+
+2.008000    22.3.17
+            * Added metacpan_url method to the entity objects
+              (Mickey, #GH69)
+
+2.007000    8.3.17
+            * Update tests for newer Perl versions, to run without
+              '.' in @INC (Sawyer X, GH#72)
+
+2.006000    24.2.17
+            * Support '_source' filtering (Mickey, GH#70)
+            * Support debug-mode for detailed error messages (Mickey)
+
+2.005000    13.2.17
+            * Added the ascii_name and perlmongers fields to the Author object
+              (Dave Rolsky, GH #66)
+            * Fixed Author->dir to actually return something (Dave Rolsky, GH
+              #66)
+
 2.004000    30.12.16
             * Speed up own scroller (Mickey)
             * Fixed rev_deps (Mickey)
@@ -136,7 +213,7 @@ Revision history for MetaCPAN-Client (previously MetaCPAN-API)
 
 1.010000    23.01.15
             * support wildcard-only value in complex search (mickeyn)
-            * support raw ElasticSearch filters in 'all' queries (mickeyn)
+            * support raw Elasticsearch filters in 'all' queries (mickeyn)
 
 1.009000    11.01.15
             * GH #25 (RT #99499): added support for 'fields' filtering (mickeyn, oalders)
@@ -216,7 +293,7 @@ Revision history for MetaCPAN-Client (previously MetaCPAN-API)
                 * Simple queries return entity objects
                 * Complex queries return resultset objects (with iterator)
                 * Support for scrolled searches
-                * Inline support for ElasticSearch facets
+                * Inline support for Elasticsearch facets
                 * Documentation, tests - all cleaned, rewritten
 
 0.43        05.04.12
diff --git a/MANIFEST b/MANIFEST
index d4cc62b..9058b9b 100644
--- a/MANIFEST
+++ b/MANIFEST
@@ -15,16 +15,22 @@ examples/author.pl
 examples/author_releases.pl
 examples/authors_blogs.pl
 examples/autocomplete.pl
+examples/autocomplete_suggest.pl
+examples/changes.pl
 examples/complex-either-and.pl
 examples/complex-either-not.pl
 examples/complex-nested-either-and.pl
 examples/complex.pl
+examples/contributors.pl
 examples/distribution.pl
 examples/download_url.pl
 examples/es_filter.pl
 examples/fields-filter.pl
+examples/metacpan_url.pl
 examples/mirror.pl
 examples/module.pl
+examples/package.pl
+examples/permission.pl
 examples/pod.pl
 examples/rating.pl
 examples/recent.pl
@@ -41,12 +47,15 @@ lib/MetaCPAN/Client/Favorite.pm
 lib/MetaCPAN/Client/File.pm
 lib/MetaCPAN/Client/Mirror.pm
 lib/MetaCPAN/Client/Module.pm
+lib/MetaCPAN/Client/Package.pm
+lib/MetaCPAN/Client/Permission.pm
 lib/MetaCPAN/Client/Pod.pm
 lib/MetaCPAN/Client/Rating.pm
 lib/MetaCPAN/Client/Release.pm
 lib/MetaCPAN/Client/Request.pm
 lib/MetaCPAN/Client/ResultSet.pm
 lib/MetaCPAN/Client/Role/Entity.pm
+lib/MetaCPAN/Client/Role/HasUA.pm
 lib/MetaCPAN/Client/Scroll.pm
 lib/MetaCPAN/Client/Types.pm
 t/00-report-prereqs.dd
@@ -60,6 +69,8 @@ t/api/download_url.t
 t/api/favorite.t
 t/api/file.t
 t/api/module.t
+t/api/package.t
+t/api/permission.t
 t/api/pod.t
 t/api/rating.t
 t/api/release.t
@@ -70,6 +81,5 @@ t/resultset.t
 t/scroll.t
 t/ua_trap.t
 xt/author/00-compile.t
-xt/author/critic.t
 xt/author/pod-coverage.t
 xt/author/pod-syntax.t
diff --git a/META.json b/META.json
index ccd1a49..37ce498 100644
--- a/META.json
+++ b/META.json
@@ -33,7 +33,7 @@
       "develop" : {
          "requires" : {
             "File::Spec" : "0",
-            "HTTP::Tiny::Mech" : "0",
+            "HTTP::Tiny::Mech" : "1.001002",
             "IO::Handle" : "0",
             "IPC::Open3" : "0",
             "LWP::Protocol::https" : "0",
@@ -41,7 +41,7 @@
             "Test::More" : "0",
             "Test::Pod" : "1.41",
             "Test::Pod::Coverage" : "1.08",
-            "WWW::Mechanize::Cached" : "1.48"
+            "WWW::Mechanize::Cached" : "1.50"
          }
       },
       "runtime" : {
@@ -66,16 +66,16 @@
       "test" : {
          "recommends" : {
             "CPAN::Meta" : "2.120900",
-            "HTTP::Tiny::Mech" : "0",
-            "LWP::Protocol::https" : "0",
-            "WWW::Mechanize::Cached" : "1.48"
+            "HTTP::Tiny::Mech" : "1.001002",
+            "WWW::Mechanize::Cached" : "1.50"
          },
          "requires" : {
             "ExtUtils::MakeMaker" : "0",
             "File::Spec" : "0",
+            "LWP::Protocol::https" : "0",
             "Test::Fatal" : "0",
             "Test::More" : "0",
-            "Test::Requires" : "0",
+            "Test::Needs" : "0.002005",
             "base" : "0",
             "blib" : "1.01"
          }
@@ -84,67 +84,79 @@
    "provides" : {
       "MetaCPAN::Client" : {
          "file" : "lib/MetaCPAN/Client.pm",
-         "version" : "2.004000"
+         "version" : "2.021000"
       },
       "MetaCPAN::Client::Author" : {
          "file" : "lib/MetaCPAN/Client/Author.pm",
-         "version" : "2.004000"
+         "version" : "2.021000"
       },
       "MetaCPAN::Client::Distribution" : {
          "file" : "lib/MetaCPAN/Client/Distribution.pm",
-         "version" : "2.004000"
+         "version" : "2.021000"
       },
       "MetaCPAN::Client::DownloadURL" : {
          "file" : "lib/MetaCPAN/Client/DownloadURL.pm",
-         "version" : "2.004000"
+         "version" : "2.021000"
       },
       "MetaCPAN::Client::Favorite" : {
          "file" : "lib/MetaCPAN/Client/Favorite.pm",
-         "version" : "2.004000"
+         "version" : "2.021000"
       },
       "MetaCPAN::Client::File" : {
          "file" : "lib/MetaCPAN/Client/File.pm",
-         "version" : "2.004000"
+         "version" : "2.021000"
       },
       "MetaCPAN::Client::Mirror" : {
          "file" : "lib/MetaCPAN/Client/Mirror.pm",
-         "version" : "2.004000"
+         "version" : "2.021000"
       },
       "MetaCPAN::Client::Module" : {
          "file" : "lib/MetaCPAN/Client/Module.pm",
-         "version" : "2.004000"
+         "version" : "2.021000"
+      },
+      "MetaCPAN::Client::Package" : {
+         "file" : "lib/MetaCPAN/Client/Package.pm",
+         "version" : "2.021000"
+      },
+      "MetaCPAN::Client::Permission" : {
+         "file" : "lib/MetaCPAN/Client/Permission.pm",
+         "version" : "2.021000"
       },
       "MetaCPAN::Client::Pod" : {
          "file" : "lib/MetaCPAN/Client/Pod.pm",
-         "version" : "2.004000"
+         "version" : "2.021000"
       },
       "MetaCPAN::Client::Rating" : {
          "file" : "lib/MetaCPAN/Client/Rating.pm",
-         "version" : "2.004000"
+         "version" : "2.021000"
       },
       "MetaCPAN::Client::Release" : {
          "file" : "lib/MetaCPAN/Client/Release.pm",
-         "version" : "2.004000"
+         "version" : "2.021000"
       },
       "MetaCPAN::Client::Request" : {
          "file" : "lib/MetaCPAN/Client/Request.pm",
-         "version" : "2.004000"
+         "version" : "2.021000"
       },
       "MetaCPAN::Client::ResultSet" : {
          "file" : "lib/MetaCPAN/Client/ResultSet.pm",
-         "version" : "2.004000"
+         "version" : "2.021000"
       },
       "MetaCPAN::Client::Role::Entity" : {
          "file" : "lib/MetaCPAN/Client/Role/Entity.pm",
-         "version" : "2.004000"
+         "version" : "2.021000"
+      },
+      "MetaCPAN::Client::Role::HasUA" : {
+         "file" : "lib/MetaCPAN/Client/Role/HasUA.pm",
+         "version" : "2.021000"
       },
       "MetaCPAN::Client::Scroll" : {
          "file" : "lib/MetaCPAN/Client/Scroll.pm",
-         "version" : "2.004000"
+         "version" : "2.021000"
       },
       "MetaCPAN::Client::Types" : {
          "file" : "lib/MetaCPAN/Client/Types.pm",
-         "version" : "2.004000"
+         "version" : "2.021000"
       }
    },
    "release_status" : "stable",
@@ -160,7 +172,7 @@
       "x_IRC" : "irc://irc.perl.org/#metacpan",
       "x_WebIRC" : "https://chat.mibbit.com/#metacpan@irc.perl.org"
    },
-   "version" : "2.004000",
+   "version" : "2.021000",
    "x_Dist_Zilla" : {
       "perl" : {
          "version" : "5.022001"
@@ -326,11 +338,6 @@
             "version" : "6.008"
          },
          {
-            "class" : "Dist::Zilla::Plugin::Test::Perl::Critic",
-            "name" : "Test::Perl::Critic",
-            "version" : "3.000"
-         },
-         {
             "class" : "Dist::Zilla::Plugin::Git::GatherDir",
             "config" : {
                "Dist::Zilla::Plugin::GatherDir" : {
@@ -480,6 +487,43 @@
             "version" : "6.008"
          },
          {
+            "class" : "Dist::Zilla::Plugin::Git::Tag",
+            "config" : {
+               "Dist::Zilla::Plugin::Git::Tag" : {
+                  "branch" : null,
+                  "changelog" : "Changes",
+                  "signed" : 0,
+                  "tag" : "v2.021000",
+                  "tag_format" : "v%v",
+                  "tag_message" : "v%v"
+               },
+               "Dist::Zilla::Role::Git::Repo" : {
+                  "repo_root" : "."
+               },
+               "Dist::Zilla::Role::Git::StringFormatter" : {
+                  "time_zone" : "local"
+               }
+            },
+            "name" : "Git::Tag",
+            "version" : "2.039"
+         },
+         {
+            "class" : "Dist::Zilla::Plugin::Git::Push",
+            "config" : {
+               "Dist::Zilla::Plugin::Git::Push" : {
+                  "push_to" : [
+                     "origin"
+                  ],
+                  "remotes_must_exist" : 1
+               },
+               "Dist::Zilla::Role::Git::Repo" : {
+                  "repo_root" : "."
+               }
+            },
+            "name" : "Git::Push",
+            "version" : "2.039"
+         },
+         {
             "class" : "Dist::Zilla::Plugin::FinderCode",
             "name" : ":InstallModules",
             "version" : "6.008"
diff --git a/META.yml b/META.yml
index c95c233..7d26de4 100644
--- a/META.yml
+++ b/META.yml
@@ -6,9 +6,10 @@ author:
 build_requires:
   ExtUtils::MakeMaker: '0'
   File::Spec: '0'
+  LWP::Protocol::https: '0'
   Test::Fatal: '0'
   Test::More: '0'
-  Test::Requires: '0'
+  Test::Needs: '0.002005'
   base: '0'
   blib: '1.01'
 configure_requires:
@@ -31,52 +32,61 @@ no_index:
 provides:
   MetaCPAN::Client:
     file: lib/MetaCPAN/Client.pm
-    version: '2.004000'
+    version: '2.021000'
   MetaCPAN::Client::Author:
     file: lib/MetaCPAN/Client/Author.pm
-    version: '2.004000'
+    version: '2.021000'
   MetaCPAN::Client::Distribution:
     file: lib/MetaCPAN/Client/Distribution.pm
-    version: '2.004000'
+    version: '2.021000'
   MetaCPAN::Client::DownloadURL:
     file: lib/MetaCPAN/Client/DownloadURL.pm
-    version: '2.004000'
+    version: '2.021000'
   MetaCPAN::Client::Favorite:
     file: lib/MetaCPAN/Client/Favorite.pm
-    version: '2.004000'
+    version: '2.021000'
   MetaCPAN::Client::File:
     file: lib/MetaCPAN/Client/File.pm
-    version: '2.004000'
+    version: '2.021000'
   MetaCPAN::Client::Mirror:
     file: lib/MetaCPAN/Client/Mirror.pm
-    version: '2.004000'
+    version: '2.021000'
   MetaCPAN::Client::Module:
     file: lib/MetaCPAN/Client/Module.pm
-    version: '2.004000'
+    version: '2.021000'
+  MetaCPAN::Client::Package:
+    file: lib/MetaCPAN/Client/Package.pm
+    version: '2.021000'
+  MetaCPAN::Client::Permission:
+    file: lib/MetaCPAN/Client/Permission.pm
+    version: '2.021000'
   MetaCPAN::Client::Pod:
     file: lib/MetaCPAN/Client/Pod.pm
-    version: '2.004000'
+    version: '2.021000'
   MetaCPAN::Client::Rating:
     file: lib/MetaCPAN/Client/Rating.pm
-    version: '2.004000'
+    version: '2.021000'
   MetaCPAN::Client::Release:
     file: lib/MetaCPAN/Client/Release.pm
-    version: '2.004000'
+    version: '2.021000'
   MetaCPAN::Client::Request:
     file: lib/MetaCPAN/Client/Request.pm
-    version: '2.004000'
+    version: '2.021000'
   MetaCPAN::Client::ResultSet:
     file: lib/MetaCPAN/Client/ResultSet.pm
-    version: '2.004000'
+    version: '2.021000'
   MetaCPAN::Client::Role::Entity:
     file: lib/MetaCPAN/Client/Role/Entity.pm
-    version: '2.004000'
+    version: '2.021000'
+  MetaCPAN::Client::Role::HasUA:
+    file: lib/MetaCPAN/Client/Role/HasUA.pm
+    version: '2.021000'
   MetaCPAN::Client::Scroll:
     file: lib/MetaCPAN/Client/Scroll.pm
-    version: '2.004000'
+    version: '2.021000'
   MetaCPAN::Client::Types:
     file: lib/MetaCPAN/Client/Types.pm
-    version: '2.004000'
+    version: '2.021000'
 requires:
   Carp: '0'
   HTTP::Tiny: '0.056'
@@ -98,7 +108,7 @@ resources:
   WebIRC: https://chat.mibbit.com/#metacpan@irc.perl.org
   bugtracker: https://github.com/metacpan/metacpan-client/issues
   repository: https://github.com/metacpan/metacpan-client.git
-version: '2.004000'
+version: '2.021000'
 x_Dist_Zilla:
   perl:
     version: '5.022001'
@@ -226,10 +236,6 @@ x_Dist_Zilla:
       name: PodCoverageTests
       version: '6.008'
     -
-      class: Dist::Zilla::Plugin::Test::Perl::Critic
-      name: Test::Perl::Critic
-      version: '3.000'
-    -
       class: Dist::Zilla::Plugin::Git::GatherDir
       config:
         Dist::Zilla::Plugin::GatherDir:
@@ -346,6 +352,33 @@ x_Dist_Zilla:
       name: MetaResources
       version: '6.008'
     -
+      class: Dist::Zilla::Plugin::Git::Tag
+      config:
+        Dist::Zilla::Plugin::Git::Tag:
+          branch: ~
+          changelog: Changes
+          signed: 0
+          tag: v2.021000
+          tag_format: v%v
+          tag_message: v%v
+        Dist::Zilla::Role::Git::Repo:
+          repo_root: .
+        Dist::Zilla::Role::Git::StringFormatter:
+          time_zone: local
+      name: Git::Tag
+      version: '2.039'
+    -
+      class: Dist::Zilla::Plugin::Git::Push
+      config:
+        Dist::Zilla::Plugin::Git::Push:
+          push_to:
+            - origin
+          remotes_must_exist: 1
+        Dist::Zilla::Role::Git::Repo:
+          repo_root: .
+      name: Git::Push
+      version: '2.039'
+    -
       class: Dist::Zilla::Plugin::FinderCode
       name: ':InstallModules'
       version: '6.008'
diff --git a/Makefile.PL b/Makefile.PL
index 3494a42..9ae0f5d 100644
--- a/Makefile.PL
+++ b/Makefile.PL
@@ -35,13 +35,14 @@ my %WriteMakefileArgs = (
   "TEST_REQUIRES" => {
     "ExtUtils::MakeMaker" => 0,
     "File::Spec" => 0,
+    "LWP::Protocol::https" => 0,
     "Test::Fatal" => 0,
     "Test::More" => 0,
-    "Test::Requires" => 0,
+    "Test::Needs" => "0.002005",
     "base" => 0,
     "blib" => "1.01"
   },
-  "VERSION" => "2.004000",
+  "VERSION" => "2.021000",
   "test" => {
     "TESTS" => "t/*.t t/api/*.t"
   }
@@ -56,6 +57,7 @@ my %FallbackPrereqs = (
   "IO::Socket::SSL" => "1.42",
   "JSON::MaybeXS" => 0,
   "JSON::PP" => 0,
+  "LWP::Protocol::https" => 0,
   "Moo" => 0,
   "Moo::Role" => 0,
   "Net::SSLeay" => "1.49",
@@ -63,7 +65,7 @@ my %FallbackPrereqs = (
   "Safe::Isa" => 0,
   "Test::Fatal" => 0,
   "Test::More" => 0,
-  "Test::Requires" => 0,
+  "Test::Needs" => "0.002005",
   "Type::Tiny" => 0,
   "URI::Escape" => 0,
   "base" => 0,
diff --git a/README b/README
index a90dcef..ad09ea1 100644
--- a/README
+++ b/README
@@ -5,7 +5,7 @@ NAME
 
 VERSION
 
-    version 2.004000
+    version 2.021000
 
 SYNOPSIS
 
@@ -59,6 +59,10 @@ ATTRIBUTES
 
     If given, will be used to alter the API domain.
 
+ debug
+
+    If given, errors will include some low-level detailed message.
+
 METHODS
 
  author
@@ -70,8 +74,8 @@ METHODS
     hash reference. Since it is common to many other searches, it is
     explained below under SEARCH SPEC.
 
-    Return a MetaCPAN::Client::Author object on a simple search (PAUSE ID),
-    or a MetaCPAN::Client::ResultSet object propagated with
+    Returns a MetaCPAN::Client::Author object on a simple search (PAUSE
+    ID), or a MetaCPAN::Client::ResultSet object propagated with
     MetaCPAN::Client::Author objects on a complex (search spec based)
     search.
 
@@ -84,7 +88,7 @@ METHODS
     a hash reference. Since it is common to many other searches, it is
     explained below under SEARCH SPEC.
 
-    Return a MetaCPAN::Client::Module object on a simple search (module
+    Returns a MetaCPAN::Client::Module object on a simple search (module
     name), or a MetaCPAN::Client::ResultSet object propagated with
     MetaCPAN::Client::Module objects on a complex (search spec based)
     search.
@@ -98,26 +102,28 @@ METHODS
     spec defined by a hash reference. Since it is common to many other
     searches, it is explained below under SEARCH SPEC.
 
-    Return a MetaCPAN::Client::Distribution object on a simple search
+    Returns a MetaCPAN::Client::Distribution object on a simple search
     (distribution name), or a MetaCPAN::Client::ResultSet object propagated
     with MetaCPAN::Client::Distribution objects on a complex (search spec
     based) search.
 
  file
 
-    Return a MetaCPAN::Client::File object.
+    Returns a MetaCPAN::Client::File object.
 
  favorite
 
         my $favorite = $mcpan->favorite({ distribution => 'Moose' });
 
-    Return a MetaCPAN::Client::Favorite object.
+    Returns a MetaCPAN::Client::ResultSet object containing
+    MetaCPAN::Client::Favorite results.
 
  rating
 
         my $rating = $mcpan->rating({ distribution => 'Moose' });
 
-    Return a MetaCPAN::Client::Rating object.
+    Returns a MetaCPAN::Client::ResultSet object containing
+    MetaCPAN::Client::Rating results.
 
  release
 
@@ -128,7 +134,7 @@ METHODS
     defined by a hash reference. Since it is common to many other searches,
     it is explained below under SEARCH SPEC.
 
-    Return a MetaCPAN::Client::Release object on a simple search (release
+    Returns a MetaCPAN::Client::Release object on a simple search (release
     name), or a MetaCPAN::Client::ResultSet object propagated with
     MetaCPAN::Client::Release objects on a complex (search spec based)
     search.
@@ -139,12 +145,24 @@ METHODS
 
     Returns a MetaCPAN::Client::Mirror object.
 
+ package
+
+        my $package = $mcpan->package('MooseX::Types');
+
+    Returns a MetaCPAN::Client::Package object.
+
+ permission
+
+        my $permission = $mcpan->permission('MooseX::Types');
+
+    Returns a MetaCPAN::Client::Permission object.
+
  reverse_dependencies
 
-        my $deps = $mcpan->reverse_dependencies('ElasticSearch');
+        my $deps = $mcpan->reverse_dependencies('Search::Elasticsearch');
 
-    all MetaCPAN::Client::Release objects of releases that are dependent on
-    a given module, returned as MetaCPAN::Client::ResultSet.
+    all MetaCPAN::Client::Release objects of releases that are directly
+    dependent on a given module, returned as MetaCPAN::Client::ResultSet.
 
  rev_deps
 
@@ -158,6 +176,14 @@ METHODS
 
     Returns an array reference.
 
+ autocomplete_suggest
+
+        my $ac = $mcpan->autocomplete_suggest('Moo');
+
+    Call the search/autocomplete/suggest endpoint with a query string.
+
+    Returns an array reference.
+
  recent
 
         my $recent = $mcpan->recent(10);
@@ -200,9 +226,15 @@ METHODS
 
        my $all_releases = $mcpan->all('releases', { fields => [...] })
 
+  _source
+
+    See SEARCH PARAMS.
+
+       my $all_releases = $mcpan->all('releases', { _source => [...] })
+
   es_filter
 
-    Pass a raw ElasticSearch filter structure to reduce the number of
+    Pass a raw Elasticsearch filter structure to reduce the number of
     elements returned by the query.
 
         my $some_releases = $mcpan->all('releases', { es_filter => {...} })
@@ -227,10 +259,61 @@ SEARCH PARAMS
         my $module = $mcpan->module('Moose', { fields => "version,author" });
         my $module = $mcpan->module('Moose', { fields => [qw/version author/] });
 
+ _source
+
+    Note: this param and its description are a bit too Elasticsearch
+    specific. just like 'es_filter' - use only if you know what you're
+    dealing with.
+
+    Some fields are not indexed in Elasticsearch but stored as part of the
+    entire document.
+
+    These fields can still be read, but without the internal Elasticsearch
+    optimizations and the server will interally read the whole document.
+
+    Why do we even need those? because we don't index everything and some
+    things we can't to begin with (like non-leaf fields that hold a
+    structure)
+
+        my $module = $mcpan->all('releases', { _source => "stat" });
+
+ scroller_time
+
+    Note: please use with caution.
+
+    This parameter will set the maximum lifetime of the Elasticsearch
+    scroller on the server (default = '5m'). Normally you do not need to
+    set this value (as tweaking this value can affect resources on the
+    server). In case you do, you probably need to check the efficiency of
+    your code/queries. (Feel free to reach out to us for assistance).
+
+        my $module = $mcpan->all('releases', { scroller_time => '3m' });
+
+ scroller_size
+
+    Note: please use with caution.
+
+    This parameter will set the buffer size to be pulled from Elasticsearch
+    when scrolling (default = 1000). This will affect query performance and
+    memory usage, but you will still get an iterator back to fetch one
+    object at a time.
+
+        my $module = $mcpan->all('releases', { scroller_size => 500 });
+
+  sort
+
+    Pass a raw Elasticsearch sort specification for the query.
+
+        my $some_releases = $mcpan->all('releases', { sort => [{ date => { order => 'desc' } }] })
+
+    Note: this param and is a bit too specific to Elasticsearch. Just like
+    "es_filter", only use this if you know what you're dealing with.
+
 SEARCH SPEC
 
     The hash-based search spec is common to many searches. It is quite
-    feature-rich and allows to disambiguate different types of searches.
+    feature-rich and allows you to disambiguate different types of
+    searches.
 
     Basic search specs just contain a hash of keys and values:
 
diff --git a/cpanfile b/cpanfile
index ca7dc99..863ff7b 100644
--- a/cpanfile
+++ b/cpanfile
@@ -17,16 +17,16 @@ requires "warnings" => "0";
 on 'test' => sub {
   requires "Test::Fatal" => "0";
   requires "Test::More" => "0";
-  requires "Test::Requires" => "0";
+  requires "Test::Needs" => "0.002005";
   requires "base" => "0";
   requires "blib" => "1.01";
-  recommends "HTTP::Tiny::Mech" => "0";
-  recommends "LWP::Protocol::https" => "0";
-  recommends "WWW::Mechanize::Cached" => "1.48";
+  requires "LWP::Protocol::https" => "0";
+  recommends "HTTP::Tiny::Mech" => "1.001002";
+  recommends "WWW::Mechanize::Cached" => "1.50";
 };
 
 on 'develop' => sub {
-  requires "HTTP::Tiny::Mech" => "0";
+  requires "HTTP::Tiny::Mech" => "1.001002";
   requires "LWP::Protocol::https" => "0";
-  requires "WWW::Mechanize::Cached" => "1.48";
+  requires "WWW::Mechanize::Cached" => "1.50";
 };
diff --git a/dist.ini b/dist.ini
index 4392fa8..67327a2 100644
--- a/dist.ini
+++ b/dist.ini
@@ -5,14 +5,13 @@ license = Perl_5
 copyright_holder = Sawyer X
 copyright_year   = 2016
 
-version = 2.004000
+version = 2.021000
 
 [@Starter]
 -remove = GatherDir
 MakeMaker.eumm_version = 7.1101
 
 [PodCoverageTests]
-[Test::Perl::Critic]
 
 [Git::GatherDir]
 
@@ -35,3 +34,6 @@ repository.web  = https://github.com/metacpan/metacpan-client
 repository.type = git
 x_IRC           = irc://irc.perl.org/#metacpan
 x_WebIRC        = https://chat.mibbit.com/#metacpan@irc.perl.org
+
+[Git::Tag]
+[Git::Push]
diff --git a/examples/autocomplete_suggest.pl b/examples/autocomplete_suggest.pl
new file mode 100644
index 0000000..0d3d40a
--- /dev/null
+++ b/examples/autocomplete_suggest.pl
@@ -0,0 +1,13 @@
+
+# examples/autocomplete.pl
+
+use strict;
+use warnings;
+use Data::Printer;
+use MetaCPAN::Client;
+
+my $mcpan = MetaCPAN::Client->new();
+
+my $ac = $mcpan->autocomplete_suggest("Moos");
+
+p $ac;
diff --git a/examples/changes.pl b/examples/changes.pl
new file mode 100644
index 0000000..7d3d462
--- /dev/null
+++ b/examples/changes.pl
@@ -0,0 +1,9 @@
+use strict;
+use warnings;
+use MetaCPAN::Client;
+
+my $dist = shift || 'Moose';
+
+my $mcpan = MetaCPAN::Client->new();
+my $rel   = $mcpan->release($dist);
+print $rel->changes;
diff --git a/examples/contributors.pl b/examples/contributors.pl
new file mode 100644
index 0000000..01b3920
--- /dev/null
+++ b/examples/contributors.pl
@@ -0,0 +1,19 @@
+use strict;
+use warnings;
+use MetaCPAN::Client;
+use Data::Printer;
+
+my $mcpan = MetaCPAN::Client->new();
+
+my $release = $mcpan->release({
+    all => [
+        { distribution => 'Moose' },
+        { version => '2.2005' },
+    ]
+})->next;
+
+my $contributors = $release->contributors;
+
+p $contributors;
+
+1;
diff --git a/examples/metacpan_url.pl b/examples/metacpan_url.pl
new file mode 100644
index 0000000..42349f3
--- /dev/null
+++ b/examples/metacpan_url.pl
@@ -0,0 +1,24 @@
+use strict;
+use warnings;
+use MetaCPAN::Client;
+
+my $mcpan = MetaCPAN::Client->new();
+
+my $auth = $mcpan->author('HAARG');
+my $mod  = $mcpan->module('Moo');
+my $file = $mcpan->file('HAARG/Moo-2.003001/lib/Moo.pm');
+my $dist = $mcpan->distribution('Moo');
+my $rel  = $mcpan->release({
+    all => [
+        { distribution => 'Moo' },
+        { version => '2.002005' },
+    ]
+});
+
+printf "AUTHOR       : %s\n", $auth->metacpan_url;
+printf "RELEASE      : %s\n", $rel->next->metacpan_url;
+printf "MODULE       : %s\n", $mod->metacpan_url;
+printf "FILE         : %s\n", $file->metacpan_url;
+printf "DISTRIBUTION : %s\n", $dist->metacpan_url;
+
+1;
diff --git a/examples/package.pl b/examples/package.pl
new file mode 100644
index 0000000..4db2d1a
--- /dev/null
+++ b/examples/package.pl
@@ -0,0 +1,18 @@
+# examples/package.pl
+
+use strict;
+use warnings;
+use Data::Printer;
+use MetaCPAN::Client;
+
+my $mcpan = MetaCPAN::Client->new();
+my $pack  = $mcpan->package('MooseX::Types');
+p $pack;
+
+1;
+__END__
+
+Alternatively:
+
+my $module = $mcpan->module('MooseX::Types');
+my $pack   = $module->package;
diff --git a/examples/permission.pl b/examples/permission.pl
new file mode 100644
index 0000000..8199f06
--- /dev/null
+++ b/examples/permission.pl
@@ -0,0 +1,18 @@
+# examples/permission.pl
+
+use strict;
+use warnings;
+use Data::Printer;
+use MetaCPAN::Client;
+
+my $mcpan = MetaCPAN::Client->new();
+my $perm  = $mcpan->permission('MooseX::Types');
+p $perm;
+
+1;
+__END__
+
+Alternatively:
+
+my $module = $mcpan->module('MooseX::Types');
+my $perm   = $module->permission;
diff --git a/lib/MetaCPAN/Client.pm b/lib/MetaCPAN/Client.pm
index ead0c23..f0fbd16 100644
--- a/lib/MetaCPAN/Client.pm
+++ b/lib/MetaCPAN/Client.pm
@@ -2,7 +2,7 @@ use strict;
 use warnings;
 package MetaCPAN::Client;
 # ABSTRACT: A comprehensive, DWIM-featured client to the MetaCPAN API
-$MetaCPAN::Client::VERSION = '2.004000';
+$MetaCPAN::Client::VERSION = '2.021000';
 use Moo;
 use Carp;
 use Ref::Util qw< is_arrayref is_hashref >;
@@ -19,6 +19,8 @@ use MetaCPAN::Client::Pod;
 use MetaCPAN::Client::Rating;
 use MetaCPAN::Client::Release;
 use MetaCPAN::Client::Mirror;
+use MetaCPAN::Client::Package;
+use MetaCPAN::Client::Permission;
 use MetaCPAN::Client::ResultSet;
 
 has request => (
@@ -27,15 +29,16 @@ has request => (
 );
 
 my @supported_searches = qw<
-    author distribution favorite module rating release mirror file
+    author distribution favorite module rating release mirror file permission package
 >;
 
 sub BUILDARGS {
     my ( $class, %args ) = @_;
 
     $args{'request'} ||= MetaCPAN::Client::Request->new(
-        ( ua      => $args{ua}      )x!! $args{ua},
-        ( domain  => $args{domain}  )x!! $args{domain},
+        ( ua     => $args{ua}     )x!! $args{ua},
+        ( domain => $args{domain} )x!! $args{domain},
+        ( debug  => $args{debug}  )x!! $args{debug},
     );
 
     return \%args;
@@ -73,6 +76,22 @@ sub file {
     return $self->_get_or_search( 'file', $arg, $params );
 }
 
+sub package {
+    my $self   = shift;
+    my $arg    = shift;
+    my $params = shift;
+
+    return $self->_get_or_search( 'package', $arg, $params );
+}
+
+sub permission {
+    my $self   = shift;
+    my $arg    = shift;
+    my $params = shift;
+
+    return $self->_get_or_search( 'permission', $arg, $params );
+}
+
 sub pod {
     my $self   = shift;
     my $name   = shift;
@@ -155,14 +174,19 @@ sub all {
     my $type   = shift;
     my $params = shift;
 
-    grep { $type eq $_ } qw/ authors distributions modules releases
-                             favorites ratings mirrors files /
-        or croak "all: unsupported type";
+    # This endpoint used to support only pluralized types (mostly) and convert
+    # to singular types before redispatching.  Now it accepts both plural and
+    # unplural forms directly and relies on the underlying methods it
+    # dispatches to to check types (using the global supported types array).
     $type =~ s/s$//;
 
     $params and !is_hashref($params)
         and croak "all: params must be a hashref";
 
+    if ( $params->{fields} and !is_arrayref($params->{fields}) ) {
+        $params->{fields} = [ split /,/ => $params->{fields} ];
+    }
+
     return $self->$type( { __MATCH_ALL__ => 1 }, $params );
 }
 
@@ -193,6 +217,24 @@ sub autocomplete {
     ];
 }
 
+sub autocomplete_suggest {
+    my $self = shift;
+    my $q    = shift;
+
+    my $res;
+
+    eval {
+        $res = $self->fetch( '/search/autocomplete/suggest?q=' . uri_escape_utf8($q) );
+        1;
+
+    } or do {
+        warn $@;
+        return [];
+    };
+
+    return $res->{suggestions};
+}
+
 ###
 
 sub _get {
@@ -290,7 +332,7 @@ sub _reverse_deps {
 
     eval {
         $res = $self->fetch(
-            '/search/reverse_dependencies/'.$dist,
+            "/reverse_dependencies/dist/$dist",
             {
                 size   => 5000,
                 query  => { match_all => {} },
@@ -310,7 +352,7 @@ sub _reverse_deps {
     };
 
     return MetaCPAN::Client::ResultSet->new(
-        items => $res->{'hits'}{'hits'},
+        items => $res->{'data'},
         type  => 'release',
     );
 }
@@ -371,7 +413,7 @@ MetaCPAN::Client - A comprehensive, DWIM-featured client to the MetaCPAN API
 
 =head1 VERSION
 
-version 2.004000
+version 2.021000
 
 =head1 SYNOPSIS
 
@@ -424,6 +466,10 @@ L<MetaCPAN::Client::Request>.
 
 If given, will be used to alter the API domain.
 
+=head2 debug
+
+If given, errors will include some low-level detailed message.
+
 =head1 METHODS
 
 =head2 author
@@ -435,7 +481,7 @@ Finds an author by either its PAUSE ID or by a search spec defined by a hash
 reference. Since it is common to many other searches, it is explained below
 under C<SEARCH SPEC>.
 
-Return a L<MetaCPAN::Client::Author> object on a simple search (PAUSE ID), or
+Returns a L<MetaCPAN::Client::Author> object on a simple search (PAUSE ID), or
 a L<MetaCPAN::Client::ResultSet> object propagated with
 L<MetaCPAN::Client::Author> objects on a complex (L<search spec based|/"SEARCH SPEC">) search.
 
@@ -448,7 +494,7 @@ Finds a module by either its module name or by a search spec defined by a hash
 reference. Since it is common to many other searches, it is explained below
 under C<SEARCH SPEC>.
 
-Return a L<MetaCPAN::Client::Module> object on a simple search (module name), or
+Returns a L<MetaCPAN::Client::Module> object on a simple search (module name), or
 a L<MetaCPAN::Client::ResultSet> object propagated with
 L<MetaCPAN::Client::Module> objects on a complex (L<search spec based|/"SEARCH SPEC">) search.
 
@@ -461,26 +507,28 @@ Finds a distribution by either its distribution name or by a search spec
 defined by a hash reference. Since it is common to many other searches, it is
 explained below under C<SEARCH SPEC>.
 
-Return a L<MetaCPAN::Client::Distribution> object on a simple search
+Returns a L<MetaCPAN::Client::Distribution> object on a simple search
 (distribution name), or a L<MetaCPAN::Client::ResultSet> object propagated with
 L<MetaCPAN::Client::Distribution> objects on a complex (L<search spec based|/"SEARCH SPEC">)
 search.
 
 =head2 file
 
-Return a L<MetaCPAN::Client::File> object.
+Returns a L<MetaCPAN::Client::File> object.
 
 =head2 favorite
 
     my $favorite = $mcpan->favorite({ distribution => 'Moose' });
 
-Return a L<MetaCPAN::Client::Favorite> object.
+Returns a L<MetaCPAN::Client::ResultSet> object containing
+L<MetaCPAN::Client::Favorite> results.
 
 =head2 rating
 
     my $rating = $mcpan->rating({ distribution => 'Moose' });
 
-Return a L<MetaCPAN::Client::Rating> object.
+Returns a L<MetaCPAN::Client::ResultSet> object containing
+L<MetaCPAN::Client::Rating> results.
 
 =head2 release
 
@@ -491,7 +539,7 @@ Finds a release by either its distribution name or by a search spec defined by
 a hash reference. Since it is common to many other searches, it is explained
 below under C<SEARCH SPEC>.
 
-Return a L<MetaCPAN::Client::Release> object on a simple search (release name),
+Returns a L<MetaCPAN::Client::Release> object on a simple search (release name),
 or a L<MetaCPAN::Client::ResultSet> object propagated with
 L<MetaCPAN::Client::Release> objects on a complex (L<search spec based|/"SEARCH SPEC">) search.
 
@@ -501,12 +549,24 @@ L<MetaCPAN::Client::Release> objects on a complex (L<search spec based|/"SEARCH
 
 Returns a L<MetaCPAN::Client::Mirror> object.
 
+=head2 package
+
+    my $package = $mcpan->package('MooseX::Types');
+
+Returns a L<MetaCPAN::Client::Package> object.
+
+=head2 permission
+
+    my $permission = $mcpan->permission('MooseX::Types');
+
+Returns a L<MetaCPAN::Client::Permission> object.
+
 =head2 reverse_dependencies
 
-    my $deps = $mcpan->reverse_dependencies('ElasticSearch');
+    my $deps = $mcpan->reverse_dependencies('Search::Elasticsearch');
 
-all L<MetaCPAN::Client::Release> objects of releases that are dependent
-on a given module, returned as L<MetaCPAN::Client::ResultSet>.
+all L<MetaCPAN::Client::Release> objects of releases that are directly
+dependent on a given module, returned as L<MetaCPAN::Client::ResultSet>.
 
 =head2 rev_deps
 
@@ -520,6 +580,14 @@ Call the search/autocomplete endpoint with a query string.
 
 Returns an array reference.
 
+=head2 autocomplete_suggest
+
+    my $ac = $mcpan->autocomplete_suggest('Moo');
+
+Call the search/autocomplete/suggest endpoint with a query string.
+
+Returns an array reference.
+
 =head2 recent
 
     my $recent = $mcpan->recent(10);
@@ -561,9 +629,15 @@ See SEARCH PARAMS.
 
    my $all_releases = $mcpan->all('releases', { fields => [...] })
 
+=head3 _source
+
+See SEARCH PARAMS.
+
+   my $all_releases = $mcpan->all('releases', { _source => [...] })
+
 =head3 es_filter
 
-Pass a raw ElasticSearch filter structure to reduce the number
+Pass a raw Elasticsearch filter structure to reduce the number
 of elements returned by the query.
 
     my $some_releases = $mcpan->all('releases', { es_filter => {...} })
@@ -588,10 +662,58 @@ can be passed as a csv list or an array ref.
     my $module = $mcpan->module('Moose', { fields => "version,author" });
     my $module = $mcpan->module('Moose', { fields => [qw/version author/] });
 
+=head2 _source
+
+Note: this param and its description are a bit too Elasticsearch specific.
+just like 'es_filter' - use only if you know what you're dealing with.
+
+Some fields are not indexed in Elasticsearch but stored as part of
+the entire document.
+
+These fields can still be read, but without the internal Elasticsearch
+optimizations and the server will interally read the whole document.
+
+Why do we even need those? because we don't index everything and some things
+we can't to begin with (like non-leaf fields that hold a structure)
+
+    my $module = $mcpan->all('releases', { _source => "stat" });
+
+=head2 scroller_time
+
+Note: please use with caution.
+
+This parameter will set the maximum lifetime of the Elasticsearch scroller on
+the server (default = '5m').  Normally you do not need to set this value (as
+tweaking this value can affect resources on the server).  In case you do, you
+probably need to check the efficiency of your code/queries.  (Feel free to
+reach out to us for assistance).
+
+    my $module = $mcpan->all('releases', { scroller_time => '3m' });
+
+=head2 scroller_size
+
+Note: please use with caution.
+
+This parameter will set the buffer size to be pulled from Elasticsearch
+when scrolling (default = 1000).
+This will affect query performance and memory usage, but you will still
+get an iterator back to fetch one object at a time.
+
+    my $module = $mcpan->all('releases', { scroller_size => 500 });
+
+=head3 sort
+
+Pass a raw Elasticsearch sort specification for the query.
+
+    my $some_releases = $mcpan->all('releases', { sort => [{ date => { order => 'desc' } }] })
+
+Note: this param and is a bit too specific to Elasticsearch.  Just like
+L</es_filter>, only use this if you know what you're dealing with.
+
 =head1 SEARCH SPEC
 
 The hash-based search spec is common to many searches. It is quite
-feature-rich and allows to disambiguate different types of searches.
+feature-rich and allows you to disambiguate different types of searches.
 
 Basic search specs just contain a hash of keys and values:
 
diff --git a/lib/MetaCPAN/Client/Author.pm b/lib/MetaCPAN/Client/Author.pm
index 154389f..01b7b30 100644
--- a/lib/MetaCPAN/Client/Author.pm
+++ b/lib/MetaCPAN/Client/Author.pm
@@ -2,8 +2,9 @@ use strict;
 use warnings;
 package MetaCPAN::Client::Author;
 # ABSTRACT: An Author data object
-$MetaCPAN::Client::Author::VERSION = '2.004000';
+$MetaCPAN::Client::Author::VERSION = '2.021000';
 use Moo;
+use Ref::Util qw< is_arrayref >;
 
 with 'MetaCPAN::Client::Role::Entity';
 
@@ -11,9 +12,9 @@ my %known_fields = (
     scalar => [qw<
         city
         country
-        dir
         gravatar_url
         name
+        ascii_name
         pauseid
         region
         updated
@@ -23,6 +24,7 @@ my %known_fields = (
     arrayref => [qw<
         donation
         email
+        perlmongers
         profile
         website
     >],
@@ -35,6 +37,16 @@ my %known_fields = (
     >],
 );
 
+sub BUILDARGS {
+    my ( $class, %args ) = @_;
+
+    my $email = $args{'email'} || [];
+    $args{'email'} = [ $email ]
+        unless is_arrayref($email);
+
+    return \%args;
+}
+
 my @known_fields =
     map { @{ $known_fields{$_} } } qw< scalar arrayref hashref >;
 
@@ -63,6 +75,10 @@ sub releases {
         });
 }
 
+sub dir { $_[0]->links->{cpan_directory} }
+
+sub metacpan_url { "https://metacpan.org/author/" . $_[0]->pauseid }
+
 1;
 
 __END__
@@ -77,11 +93,11 @@ MetaCPAN::Client::Author - An Author data object
 
 =head1 VERSION
 
-version 2.004000
+version 2.021000
 
 =head1 SYNOPSIS
 
-my $author = $mcpan->author('MICKEY');
+    my $author = $mcpan->author('MICKEY');
 
 =head1 DESCRIPTION
 
@@ -91,90 +107,187 @@ a MetaCPAN author entity object.
 
 =head2 pauseid
 
+The author's pause id, which is a string like C<MICKEY> or C<XSAWYERX>.
+
 =head2 name
 
+The author's full name, if they've provided this in their MetaCPAN
+profile. This may contain Unicode characters.
+
+=head2 ascii_name
+
+An ASCII-only version of the author's full name, if they've provided this in
+their MetaCPAN profile.
+
 =head2 city
 
-=head2 country
+The author's city, if they've provided this in their MetaCPAN profile.
 
 =head2 region
 
+The author's region, if they've provided this in their MetaCPAN profile.
+
+=head2 country
+
+The author's country, if they've provided this in their MetaCPAN profile.
+
 =head2 updated
 
-=head2 dir
+An ISO8601 datetime string like C<2016-11-19T12:41:46> indicating when the
+author last updated their MetaCPAN profile. This is always provided in UTC.
 
-Directory of distribution and files.
+=head2 dir
 
-e.g. C<< id/P/PE/PERLER >>
+The author's CPAN directory, which is something like C<id/P/PE/PERLER>.
 
 =head2 gravatar_url
 
-Gravatar.com user picture URL.
-
-This URL is generated using PAUSEID at cpan.org.
+The author's gravatar.com user URL, if they have one. This URL is generated
+using PAUSEID at cpan.org.
 
 =head2 user
 
-Identification code.
+The user's internal MetaCPAN id.
 
 =head2 donation
 
-Array-Ref.
+This is an arrayref containing zero or more hashrefs. Each hashref contains
+two keys, C<name> and C<id>. The known names are currently C<paypal>,
+C<wishlist>, and C<flattr>. The id will be an appropriate id or URL for the
+thing in question.
+
+This may be empty if the author has not provided this information in their
+MetaCPAN profile.
+
+For example:
+
+    [
+        { "name" => "paypal",   "id" => "brian.d.foy at gmail.com" },
+        { "name" => "wishlist", "id" => "http://amzn.com/w/4O7IX9ZNQJR" },
+    ],
 
 =head2 email
 
-Array-Ref.
+This is an arrayref containing zero or more email addresses that the author
+has added to their MetaCPAN profile. Note that this does I<not> include the
+C<AUTHOR at cpan.org> email address that all CPAN authors have.
 
 =head2 website
 
-Array-Ref.
+This is an arrayref of website URLs provided by the author in their MetaCPAN
+profile.
 
 =head2 profile
 
-Array-Ref.
+This is an arrayref containing zero or more hashrefs. Each hashref contains
+two keys, C<name> and C<id>. The names are things like C<github> or
+C<stackoverflow>. The id will be an appropriate id for the site in question.
+
+For example:
 
-e.g.
     [
         { name => "amazon",        id => "B002MRC39U"  },
         { name => "stackoverflow", id => "brian-d-foy" },
     ]
 
+This may be empty if the author has not provided this information in their
+MetaCPAN profile.
+
+=head2 perlmongers
+
+This is an arrayref containing zero or more hashrefs. Each hashref contains
+two keys, C<name> and C<url>. The names are things like C<Minneapolis.pm>.
+
+This may be empty if the author has not provided this information in their
+MetaCPAN profile.
+
 =head2 links
 
-Hash-Ref.
+This is a hashref where the keys are a link type, and the values are URLs. The
+currently known keys are:
 
-=head2 extra
+=over 4
 
-Hash-Ref.
+=item * cpan_directory
+
+The author's CPAN directory.
+
+=item * backpan_directory
+
+The author's BackCPAN directory.
+
+=item * cpantesters_reports
+
+The author's CPAN Testers Reports page.
+
+=item * cpantesters_matrix
+
+The author's CPAN Testers matrix page.
+
+=item * cpants
+
+The author's CPANTS page.
+
+=item * metacpan_explorer
+
+A link to the MetaCPAN explorer site pre-populated with a request for the
+author's profile.
+
+=back
 
 =head2 blog
 
-Hash-Ref.
+This is an arrayref containing zer or more hashrefs. Each hashref contains two
+keys, C<url> and C<feed>. For example:
 
-  {
-    url  => "http://blogs.perl.org/users/brian_d_foy/"
-    feed => "http://blogs.perl.org/users/brian_d_foy/atom.xml",
-  }
+    {
+        url  => "http://blogs.perl.org/users/brian_d_foy/",
+        feed => "http://blogs.perl.org/users/brian_d_foy/atom.xml",
+    }
 
 =head2 release_count
 
-Hash-Ref.
+This is a hashref containing counts for various types of releases. The known
+keys are:
+
+=over 4
 
-e.g.
-   {
-      latest       => 118,
-      backpan-only => 558,
-      cpan         => 18,
-   }
+=item * cpan
+
+The total number of distribution uplaods the author currently has on CPAN.
+
+=item * latest
+
+The total number of unique distributions the author currently has on CPAN.
+
+=item * backpan-only
+
+The number of distribution uploads currently only available via BackPAN.
+
+=back
+
+=head2 extra
+
+Returns a hashref. The contents of this are entirely arbitrary and will vary
+by author.
 
 =head1 METHODS
 
+=head2 BUILDARGS
+
+Ensures format of the input.
+
 =head2 releases
 
     my $releases = $author->releases();
 
-Search all releases of current author's object.
-will return a ResultSet of MetaCPAN::Client::Release objects.
+This method returns a L<MetaCPAN::Client::ResultSet> of
+L<MetaCPAN::Client::Release> objects. It includes all of the author's releases
+with the C<latest> status.
+
+=head2 metacpan_url
+
+Returns a link to the author's page on MetaCPAN.
 
 =head1 AUTHORS
 
diff --git a/lib/MetaCPAN/Client/Distribution.pm b/lib/MetaCPAN/Client/Distribution.pm
index 1077642..9477765 100644
--- a/lib/MetaCPAN/Client/Distribution.pm
+++ b/lib/MetaCPAN/Client/Distribution.pm
@@ -2,7 +2,7 @@ use strict;
 use warnings;
 package MetaCPAN::Client::Distribution;
 # ABSTRACT: A Distribution data object
-$MetaCPAN::Client::Distribution::VERSION = '2.004000';
+$MetaCPAN::Client::Distribution::VERSION = '2.021000';
 use Moo;
 
 with 'MetaCPAN::Client::Role::Entity';
@@ -42,6 +42,8 @@ sub _known_fields { return \%known_fields }
 sub rt     { $_[0]->bugs->{rt}     || {} }
 sub github { $_[0]->bugs->{github} || {} }
 
+sub metacpan_url { "https://metacpan.org/release/" . $_[0]->name }
+
 1;
 
 __END__
@@ -56,11 +58,11 @@ MetaCPAN::Client::Distribution - A Distribution data object
 
 =head1 VERSION
 
-version 2.004000
+version 2.021000
 
 =head1 SYNOPSIS
 
-my $dist = $mcpan->distribution('MetaCPAN-Client');
+    my $dist = $mcpan->distribution('MetaCPAN-Client');
 
 =head1 DESCRIPTION
 
@@ -70,23 +72,55 @@ A MetaCPAN distribution entity object.
 
 =head2 name
 
+The distribution's name.
+
 =head2 bugs
 
-Hash-Ref.
+A hashref containing information about bugs reported in various issue
+trackers. The top-level keys are issue tracker names like C<rt> or
+C<github>. Each value is itself a hashref containing information about the
+bugs in that tracker. The keys vary between trackers, but this will always
+contain a C<source> key, which is a URL for the tracker. There may also be
+keys containing counts such as C<active>, C<closed>, etc.
 
 =head2 river
 
-Hash-Ref.
+A hashref containing L<"CPAN
+River"|http://neilb.org/2015/04/20/river-of-cpan.html> information about the
+distro. The hashref contains the following keys:
+
+=over 4
+
+=item * bucket
+
+A positive or zero integer. The higher the number the farther upstream this
+distribution is.
+
+=item * immediate
+
+The number of distributions that directly depend on this one.
+
+=item * total
+
+The number of distributions that depend on this one, directly or indirectly.
+
+=back
 
 =head1 METHODS
 
 =head2 rt
 
-Returns 'bugs.rt' hash ref (defaults to {}).
+Returns the hashref of data for the rt bug tracker. This defaults to an empty
+hashref.
 
 =head2 github
 
-Returns 'bugs.github' hash ref (defaults to {}).
+Returns the hashref of data for the github bug tracker. This defaults to an
+empty hashref.
+
+=head2 metacpan_url
+
+Returns a link to the distribution page on MetaCPAN.
 
 =head1 AUTHORS
 
diff --git a/lib/MetaCPAN/Client/DownloadURL.pm b/lib/MetaCPAN/Client/DownloadURL.pm
index 5b2e1fe..163197d 100644
--- a/lib/MetaCPAN/Client/DownloadURL.pm
+++ b/lib/MetaCPAN/Client/DownloadURL.pm
@@ -2,7 +2,7 @@ use strict;
 use warnings;
 package MetaCPAN::Client::DownloadURL;
 # ABSTRACT: A Download URL data object
-$MetaCPAN::Client::DownloadURL::VERSION = '2.004000';
+$MetaCPAN::Client::DownloadURL::VERSION = '2.021000';
 use Moo;
 
 with 'MetaCPAN::Client::Role::Entity';
@@ -43,26 +43,34 @@ MetaCPAN::Client::DownloadURL - A Download URL data object
 
 =head1 VERSION
 
-version 2.004000
+version 2.021000
 
 =head1 SYNOPSIS
 
-my $download_url = $mcpan->download_url('Moose');
+    my $download_url = $mcpan->download_url('Moose');
 
 =head1 DESCRIPTION
 
-A MetaCPAN download_url entiry object.
+A MetaCPAN download_url entity object.
 
 =head1 ATTRIBUTES
 
 =head2 date
 
+Returns the date of the release that this URL refers to.
+
 =head2 download_url
 
+The actual download URL.
+
 =head2 status
 
+The release status, which is something like C<latest> or C<cpan>
+
 =head2 version
 
+The version number for the distribution.
+
 =head1 AUTHORS
 
 =over 4
diff --git a/lib/MetaCPAN/Client/Favorite.pm b/lib/MetaCPAN/Client/Favorite.pm
index 99e4a4e..27d1b65 100644
--- a/lib/MetaCPAN/Client/Favorite.pm
+++ b/lib/MetaCPAN/Client/Favorite.pm
@@ -2,7 +2,7 @@ use strict;
 use warnings;
 package MetaCPAN::Client::Favorite;
 # ABSTRACT: A Favorite data object
-$MetaCPAN::Client::Favorite::VERSION = '2.004000';
+$MetaCPAN::Client::Favorite::VERSION = '2.021000';
 use Moo;
 
 with 'MetaCPAN::Client::Role::Entity';
@@ -43,13 +43,14 @@ MetaCPAN::Client::Favorite - A Favorite data object
 
 =head1 VERSION
 
-version 2.004000
+version 2.021000
 
 =head1 SYNOPSIS
 
-my $favorite = $mcpan->favorite( {
-    distribution => 'Moose'
-} );
+    my $favorites = $mcpan->favorite( {
+        distribution => 'Moose'
+    } );
+    while ( my $fav = $favorites->next ) { ... }
 
 =head1 DESCRIPTION
 
@@ -59,11 +60,13 @@ A MetaCPAN favorite entity object.
 
 =head2 date
 
-Date of the favorite.
+An ISO8601 datetime string like C<2016-11-19T12:41:46> indicating when the
+favorite was created.
 
 =head2 user
 
-The user ID (B<not> PAUSE ID) of who favorited.
+The user ID (B<not> PAUSE ID) of the person who favorited the thing in
+question.
 
 =head2 release
 
diff --git a/lib/MetaCPAN/Client/File.pm b/lib/MetaCPAN/Client/File.pm
index 77339f1..7179109 100644
--- a/lib/MetaCPAN/Client/File.pm
+++ b/lib/MetaCPAN/Client/File.pm
@@ -2,7 +2,7 @@ use strict;
 use warnings;
 package MetaCPAN::Client::File;
 # ABSTRACT: A File data object
-$MetaCPAN::Client::File::VERSION = '2.004000';
+$MetaCPAN::Client::File::VERSION = '2.021000';
 use Moo;
 use Carp;
 
@@ -90,6 +90,12 @@ sub source {
         );
 }
 
+sub metacpan_url {
+    my $self = shift;
+    sprintf("https://metacpan.org/source/%s/%s/%s",
+            $self->author, $self->release, $self->path );
+}
+
 1;
 
 __END__
@@ -104,7 +110,7 @@ MetaCPAN::Client::File - A File data object
 
 =head1 VERSION
 
-version 2.004000
+version 2.021000
 
 =head1 DESCRIPTION
 
@@ -114,59 +120,164 @@ A MetaCPAN file entity object.
 
 =head2 status
 
+Returns a release status like C<backpan>, C<cpan>, or C<latest>.
+
 =head2 date
 
+An ISO8601 datetime string like C<2016-11-19T12:41:46> indicating when the
+file was uploaded.
+
 =head2 author
 
+The author's PAUSE id.
+
 =head2 maturity
 
+This will be either C<release> or C<developer>.
+
 =head2 directory
 
+A boolean indicating whether or not the path represents a directory.
+
 =head2 indexed
 
+A boolean indicating whether or not the content is indexed.
+
 =head2 documentation
 
+The name of the module for which this file contains docs. This may be C<undef>
+
 =head2 id
 
+The file's internal MetaCPAN id.
+
 =head2 authorized
 
-=head2 version
+A boolean indicating whether or not this file was part of an authorized
+upload.
 
-=head2 binary
+=head2 version
 
-=head2 name
+The distribution version that contains this file.
 
 =head2 version_numified
 
+The numified version of the distribution that contains the file.
+
 =head2 release
 
+The release that contains this file, which will be something like
+C<Moose-2.2004>.
+
+=head2 binary
+
+A boolean indicating whether or not this file contains binary content.
+
+=head2 name
+
+The File's name, without any directory path included.
+
 =head2 path
 
+The file's path I<within the distribution archive>, relative to the root of
+the archive.
+
+=head2 abstract
+
+If the file contains POD with a C<NAME> section, then this attribute will
+include the abstract portion of the name.
+
 =head2 description
 
+If the file contains POD with a C<DESCRIPTION> section, then this attribute
+will contain that description.
+
 =head2 distribution
 
+The name of the distribution that contains the file.
+
 =head2 level
 
+A 0-indexed indication of how many directories deep this file is, relative to
+the archive root.
+
 =head2 sloc
 
-=head2 abstract
+If the file contains code, this will contain the number of lines of code in
+the file.
 
 =head2 slop
 
+If the file contains POD, this will contain the number of lines of POD in
+the file.
+
 =head2 mime
 
+The file's mime type.
+
 =head2 module
 
-Array-Ref.
+If the file contains module indexed by PAUSE, then this attribute contains an
+arrayref of hashrefs, one for each module. The hashrefs have the following
+keys:
+
+=over 4
+
+=item * name
+
+The module name.
+
+=item * indexed
+
+Whether or not the file is indexed by MetaCPAN.
+
+=item * authorized
+
+Whether or not the module is part of an authorized upload.
+
+=item * version
+
+The version of the module that this file contains.
+
+=item * version_numified
+
+The numified version of the module that this file contains.
+
+=item * associated_pod
+
+A path you can use with the C<< MetaCPAN::Client->file >> method to get the
+file that contains POD for this module. In most cases, that will be the same
+file as that one that contains this C<module> data.
+
+=back
 
 =head2 pod_lines
 
-Array-Ref.
+An arrayref.
 
 =head2 stat
 
-Hash-Ref.
+A hashref containing C<stat()> all information about the file. The keys are:
+
+=over 4
+
+=item * mtime
+
+The Unix epoch of the file's last modified time.
+
+=item * mode
+
+The file's mode (as an integer, not an octal representation).
+
+=item * size
+
+The file's size in bytes.
+
+=back
+
+=head2 download_url
+
+A URL for the distribution archive that contains this file.
 
 =head1 METHODS
 
@@ -187,6 +298,10 @@ Supported types: B<plain>, B<html>, B<x-pod>, B<x-markdown>.
 
 Returns the source code for the file.
 
+=head2 metacpan_url
+
+Returns a link to the file source page on MetaCPAN.
+
 =head1 AUTHORS
 
 =over 4
diff --git a/lib/MetaCPAN/Client/Mirror.pm b/lib/MetaCPAN/Client/Mirror.pm
index cee5638..13df859 100644
--- a/lib/MetaCPAN/Client/Mirror.pm
+++ b/lib/MetaCPAN/Client/Mirror.pm
@@ -2,7 +2,7 @@ use strict;
 use warnings;
 package MetaCPAN::Client::Mirror;
 # ABSTRACT: A Mirror data object
-$MetaCPAN::Client::Mirror::VERSION = '2.004000';
+$MetaCPAN::Client::Mirror::VERSION = '2.021000';
 use Moo;
 use Carp;
 
@@ -66,11 +66,11 @@ MetaCPAN::Client::Mirror - A Mirror data object
 
 =head1 VERSION
 
-version 2.004000
+version 2.021000
 
 =head1 SYNOPSIS
 
-my $mirror = $mcpan->mirror('eutelia.it');
+    my $mirror = $mcpan->mirror('eutelia.it');
 
 =head1 DESCRIPTION
 
@@ -80,18 +80,34 @@ A MetaCPAN mirror entity object.
 
 =head2 name
 
+The name of the mirror, which is what you passed
+
 =head2 org
 
+The organization that maintains the mirror.
+
 =head2 ftp
 
-=head2 city
+An FTP url for the mirror.
 
 =head2 rsync
 
+An rsync url for the mirror.
+
 =head2 src
 
+=head2 city
+
+The city where the mirror is located.
+
+=head2 country
+
+The name of the country where the mirror is located.
+
 =head2 ccode
 
+The ISO country code for the mirror's country.
+
 =head2 aka_name
 
 =head2 tz
@@ -104,8 +120,6 @@ A MetaCPAN mirror entity object.
 
 =head2 inceptdate
 
-=head2 country
-
 =head2 freq
 
 =head2 continent
diff --git a/lib/MetaCPAN/Client/Module.pm b/lib/MetaCPAN/Client/Module.pm
index 7e50f96..ac5e886 100644
--- a/lib/MetaCPAN/Client/Module.pm
+++ b/lib/MetaCPAN/Client/Module.pm
@@ -2,10 +2,26 @@ use strict;
 use warnings;
 package MetaCPAN::Client::Module;
 # ABSTRACT: A Module data object
-$MetaCPAN::Client::Module::VERSION = '2.004000';
+$MetaCPAN::Client::Module::VERSION = '2.021000';
 use Moo;
 extends 'MetaCPAN::Client::File';
 
+sub metacpan_url {
+    my $self = shift;
+    sprintf("https://metacpan.org/pod/release/%s/%s/%s",
+            $self->author, $self->release, $self->path );
+}
+
+sub package {
+    my $self = shift;
+    return $self->client->package( $self->documentation );
+}
+
+sub permission {
+    my $self = shift;
+    return $self->client->permission( $self->documentation );
+}
+
 1;
 
 __END__
@@ -20,11 +36,11 @@ MetaCPAN::Client::Module - A Module data object
 
 =head1 VERSION
 
-version 2.004000
+version 2.021000
 
 =head1 SYNOPSIS
 
-my $module = MetaCPAN::Client->new->module('Moo');
+    my $module = MetaCPAN::Client->new->module('Moo');
 
 =head1 DESCRIPTION
 
@@ -36,6 +52,20 @@ This is currently the exact same as L<MetaCPAN::Client::File>.
 
 Whatever L<MetaCPAN::Client::File> has.
 
+=head1 METHODS
+
+=head2 metacpan_url
+
+Returns a link to the module page on MetaCPAN.
+
+=head2 package
+
+Returns an L<MetaCPAN::Client::Package> object for the module.
+
+=head2 permission
+
+Returns an L<MetaCPAN::Client::Permission> object for the module.
+
 =head1 AUTHORS
 
 =over 4
diff --git a/lib/MetaCPAN/Client/Rating.pm b/lib/MetaCPAN/Client/Package.pm
similarity index 56%
copy from lib/MetaCPAN/Client/Rating.pm
copy to lib/MetaCPAN/Client/Package.pm
index 4605138..956eb6a 100644
--- a/lib/MetaCPAN/Client/Rating.pm
+++ b/lib/MetaCPAN/Client/Package.pm
@@ -1,24 +1,15 @@
 use strict;
 use warnings;
-package MetaCPAN::Client::Rating;
-# ABSTRACT: A Rating data object
-$MetaCPAN::Client::Rating::VERSION = '2.004000';
+package MetaCPAN::Client::Package;
+# ABSTRACT: A package data object (02packages.details entry)
+$MetaCPAN::Client::Package::VERSION = '2.021000';
 use Moo;
 
 with 'MetaCPAN::Client::Role::Entity';
 
 my %known_fields = (
-    scalar => [qw<
-        author
-        date
-        details
-        distribution
-        helpful
-        rating
-        release
-        user
-    >],
-    arrayref => [],
+    scalar   => [qw< author distribution dist_version file module_name version >],
+    arrayref => [qw<>],
     hashref  => [],
 );
 
@@ -48,37 +39,45 @@ __END__
 
 =head1 NAME
 
-MetaCPAN::Client::Rating - A Rating data object
+MetaCPAN::Client::Package - A package data object (02packages.details entry)
 
 =head1 VERSION
 
-version 2.004000
+version 2.021000
 
 =head1 SYNOPSIS
 
-my $rating = $mcpan->rating({ distribution => "Moo" });
+    my $package = $mcpan->package('MooseX::Types');
 
 =head1 DESCRIPTION
 
-A MetaCPAN rating entity object.
+A MetaCPAN package (02packages.details) entity object.
 
 =head1 ATTRIBUTES
 
-=head2 date
+=head2 module_name
 
-=head2 release
+Returns the name of the module.
 
-=head2 author
-
-=head2 details
+=head2 file
 
-=head2 rating
+The file path in CPAN for the module (latest release)
 
 =head2 distribution
 
-=head2 helpful
+The distribution in which the module exist
+
+=head2 version
+
+The (latest) version of the module
+
+=head2 dist_version
+
+The (latest) version of the distribution
+
+=head2 author
 
-=head2 user
+The pauseid of the release author
 
 =head1 AUTHORS
 
diff --git a/lib/MetaCPAN/Client/Rating.pm b/lib/MetaCPAN/Client/Permission.pm
similarity index 62%
copy from lib/MetaCPAN/Client/Rating.pm
copy to lib/MetaCPAN/Client/Permission.pm
index 4605138..792030a 100644
--- a/lib/MetaCPAN/Client/Rating.pm
+++ b/lib/MetaCPAN/Client/Permission.pm
@@ -1,24 +1,15 @@
 use strict;
 use warnings;
-package MetaCPAN::Client::Rating;
-# ABSTRACT: A Rating data object
-$MetaCPAN::Client::Rating::VERSION = '2.004000';
+package MetaCPAN::Client::Permission;
+# ABSTRACT: A Permission data object
+$MetaCPAN::Client::Permission::VERSION = '2.021000';
 use Moo;
 
 with 'MetaCPAN::Client::Role::Entity';
 
 my %known_fields = (
-    scalar => [qw<
-        author
-        date
-        details
-        distribution
-        helpful
-        rating
-        release
-        user
-    >],
-    arrayref => [],
+    scalar   => [qw< module_name owner >],
+    arrayref => [qw< co_maintainers >],
     hashref  => [],
 );
 
@@ -48,37 +39,33 @@ __END__
 
 =head1 NAME
 
-MetaCPAN::Client::Rating - A Rating data object
+MetaCPAN::Client::Permission - A Permission data object
 
 =head1 VERSION
 
-version 2.004000
+version 2.021000
 
 =head1 SYNOPSIS
 
-my $rating = $mcpan->rating({ distribution => "Moo" });
+    my $permission = $mcpan->permission('MooseX::Types');
 
 =head1 DESCRIPTION
 
-A MetaCPAN rating entity object.
+A MetaCPAN permission entity object.
 
 =head1 ATTRIBUTES
 
-=head2 date
+=head2 module_name
 
-=head2 release
+Returns the name of the module.
 
-=head2 author
+=head2 owner
 
-=head2 details
+The module owner (first-come permissions).
 
-=head2 rating
+=head2 co_maintainers
 
-=head2 distribution
-
-=head2 helpful
-
-=head2 user
+Other maintainers with permissions to this module.
 
 =head1 AUTHORS
 
diff --git a/lib/MetaCPAN/Client/Pod.pm b/lib/MetaCPAN/Client/Pod.pm
index f1f922a..a3b5228 100644
--- a/lib/MetaCPAN/Client/Pod.pm
+++ b/lib/MetaCPAN/Client/Pod.pm
@@ -2,7 +2,7 @@ use strict;
 use warnings;
 package MetaCPAN::Client::Pod;
 # ABSTRACT: A Pod object
-$MetaCPAN::Client::Pod::VERSION = '2.004000';
+$MetaCPAN::Client::Pod::VERSION = '2.021000';
 use Moo;
 use Carp;
 
@@ -62,7 +62,7 @@ MetaCPAN::Client::Pod - A Pod object
 
 =head1 VERSION
 
-version 2.004000
+version 2.021000
 
 =head1 SYNOPSIS
 
diff --git a/lib/MetaCPAN/Client/Rating.pm b/lib/MetaCPAN/Client/Rating.pm
index 4605138..61c4805 100644
--- a/lib/MetaCPAN/Client/Rating.pm
+++ b/lib/MetaCPAN/Client/Rating.pm
@@ -2,7 +2,7 @@ use strict;
 use warnings;
 package MetaCPAN::Client::Rating;
 # ABSTRACT: A Rating data object
-$MetaCPAN::Client::Rating::VERSION = '2.004000';
+$MetaCPAN::Client::Rating::VERSION = '2.021000';
 use Moo;
 
 with 'MetaCPAN::Client::Role::Entity';
@@ -52,11 +52,12 @@ MetaCPAN::Client::Rating - A Rating data object
 
 =head1 VERSION
 
-version 2.004000
+version 2.021000
 
 =head1 SYNOPSIS
 
-my $rating = $mcpan->rating({ distribution => "Moo" });
+    my $ratings = $mcpan->rating({ distribution => "Moo" });
+    while ( my $rat = $ratings->next ) { ... }
 
 =head1 DESCRIPTION
 
@@ -66,6 +67,9 @@ A MetaCPAN rating entity object.
 
 =head2 date
 
+An ISO8601 datetime string like C<2016-11-19T12:41:46> indicating when the
+rating was created.
+
 =head2 release
 
 =head2 author
diff --git a/lib/MetaCPAN/Client/Release.pm b/lib/MetaCPAN/Client/Release.pm
index 62acde5..54daa03 100644
--- a/lib/MetaCPAN/Client/Release.pm
+++ b/lib/MetaCPAN/Client/Release.pm
@@ -2,10 +2,13 @@ use strict;
 use warnings;
 package MetaCPAN::Client::Release;
 # ABSTRACT: A Release data object
-$MetaCPAN::Client::Release::VERSION = '2.004000';
+$MetaCPAN::Client::Release::VERSION = '2.021000';
 use Moo;
+use Ref::Util qw< is_hashref >;
+use JSON::MaybeXS qw< decode_json >;
 
-with 'MetaCPAN::Client::Role::Entity';
+with 'MetaCPAN::Client::Role::Entity',
+     'MetaCPAN::Client::Role::HasUA';
 
 my %known_fields = (
     scalar => [qw<
@@ -19,6 +22,7 @@ my %known_fields = (
         first
         id
         maturity
+        main_module
         name
         status
         version
@@ -55,6 +59,29 @@ foreach my $field (@known_fields) {
 
 sub _known_fields { return \%known_fields }
 
+sub changes {
+    my $self = shift;
+    my $url  = sprintf "https://fastapi.metacpan.org/changes/%s/%s", $self->author, $self->name;
+    my $res = $self->ua->get($url);
+    return unless is_hashref($res);
+    my $content = decode_json $res->{'content'};
+    return $content->{'content'};
+}
+
+sub metacpan_url {
+    my $self = shift;
+    sprintf( "https://metacpan.org/release/%s/%s", $self->author, $self->name )
+}
+
+sub contributors {
+    my $self = shift;
+    my $url = sprintf( "https://fastapi.metacpan.org/release/contributors/%s/%s", $self->author, $self->name );
+    my $res = $self->ua->get($url);
+    return unless is_hashref($res);
+    my $content = decode_json $res->{'content'};
+    return $content->{'contributors'};
+}
+
 1;
 
 __END__
@@ -69,7 +96,7 @@ MetaCPAN::Client::Release - A Release data object
 
 =head1 VERSION
 
-version 2.004000
+version 2.021000
 
 =head1 SYNOPSIS
 
@@ -83,59 +110,152 @@ A MetaCPAN release entity object.
 
 =head2 status
 
+The release's status, C<latest>, C<cpan>, or C<backpan>.
+
+=head2 name
+
+The release's name, something like C<Moose>.
+
 =head2 date
 
+An ISO8601 datetime string like C<2016-11-19T12:41:46> indicating when the
+release was uploaded.
+
 =head2 author
 
+The PAUSE ID of the author who uploaded the release.
+
 =head2 maturity
 
+This will be either C<released> or C<developer>.
+
+=head2 main_module
+
+The release's main module name.
+
 =head2 id
 
+The release's internal MetaCPAN id.
+
 =head2 authorized
 
+A boolean indicating whether or not this was an authorized release.
+
 =head2 download_url
 
+A URL for this release's distribution archive file.
+
 =head2 first
 
+A boolean indicating whether or not this is the first release of this
+distribution.
+
 =head2 archive
 
+The filename of the archive file for this release.
+
 =head2 version
 
-=head2 name
+The release's version.
 
 =head2 version_numified
 
+The numified form of the release's version.
+
 =head2 distribution
 
+The name of the distribution to which this release belongs.
+
 =head2 abstract
 
+The abstract from this release's metadata.
+
 =head2 dependency
 
-Array-Ref.
+This is an arrayref of hashrefs. Each hashref contains the following keys:
+
+=over 4
+
+=item * phase
+
+The phase to which this dependency belongs. This will be one of C<configure>,
+C<build>, C<runtime>, C<test>, or C<develop>.
+
+=item * relationship
+
+This will be one of C<requires>, C<recommends>, or C<suggests>.
+
+=item * module
+
+The name of the module which is depended on.
+
+=item * version
+
+The required version of the dependency. This may be C<0>, indicating that any
+version is acceptable.
+
+=back
 
 =head2 license
 
-Array-Ref.
+An arrayref containing the license(s) under which this release has been made
+available. These licenses are represented by strings like C<perl_5> or
+C<gpl2>.
 
 =head2 provides
 
-Array-Ref.
+This an arrayref containing a list of all the modules provided by this distribution.
 
 =head2 metadata
 
-Hash-Ref.
+This is a hashref containing metadata provided by the distribution. The exact
+contents of this hashref will vary across CPAN, but should largely conform to
+the spec defined by L<CPAN::Meta::Spec>.
 
 =head2 resources
 
-Hash-Ref.
+The resources portion of the release's metadata, returned as a hashref.
 
 =head2 stat
 
-Hash-Ref.
+A hashref containing C<stat()> all information about the release's archive
+file. The keys are:
+
+=over 4
+
+=item * mtime
+
+The Unix epoch of the file's last modified time.
+
+=item * mode
+
+The file's mode (as an integer, not an octal representation).
+
+=item * size
+
+The file's size in bytes.
+
+=back
 
 =head2 tests
 
-Hash-Ref.
+Returns a hashref of information about CPAN testers results for this
+release. The keys are C<pass>, C<fail>, C<unknown>, and C<na>. The values are
+the count of that particular result on CPAN Testers for this release.
+
+=head1 METHODS
+
+=head2 changes
+
+Returns the Changes text for the release.
+
+=head2 metacpan_url
+
+Returns a link to the release page on MetaCPAN.
+
+=head2 contributors
+
+Returns a structure with release contributors info.
 
 =head1 AUTHORS
 
diff --git a/lib/MetaCPAN/Client/Request.pm b/lib/MetaCPAN/Client/Request.pm
index e54e949..089f36b 100644
--- a/lib/MetaCPAN/Client/Request.pm
+++ b/lib/MetaCPAN/Client/Request.pm
@@ -2,15 +2,16 @@ use strict;
 use warnings;
 package MetaCPAN::Client::Request;
 # ABSTRACT: Object used for making requests to MetaCPAN
-$MetaCPAN::Client::Request::VERSION = '2.004000';
+$MetaCPAN::Client::Request::VERSION = '2.021000';
 use Moo;
 use Carp;
 use JSON::MaybeXS qw<decode_json encode_json>;
-use HTTP::Tiny;
-use Ref::Util qw< is_arrayref is_hashref >;
+use Ref::Util qw< is_arrayref is_hashref is_ref >;
 
 use MetaCPAN::Client::Scroll;
-use MetaCPAN::Client::Types qw< HashRef >;
+use MetaCPAN::Client::Types qw< HashRef Int >;
+
+with 'MetaCPAN::Client::Role::HasUA';
 
 has _clientinfo => (
     is      => 'ro',
@@ -36,30 +37,16 @@ has base_url => (
     },
 );
 
-has _user_ua => (
-    init_arg  => 'ua',
-    is        => 'ro',
-    predicate => '_has_user_ua',
-);
-
-has ua => (
-    init_arg => undef,
-    is       => 'ro',
-    lazy     => 1,
-    builder  => '_build_ua',
-);
-
-has ua_args => (
+has _is_agg => (
     is      => 'ro',
-    default => sub {
-        [ agent => 'MetaCPAN::Client/'.($MetaCPAN::Client::VERSION||'xx') ]
-    },
+    default => 0,
+    writer  => '_set_is_agg'
 );
 
-has _is_agg => (
+has debug => (
     is      => 'ro',
+    isa     => Int,
     default => 0,
-    writer  => '_set_is_agg'
 );
 
 sub BUILDARGS {
@@ -68,24 +55,6 @@ sub BUILDARGS {
     return \%args;
 }
 
-sub _build_ua {
-    my $self = shift;
-
-    # This level of indirection is so that if a user has not specified a custom UA
-    # MetaCPAN::Client will have its own UA's
-    #
-    # But if the user **has** specified a custom UA, that UA is used for both.
-    if ( $self->_has_user_ua ) {
-        my $ua = $self->_user_ua;
-        croak "cannot use given ua (must support 'get' and 'post' methods)"
-            unless $ua->can("get") and $ua->can("post");
-
-        return $self->_user_ua;
-    }
-
-    return HTTP::Tiny->new( @{ $self->ua_args } );
-}
-
 sub _build_clientinfo {
     my $self = shift;
 
@@ -98,8 +67,8 @@ sub _build_clientinfo {
     }
     or $info = +{
         production => {
-            url => 'https://fastapi.metacpan.org/v1/', # last known production url
-            domain => 'https://fastapi.metacpan.org/'  # last known production domain
+            url    => 'https://fastapi.metacpan.org', # last known production url
+            domain => 'https://fastapi.metacpan.org', # last known production domain
         }
     };
 
@@ -110,6 +79,7 @@ sub fetch {
     my $self    = shift;
     my $url     = shift or croak 'fetch must be called with a URL parameter';
     my $params  = shift || {};
+    $url =~ s{^/}{};
     my $req_url = sprintf '%s/%s', $self->base_url, $url;
     my $ua      = $self->ua;
 
@@ -126,12 +96,17 @@ sub ssearch {
     my $args   = shift;
     my $params = shift;
 
+    my $time = delete $params->{'scroller_time'} || '5m';
+    my $size = delete $params->{'scroller_size'} || 1000;
+
     my $scroller = MetaCPAN::Client::Scroll->new(
         ua       => $self->ua,
-        size     => 1000,
+        size     => $size,
+        time     => $time,
         base_url => $self->base_url,
         type     => $type,
         body     => $self->_build_body($args, $params),
+        debug    => $self->debug,
     );
 
     return $scroller;
@@ -181,8 +156,10 @@ sub _build_body {
 
     return +{
         query => $query,
-        _read_filters($params),
-        $self->_read_aggregations($params)
+        $self->_read_filters($params),
+        $self->_read_fields($params),
+        $self->_read_aggregations($params),
+        $self->_read_sort($params)
     };
 }
 
@@ -192,6 +169,30 @@ my %key2es = (
     not    => 'must_not',
 );
 
+sub _read_fields {
+    my $self   = shift;
+    my $params = shift;
+
+    my $fields  = delete $params->{fields};
+    my $_source = delete $params->{_source};
+
+    my @ret;
+
+    if ( $fields ) {
+        is_arrayref($fields) or
+            croak "fields must be an arrayref";
+        push @ret => ( fields => $fields );
+    }
+
+    if ( $_source ) {
+        is_arrayref($_source) or !is_ref($_source) or
+            croak "_source must be an arrayref or a string";
+        push @ret => ( _source => $_source );
+    }
+
+    return @ret;
+}
+
 sub _read_aggregations {
     my $self   = shift;
     my $params = shift;
@@ -204,6 +205,7 @@ sub _read_aggregations {
 }
 
 sub _read_filters {
+    my $self   = shift;
     my $params = shift;
 
     my $filter = delete $params->{es_filter};
@@ -212,6 +214,16 @@ sub _read_filters {
     return ( filter => $filter );
 }
 
+sub _read_sort {
+    my $self   = shift;
+    my $params = shift;
+
+    my $sort = delete $params->{sort};
+    ref($sort) or return ();
+
+    return ( sort => $sort );
+}
+
 sub _build_query_rec {
     my $args  = shift;
     is_hashref($args) or croak 'query args must be a hash';
@@ -270,7 +282,7 @@ MetaCPAN::Client::Request - Object used for making requests to MetaCPAN
 
 =head1 VERSION
 
-version 2.004000
+version 2.021000
 
 =head1 ATTRIBUTES
 
@@ -293,42 +305,9 @@ The C<base_url> will be set appropriately automatically.
 
 Default: I<https://$domain>.
 
-=head2 ua
-
-    my $mcpan = MetaCPAN::Client->new( ua => HTTP::Tiny->new(...) );
-
-The user agent object for running requests.
-
-It must provide an interface that matches L<HTTP::Tiny>. Explicitly:
-
-=over 4
-
-=item * Implement post()
-
-Method C<post> must be available that accepts a request URL and a hashref of
-options.
-
-=item * Implement get()
-
-Method C<get> must be available that accepts a request URL.
-
-=item * Return result hashref
-
-Must return a result hashref which has key C<success> and key C<content>.
-
-=back
-
-Default: L<HTTP::Tiny>,
-
-=head2 ua_args
-
-    my $mcpan = MetaCPAN::Client->new(
-        ua_args => [ agent => 'MyAgent' ],
-    );
-
-Arguments sent to the user agent.
+=head2 debug
 
-Default: user agent string: B<MetaCPAN::Client/$version>.
+debug-mode for more detailed error messages.
 
 =head1 METHODS
 
@@ -348,7 +327,7 @@ Fetches a path from MetaCPAN (post or get), and returns the decoded result.
 
 =head2 ssearch
 
-Calls an ElasticSearch query and returns an L<MetaCPAN::Client::Scroll>
+Calls an Elasticsearch query and returns an L<MetaCPAN::Client::Scroll>
 scroller object.
 
 =head1 AUTHORS
diff --git a/lib/MetaCPAN/Client/ResultSet.pm b/lib/MetaCPAN/Client/ResultSet.pm
index 5909b50..b55e522 100644
--- a/lib/MetaCPAN/Client/ResultSet.pm
+++ b/lib/MetaCPAN/Client/ResultSet.pm
@@ -2,7 +2,7 @@ use strict;
 use warnings;
 package MetaCPAN::Client::ResultSet;
 # ABSTRACT: A Result Set
-$MetaCPAN::Client::ResultSet::VERSION = '2.004000';
+$MetaCPAN::Client::ResultSet::VERSION = '2.021000';
 use Moo;
 use Carp;
 
@@ -13,7 +13,7 @@ has type => (
     isa      => sub {
         croak 'Invalid type' unless
             grep { $_ eq $_[0] } qw<author distribution favorite
-                                   file module rating release mirror>;
+                                   file module rating release mirror package>;
     },
     required => 1,
 );
@@ -65,7 +65,7 @@ sub next {
     defined $result or return;
 
     my $class = 'MetaCPAN::Client::' . ucfirst $self->type;
-    return $class->new_from_request( $result->{'_source'} || $result->{'fields'} );
+    return $class->new_from_request( $result->{'_source'} || $result->{'fields'} || $result );
 }
 
 sub aggregations {
@@ -89,7 +89,7 @@ MetaCPAN::Client::ResultSet - A Result Set
 
 =head1 VERSION
 
-version 2.004000
+version 2.021000
 
 =head1 DESCRIPTION
 
diff --git a/lib/MetaCPAN/Client/Role/Entity.pm b/lib/MetaCPAN/Client/Role/Entity.pm
index ba8508c..b93c59d 100644
--- a/lib/MetaCPAN/Client/Role/Entity.pm
+++ b/lib/MetaCPAN/Client/Role/Entity.pm
@@ -2,7 +2,7 @@ use strict;
 use warnings;
 package MetaCPAN::Client::Role::Entity;
 # ABSTRACT: A role for MetaCPAN entities
-$MetaCPAN::Client::Role::Entity::VERSION = '2.004000';
+$MetaCPAN::Client::Role::Entity::VERSION = '2.021000';
 use Moo::Role;
 
 use JSON::PP;
@@ -42,6 +42,12 @@ sub BUILDARGS {
     }
 
     for my $k ( @{ $known_fields->{arrayref} } ) {
+        # fix the case when we expect an array ref but get a scalar because
+        # the result array had one element and we received a scalar
+        if ( defined($args{data}{$k}) and !is_ref($args{data}{$k}) ) {
+            $args{data}{$k} = [ $args{data}{$k} ]
+        }
+
         delete $args{data}{$k}
             unless is_arrayref( $args{data}{$k} ); # warn?
     }
@@ -83,7 +89,7 @@ MetaCPAN::Client::Role::Entity - A role for MetaCPAN entities
 
 =head1 VERSION
 
-version 2.004000
+version 2.021000
 
 =head1 DESCRIPTION
 
diff --git a/lib/MetaCPAN/Client/Role/HasUA.pm b/lib/MetaCPAN/Client/Role/HasUA.pm
new file mode 100644
index 0000000..cdc8892
--- /dev/null
+++ b/lib/MetaCPAN/Client/Role/HasUA.pm
@@ -0,0 +1,124 @@
+use strict;
+use warnings;
+package MetaCPAN::Client::Role::HasUA;
+# ABSTRACT: Role for supporting user-agent attribute
+$MetaCPAN::Client::Role::HasUA::VERSION = '2.021000';
+use Moo::Role;
+use Carp;
+use HTTP::Tiny;
+
+has _user_ua => (
+    init_arg  => 'ua',
+    is        => 'ro',
+    predicate => '_has_user_ua',
+);
+
+has ua => (
+    init_arg => undef,
+    is       => 'ro',
+    lazy     => 1,
+    builder  => '_build_ua',
+);
+
+has ua_args => (
+    is      => 'ro',
+    default => sub {
+        [ agent => 'MetaCPAN::Client/'.($MetaCPAN::Client::VERSION||'xx') ]
+    },
+);
+
+sub _build_ua {
+    my $self = shift;
+
+    # This level of indirection is so that if a user has not specified a custom UA
+    # MetaCPAN::Client will have its own UA's
+    #
+    # But if the user **has** specified a custom UA, that UA is used for both.
+    if ( $self->_has_user_ua ) {
+        my $ua = $self->_user_ua;
+        croak "cannot use given ua (must support 'get' and 'post' methods)"
+            unless $ua->can("get") and $ua->can("post");
+
+        return $self->_user_ua;
+    }
+
+    return HTTP::Tiny->new( @{ $self->ua_args } );
+}
+
+1;
+
+__END__
+
+=pod
+
+=encoding UTF-8
+
+=head1 NAME
+
+MetaCPAN::Client::Role::HasUA - Role for supporting user-agent attribute
+
+=head1 VERSION
+
+version 2.021000
+
+=head1 ATTRIBUTES
+
+=head2 ua
+
+    my $mcpan = MetaCPAN::Client->new( ua => HTTP::Tiny->new(...) );
+
+The user agent object for running requests.
+
+It must provide an interface that matches L<HTTP::Tiny>. Explicitly:
+
+=over 4
+
+=item * Implement post()
+
+Method C<post> must be available that accepts a request URL and a hashref of
+options.
+
+=item * Implement get()
+
+Method C<get> must be available that accepts a request URL.
+
+=item * Return result hashref
+
+Must return a result hashref which has key C<success> and key C<content>.
+
+=back
+
+Default: L<HTTP::Tiny>,
+
+=head2 ua_args
+
+    my $mcpan = MetaCPAN::Client->new(
+        ua_args => [ agent => 'MyAgent' ],
+    );
+
+Arguments sent to the user agent.
+
+Default: user agent string: B<MetaCPAN::Client/$version>.
+
+=head1 AUTHORS
+
+=over 4
+
+=item *
+
+Sawyer X <xsawyerx at cpan.org>
+
+=item *
+
+Mickey Nasriachi <mickey at cpan.org>
+
+=back
+
+=head1 COPYRIGHT AND LICENSE
+
+This software is copyright (c) 2016 by Sawyer X.
+
+This is free software; you can redistribute it and/or modify it under
+the same terms as the Perl 5 programming language system itself.
+
+=cut
diff --git a/lib/MetaCPAN/Client/Scroll.pm b/lib/MetaCPAN/Client/Scroll.pm
index 1ced192..7b83715 100644
--- a/lib/MetaCPAN/Client/Scroll.pm
+++ b/lib/MetaCPAN/Client/Scroll.pm
@@ -2,13 +2,13 @@ use strict;
 use warnings;
 package MetaCPAN::Client::Scroll;
 # ABSTRACT: A MetaCPAN::Client scroller
-$MetaCPAN::Client::Scroll::VERSION = '2.004000';
+$MetaCPAN::Client::Scroll::VERSION = '2.021000';
 use Moo;
 use Carp;
 use Ref::Util qw< is_hashref >;
 use JSON::MaybeXS qw< decode_json encode_json >;
 
-use MetaCPAN::Client::Types qw< Str Int Time ArrayRef HashRef >;
+use MetaCPAN::Client::Types qw< Str Int Time ArrayRef HashRef Bool >;
 
 has ua => (
     is       => 'ro',
@@ -48,28 +48,18 @@ has _id => (
     isa      => Str,
 );
 
-has _read => (
-    init_arg => undef,
-    is       => 'ro',
-    isa      => Int,
-    default  => sub { 0 },
-    writer   => '_set_read',
-);
-
-has _idx => (
-    init_arg => undef,
-    is       => 'ro',
-    isa      => Int,
-    default  => sub { 0 },
-    writer   => '_set_idx',
-);
-
 has _buffer => (
     is       => 'ro',
     isa      => ArrayRef,
     default  => sub { [] },
 );
 
+has _done => (
+    is       => 'rw',
+    isa      => Bool,
+    default  => sub { 0 },
+);
+
 has total => (
     is       => 'ro',
     isa      => Int,
@@ -96,8 +86,11 @@ sub BUILDARGS {
         { content => encode_json $body }
     );
 
-    croak "failed to create a scrolled search"
-        unless $res->{status} == 200;
+    if ( $res->{status} != 200 ) {
+        my $msg = "failed to create a scrolled search";
+        $args{debug} and $msg .= "\n(" . $res->{content} . ")";
+        croak $msg;
+    }
 
     my $content = decode_json $res->{content};
 
@@ -114,22 +107,23 @@ sub BUILDARGS {
 }
 
 sub next {
-    my $self = shift;
-    my $read = $self->_read;
-    return if $read >= $self->total;
+    my $self   = shift;
+    my $buffer = $self->_buffer;
 
-    my $idx = $self->_idx;
+    # We're exhausted and will do no more.
+    return if $self->_done;
 
-    if ( $idx >= ($self->size * 10) ) {
-        @{ $self->_buffer } = ();
-        $idx = 0;
-    }
+    # Refill the buffer if it's empty.
+    @$buffer = @{ $self->_fetch_next }
+        unless @$buffer;
+
+    # Grab the next result from the buffer.  If there's no result, then that's
+    # all, folks!
+    my $next = shift @$buffer;
 
-    $self->_fetch_next if $read % $self->size == 0;
+    $self->_done(1) unless $next;
 
-    $self->_set_idx( $idx + 1 );
-    $self->_set_read( $read + 1 );
-    return $self->_buffer->[ $idx ];
+    return $next;
 }
 
 sub _fetch_next {
@@ -145,19 +139,16 @@ sub _fetch_next {
 
     my $content = decode_json $res->{content};
 
-    push @{ $self->_buffer } => @{ $content->{hits}{hits} };
+    return $content->{hits}{hits};
 }
 
 sub DEMOLISH {
     my $self = shift;
 
-    my $res = $self->ua->delete(
+    $self->ua->delete(
         sprintf( '%s/_search/scroll?scroll=%s', $self->base_url, $self->time ),
         { content => $self->_id }
     );
-
-    warn "failed to delete scroller"
-        unless $res->{status} == 200;
 }
 
 1;
@@ -174,7 +165,7 @@ MetaCPAN::Client::Scroll - A MetaCPAN::Client scroller
 
 =head1 VERSION
 
-version 2.004000
+version 2.021000
 
 =head1 METHODS
 
@@ -203,7 +194,7 @@ The request body.
 
 =head2 size
 
-The numebr of docs to pull from each shard per request.
+The number of docs to pull from each shard per request.
 
 =head2 time
 
@@ -215,7 +206,7 @@ The total number of matches.
 
 =head2 type
 
-The ElasticSearch type to query.
+The Elasticsearch type to query.
 
 =head2 ua
 
diff --git a/lib/MetaCPAN/Client/Types.pm b/lib/MetaCPAN/Client/Types.pm
index 1dd6304..3e3e7ed 100644
--- a/lib/MetaCPAN/Client/Types.pm
+++ b/lib/MetaCPAN/Client/Types.pm
@@ -2,18 +2,19 @@ use strict;
 use warnings;
 package MetaCPAN::Client::Types;
 # ABSTRACT: type checking helper class
-$MetaCPAN::Client::Types::VERSION = '2.004000';
+$MetaCPAN::Client::Types::VERSION = '2.021000';
 use Type::Tiny      ();
 use Types::Standard ();
 use Ref::Util qw< is_ref >;
 
 use parent 'Exporter';
-our @EXPORT_OK = qw< Str Int Time ArrayRef HashRef >;
+our @EXPORT_OK = qw< Str Int Time ArrayRef HashRef Bool >;
 
 sub Str      { Types::Standard::Str      }
 sub Int      { Types::Standard::Int      }
 sub ArrayRef { Types::Standard::ArrayRef }
 sub HashRef  { Types::Standard::HashRef  }
+sub Bool     { Types::Standard::Bool     }
 
 sub Time {
     return Type::Tiny->new(
@@ -37,12 +38,14 @@ MetaCPAN::Client::Types - type checking helper class
 
 =head1 VERSION
 
-version 2.004000
+version 2.021000
 
 =head1 METHODS
 
 =head2 ArrayRef
 
+=head2 Bool
+
 =head2 HashRef
 
 =head2 Int
diff --git a/t/00-report-prereqs.dd b/t/00-report-prereqs.dd
index b3fa3c9..39be011 100644
--- a/t/00-report-prereqs.dd
+++ b/t/00-report-prereqs.dd
@@ -7,7 +7,7 @@ do { my $x = {
        'develop' => {
                       'requires' => {
                                       'File::Spec' => '0',
-                                      'HTTP::Tiny::Mech' => '0',
+                                      'HTTP::Tiny::Mech' => '1.001002',
                                       'IO::Handle' => '0',
                                       'IPC::Open3' => '0',
                                       'LWP::Protocol::https' => '0',
@@ -15,7 +15,7 @@ do { my $x = {
                                       'Test::More' => '0',
                                       'Test::Pod' => '1.41',
                                       'Test::Pod::Coverage' => '1.08',
-                                      'WWW::Mechanize::Cached' => '1.48'
+                                      'WWW::Mechanize::Cached' => '1.50'
                                     }
                     },
        'runtime' => {
@@ -40,16 +40,16 @@ do { my $x = {
        'test' => {
                    'recommends' => {
                                      'CPAN::Meta' => '2.120900',
-                                     'HTTP::Tiny::Mech' => '0',
-                                     'LWP::Protocol::https' => '0',
-                                     'WWW::Mechanize::Cached' => '1.48'
+                                     'HTTP::Tiny::Mech' => '1.001002',
+                                     'WWW::Mechanize::Cached' => '1.50'
                                    },
                    'requires' => {
                                    'ExtUtils::MakeMaker' => '0',
                                    'File::Spec' => '0',
+                                   'LWP::Protocol::https' => '0',
                                    'Test::Fatal' => '0',
                                    'Test::More' => '0',
-                                   'Test::Requires' => '0',
+                                   'Test::Needs' => '0.002005',
                                    'base' => '0',
                                    'blib' => '1.01'
                                  }
diff --git a/t/api/_get.t b/t/api/_get.t
index 6bc4526..8c0e940 100644
--- a/t/api/_get.t
+++ b/t/api/_get.t
@@ -5,6 +5,7 @@ use warnings;
 use Test::More tests => 13;
 use Test::Fatal;
 
+use lib '.';
 use t::lib::Functions;
 
 {
diff --git a/t/api/_get_or_search.t b/t/api/_get_or_search.t
index b6a1b10..85ed571 100644
--- a/t/api/_get_or_search.t
+++ b/t/api/_get_or_search.t
@@ -5,6 +5,7 @@ use warnings;
 use Test::More tests => 10;
 use Test::Fatal;
 
+use lib '.';
 use t::lib::Functions;
 
 {
diff --git a/t/api/_search.t b/t/api/_search.t
index 493bfe1..c87b1e8 100644
--- a/t/api/_search.t
+++ b/t/api/_search.t
@@ -5,6 +5,7 @@ use warnings;
 use Test::More tests => 19;
 use Test::Fatal;
 
+use lib '.';
 use t::lib::Functions;
 
 {
diff --git a/t/api/author.t b/t/api/author.t
index 7da1034..404a63b 100644
--- a/t/api/author.t
+++ b/t/api/author.t
@@ -6,6 +6,7 @@ use Test::More;
 use Test::Fatal;
 use Ref::Util qw< is_arrayref >;
 
+use lib '.';
 use t::lib::Functions;
 
 my $mc = mcpan();
diff --git a/t/api/distribution.t b/t/api/distribution.t
index d74ebd4..33d2002 100644
--- a/t/api/distribution.t
+++ b/t/api/distribution.t
@@ -6,6 +6,7 @@ use Test::More tests => 9;
 use Test::Fatal;
 use Ref::Util qw< is_hashref >;
 
+use lib '.';
 use t::lib::Functions;
 
 my $mc = mcpan();
diff --git a/t/api/download_url.t b/t/api/download_url.t
index a770f9f..09333c8 100644
--- a/t/api/download_url.t
+++ b/t/api/download_url.t
@@ -5,6 +5,7 @@ use warnings;
 use Test::More tests => 7;
 use Test::Fatal;
 
+use lib '.';
 use t::lib::Functions;
 
 my $mc = mcpan();
diff --git a/t/api/favorite.t b/t/api/favorite.t
index 3a5c9a2..7f3e161 100644
--- a/t/api/favorite.t
+++ b/t/api/favorite.t
@@ -5,6 +5,7 @@ use warnings;
 use Test::More tests => 2 + 4 * 2;
 use Test::Fatal;
 
+use lib '.';
 use t::lib::Functions;
 
 my $mc = mcpan();
diff --git a/t/api/file.t b/t/api/file.t
index 876d198..ef7b18a 100644
--- a/t/api/file.t
+++ b/t/api/file.t
@@ -5,6 +5,7 @@ use warnings;
 use Test::More tests => 11;
 use Test::Fatal;
 
+use lib '.';
 use t::lib::Functions;
 
 my $mc = mcpan();
diff --git a/t/api/module.t b/t/api/module.t
index e0d1251..ff8eb23 100644
--- a/t/api/module.t
+++ b/t/api/module.t
@@ -5,6 +5,7 @@ use warnings;
 use Test::More tests => 10;
 use Test::Fatal;
 
+use lib '.';
 use t::lib::Functions;
 
 my $mc = mcpan();
diff --git a/t/api/package.t b/t/api/package.t
new file mode 100644
index 0000000..0ee5288
--- /dev/null
+++ b/t/api/package.t
@@ -0,0 +1,22 @@
+#!perl
+
+use strict;
+use warnings;
+use Test::More tests => 10;
+use Ref::Util qw< is_arrayref is_ref >;
+
+use lib '.';
+use t::lib::Functions;
+
+my $mc = mcpan();
+can_ok( $mc, 'package' );
+
+my $pack = $mc->package('MooseX::Types');
+isa_ok( $pack, 'MetaCPAN::Client::Package' );
+can_ok( $pack, qw< module_name file distribution version author > );
+ok( !is_ref($pack->module_name),  "module_name is not a ref");
+ok( !is_ref($pack->file),         "file is not a ref");
+ok( !is_ref($pack->distribution), "distribution is not a ref");
+ok( !is_ref($pack->version),      "version is not a ref");
+ok( !is_ref($pack->dist_version), "version is not a ref");
+ok( !is_ref($pack->author),       "author is not a ref");
diff --git a/t/api/permission.t b/t/api/permission.t
new file mode 100644
index 0000000..4c51ec0
--- /dev/null
+++ b/t/api/permission.t
@@ -0,0 +1,19 @@
+#!perl
+
+use strict;
+use warnings;
+use Test::More tests => 7;
+use Ref::Util qw< is_arrayref is_ref >;
+
+use lib '.';
+use t::lib::Functions;
+
+my $mc = mcpan();
+can_ok( $mc, 'permission' );
+
+my $perm = $mc->permission('MooseX::Types');
+isa_ok( $perm, 'MetaCPAN::Client::Permission' );
+can_ok( $perm, qw< module_name owner co_maintainers > );
+ok( !is_ref($perm->module_name), "module_name is not a ref");
+ok( !is_ref($perm->owner), "owner is not a ref");
+ok( is_arrayref($perm->co_maintainers), "co_maintainers is an arrayref");
diff --git a/t/api/pod.t b/t/api/pod.t
index 1f07008..abe3153 100644
--- a/t/api/pod.t
+++ b/t/api/pod.t
@@ -4,6 +4,7 @@ use strict;
 use warnings;
 use Test::More tests => 5;
 
+use lib '.';
 use t::lib::Functions;
 
 my $mc = mcpan();
diff --git a/t/api/rating.t b/t/api/rating.t
index ce2c086..eb6c3b0 100644
--- a/t/api/rating.t
+++ b/t/api/rating.t
@@ -5,6 +5,7 @@ use warnings;
 use Test::More tests => 7;
 use Test::Fatal;
 
+use lib '.';
 use t::lib::Functions;
 
 my $mc = mcpan();
diff --git a/t/api/release.t b/t/api/release.t
index 2745ae3..7e5fdb7 100644
--- a/t/api/release.t
+++ b/t/api/release.t
@@ -5,6 +5,7 @@ use warnings;
 use Test::More tests => 5;
 use Test::Fatal;
 
+use lib '.';
 use t::lib::Functions;
 
 my $mc = mcpan();
diff --git a/t/scroll.t b/t/scroll.t
index d644596..123b05a 100644
--- a/t/scroll.t
+++ b/t/scroll.t
@@ -14,7 +14,7 @@ my $scroller = MetaCPAN::Client::Scroll->new(
    base_url => 'https://fastapi.metacpan.org/v1/',
    type     => 'release',
    body     => { query => { term => { distribution => 'MetaCPAN-Client' } } },
-   size     => 5,
+   size     => 50,
 );
 isa_ok( $scroller, 'MetaCPAN::Client::Scroll' );
 
@@ -22,7 +22,7 @@ can_ok(
     $scroller,
     qw< aggregations base_url body _buffer
         BUILDARGS DEMOLISH _fetch_next _id
-        next _read size time total type ua >
+        next size time total type ua >
 );
 
 my $next = $scroller->next;
@@ -32,7 +32,8 @@ my $rel = MetaCPAN::Client::Release->new_from_request( $next->{'_source'} );
 isa_ok( $rel, 'MetaCPAN::Client::Release' );
 is( $rel->distribution, 'MetaCPAN-Client', 'release object can be created from next doc' );
 
-while ( my $n = $scroller->next ) { 1 }
-is( $scroller->total, $scroller->_read, 'can read all matching docs' );
+my $got = 1;  # we call ->next once above
+while ( my $n = $scroller->next ) { $got++ }
+is( $got, $scroller->total, 'can read all matching docs' );
 
 1;
diff --git a/t/ua_trap.t b/t/ua_trap.t
index 94d31bf..92dfb06 100644
--- a/t/ua_trap.t
+++ b/t/ua_trap.t
@@ -5,9 +5,9 @@ use Test::More;
 
 # ABSTRACT: Make sure passed value of UA gets used for things.
 
-use Test::Requires {
-    'WWW::Mechanize::Cached' => 0,
-    'HTTP::Tiny::Mech'       => 0,
+use Test::Needs {
+    'WWW::Mechanize::Cached' => 1.50,
+    'HTTP::Tiny::Mech'       => 1.001002,
 };
 use Test::Fatal qw( exception );
 
diff --git a/xt/author/00-compile.t b/xt/author/00-compile.t
index 36687c2..0134d2a 100644
--- a/xt/author/00-compile.t
+++ b/xt/author/00-compile.t
@@ -6,7 +6,7 @@ use warnings;
 
 use Test::More;
 
-plan tests => 17;
+plan tests => 20;
 
 my @module_files = (
     'MetaCPAN/Client.pm',
@@ -17,12 +17,15 @@ my @module_files = (
     'MetaCPAN/Client/File.pm',
     'MetaCPAN/Client/Mirror.pm',
     'MetaCPAN/Client/Module.pm',
+    'MetaCPAN/Client/Package.pm',
+    'MetaCPAN/Client/Permission.pm',
     'MetaCPAN/Client/Pod.pm',
     'MetaCPAN/Client/Rating.pm',
     'MetaCPAN/Client/Release.pm',
     'MetaCPAN/Client/Request.pm',
     'MetaCPAN/Client/ResultSet.pm',
     'MetaCPAN/Client/Role/Entity.pm',
+    'MetaCPAN/Client/Role/HasUA.pm',
     'MetaCPAN/Client/Scroll.pm',
     'MetaCPAN/Client/Types.pm'
 );
diff --git a/xt/author/critic.t b/xt/author/critic.t
deleted file mode 100644
index d5b4c96..0000000
--- a/xt/author/critic.t
+++ /dev/null
@@ -1,12 +0,0 @@
-#!perl
-
-use strict;
-use warnings;
-
-use Test::More;
-use English qw(-no_match_vars);
-
-eval "use Test::Perl::Critic";
-plan skip_all => 'Test::Perl::Critic required to criticise code' if $@;
-Test::Perl::Critic->import( -profile => "perlcritic.rc" ) if -e "perlcritic.rc";
-all_critic_ok();

-- 
Alioth's /usr/local/bin/git-commit-notice on /srv/git.debian.org/git/pkg-perl/packages/libmetacpan-client-perl.git



More information about the Pkg-perl-cvs-commits mailing list