├── .gitignore ├── package.json ├── test.js └── index.js /.gitignore: -------------------------------------------------------------------------------- 1 | node_modules 2 | npm-debug.log 3 | -------------------------------------------------------------------------------- /package.json: -------------------------------------------------------------------------------- 1 | { 2 | "name": "is-native", 3 | "version": "0.0.1", 4 | "description": "Check if a given node package has a compilation build step.", 5 | "main": "index.js", 6 | "dependencies": { 7 | "tar-stream": "^1.0.0", 8 | "debug": "^2.0.0", 9 | "request": "^2.45.0" 10 | }, 11 | "devDependencies": {}, 12 | "scripts": { 13 | "test": "node test.js" 14 | }, 15 | "repository": { 16 | "type": "git", 17 | "url": "git@github.com:pose/is-native.git" 18 | }, 19 | "author": "", 20 | "license": "MIT", 21 | "bugs": { 22 | "url": "https://github.com/pose/is-native/issues" 23 | }, 24 | "homepage": "https://github.com/pose/is-native" 25 | } 26 | -------------------------------------------------------------------------------- /test.js: -------------------------------------------------------------------------------- 1 | var assert = require('assert'); 2 | 3 | var isNative = require('./index'); 4 | 5 | isNative('https://registry.npmjs.org/geoip/-/geoip-0.5.4.tgz', function (err, isNative) { 6 | assert.ifError(err); 7 | assert.equal(true, isNative); 8 | }); 9 | 10 | isNative('https://registry.npmjs.org/oauth-sign/-/oauth-sign-0.3.0.tgz', function (err, isNative) { 11 | assert.ifError(err); 12 | assert.equal(false, isNative); 13 | }); 14 | 15 | isNative('http://registry.npmjs.org/couchbase/-/couchbase-2.0.0.tgz', function (err, isNative) { 16 | assert.ifError(err); 17 | assert.equal(true, isNative); 18 | }); 19 | 20 | isNative('foo', function (err, isNative) { 21 | assert.equal('Invalid URI "foo"', err.message); 22 | }); 23 | 24 | isNative('http://registry.npmjs.org/couchbase/', function (err, isNative) { 25 | assert.equal('incorrect header check', err.message); 26 | }); 27 | -------------------------------------------------------------------------------- /index.js: -------------------------------------------------------------------------------- 1 | var assert = require('assert'); 2 | var zlib = require('zlib'); 3 | 4 | var debug = require('debug')('is-native'); 5 | var request = require('request'); 6 | var tar = require('tar-stream'); 7 | 8 | module.exports = function isNative(url, cb) { 9 | 10 | function onError (err) { 11 | extract.removeAllListeners('finish'); 12 | extract.removeAllListeners('entry'); 13 | extract.removeAllListeners('error'); 14 | gunzip.removeAllListeners('error'); 15 | resourceStream.removeAllListeners('end'); 16 | resourceStream.removeAllListeners('data'); 17 | resourceStream.removeAllListeners('response'); 18 | resourceStream.removeAllListeners('error'); 19 | cb(err); 20 | } 21 | 22 | var extract = tar.extract(); 23 | var resourceStream; 24 | var gunzip = zlib.createGunzip(); 25 | var totalLength = 0; 26 | 27 | try { 28 | resourceStream = request.get(url); 29 | } catch (e) { 30 | return cb(e); 31 | } 32 | 33 | extract.on('entry', function (header, stream, callback) { 34 | // TODO In old packages we should check for node-waaf 35 | if (header.name === 'package/binding.gyp') { 36 | extract.removeAllListeners('entry'); 37 | extract.removeAllListeners('finish'); 38 | extract.removeAllListeners('error'); 39 | resourceStream.removeAllListeners('data'); 40 | unzippedStream.unpipe(extract); 41 | extract.end(); 42 | unzippedStream.end(); 43 | resourceStream.end(); 44 | cb(null, true); 45 | callback(); 46 | return; 47 | } 48 | stream.resume(); 49 | callback(); 50 | }); 51 | 52 | extract.once('finish', function () { 53 | extract.removeAllListeners('error'); 54 | extract.removeAllListeners('entry'); 55 | cb(null, false); 56 | }); 57 | 58 | var readBytes = 0; 59 | resourceStream.on('data', function (data) { 60 | readBytes += data.length; 61 | }); 62 | 63 | resourceStream.once('end', function () { 64 | debug('Total Read ' + readBytes + ' out of ' + totalLength + ' ' + Math.floor((readBytes / totalLength) * 100) + '%'); 65 | }); 66 | 67 | resourceStream.once('response', function (response) { 68 | totalLength = response.headers['content-length']; 69 | }); 70 | 71 | var unzippedStream = resourceStream.pipe(gunzip); 72 | 73 | gunzip.once('error', onError); 74 | extract.once('error', onError); 75 | resourceStream.once('error', onError); 76 | unzippedStream.once('error', onError); 77 | 78 | unzippedStream.pipe(extract); 79 | 80 | }; 81 | 82 | --------------------------------------------------------------------------------