Huge News!Announcing our $40M Series B led by Abstract Ventures.Learn More
Socket
Sign inDemoInstall
Socket

loader-cache

Package Overview
Dependencies
Maintainers
2
Versions
15
Alerts
File Explorer

Advanced tools

Socket logo

Install Socket

Detect and block malicious and high-risk dependencies

Install

loader-cache - npm Package Compare versions

Comparing version 0.4.0 to 0.5.0

414

index.js

@@ -12,2 +12,4 @@ /*!

var typeOf = require('kind-of');
var flatten = require('arr-flatten');
var isStream = require('is-stream');

@@ -38,94 +40,24 @@ /**

function Loaders(cache) {
this.cache = cache || {};
function Loaders(options) {
if (!(this instanceof Loaders)) {
return new Loaders(options);
}
options = options || {};
this.cache = options.cache || {};
this.iterator = options.iterator;
}
/**
* Base register method used by all other register method.
* Get a loader stack from the cache.
*
* @param {String} `ext`
* @param {Function} `fn`
* @param {String} `type`
* @return {String}
*/
Loaders.prototype.register = function(/*ext, fns, arr, type*/) {
return this.compose.apply(this, arguments);
};
/**
* Register the given loader callback `fn` as `ext`. Any arbitrary
* name can be assigned to a loader, however, the loader will only be
* called when either:
* a. `ext` matches the file extension of a path passed to the `.load()` method, or
* b. `ext` is an arbitrary name passed on the loader stack of another loader. Example below.
*
* @param {String|Array} `ext` File extension or name of the loader.
* @param {Function|Array} `fn` A loader function, or create a loader from other others by passing an array of names.
* @return {Object} `Loaders` to enable chaining
* @param {String} `name`
* @return {Object}
* @api public
*/
Loaders.prototype.registerSync = function(ext, stack, fn) {
this.register(ext, stack, fn, 'sync');
Loaders.prototype.getStack = function(name) {
return this.cache[name] || [];
};
/**
* Register the given async loader callback `fn` as `ext`. Any arbitrary
* name can be assigned to a loader, however, the loader will only be
* called when either:
* a. `ext` matches the file extension of a path passed to the `.load()` method, or
* b. `ext` is an arbitrary name passed on the loader stack of another loader. Example below.
*
* @param {String|Array} `ext` File extension or name of the loader.
* @param {Function|Array} `fn` A loader function with a callback parameter, or create a loader from other others by passing an array of names.
* @return {Object} `Loaders` to enable chaining
* @api public
*/
Loaders.prototype.registerAsync = function(/*ext, stack, fn*/) {
var i = arguments.length, args = new Array(i);
while (i--) args[i] = arguments[i];
this.register.apply(this, args.concat('async'));
};
/**
* Register the given promise loader callback `fn` as `ext`. Any arbitrary
* name can be assigned to a loader, however, the loader will only be
* called when either:
* a. `ext` matches the file extension of a path passed to the `.load()` method, or
* b. `ext` is an arbitrary name passed on the loader stack of another loader. Example below.
*
* @param {String|Array} `ext` File extension or name of the loader.
* @param {Function|Array} `fn` A loader function that returns a promise, or create a loader from other others by passing an array of names.
* @return {Object} `Loaders` to enable chaining
* @api public
*/
Loaders.prototype.registerPromise = function(/*ext, stack, fn*/) {
var i = arguments.length, args = new Array(i);
while (i--) args[i] = arguments[i];
this.register.apply(this, args.concat('promise'));
};
/**
* Register the given stream loader callback `fn` as `ext`. Any arbitrary
* name can be assigned to a loader, however, the loader will only be
* called when either:
* a. `ext` matches the file extension of a path passed to the `.load()` method, or
* b. `ext` is an arbitrary name passed on the loader stack of another loader. Example below.
*
* @param {String|Array} `ext` File extension or name of the loader.
* @param {Stream|Array} `fn` A stream loader, or create a loader from other others by passing an array of names.
* @return {Object} `Loaders` to enable chaining
* @api public
*/
Loaders.prototype.registerStream = function(/*ext, stack, fn*/) {
var i = arguments.length, args = new Array(i);
while (i--) args[i] = arguments[i];
this.register.apply(this, args.concat('stream'));
};
/**
* Create a loader from other (previously cached) loaders. For

@@ -135,28 +67,13 @@ * example, you might create a loader like the following:

*
* @param {String} `ext` File extension to select the loader or loader stack to use.
* @param {String} `loaders` Array of loader names.
* @param {String} `name` Name of the loader or loader stack to use.
* @param {Array} `stack` Array of loader names.
* @param {Function} `fn` Optional loader function
* @return {Object} `Loaders` to enable chaining
*/
Loaders.prototype.compose = function(ext/*, stack, fns*/) {
var len = arguments.length - 1, i = 1;
var stack = [], type;
while (len--) {
var arg = arguments[i++];
if (typeof arg === 'string') {
type = arg;
} else if (arg) {
stack.push(arg);
}
}
if (typeof type === 'undefined') {
type = 'sync';
}
this.cache[type] = this.cache[type] || {};
stack = this.buildStack(type, stack);
this.cache[type][ext] = union(this.cache[type][ext] || [], stack);
Loaders.prototype.register = function(name, loaders) {
var args = [].slice.call(arguments, 1);
var cached = this.getStack(name);
var stack = this.buildStack(args).stack;
this.cache[name] = cached.concat(stack);
return this;

@@ -166,56 +83,38 @@ };

/**
* Create a from other (previously cached) loaders.
* Build a loader stack from a mix of functions and loader names.
*
* @param {String} `name` Name of the loader or loader stack to use, usually this is a file extension.
* @param {String} `loaders` Array of loader names.
* @return {Object} `Loaders` to enable chaining
* @param {Array} `stack` array of loader functions and names.
* @return {Array} Resolved loader functions
* @api public
*/
Loaders.prototype.composeStream = function() {
var fn = this._makeComposer('stream');
return fn.apply(fn, arguments);
};
Loaders.prototype.buildStack = function(args, cache) {
if (!Array.isArray(args)) {
throw new TypeError('Loaders#buildStack expects an array.');
}
/**
* Internal method for creating composers.
*
* @param {String} `type` The type of composer to create.
* @return {Function} Composer function for the given `type.
*/
var len = args.length, i = 0;
var stack = [], other = [];
cache = cache || this.cache;
Loaders.prototype._makeComposer = function() {
return function () {
// don't slice args (for v8 optimizations)
var len = arguments.length, i = 0;
var args = new Array(i);
while (len--) {
args[i] = arguments[i++];
}
args[i] = 'stream';
this.compose.apply(this, args);
}.bind(this);
};
while (len--) {
var arg = args[i++];
var type = typeOf(arg);
/**
* Build a stack of loader functions when given a mix of functions and names.
*
* @param {String} `type` Loader type to get loaders from.
* @param {Array} `stack` Stack of loader functions and names.
* @return {Array} Resolved loader functions
*/
Loaders.prototype.buildStack = function(type, stack) {
var len = stack && stack.length, i = 0;
var res = [];
while (i < len) {
var name = stack[i++];
if (typeOf(name) === 'string') {
res = res.concat(this.cache[type][name]);
} else if (typeOf(name) === 'array') {
res = res.concat(this.buildStack(type, name));
if (type === 'string' && cache[arg]) {
stack.push(cache[arg]);
} else if (type === 'function') {
stack.push(arg);
} else if (type === 'array') {
stack.push.apply(stack, this.buildStack(arg, cache).stack);
} else if (isStream(arg)) {
stack.push(arg);
} else {
res.push(name);
other.push(arg);
}
}
var res = {};
res.stack = flatten(stack);
res.args = other;
return res;

@@ -225,213 +124,22 @@ };

/**
* Run loaders associated with `ext` of the given filepath.
* Compose a loader function from the given functions and/or
* the names of loaders.
*
* **Example**
*
* ```js
* // this will run the `yml` loader from the `.compose()` example
* loaders.load('config.yml');
* ```
*
* @param {String} `val` Value to load, like a file path.
* @param {String} `options` Options to pass to whatever loaders are defined.
* @return {String}
* @api public
*/
Loaders.prototype.load = function(val, stack, options) {
if (!Array.isArray(stack)) {
options = stack; stack = [];
}
var loader = matchLoader(val, options, this);
stack = this.buildStack('sync', stack);
var fns = [];
if (this.cache.sync.hasOwnProperty(loader)) {
fns = fns.concat(this.cache.sync[loader]);
}
if (stack && stack.length) {
fns = fns.concat(stack);
}
if (!fns.length) return val;
var len = fns.length, i = 0;
while (len--) {
var fn = fns[i++];
val = fn(val, options);
}
return val;
};
/**
* Run async loaders associated with `ext` of the given filepath.
*
* **Example**
*
* ```js
* // this will run the `yml` async loader from the `.compose()` example
* loaders.loadAsync('config.yml', function (err, obj) {
* // do some async stuff
* // this will return a function from the given loaders
* // and function
* loaders.compose(['a', 'b', 'c'], function(val) {
* //=> do stuff to val
* });
* ```
*
* @param {String} `fp` File path to load.
* @param {Object} `options` Options to pass to whatever loaders are defined.
* @param {Function} `cb` Callback to indicate loading has finished
* @return {String}
* @param {String|Array|Function} `loader(s)` String, list or array of loader names or functions, in any combination or order.
* @return {Function} Returns a function to use for loading.
* @api public
*/
Loaders.prototype.loadAsync = function(fp, stack, options, cb) {
var async = requires.async || (requires.async = require('async'));
if (typeOf(stack) === 'function') {
cb = stack; stack = []; options = {};
}
if (typeOf(options) === 'function') {
cb = options; options = {};
}
if (!Array.isArray(stack)) {
options = stack; stack = [];
}
stack = this.buildStack('async', stack);
var loader = matchLoader(fp, options, this);
var fns = union(this.cache.async[loader] || [], stack);
if (!fns.length) {
return fp;
}
async.reduce(fns, fp, function (acc, fn, next) {
fn(acc, options, next);
}, cb);
Loaders.prototype.compose = function() {
var args = [].slice.call(arguments);
var fns = this.buildStack(args).stack;
return this.iterator.call(this, fns);
};
/**
* Run promise loaders associated with `ext` of the given filepath.
*
* **Example**
*
* ```js
* // this will run the `yml` promise loader from the `.compose()` example
* loaders.loadPromise('config.yml')
* .then(function (results) {
* // do some promise stuff
* });
* ```
*
* @param {String} `fp` File path to load.
* @param {Object} `options` Options to pass to whatever loaders are defined.
* @return {Promise} a promise that will be fulfilled later
* @api public
*/
Loaders.prototype.loadPromise = function(fp, stack, options) {
var Promise = requires.promise || (requires.promise = require('bluebird'));
if (!Array.isArray(stack)) {
options = stack;
stack = [];
}
var current = Promise.resolve();
options = options || {};
var loader = matchLoader(fp, options, this);
stack = this.buildStack('promise', stack);
var fns = union(this.cache.promise[loader] || [], stack);
if (!fns.length) {
return current.then(function () {
return fp;
});
}
return Promise.reduce(fns, function (acc, fn) {
return fn(acc, options);
}, fp);
};
/**
* Run stream loaders associated with `ext` of the given filepath.
*
* **Example**
*
* ```js
* // this will run the `yml` stream loader from the `.compose()` example
* loaders.LoadStream('config.yml')
* .pipe(foo())
* .on('data', function (results) {
* // do stuff
* });
* ```
*
* @param {String} `fp` File path to load.
* @param {Object} `options` Options to pass to whatever loaders are defined.
* @return {Stream} a stream that will be fulfilled later
* @api public
*/
Loaders.prototype.loadStream = function(fp, stack, options) {
var es = requires.es || (requires.es = require('event-stream'));
if (!Array.isArray(stack)) {
options = stack;
stack = [];
}
options = options || {};
var loader = matchLoader(fp, options, this);
stack = this.buildStack('stream', stack);
var fns = union(this.cache.stream[loader] || [], stack);
if (!fns.length) {
var noop = es.through(function (fp) {
this.emit('data', fp);
});
noop.stream = true;
fns = [noop];
}
var stream = es.pipe.apply(es, fns);
process.nextTick(function () {
stream.write(fp);
stream.end();
});
return stream;
};
/**
* Get a loader based on the given pattern.
*
* @param {String} `pattern` By default, this is assumed to be a filepath.
* @return {Object} Object
*/
function matchLoader(pattern, options, thisArg) {
if (options && options.matchLoader) {
return options.matchLoader(pattern, options, thisArg);
}
return formatExt(path.extname(pattern));
}
/**
* Format extensions.
*
* @param {String} `ext`
* @return {String}
*/
function formatExt(ext) {
return (ext[0] === '.') ? ext.slice(1) : ext;
}
/**
* Concat a list of arrays.
*/
function union() {
return [].concat.apply([], arguments);
}

29

package.json
{
"name": "loader-cache",
"description": "Register loader functions that dynamically read, parse or otherwise transform file contents when the name of the loader matches a file extension. You can also compose loaders from other loaders.",
"version": "0.4.0",
"version": "0.5.0",
"homepage": "https://github.com/jonschlinkert/loader-cache",

@@ -16,2 +16,3 @@ "author": {

"files": [
"iterators/",
"index.js"

@@ -27,11 +28,25 @@ ],

"dependencies": {
"async": "^0.9.0",
"bluebird": "^2.3.11",
"event-stream": "^3.1.7",
"kind-of": "^0.1.2"
"arr-flatten": "^1.0.1",
"bluebird": "^2.9.27",
"event-stream": "^3.3.1",
"is-stream": "^1.0.1",
"kind-of": "^2.0.0"
},
"devDependencies": {
"extend-shallow": "^1.1.4",
"glob": "^5.0.10",
"gulp-istanbul": "^0.10.0",
"gulp-jshint": "^1.11.0",
"gulp-mocha": "^2.1.1",
"gulp-util": "^3.0.5",
"iterator-async": "^0.1.0",
"iterator-promise": "^0.1.0",
"iterator-streams": "^0.1.0",
"iterator-sync": "^0.1.0",
"js-yaml": "^3.2.3",
"jshint-stylish": "^2.0.0",
"mocha": "*",
"should": "^5.0.1"
"should": "^5.0.1",
"strip-ansi": "^2.0.1",
"verb": "^0.8.6"
},

@@ -50,2 +65,2 @@ "keywords": [

]
}
}

@@ -1,14 +0,16 @@

# loader-cache [![NPM version](https://badge.fury.io/js/loader-cache.svg)](http://badge.fury.io/js/loader-cache) [![Build Status](https://travis-ci.org/jonschlinkert/loader-cache.svg)](https://travis-ci.org/jonschlinkert/loader-cache)
# loader-cache [![NPM version](https://badge.fury.io/js/loader-cache.svg)](http://badge.fury.io/js/loader-cache) [![Build Status](https://travis-ci.org/jonschlinkert/loader-cache.svg)](https://travis-ci.org/jonschlinkert/loader-cache)
> Register loader functions that dynamically read, parse or otherwise transform file contents when the name of the loader matches a file extension. You can also compose loaders from other loaders.
## Install with [npm](npmjs.org)
## Example usage
```bash
npm i loader-cache --save
```
```js
var LoaderCache = require('loader-cache');
var loaders = new LoaderCache();
## Example
// register a loader for reading files
loaders.register('read', function(fp) {
return fs.readFileSync(fp, 'utf8');
});
```js
// register a loader for parsing YAML

@@ -19,34 +21,44 @@ loaders.register('yaml', function(fp) {

// register a loader to be used in other loaders
loaders.register('read', function(fp) {
return fs.readFileSync(fp, 'utf8');
// create a loader from any combination of other
// registered loaders and functions.
loaders.register('dataLoader', ['read', 'yaml'], function(data) {
if (!data) throw new Error('no data!');
return data;
});
// create a new loader from the `yaml` and `read` loaders.
loaders.register('yml', ['read', 'yaml']);
// the `.load()` method calls any loaders registered
// to the `ext` on the given filepath
loaders.load('config.yml');
// pass a loader stack or the name of a loader to `.compose()`
// to create the actual function to be used for loading
var fn = loaders.compose('dataLoader');
var data = fn('config.yml');
```
## Running tests
Install dev dependencies.
## Install
```bash
npm i -d && npm test
Install with [npm](https://www.npmjs.com/)
```sh
$ npm i loader-cache --save
```
## Table of contents
## Usage
<!-- toc -->
```js
var loaders = require('loader-cache');
```
* [API](#api)
* [Related libs](#related-libs)
* [Running tests](#running-tests)
* [Code coverage](#code-coverage)
_(Table of contents generated by [verb])_
<!-- tocstop -->
## API
### [Loaders](./index.js#L37)
### [Loaders](index.js#L39)
Create a new instance of `Loaders`
**Example**
```js

@@ -57,138 +69,91 @@ var Loaders = require('loader-cache');

### [.registerSync](./index.js#L67)
### [.getStack](index.js#L56)
* `ext` **{String|Array}**: File extension or name of the loader.
* `fn` **{Function|Array}**: A loader function, or create a loader from other others by passing an array of names.
* `returns` **{Object}** `Loaders`: to enable chaining
Get a loader stack from the cache.
Register the given loader callback `fn` as `ext`. Any arbitrary
name can be assigned to a loader, however, the loader will only be
called when either:
a. `ext` matches the file extension of a path passed to the `.load()` method, or
b. `ext` is an arbitrary name passed on the loader stack of another loader. Example below.
**Params**
### [.registerAsync](./index.js#L84)
* `name` **{String}**
* `returns` **{Object}**
* `ext` **{String|Array}**: File extension or name of the loader.
* `fn` **{Function|Array}**: A loader function with a callback parameter, or create a loader from other others by passing an array of names.
* `returns` **{Object}** `Loaders`: to enable chaining
### [.buildStack](index.js#L87)
Register the given async loader callback `fn` as `ext`. Any arbitrary
name can be assigned to a loader, however, the loader will only be
called when either:
a. `ext` matches the file extension of a path passed to the `.load()` method, or
b. `ext` is an arbitrary name passed on the loader stack of another loader. Example below.
Build a loader stack from a mix of functions and loader names.
### [.registerPromise](./index.js#L103)
**Params**
* `ext` **{String|Array}**: File extension or name of the loader.
* `fn` **{Function|Array}**: A loader function that returns a promise, or create a loader from other others by passing an array of names.
* `returns` **{Object}** `Loaders`: to enable chaining
* `stack` **{Array}**: array of loader functions and names.
* `returns` **{Array}**: Resolved loader functions
Register the given promise loader callback `fn` as `ext`. Any arbitrary
name can be assigned to a loader, however, the loader will only be
called when either:
a. `ext` matches the file extension of a path passed to the `.load()` method, or
b. `ext` is an arbitrary name passed on the loader stack of another loader. Example below.
### [.compose](index.js#L135)
### [.registerStream](./index.js#L122)
Compose a loader function from the given functions and/or the names of loaders.
* `ext` **{String|Array}**: File extension or name of the loader.
* `fn` **{Stream|Array}**: A stream loader, or create a loader from other others by passing an array of names.
* `returns` **{Object}** `Loaders`: to enable chaining
**Params**
Register the given stream loader callback `fn` as `ext`. Any arbitrary
name can be assigned to a loader, however, the loader will only be
called when either:
a. `ext` matches the file extension of a path passed to the `.load()` method, or
b. `ext` is an arbitrary name passed on the loader stack of another loader. Example below.
* `loader(s)` **{String|Array|Function}**: String, list or array of loader names or functions, in any combination or order.
* `returns` **{Function}**: Returns a function to use for loading.
### [.load](./index.js#L236)
Run loaders associated with `ext` of the given filepath.
* `val` **{String}**: Value to load, like a file path.
* `options` **{String}**: Options to pass to whatever loaders are defined.
* `returns`: {String}
**Example**
```js
// this will run the `yml` loader from the `.compose()` example
loaders.load('config.yml');
```
### [.loadAsync](./index.js#L282)
Run async loaders associated with `ext` of the given filepath.
* `fp` **{String}**: File path to load.
* `options` **{Object}**: Options to pass to whatever loaders are defined.
* `cb` **{Function}**: Callback to indicate loading has finished
* `returns`: {String}
**Example**
```js
// this will run the `yml` async loader from the `.compose()` example
loaders.loadAsync('config.yml', function (err, obj) {
// do some async stuff
// this will return a function from the given loaders
// and function
loaders.compose(['a', 'b', 'c'], function(val) {
//=> do stuff to val
});
```
### [.loadPromise](./index.js#L328)
## Related libs
Run promise loaders associated with `ext` of the given filepath.
* [config-cache](https://github.com/jonschlinkert/config-cache): General purpose JavaScript object storage methods.
* [cache-base](https://github.com/jonschlinkert/cache-base): Generic object cache for node.js/javascript projects.
* [engine-cache](https://github.com/jonschlinkert/engine-cache): express.js inspired template-engine manager.
* [helper-cache](https://github.com/jonschlinkert/helper-cache): Easily register and get helper functions to be passed to any template engine or node.js… [more](https://github.com/jonschlinkert/helper-cache)
* [option-cache](https://github.com/jonschlinkert/option-cache): Simple API for managing options in JavaScript applications.
* [parser-cache](https://github.com/jonschlinkert/parser-cache): Cache and load parsers, similiar to consolidate.js engines.
* `fp` **{String}**: File path to load.
* `options` **{Object}**: Options to pass to whatever loaders are defined.
* `returns` **{Promise}**: a promise that will be fulfilled later
## Running tests
**Example**
Install dev dependencies:
```js
// this will run the `yml` promise loader from the `.compose()` example
loaders.loadPromise('config.yml')
.then(function (results) {
// do some promise stuff
});
```sh
$ npm i -d && npm test
```
### [.loadStream](./index.js#L373)
## Code coverage
Run stream loaders associated with `ext` of the given filepath.
Please help improve code coverage by [adding unit tests](#contributing).
* `fp` **{String}**: File path to load.
* `options` **{Object}**: Options to pass to whatever loaders are defined.
* `returns` **{Stream}**: a stream that will be fulfilled later
**Example**
```js
// this will run the `yml` stream loader from the `.compose()` example
loaders.LoadStream('config.yml')
.pipe(foo())
.on('data', function (results) {
// do stuff
});
-----------------|-----------|-----------|-----------|-----------|
File | % Stmts |% Branches | % Funcs | % Lines |
-----------------|-----------|-----------|-----------|-----------|
loader-cache/ | 91.27 | 82.35 | 85.71 | 92.5 |
index.js | 91.27 | 82.35 | 85.71 | 92.5 |
-----------------|-----------|-----------|-----------|-----------|
All files | 91.27 | 82.35 | 85.71 | 92.5 |
-----------------|-----------|-----------|-----------|-----------|
```
## Contributing
Pull requests and stars are always welcome. For bugs and feature requests, [please create an issue](https://github.com/jonschlinkert/loader-cache/issues)
Pull requests and stars are always welcome. For bugs and feature requests, [please create an issue](https://github.com/jonschlinkert/loader-cache/issues/new)
## Author
**Jon Schlinkert**
+ [github/jonschlinkert](https://github.com/jonschlinkert)
+ [twitter/jonschlinkert](http://twitter.com/jonschlinkert)
+ [twitter/jonschlinkert](http://twitter.com/jonschlinkert)
## License
Copyright (c) 2015 Jon Schlinkert
Released under the MIT license
Copyright © 2015 Jon Schlinkert
Released under the MIT license.
***
_This file was generated by [verb-cli](https://github.com/assemble/verb-cli) on March 10, 2015._
_This file was generated by [verb-cli](https://github.com/assemble/verb-cli) on June 13, 2015._
<!-- deps:mocha -->
SocketSocket SOC 2 Logo

Product

  • Package Alerts
  • Integrations
  • Docs
  • Pricing
  • FAQ
  • Roadmap
  • Changelog

Packages

npm

Stay in touch

Get open source security insights delivered straight into your inbox.


  • Terms
  • Privacy
  • Security

Made with ⚡️ by Socket Inc