Skip to content

Commit 23d4bf1

Browse files
committed
fix: bump deps, rewrite, added mime-types, rewrote isHidden with findIndex for performance
1 parent 2361f9a commit 23d4bf1

19 files changed

+124
-7608
lines changed

.commitlintrc.js

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,3 @@
1+
module.exports = {
2+
extends: ['@commitlint/config-conventional']
3+
};

.eslintignore

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1 @@
1+
!.*.js

.gitattributes

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1 +1 @@
1-
* text=auto
1+
* text=auto eol=lf

.github/workflows/ci.yml

Lines changed: 24 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,24 @@
1+
name: CI
2+
on:
3+
- push
4+
- pull_request
5+
jobs:
6+
build:
7+
runs-on: ${{ matrix.os }}
8+
strategy:
9+
matrix:
10+
os:
11+
- ubuntu-latest
12+
node_version:
13+
- 18
14+
name: Node ${{ matrix.node_version }} on ${{ matrix.os }}
15+
steps:
16+
- uses: actions/checkout@v3
17+
- name: Setup node
18+
uses: actions/setup-node@v3
19+
with:
20+
node-version: ${{ matrix.node_version }}
21+
- name: Install dependencies
22+
run: npm install
23+
- name: Run tests
24+
run: npm run test

.gitignore

Lines changed: 9 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -4,3 +4,12 @@
44
node_modules
55
coverage
66
.nyc_output
7+
locales/
8+
package-lock.json
9+
yarn.lock
10+
11+
Thumbs.db
12+
tmp/
13+
temp/
14+
*.lcov
15+
.env

.lintstagedrc.js

Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,5 @@
1+
module.exports = {
2+
"*.md": filenames => filenames.map(filename => `remark ${filename} -qfo`),
3+
'package.json': 'fixpack',
4+
'*.js': 'xo --fix'
5+
};

.npmrc

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1 @@
1+
package-lock=false

.prettierrc.js

Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,5 @@
1+
module.exports = {
2+
singleQuote: true,
3+
bracketSpacing: true,
4+
trailingComma: 'none'
5+
};

.remarkignore

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1 @@
1+
test/snapshots/**/*.md

.remarkrc.js

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,3 @@
1+
module.exports = {
2+
plugins: ['preset-github']
3+
};

.travis.yml

Lines changed: 0 additions & 8 deletions
This file was deleted.

.xo-config.js

Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,5 @@
1+
module.exports = {
2+
prettier: true,
3+
space: true,
4+
extends: ['xo-lass']
5+
};

README.md

Lines changed: 4 additions & 11 deletions
Original file line numberDiff line numberDiff line change
@@ -1,7 +1,6 @@
11
# [**@ladjs/koa-better-static**](https://github.com/ladjs/koa-better-static)
22

3-
[![build status](https://img.shields.io/travis/ladjs/koa-better-static.svg)](https://travis-ci.com/ladjs/koa-better-static)
4-
[![code coverage](https://img.shields.io/codecov/c/github/ladjs/koa-better-static.svg)](https://codecov.io/gh/ladjs/koa-better-static)
3+
[![build status](https://github.com/ladjs/koa-better-static/actions/workflows/ci.yml/badge.svg)](https://github.com/ladjs/koa-better-static/actions/workflows/ci.yml)
54
[![code style](https://img.shields.io/badge/code_style-XO-5ed9c7.svg)](https://github.com/sindresorhus/xo)
65
[![styled with prettier](https://img.shields.io/badge/styled_with-prettier-ff69b4.svg)](https://github.com/prettier/prettier)
76
[![made with lass](https://img.shields.io/badge/made_with-lass-95CC28.svg)](https://lass.js.org)
@@ -30,6 +29,8 @@ Our package `@ladjs/koa-better-static` is a high-performance, drop-in replacemen
3029
* Removal of `gzip` option (which checks for .gz files)
3130
* Removal of `defer` (if you want this behavior, put the middleware at the end)
3231
* No default `index` file
32+
* Faster performance with `findIndex` hidden file lookup
33+
* Properly sets `Content-Type` header using `mime-types`
3334

3435

3536
## Install
@@ -40,12 +41,6 @@ Our package `@ladjs/koa-better-static` is a high-performance, drop-in replacemen
4041
npm install @ladjs/koa-better-static
4142
```
4243

43-
[yarn][]:
44-
45-
```sh
46-
yarn add @ladjs/koa-better-static
47-
```
48-
4944

5045
## Usage
5146

@@ -92,8 +87,6 @@ app.listen(3000, () => {
9287
[MIT](LICENSE) © [Nick Baugh](http://niftylettuce.com/)
9388

9489

95-
##
90+
##
9691

9792
[npm]: https://www.npmjs.com/
98-
99-
[yarn]: https://yarnpkg.com/

ava.config.js

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,3 @@
1+
module.exports = {
2+
files: ['test/*.js', 'test/**/*.js']
3+
};

index.js

Lines changed: 11 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -1,4 +1,4 @@
1-
const { normalize, resolve, parse, sep } = require('path');
1+
const { normalize, resolve, parse, sep } = require('node:path');
22
const resolvePath = require('resolve-path');
33
const debug = require('debug')('@ladjs/koa-better-static');
44
const send = require('./send');
@@ -35,17 +35,17 @@ function serve(root, opts = {}) {
3535
// Options
3636
debug('static "%s" %j', root, opts);
3737

38-
return async function(ctx, next) {
38+
return async function (ctx, next) {
3939
if (ctx.method === 'HEAD' || ctx.method === 'GET') {
40-
let path = ctx.path.substr(parse(ctx.path).root.length);
40+
let path = ctx.path.slice(parse(ctx.path).root.length);
4141
try {
4242
path = decodeURIComponent(path);
43-
} catch (err) {
43+
} catch {
4444
ctx.throw('Could not decode path', 400);
4545
return;
4646
}
4747

48-
if (options.index && ctx.path[ctx.path.length - 1] === '/') {
48+
if (options.index && ctx.path.at(-1) === '/') {
4949
path += options.index;
5050
}
5151

@@ -59,17 +59,21 @@ function serve(root, opts = {}) {
5959
return;
6060
}
6161
}
62+
6263
return next();
6364
};
6465
}
6566

66-
// TODO: this can be sped up, with an findIndexOf loop
6767
function isHidden(root, path) {
68-
path = path.substr(root.length).split(sep);
68+
path = path.slice(root.length).split(sep);
69+
// optimized with `findIndex`
70+
/*
6971
for (let i = 0; i < path.length; i++) {
7072
if (path[i][0] === '.') {
7173
return true;
7274
}
7375
}
7476
return false;
77+
*/
78+
return path.findIndex((segment) => segment[0] === '.') !== -1;
7579
}

package.json

Lines changed: 21 additions & 69 deletions
Original file line numberDiff line numberDiff line change
@@ -3,59 +3,44 @@
33
"description": "Static file serving middleware for koa",
44
"version": "2.0.1",
55
"author": "Nick Baugh <[email protected]> (http://niftylettuce.com/)",
6-
"ava": {
7-
"failFast": true,
8-
"verbose": true
9-
},
106
"bugs": {
117
"url": "https://github.com/ladjs/koa-better-static/issues",
128
"email": "[email protected]"
139
},
14-
"commitlint": {
15-
"extends": [
16-
"@commitlint/config-conventional"
17-
]
18-
},
1910
"contributors": [
2011
"Nick Baugh <[email protected]> (http://niftylettuce.com/)"
2112
],
2213
"dependencies": {
2314
"debug": "*",
15+
"mime-types": "^2.1.35",
2416
"resolve-path": "^1.4.0"
2517
},
2618
"devDependencies": {
27-
"@commitlint/cli": "^7.2.1",
28-
"@commitlint/config-conventional": "^7.1.2",
29-
"ava": "^1.0.1",
30-
"codecov": "^3.1.0",
31-
"cross-env": "^5.2.0",
32-
"eslint": "^5.12.0",
33-
"eslint-config-xo-lass": "^1.0.3",
34-
"fixpack": "^2.3.1",
35-
"husky": "^1.3.1",
36-
"koa": "^2.6.2",
19+
"@commitlint/cli": "^19.7.1",
20+
"@commitlint/config-conventional": "^19.7.1",
21+
"ava": "^5.2.0",
22+
"cross-env": "^7.0.3",
23+
"eslint": "^8.55.0",
24+
"eslint-config-xo-lass": "^2.0.1",
25+
"fixpack": "^4.0.0",
26+
"husky": "^9.1.7",
27+
"koa": "^2.16.0",
3728
"koa-mount": "^4.0.0",
38-
"lint-staged": "^8.1.0",
39-
"nyc": "^13.1.0",
40-
"remark-cli": "^6.0.1",
41-
"remark-preset-github": "^0.0.13",
42-
"supertest": "^3.3.0",
43-
"xo": "^0.23.0"
29+
"lint-staged": "^15.4.3",
30+
"nyc": "^17.1.0",
31+
"remark-cli": "11.0.0",
32+
"remark-preset-github": "^4.0.4",
33+
"supertest": "^7.0.0",
34+
"xo": "0.56.0"
4435
},
4536
"engines": {
46-
"node": ">=8.3"
37+
"node": ">=18"
4738
},
4839
"files": [
4940
"index.js",
5041
"send.js"
5142
],
5243
"homepage": "https://github.com/ladjs/koa-better-static",
53-
"husky": {
54-
"hooks": {
55-
"pre-commit": "lint-staged && npm test",
56-
"commit-msg": "commitlint -E HUSKY_GIT_PARAMS"
57-
}
58-
},
5944
"keywords": [
6045
"assets",
6146
"file",
@@ -70,50 +55,17 @@
7055
"static-serve"
7156
],
7257
"license": "MIT",
73-
"lint-staged": {
74-
"linters": {
75-
"*.js": [
76-
"xo --fix",
77-
"git add"
78-
],
79-
"*.md": [
80-
"remark . -qfo",
81-
"git add"
82-
],
83-
"package.json": [
84-
"fixpack",
85-
"git add"
86-
]
87-
}
88-
},
8958
"main": "index.js",
90-
"prettier": {
91-
"singleQuote": true,
92-
"bracketSpacing": true,
93-
"trailingComma": "none"
94-
},
95-
"remarkConfig": {
96-
"plugins": [
97-
"preset-github"
98-
]
99-
},
10059
"repository": {
10160
"type": "git",
10261
"url": "https://github.com/ladjs/koa-better-static"
10362
},
10463
"scripts": {
10564
"ava": "cross-env NODE_ENV=test ava",
106-
"coverage": "nyc report --reporter=text-lcov > coverage.lcov && codecov",
107-
"lint": "xo && remark . -qfo",
65+
"lint": "xo --fix && remark . -qfo && fixpack",
10866
"nyc": "cross-env NODE_ENV=test nyc ava",
109-
"test": "npm run lint && npm run ava",
110-
"test-coverage": "npm run lint && npm run nyc"
111-
},
112-
"xo": {
113-
"prettier": true,
114-
"space": true,
115-
"extends": [
116-
"xo-lass"
117-
]
67+
"prepare": "husky install",
68+
"pretest": "npm run lint",
69+
"test": "npm run nyc"
11870
}
11971
}

send.js

Lines changed: 10 additions & 29 deletions
Original file line numberDiff line numberDiff line change
@@ -1,32 +1,10 @@
1-
const { extname } = require('path');
2-
const fs = require('fs');
1+
const fs = require('node:fs');
2+
const { extname } = require('node:path');
3+
const mime = require('mime-types');
34
const debug = require('debug')('@ladjs/koa-better-static:send');
45

56
module.exports = send;
67

7-
/**
8-
* Send file at `path` with the
9-
* given `options` to the koa `ctx`.
10-
*
11-
* @param {Context} ctx
12-
* @param {String} root
13-
* @param {String} path
14-
* @param {Object} [opts]
15-
* @return {Function}
16-
* @api public
17-
*/
18-
19-
function stat(path) {
20-
return new Promise((resolve, reject) => {
21-
fs.stat(path, (err, data) => {
22-
if (err) {
23-
return reject(err);
24-
}
25-
resolve(data);
26-
});
27-
});
28-
}
29-
308
async function send(ctx, path, opts) {
319
if (typeof ctx !== 'object') throw new Error('`ctx` is required');
3210
if (typeof path !== 'string') throw new Error('`path` is required');
@@ -39,12 +17,13 @@ async function send(ctx, path, opts) {
3917
// Stat
4018
let stats;
4119
try {
42-
stats = await stat(path);
20+
stats = await fs.promises.stat(path);
4321
} catch (err) {
4422
const notfound = ['ENOENT', 'ENAMETOOLONG', 'ENOTDIR'];
45-
if (notfound.indexOf(err.code) !== -1) {
23+
if (notfound.includes(err.code)) {
4624
return;
4725
}
26+
4827
err.status = 500;
4928
throw err;
5029
}
@@ -55,12 +34,13 @@ async function send(ctx, path, opts) {
5534
if (stats.isDirectory()) {
5635
if (format && index) {
5736
path += '/' + index;
58-
stats = await stat(path);
37+
stats = await fs.promises.stat(path);
5938
} else {
6039
return;
6140
}
6241
}
6342

43+
// eslint-disable-next-line no-bitwise,unicorn/prefer-math-trunc
6444
ctx.set('Cache-Control', 'max-age=' + ((maxage / 1000) | 0));
6545

6646
// Check if we can return a cache hit
@@ -81,7 +61,8 @@ async function send(ctx, path, opts) {
8161
// Stream
8262
ctx.set('Last-Modified', stats.mtime.toUTCString());
8363
ctx.set('Content-Length', stats.size);
84-
ctx.type = extname(path);
64+
65+
if (!ctx.type) ctx.type = mime.contentType(extname(path));
8566
ctx.body = fs.createReadStream(path);
8667

8768
return path;

0 commit comments

Comments
 (0)