New Case Study:See how Anthropic automated 95% of dependency reviews with Socket.Learn More
Socket
Sign inDemoInstall
Socket

staticify

Package Overview
Dependencies
Maintainers
2
Versions
22
Alerts
File Explorer

Advanced tools

Socket logo

Install Socket

Detect and block malicious and high-risk dependencies

Install

staticify - npm Package Compare versions

Comparing version 1.0.0 to 2.0.0

148

index.js
'use strict';
const path = require('path');
const crypto = require('crypto');
const fs = require('fs');
const path = require('path');
const url = require('url');
const ignoredDirectories = require('ignore-by-default').directories();
const send = require('send');
function buildVersionHash(directory, root, versions) {
// Walks the directory tree, finding files, generating a version hash
const files = fs.readdirSync(directory);
const staticify = (root, options) => {
const MAX_AGE = 1000 * 60 * 60 * 24 * 365; // 1 year in milliseconds
root = root || directory;
versions = versions || {};
const setOptions = opts => {
opts = opts || {};
files.forEach(file => {
const filePath = path.posix.join(directory, file);
const stat = fs.statSync(filePath);
let defaultOptions = {
includeAll: opts.includeAll || false,
shortHash: opts.shortHash || true,
sendOptions: opts.sendOptions || {}
};
if (stat.isDirectory()) {
buildVersionHash(filePath, root, versions); // Whee!
} else if (stat.isFile()) {
const fileStr = fs.readFileSync(filePath, 'utf8');
const hash = crypto.createHash('md5')
.update(fileStr, 'utf8')
.digest('hex')
.slice(0, 7);
defaultOptions = Object.assign(defaultOptions, opts);
versions[`/${path.posix.relative(root, filePath)}`] = hash;
return defaultOptions;
};
const opts = setOptions(options);
// Walks the directory tree, finding files, generating a version hash
const buildVersionHash = (directory, root, vers) => {
root = root || directory;
vers = vers || {};
if (opts.includeAll === false && ignoredDirectories.some(d => directory.includes(d))) {
return;
}
});
return versions;
}
const files = fs.readdirSync(directory);
function stripVersion(p) {
// index.<hash>.js -> index.js
const fileName = path.basename(p);
const fileNameParts = fileName.split('.');
files.forEach(file => {
const filePath = path.posix.join(directory, file);
const stat = fs.statSync(filePath);
if (fileNameParts.length >= 3 &&
fileNameParts[fileNameParts.length - 2].length === 7 &&
/^[0-9a-f]{7}$/i.exec(fileNameParts[fileNameParts.length - 2])[0] === fileNameParts[fileNameParts.length - 2]
) {
const stripped = fileNameParts.slice(0, fileNameParts.length - 2);
if (stat.isDirectory()) {
buildVersionHash(filePath, root, vers); // Whee!
} else if (stat.isFile()) {
const fileStr = fs.readFileSync(filePath, 'utf8');
let hash = crypto.createHash('md5')
.update(fileStr, 'utf8')
.digest('hex');
stripped.push(fileNameParts[fileNameParts.length - 1]);
if (opts.shortHash) {
hash = hash.slice(0, 7);
}
return path.join(path.dirname(p), stripped.join('.'));
}
vers[`/${path.posix.relative(root, filePath)}`] = hash;
}
});
return p;
}
return vers;
};
module.exports = (root, options) => {
let versions = buildVersionHash(root);
options = options || {};
function getVersionedPath(p) {
// index.js -> index.<hash>.js
// index.js -> index.<hash>.js
const getVersionedPath = p => {
if (!versions[p]) {

@@ -71,17 +78,36 @@ return p;

return path.posix.join(path.dirname(p), fileNameParts.join('.'));
}
};
function serve(req) {
// index.<hash>.js -> index.js
const stripVersion = p => {
const HASH_LEN = opts.shortHash === true ? 7 : 32;
const fileName = path.basename(p);
const fileNameParts = fileName.split('.');
const re = new RegExp(`^[0-9a-f]{${HASH_LEN}}$`, 'i');
if (fileNameParts.length >= 3 &&
fileNameParts[fileNameParts.length - 2].length === HASH_LEN &&
re.exec(fileNameParts[fileNameParts.length - 2])[0] === fileNameParts[fileNameParts.length - 2]
) {
const stripped = fileNameParts.slice(0, fileNameParts.length - 2);
stripped.push(fileNameParts[fileNameParts.length - 1]);
return path.join(path.dirname(p), stripped.join('.'));
}
return p;
};
const serve = req => {
const filePath = stripVersion(url.parse(req.url).pathname);
const MAX_AGE = 1000 * 60 * 60 * 24 * 365; // 1 year
return send(req, filePath, {
maxage: filePath === req.url ? 0 : MAX_AGE,
index: options.index || 'index.html',
ignore: options.hidden,
root
});
}
opts.sendOptions.maxAge = filePath === req.url ? 0 : (opts.sendOptions.maxAge ? opts.sendOptions.maxAge : MAX_AGE);
opts.sendOptions.root = root;
function middleware(req, res, next) {
return send(req, filePath, opts.sendOptions);
};
const middleware = (req, res, next) => {
if (req.method !== 'GET' && req.method !== 'HEAD') {

@@ -99,17 +125,13 @@ return next();

.pipe(res);
}
};
function replacePaths(fileContents) {
const urls = Object.keys(versions);
const replacePaths = fileContents => {
return Object.keys(versions).reduce((f, url) => {
return f.replace(url, getVersionedPath(url));
}, fileContents);
};
urls.forEach(url => {
fileContents = fileContents.replace(url, getVersionedPath(url));
});
return fileContents;
}
function refresh() {
const refresh = () => {
versions = buildVersionHash(root);
}
};

@@ -126,1 +148,3 @@ return {

};
module.exports = staticify;
{
"name": "staticify",
"version": "1.0.0",
"description": "A better static asset handler for node.js",
"version": "2.0.0",
"description": "A better static asset handler for Node.js / express.js",
"main": "index.js",

@@ -29,7 +29,8 @@ "author": "Rakesh Pai <rakeshpai@errorception.com>",

"dependencies": {
"send": "~0.16.1"
"ignore-by-default": "^1.0.1",
"send": "^0.16.1"
},
"devDependencies": {
"mocha": "~4.0.1",
"should": "~13.1.3",
"mocha": "^4.0.1",
"should": "^13.1.3",
"xo": "^0.18.2"

@@ -40,3 +41,8 @@ },

"rules": {
"capitalized-comments": "off"
"capitalized-comments": "off",
"spaced-comment": "off",
"func-style": [
"error",
"expression"
]
},

@@ -43,0 +49,0 @@ "overrides": [

@@ -9,3 +9,3 @@ # staticify

A better static asset handler for node.js / express.js
A better static asset handler for Node.js / express.js.

@@ -31,5 +31,5 @@ Provides helpers to add a version identifier to your static asset's public URLs, and to remove the hash before serving the file from the file system.

```javascript
var path = require("path");
var staticify = require("staticify")(path.join(__dirname, "public"));
```js
var path = require('path');
var staticify = require('staticify')(path.join(__dirname, 'public'));

@@ -48,2 +48,25 @@ ...

## Options
### includeAll
Include all files when scanning the public directory. By default, the directories from [ignore-by-default](https://github.com/novemberborn/ignore-by-default/blob/master/index.js) are ignored.
* Type: Boolean
* Default: `false`
### shortHash
Generate a short (7-digit) md5 hash instead of the full (32-digit) one.
* Type: Boolean
* Default: `true`
### sendOptions
* Type: Object
* Default: `sendOptions: { maxAge: '1y' }` for hashed assets or `maxAge: 0` for non-hashed assets.
You can pass any [send](https://github.com/pillarjs/send) options; used in `middleware` and `serve` functions.
## Usage

@@ -59,5 +82,5 @@

```javascript
var path = require("path");
var statificy = require("staticify")(path.join(__dirname, "public"));
```js
var path = require('path');
var statificy = require('staticify')(path.join(__dirname, 'public'));
```

@@ -71,3 +94,3 @@

```javascript
```js
staticify.getVersionedPath('/path/to/file.ext'); // --> /path/to/file.<md5 of the contents of file.ext>.ext

@@ -84,4 +107,4 @@ ```

```javascript
app.use(staticify.middleware) // `app` is your express instance
```js
app.use(staticify.middleware); // `app` is your express instance
```

@@ -93,4 +116,4 @@

```javascript
staticify.replacePaths("body { background: url('/index.js') }");
```js
staticify.replacePaths('body { background: url("/index.js") }');
```

@@ -100,3 +123,3 @@

```javascript
```js
"body { background: url('/index.d766c4a983224a3696bc4913b9e47305.js') }"

@@ -111,3 +134,3 @@ ```

```javascript
```js
staticify.stripVersion('/path/to/file.ae2b1fca515949e5d54fb22b8ed95575.ext'); // --> /path/to/file.ext

@@ -124,6 +147,10 @@ ```

Handles an incoming request for the file. Internally calls `.stripVersion` to strip the version identifier, and serves the file with a `maxage` of a year, using [send](https://github.com/tj/send). Returns a stream that can be `.pipe`d to a http response stream.
Handles an incoming request for the file. Internally calls `.stripVersion` to strip the version identifier, and serves the file with a `maxAge` of one year, using [send](https://github.com/pillarjs/send). Returns a stream that can be `.pipe`d to a http response stream. See [here](https://github.com/pillarjs/send#options) for the options you can pass.
```javascript
staticify.serve(req).pipe(res)
```js
staticify.serve(req, {
sendOptions: {
maxAge: 3600 * 1000 // milliseconds
}
}).pipe(res);
```

@@ -130,0 +157,0 @@

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