Alternative Mappings Strawman

16 views
Skip to first unread message

khs4473

unread,
Nov 9, 2010, 10:09:39 AM11/9/10
to CommonJS
As a detour from transport formats, I'd like to throw out an
alternative mappings solution and see what the knee-jerk reactions
are. The reason that I'm dissatisfied with package mappings is that
they couple the identification of a dependency with the location of
the dependency, as specified by a URL. I think we can all agree it
would be preferable (all other things being equal) if this coupling
did not exist. Plus, it's just damn confusing (to me anyway).

Let's call this "Simple Mappings" (although putting "simple" in the
name of anything almost always guarantees complexity):

[dep.js]

exports.libraryA = require("khs4473/Q/0.5");
exports.libraryB = require("khs4473/Codera/0.1");

[program.js]

var libA = require("./dep").libraryA;
var libB = require("./dep").libraryB;


In this example, "khs4473/Q/0.5" would be a *globally registered*
package identifier. Now I can hear some of you sneezing. Your
allergies are probably kicking in with the idea of a global registry.
But consider this: does not GitHub have it's own global registry?
Could there not be a "registry.commonjs.org" site that maintains user
and group accounts in a similar manner?

Ash Berlin

unread,
Nov 9, 2010, 10:16:23 AM11/9/10
to comm...@googlegroups.com


I've always been in favour of a global package registry but I seem to be in a minority here (or I was a year ago).

-ash

Wes Garland

unread,
Nov 9, 2010, 10:34:07 AM11/9/10
to comm...@googlegroups.com
> I've always been in favour of a global package registry but I seem to be in a minority here (or I was a year ago).

Food for thought: if we had globally-available module loading facilities, like Loaders/B or ES-Harmony SM loaders, it would be possible to develop and deploy a portable package system.  This in turn means that we don't have to get environment implementers to implement the package system for every CommonJS platform for it to work -- meaning that eventually the market can decide on the value of such a registry, rather than the twenty-or-so people implementing CommonJS environments.

Wes

--
Wesley W. Garland
Director, Product Development
PageMail, Inc.
+1 613 542 2787 x 102

Christoph Dorn

unread,
Nov 9, 2010, 11:03:35 AM11/9/10
to comm...@googlegroups.com

I hope to roll out my package system in the next few months which will
include a central registry we could use for CommonJS. The design is
documented here:

https://github.com/cadorn/pinf/blob/master/docs/Design/Foundation.md

To use packages from this system I envision the following:

[JS Engine] -> [CommonJS Platform] -> [PureJS PM] -> [User Program]

Depending on the implementation of the [PureJS Package Manager] (I'll
provide one), package dependencies can be made available on a package
basis or on a global basis as you desire.

At this stage I am leaning towards building the PM on top of nodules for
completely transparent dependency resolution (without installation
step). If compilation of a depdnency is required a program could be
"primed" before it is run.

Christoph

AJ ONeal

unread,
Nov 9, 2010, 12:42:43 PM11/9/10
to comm...@googlegroups.com
+1

I'm pro a global registry.

I use npm with Node and it's absolutely great.

(and, as always, I'd like it to work with the browser too)

AJ ONeal



--
You received this message because you are subscribed to the Google Groups "CommonJS" group.
To post to this group, send email to comm...@googlegroups.com.
To unsubscribe from this group, send email to commonjs+u...@googlegroups.com.
For more options, visit this group at http://groups.google.com/group/commonjs?hl=en.


Kris Kowal

unread,
Nov 9, 2010, 12:55:52 PM11/9/10
to comm...@googlegroups.com
I'm

* for a registry standard
* for package management solutions that support multiple registries
* against having one registry to rule them all
* against having a registry that couples global package names to local
module identifiers

I support the notion of a CommonJS registry. However, I think that a
registry format and implementation have to prove themselves and meet
the above criteria before I would be willing to support it. I also
would insist that inclusion in the registry be carefully curated. The
question then is "who" would curate it and what principles would they
follow.

* achieving unanimous support for packages on CommonJS would be
impractical since it would be likely to proceed at the same pace as
standards development.
* achieving a quorum on CommonJS is difficult because it's unclear who
the voting membership would consist of.
* CommonJS could delegate authority to manage the registry to a
committee, but the would involve more process and procedure than is in
keeping with the spirit of our organization.
* the principles of a single package registry curator are unlikely to
be representative of the wide variety of stances held by CommonJS
proponents.

Summarily, I think that per-implementation registries like NPM's will
be necessary and a CommonJS registry would not be inclusive enough to
be sufficient. I think it would be useful to have a CommonJS registry
and for all implementations to include it in their multi-registry
package management solution, but such an initiative is presently
premature.

Kris Kowal

khs4473

unread,
Nov 11, 2010, 10:14:14 PM11/11/10
to CommonJS
> * against having a registry that couples global package names to local
module identifiers

Can you explain?

Christoph Dorn

unread,
Nov 12, 2010, 12:37:16 PM11/12/10
to comm...@googlegroups.com
On 10-11-11 7:14 PM, khs4473 wrote:
>> * against having a registry that couples global package names to local
> module identifiers
>
> Can you explain?

A system that has no level of indirection between registry package names
and names used in program code.


i.e. This is insufficient:

http://registry.org/packages/foo

pm add registry http://registry.org/packages/
pm install foo

require("foo/bar")


It should be more like:

pm install http://registry.org/packages/foo

package.json ~ {
"mappings": {
"myfoo": "http://registry.org/packages/foo"
}
}

require("myfoo/bar")

Christoph

Kris Kowal

unread,
Nov 12, 2010, 1:16:23 PM11/12/10
to comm...@googlegroups.com
On Fri, Nov 12, 2010 at 9:37 AM, Christoph Dorn
<christ...@christophdorn.com> wrote:
>
> A system that has no level of indirection between registry package names and
> names used in program code.

Right.

> i.e. This is insufficient:
>
> http://registry.org/packages/foo
>
> pm add registry http://registry.org/packages/
> pm install foo
>
> require("foo/bar")
>
>
> It should be more like:
>
> pm install http://registry.org/packages/foo
>
> package.json ~ {
>  "mappings": {
>    "myfoo": "http://registry.org/packages/foo"
>  }
> }
>
> require("myfoo/bar")

However, it would also be sufficient for there to be explicit
references to a common registry, and even an implied registry for a
particular package manager. Ergo,

package.json ~ {
"dependencies": {
"myfoo": "thei...@1.0.0"
}
}

Or more explicitly:

package.json ~ {
"dependencies": {
"myfoo": "thei...@1.0.0"
},
"registry": "http://example.org/registry/"
}

Or even more explicitly if need be:

package.json ~ {
"dependencies": {
"myfoo": "http://example.org/registry/thei...@1.0.0"
},
}

Or words and schema to that effect.

Kris Kowal

khs4473

unread,
Nov 12, 2010, 1:59:24 PM11/12/10
to CommonJS
> A system that has no level of indirection between registry package names and
> names used in program code.

Why? Indirection is generally useful but what problem does it solve
here?



On Nov 12, 1:16 pm, Kris Kowal <kris.ko...@cixar.com> wrote:
> On Fri, Nov 12, 2010 at 9:37 AM, Christoph Dorn
>
> <christoph...@christophdorn.com> wrote:
>
> > A system that has no level of indirection between registry package names and
> > names used in program code.
>
> Right.
>
>
>
>
>
>
>
>
>
> > i.e. This is insufficient:
>
> >http://registry.org/packages/foo
>
> > pm add registryhttp://registry.org/packages/
> > pm install foo
>
> > require("foo/bar")
>
> > It should be more like:
>
> > pm installhttp://registry.org/packages/foo
>
> > package.json ~ {
> >  "mappings": {
> >    "myfoo": "http://registry.org/packages/foo"
> >  }
> > }
>
> > require("myfoo/bar")
>
> However, it would also be sufficient for there to be explicit
> references to a common registry, and even an implied registry for a
> particular package manager.  Ergo,
>
> package.json ~ {
>     "dependencies": {
>         "myfoo": "their...@1.0.0"
>     }
>
> }
>
> Or more explicitly:
>
> package.json ~ {
>     "dependencies": {
>         "myfoo": "their...@1.0.0"
>     },
>     "registry": "http://example.org/registry/"
>
> }
>
> Or even more explicitly if need be:
>
> package.json ~ {
>     "dependencies": {
>         "myfoo": "http://example.org/registry/their...@1.0.0"

Christoph Dorn

unread,
Nov 12, 2010, 2:02:22 PM11/12/10
to comm...@googlegroups.com
On 10-11-12 10:59 AM, khs4473 wrote:
>> A system that has no level of indirection between registry package names and
>> names used in program code.
>
> Why? Indirection is generally useful but what problem does it solve
> here?

Avoid naming conflicts if two different packages with the same name are
used from two different registries.

Christoph

Kris Kowal

unread,
Nov 12, 2010, 2:06:27 PM11/12/10
to comm...@googlegroups.com
On Fri, Nov 12, 2010 at 10:59 AM, khs4473 <khs...@gmail.com> wrote:
>> A system that has no level of indirection between registry package names and
>> names used in program code.
> Why?  Indirection is generally useful but what problem does it solve
> here?

It solves the problem of a single opinion prevailing against other
opinions in a situation where politics could be entirely avoided.
Without indirection, a registry represents an opinion about how
modules should be named in all programs that subscribe to that
registry. The NPM registry's opinion is that the absolute names of
modules used in every program in that ecosystem should be reserved on
a first-come-first-served basis. The Tusk opinion is that these names
should be subject to minimal review to ensure consistency. A CommonJS
registry's opinion would probably be based on voting. All of these are
valid opinions and developers should not be forced to subscribe to any
single one. They should be given autonomy of the nomenclature used in
their package so as to avoid name conflicts across registries.

Kris Kowal

khs4473

unread,
Nov 12, 2010, 2:07:41 PM11/12/10
to CommonJS
> Why?  Indirection is generally useful but what problem does it solve
> here?

Sorry - I think I understand now - I misread Christoph's post at
first.

I just don't like the idea that I have to write a package.json file to
get anything working though. IMO, that's too much to remember (I
suffer from short term memory loss due to college miseducation, you
see..).

Anyway, how would you feel about a global module namespace? Something
like this:

require("npm/khs4473/flyscript/0.1/main");

where the top level "npm" identifier would be delegated by CommonJS
(somehow...) to a registry and the registry would maintain the
namespace underneath that identifier.

Kris Kowal

unread,
Nov 12, 2010, 2:16:39 PM11/12/10
to comm...@googlegroups.com
On Fri, Nov 12, 2010 at 11:07 AM, khs4473 <khs...@gmail.com> wrote:
> Anyway, how would you feel about a global module namespace?  Something
> like this:
>
> require("npm/khs4473/flyscript/0.1/main");
>
> where the top level "npm" identifier would be delegated by CommonJS
> (somehow...) to a registry and the registry would maintain the
> namespace underneath that identifier.

This amounts to CommonJS dictating an opinion about absolute module
identifiers, and I just don't see it flying. That particular ship has
sailed. There are already many opinions codified on the absolute
module name space. What we need is flexibility to accommodate them.

Kris Kowal

Christoph Dorn

unread,
Nov 12, 2010, 2:22:25 PM11/12/10
to comm...@googlegroups.com
On 10-11-12 11:07 AM, khs4473 wrote:
> Anyway, how would you feel about a global module namespace? Something
> like this:
>
> require("npm/khs4473/flyscript/0.1/main");
>
> where the top level "npm" identifier would be delegated by CommonJS
> (somehow...) to a registry and the registry would maintain the
> namespace underneath that identifier.

FYI: Npm indexes modules by name only and does not include an author prefix:

e.g. http://registry.npmjs.org/Spec_My_Node/-/Spec_My_Node-0.0.2.tgz

In my view dependencies should be declared on a package basis and
modules required via an alias prefix for the package.

All CommonJS programs and libraries (grouping multiple modules) should
have a package.json indicating name, license, author etc... if
distributed online.

You can of course write your own loader that loads individual modules,
but when looking at:

require("npm/khs4473/flyscript/0.1/main");

where is the package/module boundary and where do you download the
module from? If you look back in the package and dependency discussions
a lot of these issues were brought up. Hence the mappings/C spec in its
current form.

Christoph

khs4473

unread,
Nov 12, 2010, 2:58:22 PM11/12/10
to CommonJS
I'll take a look at the packages discussions. I think right now I
just don't get packages. I understand the concept of an "installable
unit" but for the problem that I'm working on there's no such thing.
Everything just is a module. And the fact that you have to go through
baroque transformations in order to figure what a module ID refers
to... But it could be that I just don't understand - I'll try reading
up.



On Nov 12, 2:22 pm, Christoph Dorn <christoph...@christophdorn.com>
wrote:
> On 10-11-12 11:07 AM, khs4473 wrote:
>
> > Anyway, how would you feel about a global module namespace?  Something
> > like this:
>
> > require("npm/khs4473/flyscript/0.1/main");
>
> > where the top level "npm" identifier would be delegated by CommonJS
> > (somehow...) to a registry and the registry would maintain the
> > namespace underneath that identifier.
>
> FYI: Npm indexes modules by name only and does not include an author prefix:
>
> e.g.http://registry.npmjs.org/Spec_My_Node/-/Spec_My_Node-0.0.2.tgz

Ash Berlin

unread,
Nov 12, 2010, 3:05:13 PM11/12/10
to comm...@googlegroups.com
Ignoring any implementation/specifics:

a package is a collection of related modules and possible other resources (templates,images,scripts, etc) where as a module is just a single js file.

-ash

khs4473

unread,
Nov 12, 2010, 8:21:30 PM11/12/10
to CommonJS
> a package is a collection of related modules and possible other resources (templates,images,scripts, etc) where as a module is just a single js file.

er - you mean a folder? : ) JK

Let me give an analogy that hopefully illustrates where I'm coming
from:

Let's say that I (living in the USA) cannot directly send a letter
directly to J (who lives in the UK). I have a USA address and J has a
UK address, but our mail systems don't understand each other's
addresses. In order to send a letter to J, I have to take my letter,
put it in another letter, and address it to some phony address. The
person at the phony address will then get my letter, look up J's name
in a UK phone book and write his UK address on my envelope. Then J
takes a plane to the UK and drops it in a mailbox there.

Huh?

I'm working on a browser/server module transport system where anything
is available from one or more module servers located around the
world. There needs to be an easy way to directly identify modules in
this context. I tried scoping module identifiers to source servers
and other things like that but I nearly twisted my own head off trying
to figure it out. The only sane thing to do is to have a global
module namespace.

Kris Kowal

unread,
Nov 12, 2010, 8:22:59 PM11/12/10
to comm...@googlegroups.com
On Fri, Nov 12, 2010 at 5:21 PM, khs4473 <khs...@gmail.com> wrote:

> The only sane thing to do is to have a global
> module namespace.

The only sane global name space is URL's.

Kris Kowal

khs4473

unread,
Nov 12, 2010, 8:34:22 PM11/12/10
to CommonJS
> The only sane global name space is URL's.

: ) You may be right - that may be what I'm after, ultimately - but
unfortunately it's too late in the day for any more figuring.


On Nov 12, 8:22 pm, Kris Kowal <kris.ko...@cixar.com> wrote:

Wes Garland

unread,
Nov 13, 2010, 10:23:55 AM11/13/10
to comm...@googlegroups.com

I am using URL-without-protocol as a module identifiers in one of my browser implementations right now.  It is working out fairly well.  Adding protocol to the module identifier has two minor gotchas -- going SSL requires source code changes or heuristics, and it's trickier to figure out if we're talking about a module off require.paths or not.  ("conceptual module root" in Modules/1.1 but I don't think that expression is adequate).

Speaking of require.paths, this has also been giving me some implementation-cruftiness; it works out well if you can put the main module's directory on the require path, but of course, a require.paths with length > 1 is pretty much a non-starter in browser land.

"works out well" - is convenient, and allows the interoperable JS test suite to run.  Since, in my model, program modules are normally (but not absolutely) found in the web page the module system is loaded from, I populate require.paths with dirname(window.location.href) during the bootstrap.

So, in this product, I look for leading slashes to tell me that it is a "root-relative" module, i.e. a module identifier which contains all pathing information required to find it -- I then construct a URL for fetching by prepending window.location.protocol.

This doesn't interoperate really well with server-based products, however, which may use a leading slash to indicate that the path is an absolute UNIX path.

Of course, relative module identifiers work like an absolute charm on both the browser and in server-land, and are a real benefit to CommonJS programmers.  Hopefully package authors make good use of these.

Wes

Christoph Dorn

unread,
Nov 13, 2010, 1:39:22 PM11/13/10
to comm...@googlegroups.com

I have been using URL-without-protocol to identify modules and packages
and store them in a corresponding file path and it has been working out
well.

The original purpose of require2 was to have a distinct separation
between a package identifier and a module identifier which is needed
when using URL likes.

i.e. require("foo", "registry.org/packages/a-package");

Since then it has been decided to use package mappings to accomplish the
same with a one-term prefix on the module ID:

package.json ~ {
"mappings":
"my-package": {
"location": "http://registry.org/packages/a-package/"
}
}
}

require("my-package/foo");

If the prefix does not match the module is to be looked up on the global
system namespace.

I just posted on the requirejs list to get this working in the browser
as well [1].

This will allow you to run the same set of packages and modules on
browser and server without having to think about ID issues and sacrifice
in the area of transitive dependencies.

Christoph

[1] -
http://groups.google.com/group/requirejs/browse_thread/thread/f934c7aaf8683c41

Reply all
Reply to author
Forward
0 new messages