Skip to content

Commit

Permalink
Initial commit
Browse files Browse the repository at this point in the history
  • Loading branch information
sergeche committed Jun 20, 2016
0 parents commit 6d4891f
Show file tree
Hide file tree
Showing 6 changed files with 133 additions and 0 deletions.
1 change: 1 addition & 0 deletions .gitignore
Original file line number Diff line number Diff line change
@@ -0,0 +1 @@
node_modules
86 changes: 86 additions & 0 deletions index.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,86 @@
/**
* Get stats of given file path.
*/

'use strict';
const path = require('path');
const fs = require('fs');
const crc = require('crc');

const fileStatCache = {};
const defaultConfig = {
statCacheTime: 10000
};

module.exports = function(url, config) {
config = Object.assign({}, defaultConfig, config || {});
let lookups = [path.join(config.baseDir, url)];
if (config.staticFileDirs) {
let lookupDirs = Array.isArray(config.staticFileDirs)
? config.staticFileDirs
: [config.staticFileDirs];

lookupDirs.forEach(dir => lookups.push(path.join(dir, url)));
}

return tryFiles(url, lookups, config);
};

function tryFiles(url, lookups, config) {
invalidateCache(url, config);
if (!fileStatCache[url]) {
for (let i = 0; i < lookups.length; i++) {
try {
let stats = fs.statSync(lookups[i]);
if (stats.isFile()) {
putInCache(url, stats, lookups[i]);
break;
}
} catch (e) {}
}
}

if (!fileStatCache[url]) {
// still no file, save error result instead
let error = new Error(`Unable to locate file for "${url}" url`);
error.code = 'ENOENT';
putInCache(url, error);
}

return fileStatCache[url].stats;
}

function invalidateCache(key, config) {
if (key in fileStatCache && fileStatCache[key].created < Date.now() + config.statCacheTime) {
delete fileStatCache[key];
}
}

function putInCache(key, data, file) {
var stats = {
get hash() {
if (this.error) {
throw new Error(this.error);
}

if (!this._hash) {
this._hash = crc.crc32(fs.readFileSync(this.file));
}

return this._hash;
}
};

if (data instanceof Error) {
stats.error = data;
} else {
stats.file = file;
stats.modified = data.mtime;
stats.created = data.birthtime;
stats.size = data.size;
stats.inode = data.ino;
}

fileStatCache[key] = {stats, created: Date.now()};
return fileStatCache[key];
}
26 changes: 26 additions & 0 deletions package.json
Original file line number Diff line number Diff line change
@@ -0,0 +1,26 @@
{
"name": "file-stats",
"version": "1.0.0",
"description": "",
"main": "index.js",
"scripts": {
"test": "mocha"
},
"repository": {
"type": "git",
"url": "git+https://github.com/sergeche/file-stats.git"
},
"keywords": [],
"author": "",
"license": "ISC",
"bugs": {
"url": "https://github.com/sergeche/file-stats/issues"
},
"homepage": "https://github.com/sergeche/file-stats#readme",
"dependencies": {
"crc": "^3.4.0"
},
"devDependencies": {
"mocha": "^2.5.3"
}
}
18 changes: 18 additions & 0 deletions test/file-stats.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,18 @@
'use strict';

const path = require('path');
const assert = require('assert');
const stats = require('../');

describe('File stats', () => {
let baseDir = path.resolve(__dirname, 'files');
let staticFileDirs = [
path.resolve(baseDir, 'inner')
];

it('get file stats', () => {
assert.equal(stats('/foo.txt', {baseDir}).hash, '2117232040');
assert.equal(stats('/bar.txt', {baseDir, staticFileDirs}).hash, '77771753');
assert.throws(() => stats('/bar.txt', {baseDir}).hash, /Unable to locate file/);
});
});
1 change: 1 addition & 0 deletions test/files/foo.txt
Original file line number Diff line number Diff line change
@@ -0,0 +1 @@
foo
1 change: 1 addition & 0 deletions test/files/inner/bar.txt
Original file line number Diff line number Diff line change
@@ -0,0 +1 @@
bar

0 comments on commit 6d4891f

Please sign in to comment.