List all the Perl modules and distributions in a name-space using Meta CPAN
There are many modules on CPAN with a plug-in system, and all the plugins are usually in a specific name-space.
As far as I know even the Meta CPAN web site does not provide an easy way to list all the distributions in a given name-space.
Even though, using the MetaCPAN API it is quite easy to get this information.
The solution
The script which is included in the MetaCPAN-Clients distribution can provide the listing.
Let's see parts of the script:
List all the distributions under a name-space (with a given prefix)
use strict; use warnings; use Data::Dumper qw(Dumper); use MetaCPAN::API; my $mcpan = MetaCPAN::API->new; my $r = $mcpan->post( 'release', { query => { match_all => {} }, filter => { "and" => [ { prefix => { distribution => 'Perl-Critic' } }, { term => { status => 'latest' } }, ]}, fields => [ 'distribution', 'date' ], size => 2, }, ); #print Dumper $r; print Dumper [map {$_->{fields}} @{ $r->{hits}{hits} }];
This query will fetch all the releases (we usually also call distributions) for which the distribution field starts with Perl-Critic and which are the latest releases of the given distribution. (This just filters out multiple versions of the same distribution.) We limit the retrieved fields to the name of the distribution and the date. (The date is not used in our example.)
The returned hash has some meta-meta data in it, so we need to got a bit deeper - two levels of 'hits' and then we get a array with more meta-data and the the fields sub-key. I left in the call to Dumper on the original hash, to make it easy for you to see what's going on.
List all the modules under a name::space (with a given prefix)
use strict; use warnings; use Data::Dumper qw(Dumper); use MetaCPAN::API; my $mcpan = MetaCPAN::API->new; my $r = $mcpan->post( 'module', { query => { match_all => {} }, filter => { "and" => [ { prefix => { 'module.name' => 'Perl::Critic::Policy' } }, { term => { status => 'latest' } }, ]}, fields => [ 'distribution', 'date', 'module.name' ], size => 2, }, ); #print Dumper $r; print Dumper [map {$_->{fields}} @{ $r->{hits}{hits} }];
In this request we fetch the list of modules. In the filter we use the prefix of the module.name field. The resulting data structure is quite similar to the earlier one.
Generating HTML
It is simple to use Data::Dumper to just show the results, but it does not really look good. So in order to make it a bit easier to use the results as part of a web page, I added an extra flag --html that can generate a very simple unordered list from the distributions.
The code looks like this:
my $html = join "\n", map { sprintf(q{<li><a href="http://metacpan.org/release/%s">%s</a></li>}, $_, $_) } map { $_->{fields}{distribution} } @{ $r->{hits}{hits} }; print "<ul>\n$html\n</ul>\n";
The result
Running this:
perl bin/metacpan_namespace.pl --distro MetaCPAN --size 10 --html
Will generate the html that I embedded below, listing all the modules in the MetaCPAN name spaces:
Other uses
This script, or something similar could be used to provide a list of all the plugins for Perl Dancer, or Perl::Critic, or for any other module on CPAN.
Published on 2013-01-13