Comparing version 0.3.0 to 0.4.0
{ | ||
"name": "spelunk", | ||
"description": "Traverse a folder in node, turning its contents into an object for easy consumption", | ||
"version": "0.3.0", | ||
"version": "0.4.0", | ||
"homepage": "https://github.com/Rich-Harris/spelunk", | ||
@@ -6,0 +6,0 @@ "author": { |
@@ -71,12 +71,18 @@ # spelunk.js | ||
spelunk( 'myFolder', callback ); | ||
spelunk( 'myFolder', options, callback ); // you can omit options | ||
``` | ||
...but it also returns a promise, because this is 2014 dammit and callbacks are a lousy flow control mechanism: | ||
...but it also returns a promise, because this is 2015 dammit and callbacks are a lousy flow control mechanism: | ||
```js | ||
spelunk( 'myFolder' ).then( doSomething, handleError ); | ||
spelunk( 'myFolder', options ).then( doSomething, handleError ); | ||
``` | ||
### Synchronous usage | ||
```js | ||
var result = spelunk.sync( 'myFolder', options ); | ||
``` | ||
## Options | ||
@@ -83,0 +89,0 @@ |
175
spelunk.js
@@ -1,9 +0,13 @@ | ||
var fs, path, minimatch; | ||
var fs = require( 'graceful-fs' ); | ||
var path = require( 'path' ); | ||
var minimatch = require( 'minimatch' ); | ||
var Promise = require( 'es6-promise' ).Promise; | ||
fs = require( 'graceful-fs' ); | ||
path = require( 'path' ); | ||
minimatch = require( 'minimatch' ); | ||
Promise = require( 'es6-promise' ).Promise; | ||
var sync = require( './lib/sync' ); | ||
var async = require( './lib/async' ); | ||
var shared = require( './lib/shared' ); | ||
module.exports = function ( root, options, done ) { | ||
module.exports = spelunk; | ||
function spelunk ( root, options, done ) { | ||
var promise = new Promise( function ( fulfil, reject ) { | ||
@@ -13,24 +17,10 @@ if ( typeof options === 'function' ) { | ||
options = {}; | ||
} else { | ||
options = options || {}; | ||
} | ||
// If root has a trailing slash, remove it | ||
if ( root.substr( -1 ) === path.sep ) { | ||
root = root.substr( 0, root.length - 1 ); | ||
} | ||
options = shared.normaliseOptions( options ); | ||
// Exclude .DS_Store, Thumbs.db and any other gubbins specified by the user | ||
if ( !options.exclude ) { | ||
options.exclude = []; | ||
} else if ( typeof options.exclude === 'string' ) { | ||
options.exclude = [ options.exclude ]; | ||
} | ||
options.exclude.push( '**/*/.DS_Store', '**/*/Thumbs.db' ); | ||
root = path.resolve( root ); | ||
// Get the specified folder, then done | ||
getDir( '', root, options, function ( err, result ) { | ||
async( root, root, options, function ( err, result ) { | ||
if ( err ) { | ||
@@ -53,138 +43,5 @@ return reject( err ); | ||
function getDir ( root, dir, options, gotDir ) { | ||
var relative = path.relative( root, dir ); | ||
fs.readdir( dir, function ( err, files ) { | ||
var contents, result, remaining, check, keysAreNumeric; | ||
if ( err ) { | ||
gotDir( err ); | ||
return; | ||
} | ||
result = {}; | ||
contents = filterExclusions( files, relative, options.exclude ); | ||
if ( !contents.length ) { | ||
gotDir( null, result ); | ||
return; | ||
} | ||
keysAreNumeric = true; // assume we need to create an array, until we don't | ||
remaining = contents.length; | ||
check = function () { | ||
if ( !--remaining ) { | ||
if ( keysAreNumeric ) { | ||
result = toArray( result ); | ||
} | ||
gotDir( null, result ); | ||
} | ||
}; | ||
contents.forEach( function ( fileName ) { | ||
var filePath, key, gotFile; | ||
filePath = path.join( dir, fileName ); | ||
gotFile = function ( err, data ) { | ||
if ( err ) { | ||
gotDir( err, null ); | ||
} else if ( result[ key ] !== undefined ) { | ||
gotDir( 'You cannot have multiple files in the same folder with the same name (disregarding extensions) - failed at ' + filePath ); | ||
} else { | ||
result[ key ] = data; | ||
check(); | ||
} | ||
}; | ||
fs.stat( filePath, function ( err, stats ) { | ||
if ( err ) { | ||
gotDir( err, null ); | ||
return; | ||
} | ||
if ( stats.isDirectory() ) { | ||
key = fileName; | ||
getDir( root, filePath, options, gotFile ); | ||
} else { | ||
key = getKey( fileName, options ); | ||
getFile( filePath, gotFile ); | ||
} | ||
if ( isNaN( +key ) ) { | ||
keysAreNumeric = false; | ||
} | ||
}); | ||
}); | ||
}); | ||
} | ||
function getFile ( filePath, gotFile ) { | ||
fs.readFile( filePath, function ( err, result ) { | ||
var data; | ||
if ( err ) { | ||
gotFile( err, null ); | ||
} else { | ||
data = result.toString(); | ||
try { | ||
data = JSON.parse( data ); | ||
} catch ( e ) {} | ||
gotFile( null, data ); | ||
} | ||
}); | ||
} | ||
// Get key from path, e.g. 'project/data/config.json' -> 'config' | ||
function getKey ( fileName, options ) { | ||
var lastDotIndex = fileName.lastIndexOf( '.' ); | ||
if ( lastDotIndex > 0 && !options.keepExtensions ) { | ||
return fileName.substr( 0, lastDotIndex ); | ||
} | ||
return fileName; | ||
} | ||
function toArray ( object ) { | ||
var array = [], key; | ||
for ( key in object ) { | ||
if ( object.hasOwnProperty( key ) ) { | ||
array[ +key ] = object[ key ]; | ||
} | ||
} | ||
return array; | ||
} | ||
function filterExclusions ( files, relative, exclusions ) { | ||
if ( !exclusions ) { | ||
return files; | ||
} | ||
return files.filter( function ( fileName ) { | ||
var filePath, i; | ||
filePath = path.join( relative, fileName ); | ||
i = exclusions.length; | ||
while ( i-- ) { | ||
if ( minimatch( filePath, exclusions[i] ) ) { | ||
return false; | ||
} | ||
} | ||
return true; | ||
}); | ||
} | ||
spelunk.sync = function ( root, options ) { | ||
root = path.resolve( root ); | ||
return sync( root, root, shared.normaliseOptions( options ) ); | ||
}; |
@@ -57,3 +57,13 @@ var spelunk, fs, path, assert, FIXTURES, EXPECTED, tests, runTest; | ||
runTest = function () { | ||
// sync tests | ||
tests.forEach( function ( test ) { | ||
var actual = spelunk.sync( path.join( FIXTURES, test.id ), test.options ); | ||
var expected = require( path.resolve( EXPECTED, test.id + '.json' ) ); | ||
assert.deepEqual( actual, expected, test.message ); | ||
process.stdout.write( '.' ); | ||
}); | ||
function runAsyncTest () { | ||
var test = tests.shift(); | ||
@@ -75,10 +85,10 @@ | ||
expected = JSON.parse( fs.readFileSync( path.resolve( EXPECTED, test.id + '.json' ) ).toString() ); | ||
expected = require( path.resolve( EXPECTED, test.id + '.json' ) ); | ||
assert.deepEqual( actual, expected, test.message ); | ||
runTest(); | ||
runAsyncTest(); | ||
}); | ||
}; | ||
runTest(); | ||
runAsyncTest(); |
Major refactor
Supply chain riskPackage has recently undergone a major refactor. It may be unstable or indicate significant internal changes. Use caution when updating to versions that include significant changes.
Found 1 instance in 1 package
Dynamic require
Supply chain riskDynamic require can indicate the package is performing dangerous or unsafe dynamic code execution.
Found 1 instance in 1 package
12551
37
275
121
5
1