Packages/Mappings/A

From CommonJS Spec Wiki
Jump to: navigation, search

STATUS: PROPOSAL

Package Mappings

This specification describes an addition to the CommonJS package format for packages to define how they expect their module namespace to be mapped to referenced modules. This defines a new "mappings" property that how a set of module ids should be mapped to canonical URIs of target modules. This specification does not define how the URI target modules are installed or retrieved, and it does not define how any module ids are resolved outside of the mappings.

Simple Example Package Descriptor File

{
   "name": "mypackage",
   "mappings": {
       "other": "jar:http://github.com/someone/other/zipball/master!/lib/"
   },
   ...
}

Package Descriptor File Mappings Property

The "mappings" property may be defined in a package's package.json file and defines the expected translation of module ids for all modules within the package. The "mappings" property value should be an object, where each property represents a mapping. The name of the property indicates the string to use to match module ids for the mapping. Module ids that begin with a "." should never be translated by mappings. The mapping with the longest property in the mappings object that matches should be applied, and subsequent mapping objects may then be ignored. If no mappings are applicable for a module id, then the id should be looked up per the default id lookup scheme.

A require statement from a module in this package that uses an id that begins with the name of the property may be translated with this mapping if one of the following certain conditions:

  • If the module id is identical to the property name and the "to" value (the mapping target) does not end with a slash, the module id should be translated to the resolved "to" value as the URI for the module.
  • If the module ids starts with the property name followed by slash (/) and the "to" value does not end with a dot (.) followed exclusively by word characters ([a-zA-Z0-9]), then the module id should be translated. If the "to" value does not end with a slash, a slash should be appended. Then the remaining string after the property name and slash should be appended to the resolved "to" value (and slash if needed) as the URI for the module.

Finally, the extension (default of ".js") should be appended to create the full URI for the module if the URI does not end with a dot (.) followed exclusively by word characters ([a-zA-Z0-9]).

The value of the property may be a string that defines the target of the mapping or may be a mapping object. The meaning of a string value is identical to the "to" property of a mapping object. If the value is an object (a mapping object), it must contain the following properties:

  • to - This indicates the target id of the translation. The remainder of the string after the part that matches the property name should be appended to the "to" value. The "to" value may be a relative URI, in which case it should be resolved against the location of this package.json file.

The mapping object may contain the following optional properties, that are optionally supported by module loaders or package managers:

  • verify - Provides hash-based verification of the contents of a target archive or file. The value of the "verify" property should be an object with two properties:
    • signature - The signature or hash of the target file/archive.
    • algorithm - The algorithm to use to compute the signature or hash of the target file/archive.
  • mirrors - This denotes alternate URLs that can be used to access the target modules. It is recommended that files downloaded from a mirror only be used if the system ensures that all other packages that reference the target modules provide the same mirror URL in their list of mirrors or provide a secure hash that matches the contents of the files downloaded from mirror. This is to protect poisoning the cache for modules with a malicious files from a mirror.
  • extension - This indicates the extension to append to module ids to create full URIs. This defaults to ".js".

Example Package Descriptor File

{
   "name": "mypackage",
   "mappings": {
   	"other": "jar:http://github.com/someone/other/zipball/master!/lib",
   	"favorite": "jar:http://github.com/someone/other/zipball/master!/lib/favorite.js",
       "foo": {
           "to": "jar:http://downloads.sourceforge.net/project/foo/foo/rc1/foo-v1.zip!/lib/",
           "mirrors": [
           	"jar:http://another-download-site.com/foo-v1.zip!/lib/
           ],
           "verify": {
               "signature": "c1:b1:30:29:d7:b8:de:6c:97:77:10:d7:46:41:63:87",
               "algorithm": "rsa-sha1"
           }
       }
   },
   "overlay": {
       "rhino": {
           "mappings": {
                "http-client": "./engines/rhino/http-client"
           }
       }
   },
   ...
}

Determining Package Information From URIs/modules

When a module's id is a URI, the loader should attempt to associate it with a package, if one exists for the module. The containing package and any directives (like mappings) from its package.json should be read and observed for the target modules. However, it is beyond the normative scope of this proposal to exhaustively define all the ways that a module loader may load or install packages, which may include package management tools, on-demand downloading, packages bundled in a distribution, etc. But, the following conventions should be observed:

  • If a module's URL is within an archive (using the jar URI scheme), then the archive should be correspond to the package for the module (with package.json in the root folder).
  • If a module includes a literal in a comment of the form:

package root: <url> The URL indicates the URL of the root of the package:

  • If a request is made to server for a module the response may includes a Link header that defines "package" relation to the package root.
  • If a module's URL contains "lib" in one of the path identifiers, then the parent path should be considered to be the package root.

Other Considerations

  • It is recommended that when web servers and module loaders resolve and fulfill a URI request to a file system directory, that they look for an "index.js" in the directory to provide as the response for the module request. For example, a web server may look for a index.js in the "my-modules" directory to fulfill a URI request like "http://somesite.com/my-modules/". However, dictating web server behavior like this in beyond the scope of this specification.
  • If an "overlay" is used, the mappings from both the overlay and the base structure should be applied, with the overlay taking precedent.
  • Implementations may treat some URIs with known server URIs structures as equivalent. For example, one can generally assume that the following URIs are the same (and prefer the use of the latter):
http://github.com/{a}/{b}/raw/{c}/{d}
jar:http://github.com/{a}/{b}/zipball/{c}!/{d}

Implementations may also utilize trusted mirrors or repositories for alternate equivalent URLs.

  • This proposal does not dictate how module ids should be interpreted or mapped to packages outside of the mappings (with different mechanisms like package URI schema, two argument require, or other conventions). This proposal only provides a means for a package to declare how its modules expect an explicitly declared ranges of module ids to be mapped to URIs. These mappings only need to be applied to modules within the package.
  • This proposal does not define how or when modules with URIs for different versions of the modules should be treated as a single module (to maintain a singleton even when different versions are requested). Normally modules with different URIs should be considered separate modules, but there may be situations where implementations provide a means for enforcing a single module for a range of URIs. This is outside the scope of the mappings property.

Background