Last active
October 14, 2017 00:59
-
-
Save ugexe/10a1bf67f8849323bc855408e3577b2a to your computer and use it in GitHub Desktop.
Perl 6 module metadata microservice that uses installed modules as the data source
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
#!/usr/bin/env perl6 | |
use v6; | |
use Cro::HTTP::Server; | |
use Cro::HTTP::Router; | |
use Cro::HTTP::BodyParser; | |
# View all available distributions | |
# curl http://localhost:3000/installed | |
# View the best match from various sources for a given distribution query (name must be exact match to query name) | |
# curl -H "Content-Type: application/json" -X POST -d '{ "name" : "Zef" }' http://localhost:3000/resolve | |
# View all matching distributions from various sources (name only needs start with query name) | |
# See: https://github.com/rakudo/rakudo/pull/1125 for CUR interface proposal | |
# curl -H "Content-Type: application/json" -X POST -d '{ "name" : "Zef" }' http://localhost:3000/candidates | |
# curl -H "Content-Type: application/json" -X POST -d '{ "name" : "Z" }' http://localhost:3000/candidates | |
# curl -H "Content-Type: application/json" -X POST -d '{ "name" : "Z", "ver" : "0.1.0+" }' http://localhost:3000/candidates | |
sub MAIN(:$host = 'localhost', :$port = 3000) { | |
my $zef-meta-service = Cro::HTTP::Server.new( | |
host => $host, | |
port => $port, | |
body-parsers => [Cro::HTTP::BodyParser::JSON], | |
application => route { | |
# TODO: user submission via CUR interface | |
# get -> 'install' { | |
# # code to add the distribution to database/source | |
# } | |
# Get a hash where the keys are sources and values are distributions found in that source. | |
get -> 'installed' { | |
my $repo-dists := | |
grep { .value.values.grep(*.so) }, | |
map { $_ => $_.installed.grep(*.defined).map(*.meta.hash) }, | |
grep { $_ ~~ CompUnit::Repository::Installable }, | |
$*REPO.repo-chain; | |
content 'application/json', $repo-dists.hash; | |
} | |
# Get a hash where the keys are sources and values are distributions found in that source. | |
# The distributions will contain the single best matching candidates, e.g. what `use Foo` decides to choose from. | |
post -> 'resolve' { | |
request-body -> %spec ( | |
:$name!, | |
:$auth, | |
:$api, | |
:ver(:$version), | |
) { | |
my $cur-spec = CompUnit::DependencySpecification.new( | |
short-name => $name, | |
auth-matcher => $auth // True, | |
api-matcher => $api // True, | |
version-matcher => $version // True, | |
); | |
my $repo-dists := | |
grep { .value.values.grep(*.so) }, | |
map { $_.name => $_.resolve($cur-spec).map(*.distribution.meta.hash).cache }, | |
grep { $_ ~~ CompUnit::Repository::Installable }, | |
$*REPO.repo-chain; | |
content 'application/json', $repo-dists.hash; | |
} | |
} | |
# Get a hash where the keys are sources and values are distributions found in that source. | |
# The distributions will contain all matching candidates. | |
post -> 'candidates' { | |
request-body -> %spec ( | |
:$name!, | |
:$auth, | |
:$api, | |
:ver(:$version), | |
) { | |
# TODO: rakudo PR https://github.com/rakudo/rakudo/pull/1125 | |
# replaces the following block with a single a call to CURI.candidates | |
my &candidates := -> $cur, $cu-spec { | |
my $version-matcher = ($cu-spec.version-matcher ~~ Bool) | |
?? $cu-spec.version-matcher | |
!! Version.new($cu-spec.version-matcher); | |
my $api-matcher = ($cu-spec.api-matcher ~~ Bool) | |
?? $cu-spec.api-matcher | |
!! Version.new($cu-spec.api-matcher); | |
my sub parse-value($str-or-kv) { | |
do given $str-or-kv { | |
when Str { $_ } | |
when Hash { $_.keys[0] } | |
when Pair { $_.key } | |
} | |
} | |
my $matching-dists := $cur.installed.grep(*.defined).grep: { | |
my @names = (.meta<name>, .meta<provides>.keys.Slip).unique; | |
my @files = (.meta<provides>.values.map(*.&parse-value).Slip, .meta<files>.hash.keys.Slip); | |
my &name-matcher := { (@names.Slip, @files.Slip).first(*.starts-with($^a)) } | |
so &name-matcher($cu-spec.short-name) | |
and ($_.meta<auth> // '') ~~ $cu-spec.auth-matcher | |
and Version.new($_.meta<ver> // 0) ~~ $version-matcher | |
and Version.new($_.meta<api> // 0) ~~ $api-matcher | |
} | |
$matching-dists.list; | |
} | |
my $cur-spec = CompUnit::DependencySpecification.new( | |
short-name => $name, | |
auth-matcher => $auth // True, | |
api-matcher => $api // True, | |
version-matcher => $version // True, | |
); | |
my $repo-dists := | |
grep { .value.values }, | |
map { $_.name => candidates($_, $cur-spec).map(*.meta.hash).cache }, | |
grep { $_ ~~ CompUnit::Repository::Installable }, | |
$*REPO.repo-chain; | |
content 'application/json', $repo-dists.hash; | |
} | |
} | |
}, | |
) andthen *.start; | |
react { | |
whenever signal(SIGINT) { | |
$zef-meta-service.stop; | |
exit; | |
} | |
} | |
} | |
BEGIN die "Run `zef install Cro --/test` first\n" if (try require ::("Cro::HTTP::Server")) ~~ Nil; |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment