diff --git a/app.js b/app.js index 28a1056..273b8f9 100644 --- a/app.js +++ b/app.js @@ -1,21 +1,16 @@ var express = require('express'); var fs = require('fs'); +var config = require( __dirname + '/./config' ); +var utils = require( __dirname + '/./utils'); -var NPM_PATH = process.env.HOME + '/.npm'; -var REGISTRY_NAME = 'registry.npmjs.org'; -var LOCAL_REGISTRY = 'localhost:8080'; +var NPM_PATH = config.NPM_PATH; +var REGISTRY_NAME = config.REGISTRY_NAME; +var fetchAndCacheMetadata = utils.fetchAndCacheMetadata; +var fetchAndCacheTarball = utils.fetchAndCacheTarball; +var patchData = utils.patchData; var app = express(); - -function patchData( data ){ - Object.keys(data.versions).forEach( function( v ){ - var val = data.versions[v]; - val.dist.tarball = val.dist.tarball.replace( REGISTRY_NAME, LOCAL_REGISTRY ); - }); -} - - app.use( function(req, res, next ){ console.log(req.method, req.path ); next(); @@ -24,7 +19,13 @@ app.use( function(req, res, next ){ app.get( '/:package', function( req, res ){ var packageName = req.params.package; var cacheFile = [ NPM_PATH, REGISTRY_NAME, packageName, '.cache.json' ].join( '/' ); - var cacheData = fs.readFileSync( cacheFile, 'utf-8' ); + var cacheData; + + if( !fs.existsSync( cacheFile ) ){ + fetchAndCacheMetadata( packageName, cacheFile ); + } + + cacheData = fs.readFileSync( cacheFile, 'utf-8' ); cacheData = JSON.parse( cacheData ); patchData( cacheData ); @@ -35,6 +36,11 @@ app.get( '/:package/-/:packageName-:version.tgz', function( req, res ){ var packageName = req.params.package; var version = req.params.version.split('-').pop(); var packagePath = [ NPM_PATH , packageName, version, 'package.tgz'].join( '/' ); + + if( !fs.existsSync( packagePath ) ){ + fetchAndCacheTarball( packageName, version, packagePath ); + } + return fs.createReadStream( packagePath ).pipe( res ); }); diff --git a/bin/www b/bin/www index 3aea8e8..cbcf1ce 100755 --- a/bin/www +++ b/bin/www @@ -5,7 +5,6 @@ */ var app = require('../app'); -var debug = require('debug')('npm-proxy:server'); var http = require('http'); /** @@ -86,5 +85,5 @@ function onListening() { var bind = typeof addr === 'string' ? 'pipe ' + addr : 'port ' + addr.port; - debug('Listening on ' + bind); + console.log('Listening on ' + bind); } diff --git a/config.js b/config.js new file mode 100644 index 0000000..9ae423e --- /dev/null +++ b/config.js @@ -0,0 +1,15 @@ + +var defaultConfig = { + NPM_PATH : process.env.HOME + '/.npm', + REGISTRY_NAME : 'registry.npmjs.org', + LOCAL_REGISTRY : 'localhost:8080', +}; + +var config = {}; + +Object.keys( defaultConfig ).forEach( function(v){ + config[v] = process.env[v] || defaultConfig[v]; +}); + +module.exports = config; + diff --git a/test/utils.spec.js b/test/utils.spec.js new file mode 100644 index 0000000..bd18ccc --- /dev/null +++ b/test/utils.spec.js @@ -0,0 +1,32 @@ +/* globals describe, it */ + +var utils = require( '../utils' ); +var assert = require('assert'); +var fs = require('fs'); +var path = require('path'); + + +var fetchAndCacheMetadata = utils.fetchAndCacheMetadata; +var fetchAndCacheTarball = utils.fetchAndCacheTarball; + +/* TODO: write test */ +// var patchData = utils.patchData; + + +describe( 'Utility functions ', function(){ + + it.skip( 'should fetchAndCacheMetadata', function( ){ + var cacheFile = '/home/hari/.npm/registry.npmjs.org/lodash/.cache.json'; + fetchAndCacheMetadata( 'lodash', cacheFile ); + assert( fs.existsSync( cacheFile ) ); + }); + + it( 'should fetchAndCacheTarball', function(){ + var cacheFile = '/home/hari/.npm/lodash/4.2.1/package.tgz'; + var packageJsonFile = path.dirname( cacheFile ) + '/package/package.json'; + + fetchAndCacheTarball( 'lodash', '4.2.1', cacheFile ); + assert( fs.existsSync( cacheFile ) ); + assert( fs.existsSync( packageJsonFile ) ); + }); +}); diff --git a/utils.js b/utils.js new file mode 100644 index 0000000..079ea55 --- /dev/null +++ b/utils.js @@ -0,0 +1,30 @@ +var execSync = require('child_process').execSync; +var path = require('path'); +var config = require( __dirname + '/./config' ); + +var REGISTRY_NAME = config.REGISTRY_NAME; +var LOCAL_REGISTRY = config.LOCAL_REGISTRY; + +exports.patchData = function ( data ){ + Object.keys(data.versions).forEach( function( v ){ + var val = data.versions[v]; + val.dist.tarball = val.dist.tarball.replace( REGISTRY_NAME, LOCAL_REGISTRY ); + }); +}; + +exports.fetchAndCacheMetadata = function ( packageName, cacheFile ){ + var packageCacheDir = path.dirname( cacheFile ); + execSync( 'mkdir ' + packageCacheDir ); + execSync( 'wget http://' + REGISTRY_NAME + '/' + packageName + ' -O ' + cacheFile ); +}; + +exports.fetchAndCacheTarball = function ( packageName, version, tarballPath ){ + var tarballUrl = 'http://' + REGISTRY_NAME + '/' + packageName + '/-/' + packageName + '-' + version + '.tgz'; + var packageTarballDir = path.dirname( tarballPath ); + execSync( 'mkdir -p ' + packageTarballDir ); + execSync( 'wget ' + tarballUrl + ' -O ' + tarballPath ); + execSync( 'cd ' + packageTarballDir + ';tar -xzf package.tgz package/package.json' ); +}; + + +