Created
September 23, 2011 23:39
-
-
Save Filirom1/1238724 to your computer and use it in GitHub Desktop.
Choose the package to sync in npm
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
request = require 'request' | |
semver = require 'semver' | |
colors = require 'colors' | |
prompt = require 'prompt' | |
nopt = require 'nopt' | |
{EventEmitter} = require 'events' | |
# TODO: handle latest | |
# TODO: interactive mode | |
# Usage : coffee npm-sync.coffee -d express:1.7.1 | |
showUsage = -> | |
console.error "Please specify a package:version" | |
# optional parameters | |
knownOpts = | |
dependencies: Boolean | |
host: String | |
port: Number | |
shortHands = | |
d: ['--dependencies'] | |
h: ['--host'] | |
p: ['--port'] | |
options = nopt(knownOpts, shortHands, process.argv, 2) | |
# Default values | |
options.host || (options.host = 'localhost') | |
options.port || (options.port = 5984) | |
# URL of the public NPM registry | |
publicUrl = (package, version = "") -> | |
"http://isaacs.ic.ht/registry/_design/app/_rewrite/#{package}/#{version}" | |
# URL of your private NPM registry | |
privateUrl = (package, version = "") -> | |
"http://#{options.host}:#{options.port}/registry/_design/app/_rewrite/#{package}/#{version}" | |
# resolve NPM semantic version, i.e. '1.x || >=2.5.0 || 5.0.0 - 7.2.3' | |
resolveSemVer = (package, semVersion, callback) -> | |
# Fisrt read all versions | |
_get package, null, (err, data) -> | |
return callback err if err | |
# Filter the satisfying versions | |
satisfyingVersions = (version for version of data.versions when semver.satisfies(version, semVersion)) | |
return callback new Error("Unable to resolve version '#{semVersion}' for #{package}") unless satisfyingVersions | |
# By default choose the last one | |
satisfyingVersion = satisfyingVersions[satisfyingVersions.length-1] | |
callback null, satisfyingVersion | |
# Sync also the package dependencies | |
getPackageAndDeps = (package, version, callback) -> | |
_get package, version, (err, data) -> | |
callback(err, data) | |
for depName, depVersion of data.dependencies | |
syncPackage depName, depVersion | |
# HTTP GET to the public NPM registry | |
_get = (package, version, callback) -> | |
uri = publicUrl package, version | |
console.log "GET #{uri}".grey | |
request | |
method: 'GET' | |
uri: uri | |
'content-type': 'application/json' | |
(err, resp, body) -> | |
return callback err if err | |
return callback (statusCode: resp.statusCode, body: body) if resp.statusCode is not 200 | |
json = JSON.parse body | |
return callback (json.error) if json && json.error | |
# Clean the json of private fields | |
delete json[key] for key of json when key.indexOf('_') != -1 | |
callback null, json | |
# HTTP PUT to our private NPM registry | |
_put = (package, version, data, callback) -> | |
uri = privateUrl package, version | |
console.log "PUT #{uri}".grey | |
request | |
method: 'PUT' | |
uri: uri | |
'content-type': 'application/json' | |
body: JSON.stringify data | |
(err, resp, body) -> | |
return callback "Unable to PUT #{uri}", err if err | |
return callback (statusCode: resp.statusCode, body: body) if resp.statusCode is not 204 | |
json = JSON.parse body | |
return callback json.error, body if json && json.error | |
callback null, body | |
# main method | |
# Sync a package from the NPM public registry to our private NPM registry | |
syncPackage = (package, semVersion, callback) -> | |
callback || callback = (err, data) -> | |
return console.error "✗ #{package}:#{semVersion} failed to synchronized: #{err} #{data or ''}".red if err | |
console.log "✔ #{package}:#{semVersion} successfully synchronized.".green.bold | |
resolveSemVer package, semVersion, (err, version) -> | |
return callback err if err | |
# can also sync the dependencies | |
get = if options.dependencies then getPackageAndDeps else _get | |
get package, version, (err, data) -> | |
return callback err if err | |
_put package, version, data, (err, data) -> | |
return callback err if err | |
callback null, data | |
return showUsage() unless process.argv.length >= 3 | |
# Read stdin as a package:version argument | |
[package, version] = process.argv[process.argv.length-1].split(':') | |
return showUsage() unless package and version | |
# Go go synchronize now !!! | |
syncPackage package, version |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment