Permalink
Cannot retrieve contributors at this time
Name already in use
A tag already exists with the provided branch name. Many Git commands accept both tag and branch names, so creating this branch may cause unexpected behavior. Are you sure you want to create this branch?
steal/ext/npm-convert.js /
Go to fileThis commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
406 lines (369 sloc)
10.9 KB
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
| "format cjs"; | |
| var crawl = require('./npm-crawl'); | |
| var utils = require("./npm-utils"); | |
| exports.steal = convertSteal; | |
| exports.propertyNames = convertPropertyNames; | |
| exports.propertyNamesAndValues = convertPropertyNamesAndValues; | |
| exports.name = convertName; | |
| exports.browser = convertBrowser; | |
| exports.browserProperty = convertBrowserProperty; | |
| exports.jspm = convertJspm; | |
| exports.toPackage = convertToPackage; | |
| exports.forPackage = convertForPackage; | |
| function StealConversion(context, pkg, steal, config, isRoot, waiting) { | |
| this.context = context; | |
| this.pkg = pkg; | |
| this.steal = steal; | |
| this.config = utils.extend({}, steal, true); | |
| this.isRoot = isRoot; | |
| this.waiting = []; | |
| } | |
| // Translate helpers =============== | |
| // Given all the package.json data, these helpers help convert it to a source. | |
| function convertSteal(context, pkg, steal, root, ignoreWaiting, resavePackageInfo) { | |
| if(!steal) { | |
| return new StealConversion(context, pkg, steal, root); | |
| } | |
| var conv = new StealConversion(context, pkg, steal, root); | |
| var waiting = conv.waiting; | |
| if(steal.meta) { | |
| steal.meta = convertPropertyNames(context, pkg, steal.meta, root, | |
| waiting); | |
| } | |
| if(steal.map) { | |
| steal.map = convertPropertyNamesAndValues(context, pkg, steal.map, | |
| root, waiting); | |
| } | |
| if(steal.paths) { | |
| steal.paths = convertPropertyNames(context, pkg, steal.paths, root, | |
| waiting); | |
| } | |
| // needed for builds | |
| if(steal.buildConfig) { | |
| var buildConv = convertSteal(context, pkg, steal.buildConfig, root); | |
| conv.buildConversion = buildConv; | |
| steal.buildConfig = conv.config; | |
| } | |
| return conv; | |
| } | |
| var lazyConfig = { | |
| // Queue package reconfiguration whenever a package is first loaded. | |
| // This is for progressively loaded package.jsons | |
| updateConfigOnPackageLoad: function(conv, isPackageInfoSaved, | |
| isConfigApplied, isBuildConfigApplied) { | |
| var fns = [function(){return lazyConfig.cloneConversion.call(this, conv)}]; | |
| if(isPackageInfoSaved) { | |
| fns.push(lazyConfig.resavePackageInfo); | |
| } | |
| if(isConfigApplied) { | |
| fns.push(lazyConfig.applyConfig); | |
| } | |
| var fn = utils.flow(fns); | |
| convertLater(conv.context, conv.waiting, fn); | |
| if(isBuildConfigApplied && conv.buildConversion) { | |
| var c = conv.buildConversion; | |
| fn = utils.flow([ | |
| function(){return lazyConfig.cloneConversion.call(this, c)}, | |
| lazyConfig.resavePackageInfo, | |
| lazyConfig.applyConfig | |
| ]); | |
| convertLater(c.context, c.waiting, fn); | |
| } | |
| }, | |
| resavePackageInfo: function(conv) { | |
| var info = utils.pkg.findPackageInfo(conv.context, conv.pkg); | |
| info.steal = info.system = conv.steal; | |
| return conv; | |
| }, | |
| applyConfig: function(conv) { | |
| var config = conv.steal; | |
| var context = this; | |
| // Temporarily remove steal.main so that it doesn't set System.main | |
| var stealMain = config.main; | |
| delete config.main; | |
| delete config.transpiler; | |
| context.loader.config(config); | |
| config.main = stealMain; | |
| return conv; | |
| }, | |
| cloneConversion: function(conv) { | |
| var context = this; | |
| var local = utils.extend({}, conv.config, true); | |
| var lConv = convertSteal(context, conv.pkg, local, conv.isRoot); | |
| return lConv; | |
| } | |
| }; | |
| exports.updateConfigOnPackageLoad = lazyConfig.updateConfigOnPackageLoad; | |
| // converts only the property name | |
| function convertPropertyNames (context, pkg, map , root, waiting) { | |
| if(!map) { | |
| return map; | |
| } | |
| var clone = {}, value; | |
| for(var property in map ) { | |
| value = convertName(context, pkg, map, root, property, waiting); | |
| if(typeof value === 'string') { | |
| clone[value] = map[property]; | |
| } | |
| // do root paths b/c we don't know if they are going to be included with the package name or not. | |
| if(root) { | |
| value = convertName(context, pkg, map, false, property, waiting); | |
| if(typeof value === 'string') { | |
| clone[value] = map[property]; | |
| } | |
| } | |
| } | |
| return clone; | |
| } | |
| // converts both property name and value | |
| function convertPropertyNamesAndValues (context, pkg, map, root, waiting) { | |
| if(!map) { | |
| return map; | |
| } | |
| var clone = {}, val, name; | |
| for(var property in map ) { | |
| val = map[property]; | |
| name = convertName(context, pkg, map, root, property, waiting); | |
| val = typeof val === "object" | |
| ? convertPropertyNamesAndValues(context, pkg, val, root, waiting) | |
| : convertName(context, pkg, map, root, val, waiting); | |
| if(typeof name !== 'undefined' && typeof val !== 'undefined') { | |
| clone[name] = val; | |
| } | |
| // keep map entry if the key isn't a package but value might | |
| if (name && typeof val === "undefined") { | |
| clone[name] = map[property]; | |
| } | |
| } | |
| return clone; | |
| } | |
| function convertName (context, pkg, map, root, name, waiting) { | |
| var parsed = utils.moduleName.parse(name, pkg.name, null, context), | |
| depPkg, requestedVersion; | |
| if( name.indexOf("#") >= 0 ) { | |
| // If this is a fully converted name just return the name. | |
| if(utils.moduleName.isFullyConvertedNpm(parsed)) { | |
| return name; | |
| } | |
| if(parsed.packageName === pkg.name) { | |
| parsed.version = pkg.version; | |
| } else { | |
| // Get the requested version's actual version. | |
| requestedVersion = crawl.getDependencyMap(context.loader, pkg, root)[parsed.packageName].version; | |
| depPkg = crawl.matchedVersion(context, parsed.packageName, requestedVersion); | |
| // This hasn't been crawled yet, so convert later | |
| if(!depPkg) { | |
| waiting.push({ | |
| packageName: parsed.packageName, | |
| requestedVersion: requestedVersion | |
| }); | |
| return; | |
| } | |
| parsed.version = depPkg.version; | |
| } | |
| return utils.moduleName.create(parsed); | |
| } else { | |
| if(root && name.substr(0,2) === "./" ) { | |
| return name.substr(2); | |
| } else { | |
| // this is for a module within the package | |
| if (name.substr(0,2) === "./" ) { | |
| return utils.moduleName.create({ | |
| packageName: pkg.name, | |
| modulePath: name, | |
| version: pkg.version, | |
| plugin: parsed.plugin | |
| }); | |
| } else { | |
| // SYSTEM.NAME | |
| if( pkg.name === parsed.packageName || ( (pkg.system && pkg.system.name) === parsed.packageName) ) { | |
| depPkg = pkg; | |
| } else { | |
| var requestedProject = crawl.getDependencyMap(context.loader, pkg, root)[parsed.packageName]; | |
| if(!requestedProject) { | |
| return name; | |
| } | |
| requestedVersion = requestedProject.version; | |
| depPkg = crawl.matchedVersion(context, parsed.packageName, requestedVersion); | |
| // If we still didn't find one just use the first available version. | |
| if(!depPkg) { | |
| var versions = context.versions[parsed.packageName]; | |
| depPkg = versions && versions[requestedVersion]; | |
| if(!depPkg) { | |
| waiting.push({ | |
| packageName: parsed.packageName, | |
| requestedVersion: requestedVersion | |
| }); | |
| return; | |
| } | |
| } | |
| } | |
| // SYSTEM.NAME | |
| if(depPkg.system && depPkg.system.name) { | |
| parsed.packageName = depPkg.system.name; | |
| } | |
| parsed.version = depPkg.version; | |
| if(!parsed.modulePath) { | |
| parsed.modulePath = utils.pkg.main(depPkg); | |
| } | |
| return utils.moduleName.create(parsed); | |
| } | |
| } | |
| } | |
| } | |
| /** | |
| * Converts browser names into actual module names. | |
| * | |
| * Example: | |
| * | |
| * ``` | |
| * { | |
| * "foo": "browser-foo" | |
| * "traceur#src/node/traceur": "./browser/traceur" | |
| * "./foo" : "./foo-browser" | |
| * } | |
| * ``` | |
| * | |
| * converted to: | |
| * | |
| * ``` | |
| * { | |
| * // any foo ... regardless of where | |
| * "foo": "browser-foo" | |
| * // this module ... ideally minus version | |
| * "traceur#src/node/traceur": "transpile#./browser/traceur" | |
| * "transpile#./foo" : "transpile#./foo-browser" | |
| * } | |
| * ``` | |
| */ | |
| function convertBrowser(pkg, browser) { | |
| var type = typeof browser; | |
| if(type === "string" || type === "undefined") { | |
| return browser; | |
| } | |
| var map = {}; | |
| for(var fromName in browser) { | |
| convertBrowserProperty(map, pkg, fromName, browser[fromName]); | |
| } | |
| return map; | |
| } | |
| function convertBrowserProperty(map, pkg, fromName, toName) { | |
| var packageName = pkg.name; | |
| var fromParsed = utils.moduleName.parse(fromName, packageName); | |
| var toResult = toName; | |
| if(!toName || typeof toName === "string") { | |
| var toParsed = toName ? utils.moduleName.parse(toName, packageName) | |
| : "@empty"; | |
| toResult = utils.moduleName.create(toParsed); | |
| } else if(utils.isArray(toName)) { | |
| toResult = toName; | |
| } | |
| map[utils.moduleName.create(fromParsed)] = toResult; | |
| } | |
| function convertJspm(pkg, jspm){ | |
| var type = typeof jspm; | |
| if(type === "undefined" || type === "string") { | |
| return jspm; | |
| } | |
| return { | |
| main: jspm.main | |
| }; | |
| } | |
| function convertToPackage(context, npmPkg, index) { | |
| var pkg = npmPkg; | |
| var packages = context.pkgInfo; | |
| var nameAndVersion = pkg.name+"@"+pkg.version; | |
| var localPkg; | |
| if(!packages[nameAndVersion]) { | |
| crawl.setVersionsConfig(context, pkg, pkg.version); | |
| if(pkg.browser){ | |
| delete pkg.browser.transform; | |
| } | |
| // fake load obj, because we don't have one here | |
| pkg = utils.json.transform(context.loader, { | |
| address: pkg.fileUrl, | |
| name: pkg.fileUrl.split('/').pop(), | |
| metadata: {} | |
| }, pkg); | |
| var steal = utils.pkg.config(pkg); | |
| var stealConversion = convertSteal(context, pkg, steal, index === 0); | |
| lazyConfig.updateConfigOnPackageLoad(stealConversion, context.resavePackageInfo, | |
| true, context.applyBuildConfig); | |
| localPkg = { | |
| name: pkg.name, | |
| version: pkg.version, | |
| fileUrl: utils.path.isRelative(pkg.fileUrl) ? | |
| pkg.fileUrl : | |
| utils.relativeURI(context.loader.baseURL, pkg.fileUrl), | |
| main: pkg.main, | |
| steal: stealConversion.steal, | |
| globalBrowser: convertBrowser(pkg, pkg.globalBrowser), | |
| browser: convertBrowser(pkg, pkg.browser || pkg.browserify), | |
| jspm: convertJspm(pkg, pkg.jspm), | |
| jam: convertJspm(pkg, pkg.jam), | |
| resolutions: {} | |
| }; | |
| packages.push(localPkg); | |
| packages[nameAndVersion] = true; | |
| } else { | |
| localPkg = utils.filter(packages, function(lpkg){ | |
| if(pkg.name === lpkg.name && pkg.version === lpkg.version) { | |
| return lpkg; | |
| } | |
| })[0]; | |
| } | |
| return localPkg; | |
| } | |
| /** | |
| * waiting looks like: | |
| * | |
| * [ | |
| * { packageName: 'can', requestedVersion: '^2.3.0' }, | |
| * { packageName: 'lodash': 'requestedVersion': '~3.0.0' } | |
| * ] | |
| * | |
| * Pushes these objects into a side table. Whenver a package.json is loaded | |
| * it will convert and apply config. | |
| */ | |
| function convertLater(context, waiting, fn) { | |
| utils.forEach(waiting, function(p){ | |
| var packageName = p.packageName; | |
| var requestedVersion = p.requestedVersion; | |
| var conv = context.deferredConversions; | |
| var pkg = conv[packageName]; | |
| if(!pkg) pkg = conv[packageName] = {}; | |
| var vers = pkg[requestedVersion]; | |
| if(!vers) vers = pkg[requestedVersion] = []; | |
| vers.push(fn); | |
| }); | |
| } | |
| /** | |
| * When progressively loading package.jsons we need to convert any config | |
| * that is waiting on a package.json to load. This function is called after | |
| * a package is loaded and will call all of the callbacks that cause the | |
| * config to be applied. | |
| */ | |
| function convertForPackage(context, pkg) { | |
| var name = pkg.name; | |
| var version = pkg.version; | |
| var conv = context.deferredConversions; | |
| var pkgConv = conv[name]; | |
| var depPkg, fns, keys = 0; | |
| if(pkgConv) { | |
| for(var range in pkgConv) { | |
| depPkg = crawl.matchedVersion(context, name, range); | |
| if(depPkg) { | |
| fns = pkgConv[range]; | |
| for(var i = 0, len = fns.length; i < len; i++) { | |
| fns[i].call(context); | |
| } | |
| delete pkgConv[range]; | |
| } else { | |
| keys++; | |
| } | |
| } | |
| if(keys === 0) { | |
| delete conv[name]; | |
| } | |
| } | |
| } |