Skip to content

Instantly share code, notes, and snippets.

@ugexe
Last active October 21, 2017 23:23
Show Gist options
  • Star 0 You must be signed in to star a gist
  • Fork 0 You must be signed in to fork a gist
  • Save ugexe/10066e2608bdabb1773d69de2d7dfd57 to your computer and use it in GitHub Desktop.
Save ugexe/10066e2608bdabb1773d69de2d7dfd57 to your computer and use it in GitHub Desktop.
# Namespacing multiple versions/apis with `provides` - theoretical examples.
#
# The grammar mentioned below for parsing namespaces (depspecs):
# https://gist.github.com/ugexe/776d8794518d69749e8b53c36d802ddc#file-zef-utils-distribution-pm6-L11
#
# Consider CompUnit::DependencySpecification - it can essentially turn a hash form of depspec into
# string form (ignoring the slight naming inconsistencies), ala .new(|%( :short-name<My::API>, :api-matcher<0> )).
# What it cannot yet do is turn that same string form back into the hash form it is fed, ala .new("My::API:api<0>").
# With a grammer/parser this round trip is possible for literals. I will now extend this thought to `provides`:
{
"name" : "My::API",
"version" : "4.2",
"api". : "1",
"auth" : "foo:bar",
"provides" : {
"My::API" => "lib/My/API.pm6",
# My::API:auth<foo:bar>:api<1>:ver<4.2>
#
# The common scenario.
# CURI/Distribution and zef understand this.
"My::API:api<2>" => "lib/My/API.pm6",
# My::API:auth<foo:bar>:api<2>:ver<4.2>
#
# Mapping a specific namespace to a file that differs from parent distribution's value (api).
# Zefv2 parses the names with a grammar and can understand them (as a side effect of needing to parse
# depends name/adverbs correctly; see url of grammar above). CUR/Distribution does not (it has no need
# to parse depends from meta) and considers "My::API:api<2>" to be the short name, so installation and
# usage does not currently work.
#
# Zefv2 could just expand this to a hash for installation (so CUR/Distribution only needs to understand
# the new fields zef expands into some hash), but then CUR::FileSystem (-I.) would not work since it
# can't parse the namespace.
"My::API" => { "file" : "lib/My/API.pm6", "api" : "3" },
# My::API:auth<foo:bar>:api<3>:ver<4.2>
#
# The expanded form mentioned above. But this is flawed because `provides` is a hash, and
# "My::API" might not be unique when providing multiple api versions (precisely the situation
# here with api 1 and 3). The prior example avoids this because the unique parts (api version)
# is in the namespace string already.
# This is similar to CPAN Meta Spec v2.
"My::API:ver<6.9>" => { "file" : "lib/My/API.pm6", "api" : "4" },
# My::API:auth<foo:bar>:api<4>:ver<6.9>
#
# A hybrid approach of examples with api v2 and v3 included for novelty, along with
# changing the version from the distribution's 4.2 to 6.9.
{
"name" : "My::API",
"file" : "lib/My/API.pm6",
"api" : "5"
},
# My::API:auth<foo:bar>:api<5>:ver<4.2>
#
# `provides` is not an array so this form would require that to change.
# Probably the most generic way, but if you're really providing multiple versions of a namespace it
# would be nice if this was differentiated in the structure somehow (which this does not do).
"My::API:auth<foo:bar>:api<6>:ver<4.2>:file<lib/My/API.pm6>",
# My::API:auth<foo:bar>:api<6>:ver<4.2>
#
# `provides` is not an array so this form would require that to change.
# This is the dependency/use form taken to the near extreme (short of ':name<My::API>:auth<foo:bar>:api<6>:ver<4.2>'')
# and is the opposite of the hash form example in api v5.
#
# Note how api v5 and v6 can easily be round tripped, since its just key/value.
# I like the -availability- of this form because its a legit `use` statement, right down to the :file<>
# (in the context of the right type of distribution anyway). I also like that it makes this closer
# to what a user may put in `depends` (a better example than provides, but a namespace all the same), so
# if it can parse one (hash or string form) it can parse both - thus CURI can also be extended to better
# understand the total dependency graph of it's distributions (instead of just the individual namespaces).
"My::API" => [{ "file" : "lib/My/API.pm6", "api" : "7" }],
# My::API:auth<foo:bar>:api<7>:ver<4.2>
#
# `provides` -value- is not a -string-, so this form would require that to change.
# Its like api v3, except namespace adverbs are stored in an Array of Hash so that the namespace can
# provide multiple versions while still allowing `provides` to remain a hash. It avoids the problem
# mentioned in api v5 because each differentiation on a namespace is grouped under the namespace itself.
#
# This is arguably the best option along with v5. The advantage to v5 to me is this format is more
# human/author friendly as its easier to grok what a namespace encompases vs finding each hash with
# the same value in its name field.
}
}
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment