Skip to content

Commit

Permalink
refactor hash() option (#2)
Browse files Browse the repository at this point in the history
Also bumps a bunch of dependencies, and makes some other minor tweaks.

* xo@^0.15.0

* ava@^0.14.0

* lint test.js

* nyc@^6.4.0

* remove trailing whitespace and fix typo in readme

* replace hash option

Both AVA and nyc use the `hash` option to ensure some extra data is included in
the hash, and to store a mapping from the hash to a file. They also need to
(correctly!) use md5-hex to generate the hash.

This commit replaces the `hash` option by a `hashData` function an an `onHash`
callback.

`hashData` receives the original input and additional data and may
return a string, buffer or array of either. This is then included in the hash.

`onHash` is called with the input, additional data, and the resulting hash.
Calling code can use this to maintain mappings.

This is a breaking change.

* include package-hash for caching-transform

Include the package-hash result for caching-transform itself in the resulting
hash. This will ensure the hash changes if caching-transform is updated, e.g. if
it changes its storage format.

* remove unused spies
  • Loading branch information
novemberborn authored and jamestalmage committed May 16, 2016
1 parent 508395e commit 8195916
Show file tree
Hide file tree
Showing 4 changed files with 133 additions and 54 deletions.
28 changes: 22 additions & 6 deletions index.js
@@ -1,13 +1,16 @@
'use strict';

var mkdirp = require('mkdirp');
var md5Hex = require('md5-hex');
var fs = require('fs');
var path = require('path');
var mkdirp = require('mkdirp');
var md5Hex = require('md5-hex');
var writeFileAtomic = require('write-file-atomic');
var packageHash = require('package-hash');

function defaultHash(input, additionalData, salt) {
return md5Hex([input, salt || '']);
var ownHash = '';
function getOwnHash() {
ownHash = packageHash.sync(__dirname);
return ownHash;
}

function wrap(opts) {
Expand All @@ -27,7 +30,8 @@ function wrap(opts) {
var salt = opts.salt || '';
var shouldTransform = opts.shouldTransform;
var disableCache = opts.disableCache;
var hashFn = opts.hash || defaultHash;
var hashData = opts.hashData;
var onHash = opts.onHash;
var encoding = opts.encoding === 'buffer' ? undefined : opts.encoding || 'utf8';

function transform(input, metadata, hash) {
Expand All @@ -51,9 +55,21 @@ function wrap(opts) {
return transform(input, metadata);
}

var hash = hashFn(input, metadata, salt);
var data = [ownHash || getOwnHash(), input];
if (salt) {
data.push(salt);
}
if (hashData) {
data = data.concat(hashData(input, metadata));
}

var hash = md5Hex(data);
var cachedPath = path.join(cacheDir, hash + ext);

if (onHash) {
onHash(input, metadata, hash);
}

try {
return fs.readFileSync(cachedPath, encoding);
} catch (e) {
Expand Down
12 changes: 4 additions & 8 deletions package.json
Expand Up @@ -30,20 +30,16 @@
"dependencies": {
"md5-hex": "^1.2.0",
"mkdirp": "^0.5.1",
"package-hash": "^1.2.0",
"write-file-atomic": "^1.1.4"
},
"devDependencies": {
"ava": "^0.8.0",
"ava": "^0.14.0",
"coveralls": "^2.11.6",
"mock-fs": "^3.5.0",
"nyc": "5.0.1",
"nyc": "^6.4.0",
"proxyquire": "^1.7.3",
"sinon": "^1.17.2",
"xo": "^0.12.1"
},
"xo": {
"ignores": [
"test.js"
]
"xo": "^0.15.0"
}
}
38 changes: 26 additions & 12 deletions readme.md
Expand Up @@ -2,7 +2,7 @@

> Wraps a transform and provides caching.
Caching transform results can greatly improve performance. `nyc` saw [dramatic performance increases](https://github.com/bcoe/nyc/pull/101#issuecomment-165716069) when we implemented caching.
Caching transform results can greatly improve performance. `nyc` saw [dramatic performance increases](https://github.com/bcoe/nyc/pull/101#issuecomment-165716069) when we implemented caching.


## Install
Expand Down Expand Up @@ -44,7 +44,7 @@ Returns a transform callback that takes two arguments:
Both arguments are passed to the wrapped transform. Results are cached in the cache directory using an `md5` hash of `input` and an optional `salt` value. If a cache entry already exist for `input`, the wrapped transform function will never be called.

#### options

##### salt

Type: `string`, or `buffer`
Expand Down Expand Up @@ -79,9 +79,9 @@ A typical usage would be to prevent eagerly `require`ing expensive dependencies

```js
function factory() {
// Using the factory function, you can avoid loading Babel until you are sure it is needed.
// Using the factory function, you can avoid loading Babel until you are sure it is needed.
var babel = require('babel-core');

return function (code, metadata) {
return babel.transform(code, {filename: metadata.filename, plugins: [/* ... */]});
};
Expand All @@ -93,7 +93,7 @@ function factory() {
Type: `string`
*Required unless caching is disabled*

The directory where cached transform results will be stored. The directory is automatically created with [`mkdirp`](https://www.npmjs.com/package/mkdirp). You can set `options.createCacheDir = false` if you are certain the directory already exists.
The directory where cached transform results will be stored. The directory is automatically created with [`mkdirp`](https://www.npmjs.com/package/mkdirp). You can set `options.createCacheDir = false` if you are certain the directory already exists.

##### ext

Expand All @@ -104,25 +104,39 @@ An extension that will be appended to the salted hash to create the filename ins

##### shouldTransform

Type: `Function(input: string|buffer, additonalData: *)`
Type: `Function(input: string|buffer, additionalData: *)`
Default: `always transform`

A function that examines `input` and `metadata` to determine whether the transform should be applied. Returning `false` means the transform will not be applied and `input` will be returned unmodified.

##### disableCache

Type: `boolean`
Default: `false`

If `true`, the cache is ignored and the transform is used every time regardless of cache contents.

##### hash

Type: `Function(input: string|buffer, metadata: *, salt: string): string`
##### hashData

Type: `Function(input: string|buffer, metadata: *): string|buffer|array[string|buffer]`

Provide additional data that should be included in the hash.

One potential use is including the `metadata` in the hash by coercing it to a hashable string or buffer:

```js
function hashData(input, metadata) {
return JSON.stringify(metadata);
}
```

(Note that `metadata` is not taken into account otherwise.)

##### onHash

Provide a custom hashing function for the given input. The default hashing function does not take the `metadata` into account:
Type: `Function(input: string|buffer, metadata: *, hash: string)`

> [`md5Hex([input, salt])`](https://www.npmjs.com/package/md5-hex)
A function that is called after input is hashed.

##### encoding

Expand Down

0 comments on commit 8195916

Please sign in to comment.