npm package discovery and stats viewer.

Discover Tips

  • General search

    [free text search, go nuts!]

  • Package details

    pkg:[package-name]

  • User packages

    @[username]

Sponsor

Optimize Toolset

I’ve always been into building performant and accessible sites, but lately I’ve been taking it extremely seriously. So much so that I’ve been building a tool to help me optimize and monitor the sites that I build to make sure that I’m making an attempt to offer the best experience to those who visit them. If you’re into performant, accessible and SEO friendly sites, you might like it too! You can check it out at Optimize Toolset.

About

Hi, 👋, I’m Ryan Hefner  and I built this site for me, and you! The goal of this site was to provide an easy way for me to check the stats on my npm packages, both for prioritizing issues and updates, and to give me a little kick in the pants to keep up on stuff.

As I was building it, I realized that I was actually using the tool to build the tool, and figured I might as well put this out there and hopefully others will find it to be a fast and useful way to search and browse npm packages as I have.

If you’re interested in other things I’m working on, follow me on Twitter or check out the open source projects I’ve been publishing on GitHub.

I am also working on a Twitter bot for this site to tweet the most popular, newest, random packages from npm. Please follow that account now and it will start sending out packages soon–ish.

Open Software & Tools

This site wouldn’t be possible without the immense generosity and tireless efforts from the people who make contributions to the world and share their work via open source initiatives. Thank you 🙏

© 2024 – Pkg Stats / Ryan Hefner

file-manifest

v2.0.5

Published

Require all the files in a directory into a single object

Downloads

275

Readme

Build Status downloads npm Code Climate Test Coverage dependencies

File-Manifest

Require all the files in a directory into a single object

Installation

npm install file-manifest --save

Usage

File-manifest recursively requires everything in a given directory (optionally filtered with globstar patterns) and packages it into a single object where the keys are (by default) camel-cased file names. Thus if you had a directory called foo, whose structure looked like this:

bar
baz
  quux
  some-long-name

You'd end up with an object that looked like this:

{
  fooBar: 'foo/bar exports',
  fooBazQuux: 'foo/baz/quux exports',
  fooBazSomeLongName: 'foo/baz/some-long-name exports'
}

This is useful (for example) in an express app to create a route manifest:

var routes = require('file-manifest').generate('routes');

app.get('/', routes.home);
app.get('/users/:id', routes.profile);
// etc.

or a middleware manifest:

var middleware = require('file-manifest').generate('middleware');

app.use(middleware.setOriginPolicy);
app.use(middleware.defaultLogger);
// etc.

or in a mongoose app to load all models:

var models = require('file-manifest').generate('models');
module.exports = function(req, res, next) {
  req.models = models;
  next();
};

API

.generate(directory[, options][, callback])

The main entry point for the library. If a callback is passed (signature function(error, manifest)), file-manifest will treat this is as an asynchronous call and return the results in the callback. The possible options are:

match

A string or array of string globstar patterns to filter which files to parse. (See minimatch for pattern syntax.)

memo

The starting value for the manifest reduction. By default, this is {} (except in a couple cases defined below), but you can use a different starting value, so long as it is compatible with the reduction (that is, 'string'.push() is going to blow up).

name

A function that takes a file object and returns the name of the key to be used for this file. Or a string that points to a built-in namer function (see the list of transformers defiled exposed). By default, camel casing is used for key names. For example, setting name to "dash" will return dash delimited file names like foo-bar-baz instead of camel cased ones.

load

A function that loads the value of the key defined above. The default is require for files that can be required (.js and .json) and readFile for other files. You can pass any function that accepts a file path (absolute) and an optional callback. For instance, you could pass require('yamljs').load to parse yaml files. Load can also be a string pointing at a built-in loader: one of "readFile" or "require". You probably won't need this, since the correct one is chosen dynamically, but if you want to read javascript without loading it as source, or if you want to load a coffeescript file and you've previously called required coffee-script/register, then you may want to do this.

reduce

A custom reduce function for creating the manifest. In asynchronous implementations, this uses async.js's reduce, and in sync implementations, it uses lodash's reduce. That is, you can pass an async reducer with the signature function(manifest, file, next) where next is a callback with the signature function(err, reduction) or a sync reducer with the signature function(manifest, file[, index][, collection]) that returns the reduction. In both cases, the file parameter is a file object. The reduce function will be called with the options object as the (this) context, so you can either calculate the key and value yourself or call this.name.call(this, file) and this.load.call(this, file[, callback]) to get them.

Additionally, reduce can be a string pointing at a custom reducer. The default is "flat", which returns a single-level object of properties with their exports, but you can also pass "nested", "list", or "objectList". Given the example "foo" directory above, the results would be as follows:

// flat (default)
{
  fooBar: 'foo/bar exports',
  fooBazQuux: 'foo/baz/quux exports',
  fooBazSomeLongName: 'foo/baz/some-long-name exports'
}

// nested
{
  foo: {
    bar: 'foo/bar exports'
    baz: {
      quux: 'foo/baz/quux exports',
      someLongName: 'foo/baz/some-long-name exports'
    }
  }
}

// list
[
  'foo/bar exports',
  'foo/baz/quux exports',
  'foo/baz/some-long-name exports'
]

// objectList
[
  {
    name: 'foo/bar',
    contents: 'foo/bar exports'
  },
  {
    name: 'foo/baz/quux',
    contents: 'foo/baz/quux exports'
  },
  {
    name: 'foo/baz/some-long-name',
    contents: 'foo/baz/some-long-name exports'
  }
]

Some of this is handled smartly for you. For instance, if you set memo to [] in the options hash, reduce will automatically be set to "list." Similarly, if you set reduce to "list" or "objectList," memo will be set to [].

.generateSync(directory[, options])

This is just syntactic sugar for calling .generate without a function. It doesn't do anything that .generate doesn't; it's provided only for completeness and for those who like having "sync" in their synchronous function names.

.generatePromise(directory[, options])

An asynchronous implementation that returns a promise instead.

.generateEvent(directory[, options])

An asynchronous implementation that returns an event emitter instead.

Examples

Given var fm = require('file-manifest');:

Get all routes synchronously:

var routes = fm.generate('routes');

Get all member routes:

var routes = fm.generate('routes', { match: '**/*member*.js' });

Get all routes except index.js:

var routes = fm.generate('routes', { match: ['**/*.js', '!index.js'] }

Get all routes with dashed names:

var routes = fm.generate('routes', { name: 'dash' });

Get all routes with a random name:

var routes = fm.generate('routes', { name: require('uuid').v4 });

// or
var routes = fm.generate('routes', { name: require('randomstring').generate });

Get all markdown files in the current directory (as strings using "readFile")

var routes = fm.generate('./', { match: '**/*.md', load: "readFile" }); // not necessary, since this is the default for non .js/.json files

Get all markdown files in the current directory as markdown:

var routes = fm.generate('./', { match: '**/*.md', load: require('marky-mark').parseFileSync });

Get a list of routes:

var routes = fm.generate('routes', { reduce: 'list' });

// or
var routes = fm.generate('routes', { memo: [] });

Get a list of routes that includes the file names:

var routes = fm.generate('routes', { reduce: 'objectList' });

Get a nested object of routes:

var routes = fm.generate('routes', { reduce: 'nested' });

Get all files in lib grouped by extension

var routes = fm.generate('lib', {
  reduce: function(manifest, file) {
    var key = file.ext().replace('.', '');
    manifest[key] = manifest[key] || [];
    manifest[key].push(file.relative({ ext: false }));
    return manifest;
  }
});

Get all routes asynchronously:

fm.generate('routes', function(err, routes) {

});

Get all routes with a promise:

var promise = fm.generatePromise('routes');
promise.then(function(routes) {

}, function(error) {

});

Get all routes via event:

var emitter = fm.generateEvent('routes');
emitter.on('manifest', function(routes) {

}).on('error', function(error) {

});

Contributing

Please see the contribution guidelines.