diff --git a/lib/auth.js b/lib/auth.js
index fb34f14..9e466d5 100644
--- a/lib/auth.js
+++ b/lib/auth.js
@@ -1,9 +1,6 @@
-var asp = require('rsvp').denodeify;
+var asp = require('bluebird').promisify;
var request = require('request');
-if (typeof Promise === 'undefined') {
- // To make tests work while running under node 0.10
- Promise = require('rsvp').Promise;
-}
+var Promise = require('bluebird');
// avoid storing passwords as plain text in config
function encodeCredentials(auth) {
@@ -21,9 +18,9 @@ function decodeCredentials(str) {
exports.decodeCredentials = decodeCredentials;
// given options for request, add the auth header / option as appropriate
-function injectRequestOptions(requestOptions, auth) {
- if (!auth)
- return requestOptions;
+function injectRequestOptions(requestOptions, registryInfo) {
+ registryInfo = registryInfo || {};
+ var auth = registryInfo.auth || {};
if (auth.username)
requestOptions.auth = {
user: auth.username,
@@ -33,6 +30,10 @@ function injectRequestOptions(requestOptions, auth) {
requestOptions.headers = requestOptions.headers || {};
requestOptions.headers.authorization = 'Bearer ' + auth.token;
}
+ if (registryInfo.ca)
+ requestOptions.agentOptions = {
+ ca: registryInfo.ca
+ };
return requestOptions;
}
exports.injectRequestOptions = injectRequestOptions;
@@ -87,7 +88,7 @@ function configureCredentials(registry, _auth, ui) {
.then(function() {
return asp(request)(injectRequestOptions({
uri: registry
- }, _auth));
+ }, {auth: _auth}));
})
.then(function(res) {
if (res.statusCode == 401)
diff --git a/lib/node-conversion.js b/lib/node-conversion.js
index 7a7038c..6078cfe 100644
--- a/lib/node-conversion.js
+++ b/lib/node-conversion.js
@@ -1,542 +1,549 @@
-var Promise = require('rsvp').Promise;
-var asp = require('rsvp').denodeify;
-var nodeSemver = require('semver');
+var Promise = require('bluebird');
+var asp = require('bluebird').promisify;
var fs = require('graceful-fs');
var path = require('path');
-var glob = require('glob');
-var npmResolve = require('resolve');
-
-var nodeBuiltins = {
- 'assert': 'github:jspm/nodelibs-assert@^0.1.0',
- 'buffer': 'github:jspm/nodelibs-buffer@^0.1.0',
- 'child_process': 'github:jspm/nodelibs-child_process@^0.1.0',
- 'cluster': 'github:jspm/nodelibs-cluster@^0.1.0',
- 'console': 'github:jspm/nodelibs-console@^0.1.0',
- 'constants': 'github:jspm/nodelibs-constants@^0.1.0',
- 'crypto': 'github:jspm/nodelibs-crypto@^0.1.0',
- 'dgram': 'github:jspm/nodelibs-dgram@^0.1.0',
- 'dns': 'github:jspm/nodelibs-dns@^0.1.0',
- 'domain': 'github:jspm/nodelibs-domain@^0.1.0',
- 'events': 'github:jspm/nodelibs-events@^0.1.1',
- 'fs': 'github:jspm/nodelibs-fs@^0.1.0',
- 'http': 'github:jspm/nodelibs-http@^1.7.0',
- 'https': 'github:jspm/nodelibs-https@^0.1.0',
- 'module': 'github:jspm/nodelibs-module@^0.1.0',
- 'net': 'github:jspm/nodelibs-net@^0.1.0',
- 'os': 'github:jspm/nodelibs-os@^0.1.0',
- 'path': 'github:jspm/nodelibs-path@^0.1.0',
- 'process': 'github:jspm/nodelibs-process@^0.1.0',
- 'punycode': 'github:jspm/nodelibs-punycode@^0.1.0',
- 'querystring': 'github:jspm/nodelibs-querystring@^0.1.0',
- 'readline': 'github:jspm/nodelibs-readline@^0.1.0',
- 'repl': 'github:jspm/nodelibs-repl@^0.1.0',
- 'stream': 'github:jspm/nodelibs-stream@^0.1.0',
- 'string_decoder': 'github:jspm/nodelibs-string_decoder@^0.1.0',
- 'sys': 'github:jspm/nodelibs-util@^0.1.0',
- 'timers': 'github:jspm/nodelibs-timers@^0.1.0',
- 'tls': 'github:jspm/nodelibs-tls@^0.1.0',
- 'tty': 'github:jspm/nodelibs-tty@^0.1.0',
- 'url': 'github:jspm/nodelibs-url@^0.1.0',
- 'util': 'github:jspm/nodelibs-util@^0.1.0',
- 'vm': 'github:jspm/nodelibs-vm@^0.1.0',
- 'zlib': 'github:jspm/nodelibs-zlib@^0.1.0'
-};
-
-var jsonPlugin = exports.jsonPlugin = 'github:systemjs/plugin-json@^0.1.0';
-
-exports.convertPackage = function(pjson, dir) {
- var packageName = pjson.name;
-
- // prepare any aliases we need to create
- var aliases = {};
-
- if (typeof pjson.browser == 'object') {
- var curAlias;
- var curTarget;
- for (var module in pjson.browser) {
- curAlias = module;
- curTarget = pjson.browser[module];
-
- if (typeof curTarget != 'string')
- continue;
-
- // only looking at local aliases here
- if (curAlias.substr(0, 2) != './')
- continue;
-
- if (curAlias.substr(0, 2) == './')
- curAlias = curAlias.substr(2);
- if (curAlias.substr(curAlias.length - 3, 3) == '.js')
- curAlias = curAlias.substr(0, curAlias.length - 3);
+var url = require('url');
+var readdirp = require('readdirp');
+var detectFormat = require('./node-transformer').detectFormat;
+var parseCJS = require('./node-transformer').parseCJS;
+
+var nodelibsPathPrefix = 'npm:jspm-nodelibs-';
+var nodelibsVersion = '@^0.2.0';
+
+var nodeCoreModules = [
+ 'assert',
+ 'buffer',
+ 'child_process',
+ 'cluster',
+ 'console',
+ 'constants',
+ 'crypto',
+ 'dgram',
+ 'dns',
+ 'domain',
+ 'events',
+ 'fs',
+ 'http',
+ 'https',
+ 'module',
+ 'net',
+ 'os',
+ 'path',
+ 'process',
+ 'punycode',
+ 'querystring',
+ 'readline',
+ 'repl',
+ 'stream',
+ 'string_decoder',
+ 'sys',
+ 'timers',
+ 'tls',
+ 'tty',
+ 'url',
+ 'util',
+ 'vm',
+ 'zlib'
+];
+
+exports.convertPackage = function(packageConfig, packageName, packageDir, ui) {
+ packageName = packageName.split(':')[1];
+ packageName = packageName.substr(0, packageName.lastIndexOf('@'));
+
+ var systemConfig = packageConfig.systemjs || packageConfig;
+
+ // glob the file tree of the package
+ return new Promise(function(resolve, reject) {
+ var fileTree = {};
+ readdirp({
+ root: packageDir,
+ entryType: 'both',
+
+ // not a comprehensive filtering - doesnt handle full minimatching
+ // but will do simple directory filtering at least
+ directoryFilter: function(dir) {
+ var path = dir.path.replace(/\\/g, '/');
+
+ // ignore .git, node_modules, jspm_packages
+ if (path.match(/^(\.git|node_modules|jspm_packages)($|\/)/)) {
+ return false;
+ }
+ // files
+ if (packageConfig.files instanceof Array) {
+ if (!packageConfig.files.some(function(file) {
+ file = file.replace(/(\/\*\*\/\*|\/|\/\*|\/\*\*)$/, '');
+ return path.substr(0, file.length) == file && (path.length == file.length || path[file.length] == '/') ||
+ file.substr(0, path.length) == path && file[path.length] == '/';
+ }))
+ return false;
+ }
+ // ignores
+ if (packageConfig.ignore instanceof Array) {
+ if (packageConfig.ignore.some(function(ignore) {
+ return path.substr(0, ignore.length) == ignore && (path.length == ignore.length || path[ignore.length] == '/');
+ }))
+ return false;
+ }
+ return true;
+ }
+ }, function(entry) {
+ var listingName = entry.path.replace(/\\/g, '/');
+ if (entry.stat.isDirectory())
+ listingName += '/';
+ fileTree[listingName] = true;
+ }, function(err) {
+ if (err)
+ reject(err);
+ else
+ resolve(fileTree);
+ });
+ })
+ .then(function(fileTree) {
+ if (systemConfig.main) {
+ systemConfig.main = stripPathExtremes(systemConfig.main);
+ }
+ systemConfig.main = nodeResolve('./' + systemConfig.main, '', fileTree) || nodeResolve('./index', '', fileTree);
- if (curTarget.substr(curTarget.length - 3, 3) == '.js')
- curTarget = curTarget.substr(0, curTarget.length - 3);
+ var coreDeps = [];
- aliases[curAlias] = curTarget;
+ // meta and map are independently populated from the tree only if not already existing
+ var meta;
+ if (!systemConfig.meta) {
+ meta = {
+ '*.json': {
+ format: 'json'
+ }
+ };
}
- }
-
- var buildErrors = [];
- var newDeps = {};
- return asp(glob)(dir + path.sep + '**' + path.sep + '*.js')
- .then(function(files) {
+ var map;
+ if (!systemConfig.map)
+ map = {};
+
+ // convert package.json browser maps if map doesn't yet exist
+ if (map) {
+ // browser / browserify main
+ if (!map['./' + systemConfig.main]) {
+ var browserMain;
+ if (typeof packageConfig.browser == 'string')
+ browserMain = packageConfig.browser;
+ else if (typeof packageConfig.browserify == 'string')
+ browserMain = packageConfig.browserify;
+
+ if (browserMain) {
+ browserMain = stripPathExtremes(browserMain);
+ browserMain = nodeResolve('./' + browserMain, '', fileTree);
+ if (browserMain && browserMain != systemConfig.main)
+ map['./' + systemConfig.main] = {
+ browser: './' + browserMain
+ };
+ }
+ }
- // we store the list of directory files to make
- // only writing after this step to avoid incorrect internal resolutions
- var directoryFiles = [];
+ if (typeof packageConfig.browser == 'object')
+ for (var b in packageConfig.browser) {
+ // dont replace any existing map config
+ if (map[b])
+ continue;
+
+ var mapping = packageConfig.browser[b];
+ var mapResolve;
+
+ if (mapping === false)
+ mapResolve = '@empty';
+ else if (typeof mapping == 'string')
+ mapResolve = nodeResolve(mapping, '', fileTree, true);
+
+ if (mapResolve) {
+ var browserMap = map[b] = {
+ browser: mapResolve
+ };
+
+ // if the map is a dependency, then make sure we have a fallback path to that dependency
+ // for the non-browser case
+ var fallbackName = 'node-' + b;
+ var createdFallback = Object.keys(packageConfig.dependencies).some(function(dep) {
+ if (b.substr(0, dep.length) == dep && (b.length == dep.length || b[dep.length] == '/')) {
+ var depObj = systemConfig.dependencies = systemConfig.dependencies || {};
+ depObj[fallbackName] = packageConfig.dependencies[dep];
+ return true;
+ }
+ });
+ if (!createdFallback)
+ Object.keys(packageConfig.peerDependencies).some(function(dep) {
+ if (b.substr(0, dep.length) == dep && (b.length == dep.length || b[dep.length] == '/')) {
+ var depObj = systemConfig.peerDependencies = systemConfig.peerDependencies || {};
+ depObj[fallbackName] = packageConfig.peerDependencies[dep];
+ return true;
+ }
+ });
+
+ if (createdFallback)
+ browserMap.default = fallbackName;
+ }
+ }
+ }
- return Promise.all(files.map(function(file) {
- var filename = path.relative(dir, file).replace(/\\/g, '/');
+ // modules that need to be added as meta to skip extension handling
+ var skipExtensions = [];
+
+ // track paths that have all common meta
+ // to simplify with wildcards
+ var parsedCommonMeta = {};
+
+ // run through each file in the tree
+ return Promise.all(Object.keys(fileTree).filter(function(file) {
+ return file[file.length - 1] != '/'
+ && file.substr(file.length - 3, 3) != '.md'
+ && file != '.npmignore'
+ && file != '.gitignore';
+ }).map(function(fileName) {
+ var filePath = path.resolve(packageDir, fileName).replace(/\\/g, '/');
+
+ // when generating meta, set up the empty object now
+ var fileFormat = systemConfig.format;
+ if (meta) {
+ var curMeta = {};
+ if (filePath.substr(filePath.length - 5) == '.json')
+ fileFormat = 'json';
+ }
- // skip files in the ignore paths
- // NB this can be removed with https://github.com/jspm/jspm-cli/issues/345
- if (pjson.ignore) {
- if (pjson.ignore.some(function(path) {
- return filename.substr(0, path.length) == path && (filename.substr(path.length, 1) == '/' || filename.substr(path.length, 1) === '');
- }))
- return;
+ // otherwise read format comprehensively from existing metadata
+ else {
+ fileFormat = readMeta(fileName, systemConfig.meta).format || systemConfig.format;
}
- filename = filename.substr(0, filename.length - 3);
- var source;
- var changed = false;
- return Promise.resolve()
+ var fileSource;
+ // if not known, apply detection from source file
+ return Promise.resolve()
.then(function() {
- // if its an "index.js" file, then check if we can create a directory shortcut for it
- var parts = filename.split('/');
- if (parts.pop() != 'index')
+ if (fileFormat)
return;
- var dirName = parts.join(path.sep);
- var dirModule = path.resolve(dir, dirName) + '.js';
- return new Promise(function(resolve, reject) {
- fs.exists(dirModule, resolve);
- })
- .then(function(exists) {
- if (exists)
- return;
- directoryFiles.push(dirModule);
- });
- })
+ return asp(fs.readFile)(filePath)
+ .then(function(source) {
+ fileSource = source.toString();
- .then(function() {
- return asp(fs.readFile)(file);
+ return detectFormat(fileSource);
+ });
})
+ .then(function(detectedFormat) {
+ if (detectedFormat == 'es6')
+ detectedFormat = 'esm'
+
+ if (detectedFormat)
+ fileFormat = detectedFormat;
+
+ // provide all module format detections as configuration if not the package format
+ if (meta && detectedFormat && detectedFormat != (systemConfig.format || 'cjs'))
+ curMeta.format = detectedFormat;
+
+ // non-cjs -> disable process and we're done
+ if (fileFormat != 'cjs') {
+ // global is only format to also support globals
+ if (meta && fileFormat == 'global') {
+ curMeta.globals = curMeta.globals || {};
+ curMeta.globals['process'] = null;
+ }
+ return;
+ }
- .then(function(_source) {
- source = _source.toString();
-
- // at this point, only alter the source file if we're certain it is CommonJS in Node-style
-
- // first check if we have format meta
- var meta = source.match(metaRegEx);
- var metadata = {};
- if (meta) {
- var metaParts = meta[0].match(metaPartRegEx);
- for (var i = 0; i < metaParts.length; i++) {
- var len = metaParts[i].length;
-
- var firstChar = metaParts[i].substr(0, 1);
- if (metaParts[i].substr(len - 1, 1) == ';')
- len--;
-
- if (firstChar != '"' && firstChar != "'")
- continue;
+ // cjs -> parse the source for requires and see if it uses Buffer
+ return Promise.resolve(fileSource || asp(fs.readFile)(filePath))
+ .then(function(source) {
+ var parsed = parseCJS(source.toString(), !meta || !meta['*'] || !meta['*'].globals || !meta['*'].globals.process);
- var metaString = metaParts[i].substr(1, metaParts[i].length - 3);
+ if (meta && parsed.requireDetect === false) {
+ if (parsed.requires.length)
+ curMeta.deps = parsed.requires;
+ curMeta.cjsRequireDetection = false;
+ }
- var metaName = metaString.substr(0, metaString.indexOf(' '));
- if (metaName) {
- var metaValue = metaString.substr(metaName.length + 1, metaString.length - metaName.length - 1);
+ // add buffer global for CJS files that need it
+ if (meta && parsed.usesBuffer && (!systemConfig.map || systemConfig.map.buffer != '@empty')) {
+ curMeta.globals = curMeta.globals || {};
+ curMeta.globals.Buffer = 'buffer/global';
+ if (coreDeps.indexOf('buffer') == -1)
+ coreDeps.push('buffer');
+ }
- if (metadata[metaName] instanceof Array)
- metadata[metaName].push(metaValue);
- else
- metadata[metaName] = metaValue;
- }
+ if (meta && parsed.usesProcess && (!systemConfig.map || systemConfig.map.process != '@empty')) {
+ coreDeps.push('process');
+ meta['*'] = meta['*'] || {};
+ meta['*'].globals = meta['*'].globals || {};
+ meta['*'].globals.process = 'process';
}
- }
- if (pjson.format != 'cjs' && !metadata.format)
- return;
+ /*
+ * Comprehensive internal resolution differences between SystemJS and Node
+ * for internal package requires (that is ignoring package.json, node_modules)
+ *
+ * 1. Directory requires won't resolve to index.js in the directory
+ * 2. Files that resolve to .json, not already ending in .json, are mapped
+ * 3. Files that don't end in .js, that are actual files, will not add extensions
+ * 4. A file by the name file.js.js loaded as file.js will not add extensions
+ * 5. A file by the name file.json.js loaded as file.json will not add extensions
+ *
+ * Currently we cater to (1) by creating a directory map for any index.js file present
+ * in a directory where the directory.js file does not exist.
+ * We then cater to (2 - 5) above by parsing all CommonJS requires of all JS files in
+ * the package and where a resolution matches one of these cases, we include map or meta
+ * config for these files.
+ *
+ * We cater to these assumptions for CommonJS modules only
+ *
+ * It may turn out to be useful to do (2 - 5) for external requires as well, in which
+ * case we can switch this algorithm to a comprehensive correction configuration
+ * being constructed against the entire fileTree to handle all resolution differences.
+ * Even better may turn out to have a post-install hook phase, which can actually investigate
+ * the contents of dependencies to do a similar analysis above to avoid config bloat
+ */
+ // 1. directory resolution
+ if (map && fileName.substr(fileName.length - 9, 9) == '/index.js' && !fileTree[fileName.substr(0, fileName.length - 9)])
+ map['./' + fileName.substr(0, fileName.length - 9)] = './' + fileName;
+
+ parsed.requires.forEach(function(req) {
+ // package require by own name
+ if (req.substr(0, packageName.length) == packageName && (req[packageName.length] == '/' || req.length == packageName.length)) {
+ if (map)
+ map[packageName] = '.';
+ return;
+ }
- if (metadata.format && metadata.format != 'cjs')
- return;
+ // if it is a package require, note if we have a new core dep
+ if (req[0] != '.') {
+ // sys is an alias for util in Node
+ if (req == 'sys')
+ req = 'util';
+ if (nodeCoreModules.indexOf(req) != -1 && coreDeps.indexOf(req) == -1)
+ coreDeps.push(req);
+ return;
+ }
- if (pjson.shim && pjson.shim[filename])
- return;
+ // resolve ./ relative requires only
+ var nodeResolved = nodeResolve(req, fileName, fileTree);
- if (source.match(cmdCommentRegEx))
- source = '//' + source;
+ // if it didn't resolve, ignore it
+ if (!nodeResolved || nodeResolved == '.')
+ return;
- // Note an alternative here would be to use https://github.com/substack/insert-module-globals
- var usesBuffer = source.match(bufferRegEx), usesProcess = source.match(processRegEx);
+ // 2. auto json extension adding
+ if (map && nodeResolved.substr(nodeResolved.length - 5, 5) == '.json' && req.substr(req.length - 5, 5) != '.json')
+ map['./' + nodeResolved.substr(0, nodeResolved.length - 5)] = './' + nodeResolved;
- // the buffer and process nodelibs modules themselves don't wrap themselves
- if (pjson.name == 'buffer')
- usesBuffer = false;
- if (pjson.name == 'process')
- usesProcess = false;
+ // 3. non js file extension
+ else if (meta && nodeResolved.substr(nodeResolved.length - 3, 3) != '.js' && nodeResolved != '.' && nodeResolved != '..')
+ skipExtensions.push(nodeResolved);
- if (usesBuffer || usesProcess) {
- changed = true;
- source = "(function(" + (usesBuffer && 'Buffer' || '') + (usesBuffer && usesProcess && ", " || '') + (usesProcess && 'process' || '') + ") {" + source +
- "\n})(" + (usesBuffer && "require('buffer').Buffer" || '') + (usesBuffer && usesProcess && ", " || '') + (usesProcess && "require('process')" || '') + ");";
+ // 4. file.js.js
+ // 5. file.json.js
+ else if (map && (nodeResolved.substr(nodeResolved.length - 6, 6) == '.js.js' || nodeResolved.substr(nodeResolved.length - 8, 8) == '.json.js'))
+ map['./' + nodeResolved.substr(0, nodeResolved.length - 3)] = './' + nodeResolved;
+ });
+ });
+ })
+ .then(function() {
+ // set curMeta on the main meta object
+ if (meta) {
+ meta[fileName] = curMeta;
+
+ // note common meta for wildcard simplification
+ var pathParts = fileName.split('/');
+ for (var i = 1; i < pathParts.length; i++) {
+ var curCommonPath = pathParts.slice(0, i).join('/');
+ var curCommonParsed = parsedCommonMeta[curCommonPath] = parsedCommonMeta[curCommonPath] || extend({}, curMeta) || {};
+ if (curCommonParsed.format && curCommonParsed.format != fileFormat)
+ curCommonParsed.format = undefined;
+ if (curCommonParsed.globals && JSON.stringify(curCommonParsed.globals) != JSON.stringify(curMeta.globals))
+ curCommonParsed.globals = undefined;
+ }
}
+ });
+ }))
+ .then(function() {
- // remap require statements, with mappings:
- // require('file.json') -> require('file.json!')
- // finally we map builtins to the adjusted module
- var baseDir = path.dirname(path.relative(dir, file));
-
- // only remap if commonjs
- return require('systemjs-builder/compilers/cjs').remap(source, function(dep) {
- var relPath = path.join(baseDir, dep.replace(/\//g, path.sep)).replace(/\\/g, '/');
- var firstPart = dep.split('/').splice(0, dep.substr(0, 1) == '@' ? 2 : 1).join('/');
-
- // packages can import themselves by name
- if (firstPart == packageName) {
- // note mains work here because the npmResolve below picks up the jspm-generated main file
- var depPath = path.join(dir, dep.replace(firstPart, '').replace(/\//g, path.sep));
- dep = path.relative(path.dirname(file), depPath).replace(/\\/g, '/');
- if (dep.substr(0, 1) != '.')
- dep = './' + dep;
- }
+ systemConfig.format = systemConfig.format || 'cjs';
- // first check if this is an alias
- if (aliases[relPath]) {
- changed = true;
- dep = path.relative(baseDir, aliases[relPath].replace(/\//g, path.sep)).replace(/\\/g, '/');
- if (dep.substr(0, 1) != '.')
- dep = './' + dep;
- }
+ // add meta alphabetically
+ if (hasProperties(meta)) {
+ systemConfig.meta = {};
- // check if it is a Node builtin
- else if (!pjson.dependencies[firstPart] && nodeBuiltins[firstPart]) {
- changed = true;
- // only add explicit builtin dependency for production code
- if (!filename.match(/^(test|tests|support|example)\//))
- newDeps[firstPart] = nodeBuiltins[firstPart];
- return firstPart;
- }
+ // consolidate common meta
+ Object.keys(parsedCommonMeta).reverse().forEach(function(commonPath) {
+ var curMeta = parsedCommonMeta[commonPath];
+ if (!curMeta.format && !curMeta.globals)
+ return;
- // if not a package, check for internal resolution
- // run the NodeJS resolver, to know which file we should get
- else if (!pjson.dependencies[firstPart]) {
- try {
- var resolved = npmResolve.sync(dep, { basedir: path.dirname(file), extensions: ['.js', '.json'] });
-
- // too deep - not a jspm resolution
- if (resolved.substr(0, dir.length) == dir) {
- dep = path.relative(path.dirname(file), resolved).replace(/\\/g, '/');
- if (dep.substr(0, 1) != '.')
- dep = './' + dep;
-
- relPath = path.relative(dir, resolved);
- if (relPath.substr(relPath.length - 3, 3) == '.js')
- relPath = relPath.substr(0, relPath.length - 3);
- }
+ Object.keys(meta).forEach(function(path) {
+ if (path.substr(0, commonPath.length) == commonPath && path[commonPath.length] == '/') {
+ if (curMeta.format && meta[path].format == curMeta.format)
+ delete meta[path].format;
+ if (curMeta.globals && JSON.stringify(meta[path].globals) == JSON.stringify(curMeta.globals))
+ delete meta[path].globals;
}
- catch(e) {}
- }
-
- // check if it is an alias again
- if (aliases[relPath]) {
- changed = true;
- dep = path.relative(baseDir, aliases[relPath].replace(/\//g, path.sep)).replace(/\\/g, '/');
- if (dep.substr(0, 1) != '.')
- dep = './' + dep;
- }
-
- // now that we have resolved the dependency, do extension alterations
- if (dep.substr(dep.length - 5, 5) == '.json') {
- changed = true;
- newDeps['systemjs-json'] = jsonPlugin;
- return dep + '!systemjs-json';
- }
+ });
+ meta[commonPath + '/*'] = curMeta;
+ });
- // disable directory requires
- if (dep.substr(dep.length - 1, 1) == '/') {
- changed = true;
- dep = dep.substr(0, dep.length - 1);
- }
+ // ensure all skip extensions either have exact meta or extension meta or true
+ skipExtensions.forEach(function(m) {
+ if (!(hasProperties(meta[m]) || hasProperties(meta['*.' + m.split('/').pop().split('.').pop()])))
+ meta[m] = true;
+ });
- // remove js extensions
- if (dep.substr(dep.length - 3, 3) == '.js' && dep.indexOf('/') != -1) {
- changed = true;
- return dep.substr(0, dep.length - 3);
- }
+ Object.keys(meta).sort().forEach(function(m) {
+ // clear out unnecessary empty metas
+ // only set metas that aren't true or empty
+ if (meta[m] === true || hasProperties(meta[m]))
+ systemConfig.meta[m] = meta[m];
+ });
+ }
- return dep;
- }, file)
- .then(function(output) {
- source = output.source;
+ // add map alphabetically
+ if (map && hasProperties(map)) {
+ systemConfig.map = {};
+ Object.keys(map).sort().forEach(function(m) {
+ systemConfig.map[m] = map[m];
});
- })
- .then(function(output) {
- Object.keys(newDeps).forEach(function(dep) {
- pjson.dependencies[dep] = newDeps[dep];
+ }
+
+ // add core dependencies
+ function inMapTargets(dep) {
+ return Object.keys(systemConfig.map).some(function(map) {
+ var target = systemConfig.map[map];
+ if (typeof target == 'string')
+ target = { '1': target };
+ return Object.keys(target).some(function(submap) {
+ var curTarget = target[submap];
+ return curTarget.substr(0, dep.length) == dep && (curTarget[dep.length] == '/' || curTarget.length == dep.length);
+ });
});
+ }
- if (!changed)
+ systemConfig.peerDependencies = packageConfig.peerDependencies || {};
+ coreDeps.sort().forEach(function(dep) {
+ if (systemConfig.map && systemConfig.map[dep] && typeof systemConfig.map[dep] == 'string' && !inMapTargets(dep) ||
+ packageConfig.peerDependencies && packageConfig.peerDependencies[dep] || packageConfig.dependencies && packageConfig.dependencies[dep])
return;
-
- return asp(fs.writeFile)(file, source);
- }, function(err) {
- buildErrors.push(err);
+ if (packageConfig.browserifyCore !== false)
+ systemConfig.peerDependencies[dep] = nodelibsPathPrefix + dep + nodelibsVersion;
+ else
+ systemConfig.map[dep] = '@node/' + dep;
});
- }))
- .then(function() {
- // write directory forwarding files for external directory requires
- return Promise.all(directoryFiles.map(function(dirFile) {
- var dirName = dirFile.split(path.sep).pop();
- dirName = dirName.substr(0, dirName.length - 3).replace(/\\/g, '/');
- return fs.writeFile(dirFile, "module.exports = require('./" + dirName + "/index');\n");
- }));
+
+ return systemConfig;
});
- })
- .then(function() {
- return buildErrors;
});
-}
+};
-var bufferRegEx = /(?:^|[^$_a-zA-Z\xA0-\uFFFF.])Buffer/;
-var processRegEx = /(?:^|[^$_a-zA-Z\xA0-\uFFFF.])process/;
-
-var metaRegEx = /^(\s*\/\*.*\*\/|\s*\/\/[^\n]*|\s*"[^"]+"\s*;?|\s*'[^']+'\s*;?)+/;
-var metaPartRegEx = /\/\*.*\*\/|\/\/[^\n]*|"[^"]+"\s*;?|'[^']+'\s*;?/g;
-
-var cmdCommentRegEx = /^\s*#/;
-
-// convert NodeJS or Bower dependencies into jspm-compatible dependencies
-var githubRegEx = /^(git(\+[^:]+)?|https):\/\/github.com\/(.+)/;
-var githubHttpRegEx = /^https?:\/\/github\.com\/([^\/]+\/[^\/]+)\/archive\/([^\/]+)\.(tar\.gz|zip)$/;
-var protocolRegEx = /^[^\:\/]+:\/\//;
-var semverRegEx = /^(\d+)(?:\.(\d+)(?:\.(\d+)(?:-([\da-z-]+(?:\.[\da-z-]+)*)(?:\+([\da-z-]+(?:\.[\da-z-]+)*))?)?)?)?$/i;
-function parseDependencies(dependencies, ui) {
- // do dependency parsing
- var outDependencies = {};
- var process = function(d) {
- var dep = dependencies[d];
-
- var match, name, version = '';
-
- // 1. git://github.com/name/repo.git#version -> github:name/repo@version
- if ((match = dep.match(githubRegEx))) {
- dep = match[3];
- name = 'github:' + dep.split('#')[0];
- version = dep.split('#')[1] || '*';
- if (version.substr(0, 1) == 'v' && version.substr(1).match(semverRegEx))
- version = version.substr(1);
- if (name.substr(name.length - 4, 4) == '.git')
- name = name.substr(0, name.length - 4);
- ui.log('warn', 'npm dependency `' + name + '@' + version + '` will likely only work if its GitHub repo has %registry: npm% in its package.json');
+// pulled out of SystemJS internals...
+function readMeta(pkgPath, pkgMeta) {
+ var meta = {};
+
+ // apply wildcard metas
+ var bestDepth = 0;
+ var wildcardIndex;
+ for (var module in pkgMeta) {
+ wildcardIndex = module.indexOf('*');
+ if (wildcardIndex === -1)
+ continue;
+ if (module.substr(0, wildcardIndex) === pkgPath.substr(0, wildcardIndex)
+ && module.substr(wildcardIndex + 1) === pkgPath.substr(pkgPath.length - module.length + wildcardIndex + 1)) {
+ var depth = module.split('/').length;
+ if (depth > bestDepth)
+ bestDepth = depth;
+ extendMeta(meta, pkgMeta[module], bestDepth != depth);
}
+ }
- // 2. https?://github.com/name/repo/archive/v?[semver].tar.gz -> github:name/repo@[semver]
- else if ((match = dep.match(githubHttpRegEx))) {
- name = 'github:' + match[1];
- version = match[2];
- if (version.substr(0, 1) == 'v' && version.substr(1).match(semverRegEx))
- version = version.substr(1);
- }
+ // apply exact meta
+ if (meta[pkgPath])
+ extendMeta(load.metadata, meta[pkgPath]);
- // 3. url:// -> not supported
- else if (dep.match(protocolRegEx))
- throw 'npm dependency format ' + dep + ' not currently supported by jspm. Post an issue if required.';
+ return meta;
+}
+function extendMeta(a, b, prepend) {
+ for (var p in b) {
+ var val = b[p];
+ if (!(p in a))
+ a[p] = val;
+ else if (val instanceof Array && a[p] instanceof Array)
+ a[p] = [].concat(prepend ? val : a[p]).concat(prepend ? a[p] : val);
+ else if (typeof val == 'object' && typeof a[p] == 'object')
+ a[p] = extend(extend({}, a[p]), val, prepend);
+ else if (!prepend)
+ a[p] = val;
+ }
+}
+function extend(a, b, prepend) {
+ for (var p in b) {
+ if (!prepend || !(p in a))
+ a[p] = b[p];
+ }
+ return a;
+}
- // 4. name/repo#version -> github:name/repo@version
- else if (dep.split('/').length == 2) {
- name = 'github:' + dep.split('#')[0];
- version = dep.split('#')[1] || '*';
- if (version.substr(0, 1) == 'v' && version.substr(1).match(semverRegEx))
- version = version.substr(1);
- }
+function hasProperties(obj) {
+ for (var p in obj)
+ return true;
+ return false;
+}
- // 5. version -> name@version
- else {
- name = d;
- version = dep;
- }
+/*
+ * Given a file tree stat, work out the resolution for a package
+ * name is a path within the package, parent is also a path within the package
+ * fileTree is keyed by path, with true as the value. Folders are indicated by trailling /
+ * All paths are assumed '/' separated for this implementation
+ */
+function nodeResolve(name, parent, fileTree, dotRel) {
+ var dotPrefix = dotRel ? './' : '';
- // otherwise, we convert an npm range into something jspm-compatible
- // if it is an exact semver, or a tag, just use it directly
- if (!nodeSemver.valid(version)) {
- var range;
-
- // comma space is allowed on npm for some reason
- version = version.replace(/, /g, ' ');
-
- if (!version || version == 'latest' || version == '*')
- version = '*';
-
- // if we have a semver or fuzzy range, just keep as-is
- else if (version.indexOf(/[ <>=]/) != -1 || !version.substr(1).match(semverRegEx) || !version.substr(0, 1).match(/[\^\~]/))
- range = nodeSemver.validRange(version);
-
- if (range == '*')
- version = '*';
-
- else if (range) {
- // if it has OR semantics, we only support the last range
- if (range.indexOf('||') != -1)
- range = range.split('||').pop();
-
- var rangeParts = range.split(' ');
-
- // convert AND statements into a single lower bound and upper bound
- // enforcing the lower bound as inclusive and the upper bound as exclusive
- var lowerBound, upperBound, lEq, uEq;
- for (var i = 0; i < rangeParts.length; i++) {
- var part = rangeParts[i];
- var a = part.charAt(0);
- var b = part.charAt(1);
-
- // get the version
- var v = part;
- if (b == '=')
- v = part.substr(2);
- else if (a == '>' || a == '<' || a == '=')
- v = part.substr(1);
-
- // and the operator
- var gt = a == '>';
- var lt = a == '<';
-
- if (gt) {
- // take the highest lower bound
- if (!lowerBound || nodeSemver.gt(lowerBound, v)) {
- lowerBound = v;
- lEq = b == '=';
- }
- }
- else if (lt) {
- // take the lowest upper bound
- if (!upperBound || nodeSemver.lt(upperBound, v)) {
- upperBound = v;
- uEq = b == '=';
- }
- }
- else {
- // equality
- lowerBound = upperBound = (part.substr(0, 1) == '=' ? part.substr(1) : part);
- lEq = uEq = true;
- break;
- }
- }
+ // leave absolute paths undisturbed
+ if (name[0] == '/')
+ return;
- // for some reason nodeSemver adds "-0" when not appropriate
- if (lowerBound && lowerBound.substr(lowerBound.length - 2, 2) == '-0')
- lowerBound = lowerBound.substr(0, lowerBound.length - 2);
- if (upperBound && upperBound.substr(upperBound.length - 2, 2) == '-0')
- upperBound = upperBound.substr(0, upperBound.length - 2);
-
- var lowerSemver, upperSemver;
-
- if (lowerBound) {
- lowerSemver = lowerBound.match(semverRegEx);
- lowerSemver[1] = parseInt(lowerSemver[1], 10);
- lowerSemver[2] = parseInt(lowerSemver[2], 10);
- lowerSemver[3] = parseInt(lowerSemver[3], 10);
- if (!lEq) {
- if (!lowerSemver[4])
- lowerSemver[4] = '0';
- // NB support incrementing existing preleases
- }
- }
+ // relative paths are resolved relatively and statted
+ if (name.substr(0, 2) == './' || name.substr(0, 3) == '../' && parent.indexOf('/') != -1) {
+ name = url.resolve('/' + parent, name).substr(1);
- if (upperBound) {
- upperSemver = upperBound.match(semverRegEx);
- upperSemver[1] = parseInt(upperSemver[1], 10);
- upperSemver[2] = parseInt(upperSemver[2], 10);
- upperSemver[3] = parseInt(upperSemver[3], 10);
- }
+ if (!name)
+ name = '.';
- if (!upperBound && !lowerBound) {
- version = '';
- }
+ if (name[name.length - 1] != '/') {
+ if (fileTree.hasOwnProperty(name))
+ return dotPrefix + name;
- // if not upperBound, then just treat as a wildcard
- else if (!upperBound) {
- version = '*';
- }
+ if (fileTree.hasOwnProperty(name + '.js'))
+ return dotPrefix + name + '.js';
- // if no lowerBound, use the upperBound directly, with sensible decrementing if necessary
- else if (!lowerBound) {
+ if (fileTree.hasOwnProperty(name + '.json'))
+ return dotPrefix + name + '.json';
+ }
- if (uEq) {
- version = upperBound;
- }
+ // no file match -> try loading as a folder
+ var folderName = name + (name[name.length - 1] == '/' ? '' : '/');
- else {
- if (!upperSemver[4]) {
- if (upperSemver[3] > 0) {
- upperSemver[3]--;
- }
- else if (upperSemver[2] > 0) {
- upperSemver[2]--;
- upperSemver[3] = 0;
- }
- else if (upperSemver[1] > 0) {
- upperSemver[1]--;
- upperSemver[2] = 0;
- upperSemver[3] = 0;
- }
- }
- else {
- upperSemver[4] = undefined;
- }
- version = getVersion(upperSemver);
- }
- }
+ if (fileTree.hasOwnProperty(folderName))
+ return dotPrefix + folderName + 'index.js';
- else {
- // if upper bound is inclusive, use it
- if (uEq)
- version = upperBound;
+ // unable to resolve -> ignore
+ return;
+ }
- // if upper bound is exact major
- else if (upperSemver[2] === 0 && upperSemver[3] === 0 && !upperSemver[4]) {
+ // plain name -> package resolution
+ return name;
+}
- // if previous major is 0
- if (upperSemver[1] - 1 === 0) {
- version = '0';
- }
- else {
- // if lower bound is major below, we are semver compatible
- if (lowerSemver[1] == upperSemver[1] - 1)
- version = '^' + getVersion(lowerSemver);
- // otherwise we are semver compatible with the previous exact major
- else
- version = '^' + (upperSemver[1] - 1);
- }
- }
- // if upper bound is exact minor
- else if (upperSemver[3] === 0 && !upperSemver[4]) {
- // if lower bound is minor below, we are fuzzy compatible
- if (lowerSemver[2] == upperSemver[2] - 1)
- version = '~' + getVersion(lowerSemver);
- // otherwise we are fuzzy compatible with previous
- else
- version = '~' + upperSemver[1] + '.' + (upperSemver[2] - 1) + '.0';
- }
- // if upper bound is exact version -> use exact
- else
- throw 'Unable to translate npm version ' + version + ' into a jspm range.';
- }
- }
- }
+// Removes './' from the beginning of paths or '/' from the end of paths, etc
+function stripPathExtremes(path) {
+ if (path == '.')
+ path = '';
+ else if (path.substr(0, 2) == './')
+ path = path.substr(2);
- outDependencies[d] = name + (version ? '@' + version : '');
- };
- for (var d in dependencies) process(d);
- return outDependencies;
-}
+ if (path[path.length - 1] == '/')
+ path = path.substr(0, path.length - 1);
-function getVersion(semver) {
- return semver[1] + '.' + semver[2] + '.' + semver[3] + (semver[4] ? '-' + semver[4] : '');
+ return path;
}
-exports.parseDependencies = parseDependencies;
-
diff --git a/lib/node-transformer.js b/lib/node-transformer.js
new file mode 100644
index 0000000..7538c69
--- /dev/null
+++ b/lib/node-transformer.js
@@ -0,0 +1,238 @@
+var traceur = require('traceur');
+var traceurVersion = traceur.loader.NodeTraceurLoader.prototype.version;
+
+function traceurGet (module) {
+ return $traceurRuntime.ModuleStore.get('traceur@' + traceurVersion + '/src/' + module);
+}
+
+var ParseTreeTransformer = traceurGet('codegeneration/ParseTreeTransformer.js').ParseTreeTransformer;
+var ScopeTransformer = traceurGet('codegeneration/ScopeTransformer.js').ScopeTransformer;
+
+
+var Script = traceurGet('syntax/trees/ParseTrees.js').Script;
+var parseStatements = traceurGet('codegeneration/PlaceholderParser.js').parseStatements;
+var STRING = traceurGet('syntax/TokenType.js').STRING;
+var LiteralExpression = traceurGet('syntax/trees/ParseTrees.js').LiteralExpression;
+var LiteralToken = traceurGet('syntax/LiteralToken.js').LiteralToken;
+
+// format detection regexes
+var leadingCommentAndMetaRegEx = /^\s*(\/\*[^\*]*(\*(?!\/)[^\*]*)*\*\/|\s*\/\/[^\n]*|\s*"[^"]+"\s*;?|\s*'[^']+'\s*;?)*\s*/;
+var cjsRequireRegEx = /(?:^\uFEFF?|[^$_a-zA-Z\xA0-\uFFFF."'])require\s*\(\s*("[^"\\]*(?:\\.[^"\\]*)*"|'[^'\\]*(?:\\.[^'\\]*)*')\s*\)/g;
+var cjsExportsRegEx = /(?:^\uFEFF?|[^$_a-zA-Z\xA0-\uFFFF.])(exports\s*(\[['"]|\.)|module(\.exports|\['exports'\]|\["exports"\])\s*(\[['"]|[=,\.]))/;
+var amdRegEx = /(?:^\uFEFF?|[^$_a-zA-Z\xA0-\uFFFF.])define\s*\(\s*("[^"]+"\s*,\s*|'[^']+'\s*,\s*)?\s*(\[(\s*(("[^"]+"|'[^']+')\s*,|\/\/.*\r?\n|\/\*(.|\s)*?\*\/))*(\s*("[^"]+"|'[^']+')\s*,?)?(\s*(\/\/.*\r?\n|\/\*(.|\s)*?\*\/))*\s*\]|function\s*|{|[_$a-zA-Z\xA0-\uFFFF][_$a-zA-Z0-9\xA0-\uFFFF]*\))/;
+
+var metaRegEx = /^(\s*\/\*[^\*]*(\*(?!\/)[^\*]*)*\*\/|\s*\/\/[^\n]*|\s*"[^"]+"\s*;?|\s*'[^']+'\s*;?)+/;
+var metaPartRegEx = /\/\*[^\*]*(\*(?!\/)[^\*]*)*\*\/|\/\/[^\n]*|"[^"]+"\s*;?|'[^']+'\s*;?/g;
+
+exports.detectFormat = function(source) {
+ // read any SystemJS meta syntax
+ var meta = source.match(metaRegEx);
+ if (meta) {
+ var metaParts = meta[0].match(metaPartRegEx);
+
+ for (var i = 0; i < metaParts.length; i++) {
+ var curPart = metaParts[i];
+ var len = curPart.length;
+
+ var firstChar = curPart.substr(0, 1);
+ if (curPart.substr(len - 1, 1) == ';')
+ len--;
+
+ if (firstChar != '"' && firstChar != "'")
+ continue;
+
+ var metaString = curPart.substr(1, curPart.length - 3);
+
+ if (metaString.substr(0, 7) == 'format ')
+ return metaString.substr(7);
+ else if (metaString == 'bundle')
+ return 'register';
+ }
+ }
+
+ // detect register
+ var leadingCommentAndMeta = source.match(leadingCommentAndMetaRegEx);
+ if (leadingCommentAndMeta && source.substr(leadingCommentAndMeta[0].length, 15) == 'System.register')
+ return 'register';
+
+ // esm
+ try {
+ var compiler = new traceur.Compiler({ script: false });
+ var tree = compiler.parse(source);
+ var transformer = new ESMDetectionTransformer();
+ transformer.transformAny(tree);
+ if (transformer.isESModule)
+ return 'esm';
+ else
+ compiler = tree = undefined;
+ }
+ catch(e) {
+ compiler = tree = undefined;
+ }
+
+ // cjs
+ // (NB this should be updated to be parser based, with caching by name to parseCJS below)
+ if (source.match(cjsRequireRegEx) || source.match(cjsExportsRegEx))
+ return 'cjs';
+
+ // amd
+ if (source.match(amdRegEx))
+ return 'amd';
+
+ // fallback is cjs (not global)
+ return 'cjs';
+};
+
+exports.parseCJS = function(source, detectProcess) {
+ var output = {
+ requires: [],
+ usesBuffer: false,
+ usesProcess: false,
+ requireDetect: true
+ };
+
+ var compiler, tree, transformer;
+
+ // if this is a browserified module, then we skip require detection entirely
+ // (webpack and SystemJS builds rename internal hidden require statements so aren't a problem)
+ if (source.indexOf('(function e(t,n,r){function s(o,u){if(!n[o]){if(!t[o]){var a=typeof require=="function"&&require;') != -1) {
+ output.requireDetect = false;
+ return output;
+ }
+
+ // CJS Buffer detection and require extraction
+ try {
+ compiler = new traceur.Compiler({ script: true });
+ tree = tree || compiler.parse(source);
+ }
+ catch(e) {
+ return output;
+ }
+
+ // sets output.requires
+ transformer = new CJSDepsTransformer();
+ try {
+ transformer.transformAny(tree);
+ }
+ catch(e) {}
+ output.requires = transformer.requires;
+
+ // sets output.usesBuffer
+ transformer = new GlobalUsageTransformer('Buffer');
+ try {
+ transformer.transformAny(tree);
+ }
+ catch(e) {}
+ output.usesBuffer = !!transformer.usesGlobal;
+
+ // sets output.usesProcess
+ transformer = new GlobalUsageTransformer('process');
+ try {
+ transformer.transformAny(tree);
+ }
+ catch(e) {}
+ output.usesProcess = !!transformer.usesGlobal;
+
+ return output;
+};
+
+
+function ESMDetectionTransformer() {
+ this.isESModule = false;
+ return ParseTreeTransformer.apply(this, arguments);
+}
+ESMDetectionTransformer.prototype = Object.create(ParseTreeTransformer.prototype);
+ESMDetectionTransformer.prototype.transformExportDeclaration = function(tree) {
+ this.isESModule = true;
+ return ParseTreeTransformer.prototype.transformExportDeclaration.call(this, tree);
+};
+ESMDetectionTransformer.prototype.transformImportDeclaration = function(tree) {
+ this.isESModule = true;
+ return ParseTreeTransformer.prototype.transformImportDeclaration.call(this, tree);
+};
+
+// esm remapping not currently in use
+/*
+function ESMImportsTransformer() {
+ this.imports = [];
+ return ParseTreeTransformer.apply(this, arguments);
+}
+ESMImportsTransformer.prototype = Object.create(ParseTreeTransformer.prototype);
+ESMImportsTransformer.prototype.transformModuleSpecifier = function(tree) {
+ if (this.imports.indexOf(tree.token.processedValue) == -1)
+ this.imports.push(tree.token.processedValue);
+
+ return ParseTreeTransformer.prototype.transformModuleSpecifier.call(this, tree);
+};
+*/
+
+function CJSDepsTransformer() {
+ this.requires = [];
+ return ParseTreeTransformer.apply(this, arguments);
+}
+CJSDepsTransformer.prototype = Object.create(ParseTreeTransformer.prototype);
+
+CJSDepsTransformer.prototype.transformCallExpression = function(tree) {
+ if (!tree.operand.identifierToken || tree.operand.identifierToken.value != 'require')
+ return ParseTreeTransformer.prototype.transformCallExpression.call(this, tree);
+
+ // found a require
+ var args = tree.args.args;
+ if (args.length && args[0].type == 'LITERAL_EXPRESSION' && args.length == 1) {
+ if (this.requires.indexOf(args[0].literalToken.processedValue) == -1 && typeof args[0].literalToken.processedValue == 'string')
+ this.requires.push(args[0].literalToken.processedValue);
+ }
+
+ return ParseTreeTransformer.prototype.transformCallExpression.call(this, tree);
+};
+
+function GlobalUsageTransformer(varName) {
+ this.usesGlobal = undefined;
+ return ScopeTransformer.apply(this, arguments);
+}
+GlobalUsageTransformer.prototype = Object.create(ScopeTransformer.prototype);
+GlobalUsageTransformer.prototype.transformIdentifierExpression = function(tree) {
+ if (tree.identifierToken.value == this.varName_ && this.usesGlobal !== false)
+ this.usesGlobal = true;
+ return ScopeTransformer.prototype.transformIdentifierExpression.apply(this, arguments);
+};
+GlobalUsageTransformer.prototype.transformBindingIdentifier = function(tree) {
+ if (tree.identifierToken.value == this.varName_ && this.usesGlobal !== false)
+ this.usesGlobal = true;
+ return ScopeTransformer.prototype.transformBindingIdentifier.apply(this, arguments);
+};
+GlobalUsageTransformer.prototype.sameTreeIfNameInLoopInitializer_ = function(tree) {
+ try {
+ tree = ScopeTransformer.prototype.sameTreeIfNameInLoopInitializer_.call(this, tree);
+ }
+ catch(e) {}
+ return tree;
+};
+GlobalUsageTransformer.prototype.transformVariableDeclaration = function(tree) {
+ if (tree.lvalue.identifierToken.value == this.varName_)
+ return tree;
+ return ScopeTransformer.prototype.transformVariableDeclaration.call(this, tree);
+};
+
+// NB incorrect handling for function Buffer() {}, but we don't have better scope analysis available
+// until a shift to Babel :(
+GlobalUsageTransformer.prototype.transformFunctionDeclaration = function(tree) {
+ if (tree.name && tree.name.identifierToken && tree.name.identifierToken.value == this.varName_)
+ this.usesGlobal = false;
+ return ScopeTransformer.prototype.transformFunctionDeclaration.apply(this, arguments);
+}
+GlobalUsageTransformer.prototype.getDoNotRecurse = function(tree) {
+ var doNotRecurse;
+ try {
+ doNotRecurse = ScopeTransformer.prototype.getDoNotRecurse.call(this, tree);
+ }
+ catch(e) {}
+ return doNotRecurse;
+};
+GlobalUsageTransformer.prototype.transformBlock = function(tree) {
+ try {
+ tree = ScopeTransformer.prototype.transformBlock.call(this, tree);
+ }
+ catch(e) {}
+ return tree;
+};
diff --git a/lib/npm.js b/lib/npm.js
index be993aa..9092252 100644
--- a/lib/npm.js
+++ b/lib/npm.js
@@ -1,20 +1,30 @@
-var Promise = require('rsvp').Promise;
-var asp = require('rsvp').denodeify;
+var Promise = require('bluebird');
+var asp = require('bluebird').promisify;
var request = require('request');
var zlib = require('zlib');
-var tar = require('tar');
+var tar = require('tar-fs');
var url = require('url');
var fs = require('graceful-fs');
var path = require('path');
var mkdirp = require('mkdirp');
+var peek = require('buffer-peek-stream');
var Npmrc = require('./npmrc');
var auth = require('./auth');
+var nodeSemver = require('semver');
var nodeConversion = require('./node-conversion');
var Npmrc = require('./npmrc');
var defaultRegistry = 'https://registry.npmjs.org';
+// Test whether the contents of buffer is gzipped
+function isGzip(buffer) {
+ if (!buffer || buffer.length < 3) {
+ return false;
+ }
+ return buffer[0] === 0x1f && buffer[1] === 0x8b && buffer[2] === 0x08;
+}
+
function clone(a) {
var b = {};
for (var p in a) {
@@ -31,19 +41,13 @@ function clone(a) {
var NPMLocation = function(options, ui) {
this.ui = ui;
this.name = options.name;
-
- var npmrc = new Npmrc();
-
- this.registryURL = function (scope) {
- return scope && npmrc.getRegistry(scope) || options.registry || npmrc.getRegistry() || defaultRegistry;
- };
-
this.tmpDir = options.tmpDir;
this.remote = options.remote;
this.strictSSL = 'strictSSL' in options ? options.strictSSL : true;
+ this.maxRepoSize = 'maxRepoSize' in options ? options.maxRepoSize * 1024 * 1024 : 50000000;
// cache versioning scheme used for patches
- // this.versionString = options.versionString + '.1';
+ this.versionString = options.versionString + '.2';
if (options.username && !options.auth)
options.auth = auth.encodeCredentials(options.username, options.password);
@@ -51,16 +55,50 @@ var NPMLocation = function(options, ui) {
// delete options.username;
// delete options.password;
- if (options.authToken)
- this.auth = { token: options.authToken };
- else if (options.auth)
- this.auth = auth.decodeCredentials(options.auth);
- else
- this.auth = npmrc.getAuth(this.registryURL());
+ var npmrc = new Npmrc();
- // only alwaysAuth when the registryURL is not the defaultRegistry
- // otherwise we just auth for scopes
- this.alwaysAuth = this.registryURL() != defaultRegistry;
+ this.registryURL = function (scope) {
+ return scope && npmrc.getRegistry(scope) || options.registry || npmrc.getRegistry() || defaultRegistry;
+ };
+
+ this.registryInfo = function (repo) {
+ // scope
+ var scope;
+ if (repo[0] === '@') {
+ var scopeMatch = repo.match(/^(@.*)\//);
+ if (scopeMatch[1]) {
+ scope = scopeMatch[1];
+ }
+ }
+
+ // url
+ var url = this.registryURL(scope);
+
+ // auth
+ // only alwaysAuth when the registryURL is not the defaultRegistry
+ // otherwise we just auth for scopes
+ var authData;
+ var ca;
+ if (this.registryURL() != defaultRegistry || scope) {
+ authData = scope && npmrc.getAuth(url);
+ ca = npmrc.getCa();
+
+ if (!authData) {
+ if (options.authToken)
+ authData = { token: options.authToken };
+ else if (options.auth)
+ authData = auth.decodeCredentials(options.auth);
+ else
+ authData = npmrc.getAuth(this.registryURL());
+ }
+ }
+
+ return {
+ url: url,
+ auth: authData,
+ ca: ca
+ };
+ }
};
NPMLocation.configure = function(config, ui) {
@@ -127,7 +165,7 @@ NPMLocation.configure = function(config, ui) {
});
};
-NPMLocation.packageFormat = /^@[^\/]+\/[^\/]+|^[^@\/][^\/]+/;
+NPMLocation.packageNameFormats = ['@*/*', '*'];
NPMLocation.prototype = {
@@ -139,8 +177,6 @@ NPMLocation.prototype = {
var latestKey = 'latest';
var repoPath = repo[0] == '@' ? '@' + encodeURIComponent(repo.substr(1)) : encodeURIComponent(repo);
- var doAuth = this.alwaysAuth || repo[0] == '@';
-
return asp(fs.readFile)(path.resolve(self.tmpDir, repo + '.json'))
.then(function(lookupJSON) {
lookupCache = JSON.parse(lookupJSON.toString());
@@ -150,21 +186,17 @@ NPMLocation.prototype = {
throw e;
})
.then(function() {
- var scope;
- if (repo[0] === '@') {
- var scopeMatch = repo.match(/^(@.*)\//);
- if (scopeMatch[1]) {
- scope = scopeMatch[1];
- }
- }
+ var registryInfo = self.registryInfo(repo);
+
return asp(request)(auth.injectRequestOptions({
- uri: self.registryURL(scope) + '/' + repoPath,
+ uri: registryInfo.url + '/' + repoPath,
gzip: true,
strictSSL: self.strictSSL,
+ gzip: true,
headers: lookupCache ? {
'if-none-match': lookupCache.eTag
} : {}
- }, doAuth && self.auth)).then(function(res) {
+ }, registryInfo)).then(function(res) {
if (res.statusCode == 304)
return { versions: lookupCache.versions,
latest: lookupCache.latest };
@@ -181,10 +213,11 @@ NPMLocation.prototype = {
var versions = {};
var latest;
var packageData;
+ var distTags;
try {
var json = JSON.parse(res.body);
- var distTags = json['dist-tags'] || {};
+ distTags = json['dist-tags'] || {};
packageData = json.versions;
latest = distTags[latestKey];
}
@@ -192,6 +225,10 @@ NPMLocation.prototype = {
throw 'Unable to parse package.json';
}
+ for (var alias in distTags)
+ if (packageData[distTags[alias]])
+ packageData[alias] = packageData[distTags[alias]];
+
for (var v in packageData) {
if (packageData[v].dist && packageData[v].dist.shasum)
versions[v] = {
@@ -213,7 +250,7 @@ NPMLocation.prototype = {
return { versions: versions,
latest: latest };
}, function(err) {
- if (err.code == 'ENOTFOUND' && err.toString().indexOf('getaddrinfo') != -1 || err.code == 'ECONNRESET') {
+ if (err.code == 'ENOTFOUND' && err.toString().indexOf('getaddrinfo') != -1 || err.code == 'ECONNRESET' || err.code == 'ETIMEDOUT' || err.code == 'ESOCKETTIMEDOUT') {
err.retriable = true;
err.hideStack = true;
}
@@ -238,108 +275,87 @@ NPMLocation.prototype = {
});
},
- getPackageConfig: function(repo, version, hash, pjson) {
- if (!pjson)
+ getPackageConfig: function(repo, version, hash, packageConfig) {
+ if (!packageConfig)
throw 'Package.json meta not provided in endpoint request';
- if (hash && pjson.dist.shasum != hash)
+ if (hash && packageConfig.dist.shasum != hash)
throw 'Package.json lookup hash mismatch';
- return clone(pjson);
+ return clone(packageConfig);
},
- processPackageConfig: function(pjson, packageName) {
- if (pjson.jspmNodeConversion === false || pjson.jspmPackage)
- return pjson;
-
- // peer dependencies are just dependencies in jspm
- pjson.dependencies = pjson.dependencies || {};
- if (pjson.peerDependencies) {
- for (d in pjson.peerDependencies)
- pjson.dependencies[d] = pjson.peerDependencies[d];
- }
-
- // warn if using jspm-style dependencies at this point
- for (var d in pjson.dependencies)
- if (!pjson.dependencies[d].match(/^(https?|git)[:+]/) && pjson.dependencies[d].indexOf(':') > 0)
- throw 'Package.json dependency %' + d + '% set to `' + pjson.dependencies[d] + '`, which is not a valid dependency format for npm.'
- + '\nIt\'s advisable to publish jspm-style packages to GitHub or another `registry` so conventions are clear.';
- + '\nTo skip npm compatibility install with %jspm install ' + packageName + '-o "{jspmPackage: true}"%.'
-
-
- pjson.dependencies = nodeConversion.parseDependencies(pjson.dependencies, this.ui);
-
- pjson.format = pjson.format || 'cjs';
+ processPackageConfig: function(packageConfig, packageName) {
+ if (packageConfig.jspmNodeConversion === false || packageConfig.jspmPackage)
+ return packageConfig;
+
+ packageConfig.dependencies = parseDependencies(packageConfig.dependencies, this.ui);
+ packageConfig.peerDependencies = parseDependencies(packageConfig.peerDependencies, this.ui);
+ packageConfig.optionalDependencies = parseDependencies(packageConfig.optionalDependencies, this.ui);
+
+ // ensure optionalDependencies take preference over peer and normal dependencies
+ if (packageConfig.optionalDependencies)
+ Object.keys(packageConfig.optionalDependencies).forEach(function(dep) {
+ if (packageConfig.peerDependencies && packageConfig.peerDependencies[dep])
+ delete packageConfig.peerDependencies[dep];
+ if (packageConfig.dependencies && packageConfig.dependencies[dep])
+ delete packageConfig.dependencies[dep];
+ });
- if (pjson.main instanceof Array)
- this.ui.log('warn', 'Package `' + packageName + '` has a main array, which has been ignored as it is not supported in Node and npm.');
+ // ensure peerDependencies take preference over normal dependencies
+ if (packageConfig.peerDependencies)
+ Object.keys(packageConfig.peerDependencies).forEach(function(dep) {
+ if (packageConfig.dependencies[dep])
+ delete packageConfig.dependencies[dep];
+ });
- // json mains become plugins
- if (pjson.main && typeof pjson.main == 'string' && pjson.main.substr(pjson.main.length - 5, 5) == '.json') {
- pjson.main += '!systemjs-json';
- pjson.dependencies['systemjs-json'] = nodeConversion.jsonPlugin;
+ if (packageConfig.main instanceof Array) {
+ delete packageConfig.main;
+ this.ui.log('warn', 'Package `' + packageName + '` has a main array, which is not supported.');
}
// ignore directory flattening for NodeJS, as npm doesn't do it
// we do allow if there was an override through the jspm property though
- if (!pjson.jspm || !pjson.jspm.directories)
- delete pjson.directories;
-
- // ignore node_modules by default when processing
- if (!(pjson.ignore instanceof Array))
- pjson.ignore = [];
- pjson.ignore.push('node_modules');
-
- if (pjson.files && pjson.files instanceof Array && pjson.files.indexOf('package.json') == -1)
- pjson.files.push('package.json');
-
-
- // if there is a "browser" object, convert it into map config for browserify support
- if (typeof pjson.browserify == 'string')
- pjson.main = pjson.browserify;
- if (typeof pjson.browser == 'string')
- pjson.main = pjson.browser;
-
- if (typeof pjson.browser == 'object') {
- pjson.map = pjson.map || {};
- for (var b in pjson.browser) {
- var mapping = pjson.browser[b];
-
- if (mapping === false) {
- mapping = '@empty';
- }
- else if (typeof mapping == 'string') {
- if (b.substr(b.length - 3, 3) == '.js')
- b = b.substr(0, b.length - 3);
- if (mapping.substr(mapping.length - 3, 3) == '.js')
- mapping = mapping.substr(0, mapping.length - 3);
-
- // we handle relative maps during the build phase
- if (b.substr(0, 2) == './')
- continue;
- }
- else
- continue;
+ if (!packageConfig.jspm || !packageConfig.jspm.directories) {
+ delete packageConfig.directories;
+ }
+ else if (packageConfig.directories) {
+ if (!packageConfig.jspm.directories.lib)
+ delete packageConfig.directories.lib;
+ if (!packageConfig.jspm.directories.dist)
+ delete packageConfig.directories.dist;
+ }
- pjson.map[b] = pjson.map[b] || mapping;
- }
+ // keep the package.json and index.js around if we're doing files filtering
+ if (packageConfig.files && packageConfig.files instanceof Array) {
+ if (packageConfig.files.indexOf('package.json') == -1)
+ packageConfig.files.push('package.json');
+ if (packageConfig.files.indexOf('index.js') == -1)
+ packageConfig.files.push('index.js');
+
+ packageConfig.files = packageConfig.files.map(function(file) {
+ // dist/* means dist/**/* in npm rules
+ if (file.substr(file.length - 2) == '/*')
+ return file + '*/*';
+ return file;
+ });
}
- return pjson;
+ return packageConfig;
},
- download: function(repo, version, hash, versionData, outDir) {
+ download: function(repo, version, hash, versionData, targetDir) {
var self = this;
- var doAuth = this.alwaysAuth || repo[0] == '@';
+ var registryInfo = self.registryInfo(repo);
// Forcing protocol and port matching for tarballs on the same host as the
// registry is taken from npm at
// https://github.com/npm/npm/blob/50ce116baac8b6877434ace471104ec8587bab90/lib/cache/add-named.js#L196-L208
var tarball = url.parse(versionData.dist.tarball);
- var registry = url.parse(this.registryURL());
+ var registry = url.parse(registryInfo.url);
- if (tarball.hostname === registry.hostname && tarball.protocol !== registry.protocol) {
+ if (tarball.hostname === registry.hostname && (tarball.protocol !== registry.protocol || tarball.port !== registry.port)) {
tarball.protocol = registry.protocol;
tarball.port = registry.port;
}
@@ -350,30 +366,41 @@ NPMLocation.prototype = {
uri: tarball,
headers: { 'accept': 'application/octet-stream' },
strictSSL: self.strictSSL
- }, doAuth && self.auth))
+ }, registryInfo))
.on('response', function(npmRes) {
if (npmRes.statusCode != 200)
return reject('Bad response code ' + npmRes.statusCode);
- if (npmRes.headers['content-length'] > 50000000)
- return reject('Response too large.');
+ if (self.maxRepoSize > 0 && npmRes.headers['content-length'] > self.maxRepoSize)
+ return reject('Response too large. Consider increasing the limit: jspm config registries.npm.maxRepoSize 100');
npmRes.pause();
- var gzip = zlib.createGunzip();
+ // Peek at the first 16 bytes of npmRes to check if the contents are gzipped
+ peek(npmRes, 16, function(err, bytes, stream) {
+ if (err) return reject(err);
- npmRes
- .pipe(gzip)
- .pipe(tar.Extract({
- path: outDir,
- strip: 1,
- filter: function() {
- return !this.type.match(/^.*Link$/);
+ // If the contents are gzipped pipe to gzip
+ if (isGzip(bytes)) {
+ var gzip = zlib.createGunzip();
+ stream = stream.pipe(gzip);
}
- }))
- .on('error', reject)
- .on('end', resolve);
+
+ // Unpack contents as a tar archive and save to targetDir
+ stream
+ .pipe(tar.extract(targetDir, {
+ // all dirs and files should be readable
+ dmode: 0555,
+ fmode: 0444,
+ strip: 1,
+ chown: false,
+ filter: function(_, header) {
+ return header.type !== 'file' && header.type !== 'directory'
+ }
+ }).on('finish', resolve).on('error', reject))
+ .on('error', reject);
+ });
npmRes.resume();
})
@@ -388,13 +415,266 @@ NPMLocation.prototype = {
});
},
- build: function(pjson, dir) {
- if (pjson.jspmNodeConversion === false || pjson.jspmPackage)
- return;
+ processPackage: function(packageConfig, packageName, packageDir) {
+ if (packageConfig.jspmNodeConversion === false || packageConfig.jspmPackage)
+ return packageConfig;
// apply static conversions
- return nodeConversion.convertPackage(pjson, dir);
+ return nodeConversion.convertPackage(packageConfig, packageName, packageDir, this.ui);
}
};
+// convert NodeJS or Bower dependencies into jspm-compatible dependencies
+var githubRegEx = /^(git(\+[^:]+)?|https):\/\/github.com\/([^\/]+\/[^\/]+(\#.+|$))/;
+var githubHttpRegEx = /^https?:\/\/github\.com\/([^\/]+\/[^\/]+)\/archive\/([^\/]+)\.(tar\.gz|zip)$/;
+var githubShorthandRegEx = /^github:([^#\/]+\/[^#\/]+)(#.+)?$/;
+var canonicalRegEx = /^[^@\/\:]+\:(@?[^@]+)(@[^@\/]*)?$/;
+var protocolRegEx = /^[^\:\/]+:\/\//;
+var semverRegEx = /^(\d+)(?:\.(\d+)(?:\.(\d+)(?:-([\da-z-]+(?:\.[\da-z-]+)*)(?:\+([\da-z-]+(?:\.[\da-z-]+)*))?)?)?)?$/i;
+function parseDependencies(dependencies, ui) {
+ // do dependency parsing
+ var outDependencies = {};
+ var process = function(d) {
+ var dep = dependencies[d];
+
+ var match, name, version = '';
+
+ // 1. git://github.com/name/repo.git#version -> github:name/repo@version
+ if ((match = dep.match(githubRegEx))) {
+ dep = match[3];
+ name = 'github:' + dep.split('#')[0];
+ version = dep.split('#')[1] || '*';
+ if (version.substr(0, 1) == 'v' && version.substr(1).match(semverRegEx))
+ version = version.substr(1);
+ if (name.substr(name.length - 4, 4) == '.git')
+ name = name.substr(0, name.length - 4);
+ ui.log('warn', 'npm dependency `' + name + '@' + version + '` will likely only work if its GitHub repo has %registry: npm% in its package.json');
+ }
+
+ // 2. https?://github.com/name/repo/archive/v?[semver].tar.gz -> github:name/repo@[semver]
+ else if ((match = dep.match(githubHttpRegEx))) {
+ name = 'github:' + match[1];
+ version = match[2];
+ if (version.substr(0, 1) == 'v' && version.substr(1).match(semverRegEx))
+ version = version.substr(1);
+ }
+
+ // 3. url:// or file: -> not supported
+ else if (dep.match(protocolRegEx) || dep.substr(0, 5) == 'file:')
+ throw 'npm dependency format ' + dep + ' not supported by jspm.';
+
+ // 4. github:package/name#version
+ else if ((match = dep.match(githubShorthandRegEx))) {
+ name = 'github:' + match[1];
+ version = match[2] ? match[2].substr(1) : '*';
+ if (name.indexOf('@') != -1)
+ ui.log('warn', 'npm dependency `' + name + '` uses a %@% version which is invalid in npm. Use %#% as the version separator or set %"registry": "jspm"% in the override for the install to work.');
+ }
+
+ // 5. name/repo#version -> github:name/repo@version
+ else if (dep.split('/').length == 2) {
+ name = 'github:' + dep.split('#')[0];
+ version = dep.split('#')[1] || '*';
+ }
+
+ // 6. registry:package/name@version
+ else if ((match = dep.match(canonicalRegEx))) {
+ name = 'github:' + match[1];
+ version = match[2] ? match[2].substr(1) : '*';
+ }
+
+ // 6. version -> name@version
+ else {
+ name = d;
+ version = dep;
+ }
+
+ // otherwise, we convert an npm range into something jspm-compatible
+ // if it is an exact semver, or a tag, just use it directly
+ if (!nodeSemver.valid(version)) {
+ var range;
+
+ // comma space is allowed on npm for some reason
+ version = version.replace(/, /g, ' ');
+
+ if (!version || version == 'latest' || version == '*')
+ version = '*';
+
+ // if we have a semver or fuzzy range, just keep as-is
+ else if (version.indexOf(/[ <>=]/) != -1 || !version.substr(1).match(semverRegEx) || !version.substr(0, 1).match(/[\^\~]/))
+ range = nodeSemver.validRange(version);
+
+ if (range == '*')
+ version = '*';
+
+ else if (range) {
+ // if it has OR semantics, we only support the last range
+ if (range.indexOf('||') != -1)
+ range = range.split('||').pop();
+
+ var rangeParts = range.split(' ');
+
+ // convert AND statements into a single lower bound and upper bound
+ // enforcing the lower bound as inclusive and the upper bound as exclusive
+ var lowerBound, upperBound, lEq, uEq;
+ for (var i = 0; i < rangeParts.length; i++) {
+ var part = rangeParts[i];
+ var a = part.charAt(0);
+ var b = part.charAt(1);
+
+ // get the version
+ var v = part;
+ if (b == '=')
+ v = part.substr(2);
+ else if (a == '>' || a == '<' || a == '=')
+ v = part.substr(1);
+
+ // and the operator
+ var gt = a == '>';
+ var lt = a == '<';
+
+ if (gt) {
+ // take the highest lower bound
+ if (!lowerBound || nodeSemver.gt(lowerBound, v)) {
+ lowerBound = v;
+ lEq = b == '=';
+ }
+ }
+ else if (lt) {
+ // take the lowest upper bound
+ if (!upperBound || nodeSemver.lt(upperBound, v)) {
+ upperBound = v;
+ uEq = b == '=';
+ }
+ }
+ else {
+ // equality
+ lowerBound = upperBound = (part.substr(0, 1) == '=' ? part.substr(1) : part);
+ lEq = uEq = true;
+ break;
+ }
+ }
+
+ // for some reason nodeSemver adds "-0" when not appropriate
+ if (lowerBound && lowerBound.substr(lowerBound.length - 2, 2) == '-0')
+ lowerBound = lowerBound.substr(0, lowerBound.length - 2);
+ if (upperBound && upperBound.substr(upperBound.length - 2, 2) == '-0')
+ upperBound = upperBound.substr(0, upperBound.length - 2);
+
+ var lowerSemver, upperSemver;
+
+ if (lowerBound) {
+ lowerSemver = lowerBound.match(semverRegEx);
+ lowerSemver[1] = parseInt(lowerSemver[1], 10);
+ lowerSemver[2] = parseInt(lowerSemver[2], 10);
+ lowerSemver[3] = parseInt(lowerSemver[3], 10);
+ if (!lEq) {
+ //if (!lowerSemver[4])
+ lowerSemver[4] = '0';
+ // NB support incrementing existing preleases
+ }
+ }
+
+ if (upperBound) {
+ upperSemver = upperBound.match(semverRegEx);
+ upperSemver[1] = parseInt(upperSemver[1], 10);
+ upperSemver[2] = parseInt(upperSemver[2], 10);
+ upperSemver[3] = parseInt(upperSemver[3], 10);
+ }
+
+ if (!upperBound && !lowerBound) {
+ version = '';
+ }
+
+ // if not upperBound, then just treat as a wildcard
+ else if (!upperBound) {
+ version = '*';
+ }
+
+ // if no lowerBound, use the upperBound directly, with sensible decrementing if necessary
+ else if (!lowerBound) {
+
+ if (uEq) {
+ version = upperBound;
+ }
+
+ else {
+ if (!upperSemver[4]) {
+ lEq = true;
+ if (upperSemver[3] > 0) {
+ lowerSemver = [undefined, upperSemver[1], upperSemver[2], upperSemver[3] - 1];
+ }
+ else if (upperSemver[2] > 0) {
+ lowerSemver = [undefined, upperSemver[1], upperSemver[2] - 1, 0];
+ }
+ else if (upperSemver[1] > 0) {
+ lowerSemver = [undefined, upperSemver[1] - 1, 0, 0];
+ }
+ }
+ else {
+ upperSemver[4] = undefined;
+ version = getVersion(upperSemver);
+ }
+ }
+ }
+
+ if (upperSemver && lowerSemver) {
+ // if upper bound is inclusive, use it
+ if (uEq)
+ version = upperBound;
+
+ // if upper bound is exact major
+ else if (upperSemver[2] === 0 && upperSemver[3] === 0 && !upperSemver[4]) {
+
+ // if previous major is 0
+ if (upperSemver[1] - 1 === 0) {
+ version = '0';
+ }
+ else {
+ // if lower bound is major below, we are semver compatible
+ if (lowerSemver[1] == upperSemver[1] - 1)
+ version = '^' + getVersion(lowerSemver);
+ // otherwise we are semver compatible with the previous exact major
+ else
+ version = '^' + (upperSemver[1] - 1);
+ }
+ }
+ // if upper bound is exact minor
+ else if (upperSemver[3] === 0 && !upperSemver[4]) {
+ // if lower bound is minor below, we are fuzzy compatible
+ if (lowerSemver[2] == upperSemver[2] - 1)
+ version = '~' + getVersion(lowerSemver);
+ // otherwise we are fuzzy compatible with previous
+ else
+ version = '~' + upperSemver[1] + '.' + (upperSemver[2] - 1) + '.0';
+ }
+ // if upper bound is exact version -> use exact
+ else {
+ if (lEq)
+ version = getVersion(lowerSemver);
+ else
+ throw 'Unable to translate npm version ' + version + ' into a jspm range.';
+ }
+ }
+ }
+ }
+
+ // replace ~x.y.0 with x.y shorthand
+ var shorthandMatch = version && version.match(/^~(\d+)\.(\d+)\.0$/)
+ if (shorthandMatch)
+ version = shorthandMatch[1] + '.' + shorthandMatch[2];
+
+ outDependencies[d] = name + (version ? '@' + version : '');
+ };
+ for (var d in dependencies)
+ process(d);
+ return outDependencies;
+}
+// export for unit testing
+NPMLocation.parseDependencies = parseDependencies;
+
+function getVersion(semver) {
+ return semver[1] + '.' + semver[2] + '.' + semver[3] + (semver[4] ? '-' + semver[4] : '');
+}
+
module.exports = NPMLocation;
diff --git a/lib/npmrc.js b/lib/npmrc.js
index 3b4ccbd..56bde12 100644
--- a/lib/npmrc.js
+++ b/lib/npmrc.js
@@ -1,4 +1,4 @@
-var asp = require('rsvp').denodeify;
+var asp = require('bluebird').promisify;
var fs = require('graceful-fs');
var path = require('path');
var which = require('which');
@@ -14,6 +14,15 @@ function getFilepaths() {
return paths;
}
+function getOptionEnvironmentVariable(option) {
+ var regex = /\$\{([\w]+)\}/m;
+ var result = option.match(regex);
+ if (result)
+ return process.env[result[1]] || option;
+
+ return option;
+}
+
function getOptionExact(contents, key) {
var regex = new RegExp('^' + key + ' ?= ?(.+)', 'm');
var result;
@@ -21,7 +30,7 @@ function getOptionExact(contents, key) {
var content = contents[i];
result = content && content.match(regex);
if (result)
- return result[1];
+ return getOptionEnvironmentVariable(result[1]);
}
}
@@ -74,6 +83,18 @@ Npmrc.prototype.getAuth = function(registry) {
};
};
+Npmrc.prototype.getCa = function(registry) {
+ if (!registry)
+ registry = this.getRegistry();
+
+ if (!this.initialized)
+ this.init();
+
+ var cafile = getOption(this.contents, 'cafile', registry);
+ if (cafile)
+ return fs.readFileSync(cafile);
+};
+
Npmrc.prototype.getRegistry = function(scope) {
if (!this.initialized)
this.init();
diff --git a/package.json b/package.json
index 45bf920..213fff1 100644
--- a/package.json
+++ b/package.json
@@ -1,6 +1,6 @@
{
"name": "jspm-npm",
- "version": "0.26.8",
+ "version": "0.30.5",
"description": "jspm npm endpoint",
"main": "npm.js",
"scripts": {
@@ -17,23 +17,22 @@
"url": "https://github.com/jspm/npm/issues"
},
"dependencies": {
- "glob": "^5.0.10",
+ "bluebird": "^3.0.5",
+ "buffer-peek-stream": "^1.0.1",
"graceful-fs": "^4.1.3",
"mkdirp": "^0.5.1",
- "request": "~2.58.0",
- "resolve": "^1.1.6",
- "rmdir": "~1.1.0",
- "rsvp": "^3.0.18",
+ "readdirp": "^2.0.0",
+ "request": "^2.58.0",
"semver": "^5.0.1",
- "systemjs-builder": "^0.15.0",
- "tar": "~1.0.3",
+ "tar-fs": "^1.13.0",
+ "traceur": "0.0.105",
"which": "^1.1.1"
},
"homepage": "https://github.com/jspm/npm",
"devDependencies": {
"istanbul": "0.3.21",
- "mocha": "2.3.3",
- "unexpected": "9.16.0",
- "unexpected-mitm": "7.7.3"
+ "mocha": "^3.4.2",
+ "unexpected": "^10.29.0",
+ "unexpected-mitm": "^10.0.0"
}
}
diff --git a/test/auth.spec.js b/test/auth.spec.js
index 77756d4..b45988b 100644
--- a/test/auth.spec.js
+++ b/test/auth.spec.js
@@ -98,8 +98,10 @@ describe('lib/auth', function () {
});
it('should inject BasicAuth options into request options', function () {
requestOptions = auth.injectRequestOptions(requestOptions, {
- username: 'foo',
- password: 'bar'
+ auth: {
+ username: 'foo',
+ password: 'bar'
+ }
})
return expect(requestOptions, 'to satisfy', {
auth: {
@@ -110,7 +112,9 @@ describe('lib/auth', function () {
});
it('should inject auth tokens into request options', function () {
requestOptions = auth.injectRequestOptions(requestOptions, {
- token: 'foobar'
+ auth: {
+ token: 'foobar'
+ }
})
return expect(requestOptions, 'to satisfy', {
headers: {
@@ -123,7 +127,9 @@ describe('lib/auth', function () {
'X-Custom-Header': 'helloworld'
};
requestOptions = auth.injectRequestOptions(requestOptions, {
- token: 'foobar'
+ auth: {
+ token: 'foobar'
+ }
})
return expect(requestOptions, 'to satisfy', {
headers: {
@@ -132,6 +138,16 @@ describe('lib/auth', function () {
}
});
});
+ it('should inject certificate options into request options', function () {
+ requestOptions = auth.injectRequestOptions(requestOptions, {
+ ca: '-----BEGIN CERTIFICATE-----\n-----END CERTIFICATE-----'
+ })
+ return expect(requestOptions, 'to satisfy', {
+ agentOptions: {
+ ca: '-----BEGIN CERTIFICATE-----\n-----END CERTIFICATE-----'
+ }
+ });
+ });
});
describe('configureCredentials', function () {
it('token based authentication chosen', function () {
diff --git a/test/config.js b/test/config.js
deleted file mode 100644
index e723b19..0000000
--- a/test/config.js
+++ /dev/null
@@ -1,349 +0,0 @@
-System.config({
- "defaultJSExtensions": true,
- "transpiler": "traceur",
- "paths": {
- "github:*": "jspm_packages/github/*",
- "npm:*": "jspm_packages/npm/*"
- }
-});
-
-System.config({
- "map": {
- "assert": "github:jspm/nodelibs-assert@0.1.0",
- "buffer": "github:jspm/nodelibs-buffer@0.1.0",
- "child_process": "github:jspm/nodelibs-child_process@0.1.0",
- "cluster": "github:jspm/nodelibs-cluster@0.1.0",
- "console": "github:jspm/nodelibs-console@0.1.0",
- "constants": "github:jspm/nodelibs-constants@0.1.0",
- "crypto": "github:jspm/nodelibs-crypto@0.1.0",
- "dgram": "github:jspm/nodelibs-dgram@0.1.0",
- "dns": "github:jspm/nodelibs-dns@0.1.0",
- "domain": "github:jspm/nodelibs-domain@0.1.0",
- "events": "github:jspm/nodelibs-events@0.1.1",
- "fs": "github:jspm/nodelibs-fs@0.1.2",
- "http": "github:jspm/nodelibs-http@1.7.1",
- "https": "github:jspm/nodelibs-https@0.1.0",
- "module": "github:jspm/nodelibs-module@0.1.0",
- "net": "github:jspm/nodelibs-net@0.1.2",
- "os": "github:jspm/nodelibs-os@0.1.0",
- "path": "github:jspm/nodelibs-path@0.1.0",
- "process": "github:jspm/nodelibs-process@0.1.1",
- "punycode": "github:jspm/nodelibs-punycode@0.1.0",
- "querystring": "github:jspm/nodelibs-querystring@0.1.0",
- "readline": "github:jspm/nodelibs-readline@0.1.0",
- "repl": "github:jspm/nodelibs-repl@0.1.0",
- "stream": "github:jspm/nodelibs-stream@0.1.0",
- "string_decoder": "github:jspm/nodelibs-string_decoder@0.1.0",
- "timers": "github:jspm/nodelibs-timers@0.1.0",
- "tls": "github:jspm/nodelibs-tls@0.1.0",
- "traceur": "github:jmcriffey/bower-traceur@0.0.89",
- "traceur-runtime": "github:jmcriffey/bower-traceur-runtime@0.0.89",
- "tty": "github:jspm/nodelibs-tty@0.1.0",
- "url": "github:jspm/nodelibs-url@0.1.0",
- "util": "github:jspm/nodelibs-util@0.1.0",
- "vm": "github:jspm/nodelibs-vm@0.1.0",
- "zlib": "github:jspm/nodelibs-zlib@0.1.0",
- "github:jspm/nodelibs-assert@0.1.0": {
- "assert": "npm:assert@1.3.0"
- },
- "github:jspm/nodelibs-buffer@0.1.0": {
- "buffer": "npm:buffer@3.2.2"
- },
- "github:jspm/nodelibs-console@0.1.0": {
- "console-browserify": "npm:console-browserify@1.1.0"
- },
- "github:jspm/nodelibs-constants@0.1.0": {
- "constants-browserify": "npm:constants-browserify@0.0.1"
- },
- "github:jspm/nodelibs-crypto@0.1.0": {
- "crypto-browserify": "npm:crypto-browserify@3.9.14"
- },
- "github:jspm/nodelibs-domain@0.1.0": {
- "domain-browser": "npm:domain-browser@1.1.4"
- },
- "github:jspm/nodelibs-events@0.1.1": {
- "events": "npm:events@1.0.2"
- },
- "github:jspm/nodelibs-http@1.7.1": {
- "Base64": "npm:Base64@0.2.1",
- "events": "github:jspm/nodelibs-events@0.1.1",
- "inherits": "npm:inherits@2.0.1",
- "stream": "github:jspm/nodelibs-stream@0.1.0",
- "url": "github:jspm/nodelibs-url@0.1.0",
- "util": "github:jspm/nodelibs-util@0.1.0"
- },
- "github:jspm/nodelibs-https@0.1.0": {
- "https-browserify": "npm:https-browserify@0.0.0"
- },
- "github:jspm/nodelibs-net@0.1.2": {
- "buffer": "github:jspm/nodelibs-buffer@0.1.0",
- "crypto": "github:jspm/nodelibs-crypto@0.1.0",
- "http": "github:jspm/nodelibs-http@1.7.1",
- "net": "github:jspm/nodelibs-net@0.1.2",
- "process": "github:jspm/nodelibs-process@0.1.1",
- "stream": "github:jspm/nodelibs-stream@0.1.0",
- "timers": "github:jspm/nodelibs-timers@0.1.0",
- "util": "github:jspm/nodelibs-util@0.1.0"
- },
- "github:jspm/nodelibs-os@0.1.0": {
- "os-browserify": "npm:os-browserify@0.1.2"
- },
- "github:jspm/nodelibs-path@0.1.0": {
- "path-browserify": "npm:path-browserify@0.0.0"
- },
- "github:jspm/nodelibs-process@0.1.1": {
- "process": "npm:process@0.10.1"
- },
- "github:jspm/nodelibs-punycode@0.1.0": {
- "punycode": "npm:punycode@1.3.2"
- },
- "github:jspm/nodelibs-querystring@0.1.0": {
- "querystring": "npm:querystring@0.2.0"
- },
- "github:jspm/nodelibs-stream@0.1.0": {
- "stream-browserify": "npm:stream-browserify@1.0.0"
- },
- "github:jspm/nodelibs-string_decoder@0.1.0": {
- "string_decoder": "npm:string_decoder@0.10.31"
- },
- "github:jspm/nodelibs-timers@0.1.0": {
- "timers-browserify": "npm:timers-browserify@1.4.1"
- },
- "github:jspm/nodelibs-tty@0.1.0": {
- "tty-browserify": "npm:tty-browserify@0.0.0"
- },
- "github:jspm/nodelibs-url@0.1.0": {
- "url": "npm:url@0.10.3"
- },
- "github:jspm/nodelibs-util@0.1.0": {
- "util": "npm:util@0.10.3"
- },
- "github:jspm/nodelibs-vm@0.1.0": {
- "vm-browserify": "npm:vm-browserify@0.0.4"
- },
- "github:jspm/nodelibs-zlib@0.1.0": {
- "browserify-zlib": "npm:browserify-zlib@0.1.4"
- },
- "npm:asn1.js@2.0.4": {
- "assert": "github:jspm/nodelibs-assert@0.1.0",
- "bn.js": "npm:bn.js@2.0.5",
- "buffer": "github:jspm/nodelibs-buffer@0.1.0",
- "inherits": "npm:inherits@2.0.1",
- "minimalistic-assert": "npm:minimalistic-assert@1.0.0",
- "vm": "github:jspm/nodelibs-vm@0.1.0"
- },
- "npm:assert@1.3.0": {
- "util": "npm:util@0.10.3"
- },
- "npm:browserify-aes@1.0.1": {
- "buffer": "github:jspm/nodelibs-buffer@0.1.0",
- "create-hash": "npm:create-hash@1.1.1",
- "crypto": "github:jspm/nodelibs-crypto@0.1.0",
- "fs": "github:jspm/nodelibs-fs@0.1.2",
- "inherits": "npm:inherits@2.0.1",
- "stream": "github:jspm/nodelibs-stream@0.1.0",
- "systemjs-json": "github:systemjs/plugin-json@0.1.0"
- },
- "npm:browserify-rsa@2.0.1": {
- "bn.js": "npm:bn.js@2.0.5",
- "buffer": "github:jspm/nodelibs-buffer@0.1.0",
- "constants": "github:jspm/nodelibs-constants@0.1.0",
- "crypto": "github:jspm/nodelibs-crypto@0.1.0",
- "randombytes": "npm:randombytes@2.0.1"
- },
- "npm:browserify-sign@3.0.2": {
- "bn.js": "npm:bn.js@2.0.5",
- "browserify-rsa": "npm:browserify-rsa@2.0.1",
- "buffer": "github:jspm/nodelibs-buffer@0.1.0",
- "create-hash": "npm:create-hash@1.1.1",
- "create-hmac": "npm:create-hmac@1.1.3",
- "crypto": "github:jspm/nodelibs-crypto@0.1.0",
- "elliptic": "npm:elliptic@3.1.0",
- "inherits": "npm:inherits@2.0.1",
- "parse-asn1": "npm:parse-asn1@3.0.1",
- "stream": "github:jspm/nodelibs-stream@0.1.0",
- "systemjs-json": "github:systemjs/plugin-json@0.1.0"
- },
- "npm:browserify-zlib@0.1.4": {
- "assert": "github:jspm/nodelibs-assert@0.1.0",
- "buffer": "github:jspm/nodelibs-buffer@0.1.0",
- "pako": "npm:pako@0.2.7",
- "process": "github:jspm/nodelibs-process@0.1.1",
- "readable-stream": "npm:readable-stream@1.1.13",
- "util": "github:jspm/nodelibs-util@0.1.0"
- },
- "npm:buffer@3.2.2": {
- "base64-js": "npm:base64-js@0.0.8",
- "ieee754": "npm:ieee754@1.1.6",
- "is-array": "npm:is-array@1.0.1"
- },
- "npm:console-browserify@1.1.0": {
- "assert": "github:jspm/nodelibs-assert@0.1.0",
- "date-now": "npm:date-now@0.1.4",
- "util": "github:jspm/nodelibs-util@0.1.0"
- },
- "npm:constants-browserify@0.0.1": {
- "systemjs-json": "github:systemjs/plugin-json@0.1.0"
- },
- "npm:core-util-is@1.0.1": {
- "buffer": "github:jspm/nodelibs-buffer@0.1.0"
- },
- "npm:create-ecdh@2.0.1": {
- "bn.js": "npm:bn.js@2.0.5",
- "buffer": "github:jspm/nodelibs-buffer@0.1.0",
- "crypto": "github:jspm/nodelibs-crypto@0.1.0",
- "elliptic": "npm:elliptic@3.1.0"
- },
- "npm:create-hash@1.1.1": {
- "buffer": "github:jspm/nodelibs-buffer@0.1.0",
- "crypto": "github:jspm/nodelibs-crypto@0.1.0",
- "fs": "github:jspm/nodelibs-fs@0.1.2",
- "inherits": "npm:inherits@2.0.1",
- "ripemd160": "npm:ripemd160@1.0.1",
- "sha.js": "npm:sha.js@2.4.2",
- "stream": "github:jspm/nodelibs-stream@0.1.0"
- },
- "npm:create-hmac@1.1.3": {
- "buffer": "github:jspm/nodelibs-buffer@0.1.0",
- "create-hash": "npm:create-hash@1.1.1",
- "crypto": "github:jspm/nodelibs-crypto@0.1.0",
- "inherits": "npm:inherits@2.0.1",
- "stream": "github:jspm/nodelibs-stream@0.1.0"
- },
- "npm:crypto-browserify@3.9.14": {
- "browserify-aes": "npm:browserify-aes@1.0.1",
- "browserify-sign": "npm:browserify-sign@3.0.2",
- "create-ecdh": "npm:create-ecdh@2.0.1",
- "create-hash": "npm:create-hash@1.1.1",
- "create-hmac": "npm:create-hmac@1.1.3",
- "diffie-hellman": "npm:diffie-hellman@3.0.2",
- "inherits": "npm:inherits@2.0.1",
- "pbkdf2": "npm:pbkdf2@3.0.4",
- "public-encrypt": "npm:public-encrypt@2.0.1",
- "randombytes": "npm:randombytes@2.0.1"
- },
- "npm:diffie-hellman@3.0.2": {
- "bn.js": "npm:bn.js@2.0.5",
- "buffer": "github:jspm/nodelibs-buffer@0.1.0",
- "crypto": "github:jspm/nodelibs-crypto@0.1.0",
- "miller-rabin": "npm:miller-rabin@2.0.1",
- "randombytes": "npm:randombytes@2.0.1",
- "systemjs-json": "github:systemjs/plugin-json@0.1.0"
- },
- "npm:domain-browser@1.1.4": {
- "events": "github:jspm/nodelibs-events@0.1.1"
- },
- "npm:elliptic@3.1.0": {
- "bn.js": "npm:bn.js@2.0.5",
- "brorand": "npm:brorand@1.0.5",
- "hash.js": "npm:hash.js@1.0.3",
- "inherits": "npm:inherits@2.0.1",
- "systemjs-json": "github:systemjs/plugin-json@0.1.0"
- },
- "npm:hash.js@1.0.3": {
- "inherits": "npm:inherits@2.0.1"
- },
- "npm:https-browserify@0.0.0": {
- "http": "github:jspm/nodelibs-http@1.7.1"
- },
- "npm:inherits@2.0.1": {
- "util": "github:jspm/nodelibs-util@0.1.0"
- },
- "npm:miller-rabin@2.0.1": {
- "bn.js": "npm:bn.js@2.0.5",
- "brorand": "npm:brorand@1.0.5"
- },
- "npm:os-browserify@0.1.2": {
- "os": "github:jspm/nodelibs-os@0.1.0"
- },
- "npm:pako@0.2.7": {
- "buffer": "github:jspm/nodelibs-buffer@0.1.0",
- "process": "github:jspm/nodelibs-process@0.1.1"
- },
- "npm:parse-asn1@3.0.1": {
- "asn1.js": "npm:asn1.js@2.0.4",
- "browserify-aes": "npm:browserify-aes@1.0.1",
- "buffer": "github:jspm/nodelibs-buffer@0.1.0",
- "create-hash": "npm:create-hash@1.1.1",
- "pbkdf2": "npm:pbkdf2@3.0.4",
- "systemjs-json": "github:systemjs/plugin-json@0.1.0"
- },
- "npm:path-browserify@0.0.0": {
- "process": "github:jspm/nodelibs-process@0.1.1"
- },
- "npm:pbkdf2@3.0.4": {
- "buffer": "github:jspm/nodelibs-buffer@0.1.0",
- "child_process": "github:jspm/nodelibs-child_process@0.1.0",
- "create-hmac": "npm:create-hmac@1.1.3",
- "crypto": "github:jspm/nodelibs-crypto@0.1.0",
- "path": "github:jspm/nodelibs-path@0.1.0",
- "process": "github:jspm/nodelibs-process@0.1.1",
- "systemjs-json": "github:systemjs/plugin-json@0.1.0"
- },
- "npm:process@0.11.1": {
- "assert": "github:jspm/nodelibs-assert@0.1.0"
- },
- "npm:public-encrypt@2.0.1": {
- "bn.js": "npm:bn.js@2.0.5",
- "browserify-rsa": "npm:browserify-rsa@2.0.1",
- "buffer": "github:jspm/nodelibs-buffer@0.1.0",
- "create-hash": "npm:create-hash@1.1.1",
- "crypto": "github:jspm/nodelibs-crypto@0.1.0",
- "parse-asn1": "npm:parse-asn1@3.0.1",
- "randombytes": "npm:randombytes@2.0.1"
- },
- "npm:punycode@1.3.2": {
- "process": "github:jspm/nodelibs-process@0.1.1"
- },
- "npm:randombytes@2.0.1": {
- "buffer": "github:jspm/nodelibs-buffer@0.1.0",
- "crypto": "github:jspm/nodelibs-crypto@0.1.0",
- "process": "github:jspm/nodelibs-process@0.1.1"
- },
- "npm:readable-stream@1.1.13": {
- "buffer": "github:jspm/nodelibs-buffer@0.1.0",
- "core-util-is": "npm:core-util-is@1.0.1",
- "events": "github:jspm/nodelibs-events@0.1.1",
- "inherits": "npm:inherits@2.0.1",
- "isarray": "npm:isarray@0.0.1",
- "process": "github:jspm/nodelibs-process@0.1.1",
- "stream-browserify": "npm:stream-browserify@1.0.0",
- "string_decoder": "npm:string_decoder@0.10.31"
- },
- "npm:ripemd160@1.0.1": {
- "buffer": "github:jspm/nodelibs-buffer@0.1.0",
- "process": "github:jspm/nodelibs-process@0.1.1"
- },
- "npm:sha.js@2.4.2": {
- "buffer": "github:jspm/nodelibs-buffer@0.1.0",
- "fs": "github:jspm/nodelibs-fs@0.1.2",
- "inherits": "npm:inherits@2.0.1",
- "process": "github:jspm/nodelibs-process@0.1.1"
- },
- "npm:stream-browserify@1.0.0": {
- "events": "github:jspm/nodelibs-events@0.1.1",
- "inherits": "npm:inherits@2.0.1",
- "readable-stream": "npm:readable-stream@1.1.13"
- },
- "npm:string_decoder@0.10.31": {
- "buffer": "github:jspm/nodelibs-buffer@0.1.0"
- },
- "npm:timers-browserify@1.4.1": {
- "process": "npm:process@0.11.1"
- },
- "npm:url@0.10.3": {
- "assert": "github:jspm/nodelibs-assert@0.1.0",
- "punycode": "npm:punycode@1.3.2",
- "querystring": "npm:querystring@0.2.0",
- "util": "github:jspm/nodelibs-util@0.1.0"
- },
- "npm:util@0.10.3": {
- "inherits": "npm:inherits@2.0.1",
- "process": "github:jspm/nodelibs-process@0.1.1"
- },
- "npm:vm-browserify@0.0.4": {
- "indexof": "npm:indexof@0.0.1"
- }
- }
-});
-
diff --git a/test/fixtures/deps-transformer/process-detection1.js b/test/fixtures/deps-transformer/process-detection1.js
new file mode 100644
index 0000000..3b93d68
--- /dev/null
+++ b/test/fixtures/deps-transformer/process-detection1.js
@@ -0,0 +1,51 @@
+/**
+ * Copyright 2013-2015, Facebook, Inc.
+ * All rights reserved.
+ *
+ * This source code is licensed under the BSD-style license found in the
+ * LICENSE file in the root directory of this source tree. An additional grant
+ * of patent rights can be found in the PATENTS file in the same directory.
+ *
+ * @providesModule keyMirror
+ * @typechecks static-only
+ */
+
+'use strict';
+
+var invariant = require("./invariant");
+
+/**
+ * Constructs an enumeration with keys equal to their value.
+ *
+ * For example:
+ *
+ * var COLORS = keyMirror({blue: null, red: null});
+ * var myColor = COLORS.blue;
+ * var isColorValid = !!COLORS[myColor];
+ *
+ * The last line could not be performed if the values of the generated enum were
+ * not equal to their keys.
+ *
+ * Input: {key1: val1, key2: val2}
+ * Output: {key1: key1, key2: key2}
+ *
+ * @param {object} obj
+ * @return {object}
+ */
+var keyMirror = function(obj) {
+ var ret = {};
+ var key;
+ ("production" !== process.env.NODE_ENV ? invariant(
+ obj instanceof Object && !Array.isArray(obj),
+ 'keyMirror(...): Argument must be an object.'
+ ) : invariant(obj instanceof Object && !Array.isArray(obj)));
+ for (key in obj) {
+ if (!obj.hasOwnProperty(key)) {
+ continue;
+ }
+ ret[key] = key;
+ }
+ return ret;
+};
+
+module.exports = keyMirror;
diff --git a/test/fixtures/deps-transformer/process-detection2.js b/test/fixtures/deps-transformer/process-detection2.js
new file mode 100644
index 0000000..55aa52a
--- /dev/null
+++ b/test/fixtures/deps-transformer/process-detection2.js
@@ -0,0 +1,3 @@
+(function(p) {
+ console.log(p);
+})(process);
\ No newline at end of file
diff --git a/test/jspm.browser.js b/test/jspm.browser.js
new file mode 100644
index 0000000..673d763
--- /dev/null
+++ b/test/jspm.browser.js
@@ -0,0 +1,6 @@
+SystemJS.config({
+ paths: {
+ "github:*": "/jspm_packages/github/*",
+ "npm:*": "/jspm_packages/npm/*"
+ }
+});
\ No newline at end of file
diff --git a/test/jspm.js b/test/jspm.js
new file mode 100644
index 0000000..448e704
--- /dev/null
+++ b/test/jspm.js
@@ -0,0 +1,325 @@
+SystemJS.config({
+ packageConfigPaths: [
+ "github:*/*.json",
+ "npm:@*/*.json",
+ "npm:*.json"
+ ],
+ transpiler: "traceur",
+ paths: {
+ "github:*": "jspm_packages/github/*",
+ "npm:*": "jspm_packages/npm/*"
+ },
+ globalEvaluationScope: false,
+
+ map: {
+ "assert": "github:jspm/nodelibs-assert@0.2.0-alpha",
+ "buffer": "github:jspm/nodelibs-buffer@0.2.0-alpha",
+ "child_process": "github:jspm/nodelibs-child_process@0.2.0-alpha",
+ "cluster": "github:jspm/nodelibs-cluster@0.2.0-alpha",
+ "console": "github:jspm/nodelibs-console@0.2.0-alpha",
+ "constants": "github:jspm/nodelibs-constants@0.2.0-alpha",
+ "crypto": "github:jspm/nodelibs-crypto@0.2.0-alpha",
+ "dgram": "github:jspm/nodelibs-dgram@0.2.0-alpha",
+ "dns": "github:jspm/nodelibs-dns@0.2.0-alpha",
+ "domain": "github:jspm/nodelibs-domain@0.2.0-alpha",
+ "events": "github:jspm/nodelibs-events@0.2.0-alpha",
+ "fs": "github:jspm/nodelibs-fs@0.2.0-alpha",
+ "http": "github:jspm/nodelibs-http@0.2.0-alpha",
+ "https": "github:jspm/nodelibs-https@0.2.0-alpha",
+ "module": "github:jspm/nodelibs-module@0.2.0-alpha",
+ "net": "github:jspm/nodelibs-net@0.2.0-alpha",
+ "nodelibs": "github:jspm/nodelibs@0.1.9",
+ "os": "github:jspm/nodelibs-os@0.2.0-alpha",
+ "path": "github:jspm/nodelibs-path@0.2.0-alpha",
+ "process": "github:jspm/nodelibs-process@0.2.0-alpha",
+ "punycode": "github:jspm/nodelibs-punycode@0.2.0-alpha",
+ "querystring": "github:jspm/nodelibs-querystring@0.2.0-alpha",
+ "readline": "github:jspm/nodelibs-readline@0.2.0-alpha",
+ "repl": "github:jspm/nodelibs-repl@0.2.0-alpha",
+ "stream": "github:jspm/nodelibs-stream@0.2.0-alpha",
+ "string_decoder": "github:jspm/nodelibs-string_decoder@0.2.0-alpha",
+ "timers": "github:jspm/nodelibs-timers@0.2.0-alpha",
+ "tls": "github:jspm/nodelibs-tls@0.2.0-alpha",
+ "traceur": "github:jmcriffey/bower-traceur@0.0.89",
+ "traceur-runtime": "github:jmcriffey/bower-traceur-runtime@0.0.89",
+ "tty": "github:jspm/nodelibs-tty@0.2.0-alpha",
+ "url": "github:jspm/nodelibs-url@0.2.0-alpha",
+ "util": "github:jspm/nodelibs-util@0.2.0-alpha",
+ "vm": "github:jspm/nodelibs-vm@0.2.0-alpha",
+ "zlib": "github:jspm/nodelibs-zlib@0.2.0-alpha"
+ },
+
+ packages: {
+ "github:jspm/nodelibs-buffer@0.2.0-alpha": {
+ "map": {
+ "buffer-browserify": "npm:buffer@4.0.0"
+ }
+ },
+ "github:jspm/nodelibs-crypto@0.2.0-alpha": {
+ "map": {
+ "crypto-browserify": "npm:crypto-browserify@3.11.0"
+ }
+ },
+ "github:jspm/nodelibs-domain@0.2.0-alpha": {
+ "map": {
+ "domain-browserify": "npm:domain-browser@1.1.7"
+ }
+ },
+ "github:jspm/nodelibs-http@0.2.0-alpha": {
+ "map": {
+ "http-browserify": "npm:stream-http@2.0.3"
+ }
+ },
+ "github:jspm/nodelibs-os@0.2.0-alpha": {
+ "map": {
+ "os-browserify": "npm:os-browserify@0.2.0"
+ }
+ },
+ "github:jspm/nodelibs-punycode@0.2.0-alpha": {
+ "map": {
+ "punycode-browserify": "npm:punycode@1.3.2"
+ }
+ },
+ "github:jspm/nodelibs-stream@0.2.0-alpha": {
+ "map": {
+ "stream-browserify": "npm:stream-browserify@2.0.1"
+ }
+ },
+ "github:jspm/nodelibs-string_decoder@0.2.0-alpha": {
+ "map": {
+ "string_decoder-browserify": "npm:string_decoder@0.10.31"
+ }
+ },
+ "github:jspm/nodelibs-timers@0.2.0-alpha": {
+ "map": {
+ "timers-browserify": "npm:timers-browserify@1.4.2"
+ }
+ },
+ "github:jspm/nodelibs-url@0.2.0-alpha": {
+ "map": {
+ "url-browserify": "npm:url@0.11.0"
+ }
+ },
+ "github:jspm/nodelibs-zlib@0.2.0-alpha": {
+ "map": {
+ "zlib-browserify": "npm:browserify-zlib@0.1.4"
+ }
+ },
+ "npm:asn1.js@4.3.0": {
+ "map": {
+ "bn.js": "npm:bn.js@4.6.2",
+ "inherits": "npm:inherits@2.0.1",
+ "minimalistic-assert": "npm:minimalistic-assert@1.0.0"
+ }
+ },
+ "npm:browserify-aes@1.0.5": {
+ "map": {
+ "buffer-xor": "npm:buffer-xor@1.0.3",
+ "cipher-base": "npm:cipher-base@1.0.2",
+ "create-hash": "npm:create-hash@1.1.1",
+ "evp_bytestokey": "npm:evp_bytestokey@1.0.0",
+ "inherits": "npm:inherits@2.0.1"
+ }
+ },
+ "npm:browserify-cipher@1.0.0": {
+ "map": {
+ "browserify-aes": "npm:browserify-aes@1.0.5",
+ "browserify-des": "npm:browserify-des@1.0.0",
+ "evp_bytestokey": "npm:evp_bytestokey@1.0.0"
+ }
+ },
+ "npm:browserify-des@1.0.0": {
+ "map": {
+ "cipher-base": "npm:cipher-base@1.0.2",
+ "des.js": "npm:des.js@1.0.0",
+ "inherits": "npm:inherits@2.0.1"
+ }
+ },
+ "npm:browserify-rsa@4.0.0": {
+ "map": {
+ "bn.js": "npm:bn.js@4.6.2",
+ "randombytes": "npm:randombytes@2.0.1"
+ }
+ },
+ "npm:browserify-sign@4.0.0": {
+ "map": {
+ "bn.js": "npm:bn.js@4.6.2",
+ "browserify-rsa": "npm:browserify-rsa@4.0.0",
+ "create-hash": "npm:create-hash@1.1.1",
+ "create-hmac": "npm:create-hmac@1.1.3",
+ "elliptic": "npm:elliptic@6.0.2",
+ "inherits": "npm:inherits@2.0.1",
+ "parse-asn1": "npm:parse-asn1@5.0.0"
+ }
+ },
+ "npm:browserify-zlib@0.1.4": {
+ "map": {
+ "pako": "npm:pako@0.2.8",
+ "readable-stream": "npm:readable-stream@2.0.5"
+ }
+ },
+ "npm:buffer@4.0.0": {
+ "map": {
+ "base64-js": "npm:base64-js@0.0.8",
+ "ieee754": "npm:ieee754@1.1.6",
+ "isarray": "npm:isarray@1.0.0"
+ }
+ },
+ "npm:cipher-base@1.0.2": {
+ "map": {
+ "inherits": "npm:inherits@2.0.1"
+ }
+ },
+ "npm:create-ecdh@4.0.0": {
+ "map": {
+ "bn.js": "npm:bn.js@4.6.2",
+ "elliptic": "npm:elliptic@6.0.2"
+ }
+ },
+ "npm:create-hash@1.1.1": {
+ "map": {
+ "inherits": "npm:inherits@2.0.1",
+ "ripemd160": "npm:ripemd160@1.0.1",
+ "sha.js": "npm:sha.js@2.4.2"
+ }
+ },
+ "npm:create-hmac@1.1.3": {
+ "map": {
+ "create-hash": "npm:create-hash@1.1.1",
+ "inherits": "npm:inherits@2.0.1"
+ }
+ },
+ "npm:crypto-browserify@3.11.0": {
+ "map": {
+ "browserify-cipher": "npm:browserify-cipher@1.0.0",
+ "browserify-sign": "npm:browserify-sign@4.0.0",
+ "create-ecdh": "npm:create-ecdh@4.0.0",
+ "create-hash": "npm:create-hash@1.1.1",
+ "create-hmac": "npm:create-hmac@1.1.3",
+ "diffie-hellman": "npm:diffie-hellman@5.0.0",
+ "inherits": "npm:inherits@2.0.1",
+ "pbkdf2": "npm:pbkdf2@3.0.4",
+ "public-encrypt": "npm:public-encrypt@4.0.0",
+ "randombytes": "npm:randombytes@2.0.1"
+ }
+ },
+ "npm:des.js@1.0.0": {
+ "map": {
+ "inherits": "npm:inherits@2.0.1",
+ "minimalistic-assert": "npm:minimalistic-assert@1.0.0"
+ }
+ },
+ "npm:diffie-hellman@5.0.0": {
+ "map": {
+ "bn.js": "npm:bn.js@4.6.2",
+ "miller-rabin": "npm:miller-rabin@4.0.0",
+ "randombytes": "npm:randombytes@2.0.1"
+ }
+ },
+ "npm:elliptic@6.0.2": {
+ "map": {
+ "bn.js": "npm:bn.js@4.6.2",
+ "brorand": "npm:brorand@1.0.5",
+ "hash.js": "npm:hash.js@1.0.3",
+ "inherits": "npm:inherits@2.0.1"
+ }
+ },
+ "npm:evp_bytestokey@1.0.0": {
+ "map": {
+ "create-hash": "npm:create-hash@1.1.1"
+ }
+ },
+ "npm:hash.js@1.0.3": {
+ "map": {
+ "inherits": "npm:inherits@2.0.1"
+ }
+ },
+ "npm:inherits@2.0.1": {
+ "map": {}
+ },
+ "npm:miller-rabin@4.0.0": {
+ "map": {
+ "bn.js": "npm:bn.js@4.6.2",
+ "brorand": "npm:brorand@1.0.5"
+ }
+ },
+ "npm:parse-asn1@5.0.0": {
+ "map": {
+ "asn1.js": "npm:asn1.js@4.3.0",
+ "browserify-aes": "npm:browserify-aes@1.0.5",
+ "create-hash": "npm:create-hash@1.1.1",
+ "evp_bytestokey": "npm:evp_bytestokey@1.0.0",
+ "pbkdf2": "npm:pbkdf2@3.0.4"
+ }
+ },
+ "npm:pbkdf2@3.0.4": {
+ "map": {
+ "create-hmac": "npm:create-hmac@1.1.3",
+ "systemjs-json": "github:systemjs/plugin-json@0.1.0"
+ }
+ },
+ "npm:process@0.11.1": {
+ "map": {}
+ },
+ "npm:public-encrypt@4.0.0": {
+ "map": {
+ "bn.js": "npm:bn.js@4.6.2",
+ "browserify-rsa": "npm:browserify-rsa@4.0.0",
+ "create-hash": "npm:create-hash@1.1.1",
+ "parse-asn1": "npm:parse-asn1@5.0.0",
+ "randombytes": "npm:randombytes@2.0.1"
+ }
+ },
+ "npm:punycode@1.3.2": {
+ "map": {}
+ },
+ "npm:randombytes@2.0.1": {
+ "map": {}
+ },
+ "npm:readable-stream@2.0.5": {
+ "map": {
+ "core-util-is": "npm:core-util-is@1.0.2",
+ "inherits": "npm:inherits@2.0.1",
+ "isarray": "npm:isarray@0.0.1",
+ "process-nextick-args": "npm:process-nextick-args@1.0.6",
+ "string_decoder": "npm:string_decoder@0.10.31",
+ "util-deprecate": "npm:util-deprecate@1.0.2"
+ }
+ },
+ "npm:ripemd160@1.0.1": {
+ "map": {}
+ },
+ "npm:sha.js@2.4.2": {
+ "map": {
+ "inherits": "npm:inherits@2.0.1"
+ }
+ },
+ "npm:stream-browserify@2.0.1": {
+ "map": {
+ "inherits": "npm:inherits@2.0.1",
+ "readable-stream": "npm:readable-stream@2.0.5"
+ }
+ },
+ "npm:stream-http@2.0.3": {
+ "map": {
+ "builtin-status-codes": "npm:builtin-status-codes@1.0.0",
+ "inherits": "npm:inherits@2.0.1",
+ "xtend": "npm:xtend@4.0.1"
+ }
+ },
+ "npm:string_decoder@0.10.31": {
+ "map": {}
+ },
+ "npm:timers-browserify@1.4.2": {
+ "map": {
+ "process": "npm:process@0.11.1"
+ }
+ },
+ "npm:url@0.11.0": {
+ "map": {
+ "punycode": "npm:punycode@1.3.2",
+ "querystring": "npm:querystring@0.2.0"
+ }
+ }
+ }
+});
diff --git a/test/mocha.opts b/test/mocha.opts
index 9e399c3..13fc110 100644
--- a/test/mocha.opts
+++ b/test/mocha.opts
@@ -1,2 +1,3 @@
--reporter spec
test/auth.spec.js
+test/npmrc.spec.js
diff --git a/test/npmrc.spec.js b/test/npmrc.spec.js
new file mode 100644
index 0000000..f729adf
--- /dev/null
+++ b/test/npmrc.spec.js
@@ -0,0 +1,80 @@
+var expect = require('unexpected')
+ .clone()
+ .use(require('unexpected-mitm'));
+var Npmrc = require('../lib/npmrc');
+var fs = require('fs');
+var path = require('path');
+
+
+function extend(a, b) {
+ for (var p in b)
+ a[p] = b[p];
+ return a;
+}
+
+function FileMock(path) {
+ this.path = path;
+};
+
+FileMock.prototype.write = function(content) {
+ fs.writeFileSync(this.path, content);
+ return this;
+};
+
+FileMock.prototype.unlink = function() {
+ fs.unlinkSync(this.path);
+};
+
+describe('lib/npmrc', function () {
+
+ describe('getCa()', function () {
+ var _jspmConfigPath;
+ var npmrc;
+
+ beforeEach(function() {
+ _jspmConfigPath = process.env.jspmConfigPath;
+ npmrc = new Npmrc();
+ });
+
+ afterEach(function() {
+ if (_jspmConfigPath)
+ process.env.jspmConfigPath = _jspmConfigPath;
+ });
+
+ it('should honor cafile property', function () {
+ var npmrcFile;
+ var caFile;
+ var ca;
+
+ delete process.env.jspmConfigPath;
+ caFile = new FileMock(path.resolve(process.cwd(), 'ca.crt'))
+ .write('ca certificate');
+ npmrcFile = new FileMock(path.resolve(process.cwd(), '.npmrc'))
+ .write('cafile=' + caFile.path);
+
+
+ var ca = npmrc.getCa();
+
+
+ caFile.unlink();
+ npmrcFile.unlink();
+ return expect(ca, 'when decoded as', 'utf-8', 'to equal', 'ca certificate');
+ });
+
+ it('should have empty ca', function () {
+ var npmrcFile;
+ var ca;
+
+ delete process.env.jspmConfigPath;
+ npmrcFile = new FileMock(path.resolve(process.cwd(), '.npmrc'))
+ .write('# empty config');
+
+
+ var ca = npmrc.getCa();
+
+
+ npmrcFile.unlink();
+ return expect(ca, 'to be undefined');
+ });
+ });
+});
diff --git a/test/package.json b/test/package.json
index 7f53526..2184282 100644
--- a/test/package.json
+++ b/test/package.json
@@ -3,43 +3,81 @@
"directories": {
"lib": "lib"
},
- "dependencies": {
- "assert": "jspm/nodelibs-assert@^0.1.0",
- "buffer": "jspm/nodelibs-buffer@^0.1.0",
- "child_process": "jspm/nodelibs-child_process@^0.1.0",
- "cluster": "jspm/nodelibs-cluster@^0.1.0",
- "console": "jspm/nodelibs-console@^0.1.0",
- "constants": "jspm/nodelibs-constants@^0.1.0",
- "crypto": "jspm/nodelibs-crypto@^0.1.0",
- "dgram": "jspm/nodelibs-dgram@^0.1.0",
- "dns": "jspm/nodelibs-dns@^0.1.0",
- "domain": "jspm/nodelibs-domain@^0.1.0",
- "events": "jspm/nodelibs-events@^0.1.1",
- "fs": "jspm/nodelibs-fs@^0.1.1",
- "http": "jspm/nodelibs-http@^1.7.0",
- "https": "jspm/nodelibs-https@^0.1.0",
- "module": "jspm/nodelibs-module@^0.1.0",
- "net": "jspm/nodelibs-net@^0.1.2",
- "os": "jspm/nodelibs-os@^0.1.0",
- "path": "jspm/nodelibs-path@^0.1.0",
- "process": "jspm/nodelibs-process@^0.1.1",
- "punycode": "jspm/nodelibs-punycode@^0.1.0",
- "querystring": "jspm/nodelibs-querystring@^0.1.0",
- "readline": "jspm/nodelibs-readline@^0.1.0",
- "repl": "jspm/nodelibs-repl@^0.1.0",
- "stream": "jspm/nodelibs-stream@^0.1.0",
- "string_decoder": "jspm/nodelibs-string_decoder@^0.1.0",
- "timers": "jspm/nodelibs-timers@^0.1.0",
- "tls": "jspm/nodelibs-tls@^0.1.0",
- "tty": "jspm/nodelibs-tty@^0.1.0",
- "url": "jspm/nodelibs-url@^0.1.0",
- "util": "jspm/nodelibs-util@^0.1.0",
- "vm": "jspm/nodelibs-vm@^0.1.0",
- "zlib": "jspm/nodelibs-zlib@^0.1.0"
- },
- "devDependencies": {
+ "dependencies": {},
+ "devDependencies": {},
+ "peerDependencies": {
+ "assert": "jspm/nodelibs-assert@^0.2.0-alpha",
+ "buffer": "jspm/nodelibs-buffer@^0.2.0-alpha",
+ "child_process": "jspm/nodelibs-child_process@^0.2.0-alpha",
+ "cluster": "jspm/nodelibs-cluster@^0.2.0-alpha",
+ "console": "jspm/nodelibs-console@^0.2.0-alpha",
+ "constants": "jspm/nodelibs-constants@^0.2.0-alpha",
+ "crypto": "jspm/nodelibs-crypto@^0.2.0-alpha",
+ "dgram": "jspm/nodelibs-dgram@^0.2.0-alpha",
+ "dns": "jspm/nodelibs-dns@^0.2.0-alpha",
+ "domain": "jspm/nodelibs-domain@^0.2.0-alpha",
+ "events": "jspm/nodelibs-events@^0.2.0-alpha",
+ "fs": "jspm/nodelibs-fs@^0.2.0-alpha",
+ "http": "jspm/nodelibs-http@^0.2.0-alpha",
+ "https": "jspm/nodelibs-https@^0.2.0-alpha",
+ "module": "jspm/nodelibs-module@^0.2.0-alpha",
+ "net": "jspm/nodelibs-net@^0.2.0-alpha",
+ "nodelibs": "jspm/nodelibs@^0.1.0",
+ "os": "jspm/nodelibs-os@^0.2.0-alpha",
+ "path": "jspm/nodelibs-path@^0.2.0-alpha",
+ "process": "jspm/nodelibs-process@^0.2.0-alpha",
+ "punycode": "jspm/nodelibs-punycode@^0.2.0-alpha",
+ "querystring": "jspm/nodelibs-querystring@^0.2.0-alpha",
+ "readline": "jspm/nodelibs-readline@^0.2.0-alpha",
+ "repl": "jspm/nodelibs-repl@^0.2.0-alpha",
+ "stream": "jspm/nodelibs-stream@^0.2.0-alpha",
+ "string_decoder": "jspm/nodelibs-string_decoder@^0.2.0-alpha",
+ "timers": "jspm/nodelibs-timers@^0.2.0-alpha",
+ "tls": "jspm/nodelibs-tls@^0.2.0-alpha",
"traceur": "jmcriffey/bower-traceur@0.0.89",
- "traceur-runtime": "jmcriffey/bower-traceur-runtime@0.0.89"
+ "traceur-runtime": "jmcriffey/bower-traceur-runtime@0.0.89",
+ "tty": "jspm/nodelibs-tty@^0.2.0-alpha",
+ "url": "jspm/nodelibs-url@^0.2.0-alpha",
+ "util": "jspm/nodelibs-util@^0.2.0-alpha",
+ "vm": "jspm/nodelibs-vm@^0.2.0-alpha",
+ "zlib": "jspm/nodelibs-zlib@^0.2.0-alpha"
+ },
+ "overrides": {
+ "github:jmcriffey/bower-traceur-runtime@0.0.89": {
+ "format": "global",
+ "meta": {
+ "traceur-runtime.js": {
+ "exports": "$traceurRuntime"
+ }
+ }
+ },
+ "github:jmcriffey/bower-traceur@0.0.89": {
+ "format": "global",
+ "meta": {
+ "traceur.js": {
+ "exports": "traceur"
+ }
+ }
+ },
+ "npm:base64-js@0.0.8": {
+ "ignore": [
+ "bench"
+ ]
+ },
+ "npm:browserify-zlib@0.1.4": {
+ "dependencies": {
+ "readable-stream": "^2.0.2",
+ "pako": "~0.2.0"
+ },
+ "map": {
+ "_stream_transform": "readable-stream/transform"
+ }
+ },
+ "npm:inherits@2.0.1": {
+ "ignore": [
+ "test.js"
+ ]
+ }
},
"jspm": true
}
diff --git a/test/test-node.js b/test/test-node.js
index 6427b59..48825da 100644
--- a/test/test-node.js
+++ b/test/test-node.js
@@ -18,7 +18,7 @@ assert(cluster.fork);
assert(dgram.Socket);
assert(dns.lookup);
assert(module.Module);
-assert(net.createServer);
+assert(net.isIP('1.1.1.1'), true);
assert(readline.cursorTo);
assert(repl.start);
assert(tls.connect);
diff --git a/test/test-shared.js b/test/test-shared.js
index 6010d97..235988e 100644
--- a/test/test-shared.js
+++ b/test/test-shared.js
@@ -7,7 +7,6 @@ var domain = require('domain');
var events = require('events');
var http = require('http');
var https = require('https');
-var net = require('net');
var os = require('os');
var path = require('path');
var process = require('process');
@@ -37,8 +36,6 @@ d.run(function() {
assert(http.get);
assert(https.get);
- assert(net.isIP('1.1.1.1'), true);
-
assert(os.platform());
assert(path.join('one', 'two'), 'one' + path.sep + 'two');
diff --git a/test/test.html b/test/test.html
index 6e2a192..66bea24 100644
--- a/test/test.html
+++ b/test/test.html
@@ -1,6 +1,7 @@
-
+
+
\ No newline at end of file
diff --git a/test/unit.js b/test/unit.js
index 24bc6ef..89f4e01 100644
--- a/test/unit.js
+++ b/test/unit.js
@@ -1,10 +1,10 @@
-var nodeConversion = require('../lib/node-conversion');
-
+var parseDependencies = require('../lib/npm').parseDependencies;
+var fs = require('fs');
function testDependency(name, value, expectedName, expectedValue) {
var deps = {};
deps[name] = value;
- deps = nodeConversion.parseDependencies(deps);
+ deps = parseDependencies(deps);
for (var p in deps) {
if (p != expectedName)
@@ -16,25 +16,30 @@ function testDependency(name, value, expectedName, expectedValue) {
testDependency('react', '0.1.1', 'react', 'react@0.1.1');
testDependency('react', '=0.1.1', 'react', 'react@0.1.1');
-testDependency('react', '<0.12', 'react', 'react@0.11.0');
-testDependency('react', '<0.12.0', 'react', 'react@0.11.0');
+testDependency('react', '<0.12', 'react', 'react@0.11');
+testDependency('react', '<0.12.0', 'react', 'react@0.11');
testDependency('react', '~0.1.1', 'react', 'react@~0.1.1');
testDependency('react', '^0.12', 'react', 'react@^0.12');
-testDependency('react', '0.12.x', 'react', 'react@~0.12.0');
+testDependency('react', '0.12', 'react', 'react@0.12');
+testDependency('react', '0.12.x', 'react', 'react@0.12');
testDependency('react', '0.x', 'react', 'react@0');
testDependency('react', '>=0.12.0', 'react', 'react@*');
+testDependency('react', '<2.3.4 >=2.3.3', 'react', 'react@2.3.3');
// Scoped
testDependency('@scoped/react', '0.11.0', '@scoped/react', '@scoped/react@0.11.0');
testDependency('@scoped/react', '=0.11.0', '@scoped/react', '@scoped/react@0.11.0');
-testDependency('@scoped/react', '<0.12', '@scoped/react', '@scoped/react@0.11.0');
-testDependency('@scoped/react', '<0.12.0', '@scoped/react', '@scoped/react@0.11.0');
+testDependency('@scoped/react', '<0.12', '@scoped/react', '@scoped/react@0.11');
+testDependency('@scoped/react', '<0.12.0', '@scoped/react', '@scoped/react@0.11');
testDependency('@scoped/react', '~0.1.1', '@scoped/react', '@scoped/react@~0.1.1');
testDependency('@scoped/react', '^0.12', '@scoped/react', '@scoped/react@^0.12');
-testDependency('@scoped/react', '0.12.x', '@scoped/react', '@scoped/react@~0.12.0');
+testDependency('@scoped/react', '0.12.x', '@scoped/react', '@scoped/react@0.12');
testDependency('@scoped/react', '0.x', '@scoped/react', '@scoped/react@0');
testDependency('@scoped/react', '>=0.12.0', '@scoped/react', '@scoped/react@*');
-testDependency('get-size', '>=1.1.4 <1.3', 'get-size', 'get-size@~1.2.0');
+testDependency('get-size', '>=1.1.4 <1.3', 'get-size', 'get-size@1.2');
+
+
+
console.log('Unit tests passed');