text: import * as fs from 'fs';
  import { join, normalize, resolve } from 'path';
  import list from 'totalist/sync';
  import parser from '@polka/url';
  import mime from 'mime/lite';
  
  const FILES = {};
  const noop = () => {};
  
  function isMatch(uri, arr) {
  	for (let i=0; i < arr.length; i++) {
  		if (arr[i].test(uri)) return true;
  	}
  }
  
  function toAssume(uri, extns) {
  	let i=0, x, len=uri.length - 1;
  	if (uri.charCodeAt(len) === 47) {
  		uri = uri.substring(0, len);
  	}
  
  	let arr=[], tmp=`${uri}/index`;
  	for (; i < extns.length; i++) {
  		x = extns[i] ? `.${extns[i]}` : '';
  		if (uri) arr.push(uri + x);
  		arr.push(tmp + x);
  	}
  
  	return arr;
  }
  
  function viaCache(uri, extns) {
  	let i=0, data, arr=toAssume(uri, extns);
  	for (; i < arr.length; i++) {
  		if (data = FILES[arr[i]]) return data;
  	}
  }
  
  function viaLocal(dir, isEtag, uri, extns) {
  	let i=0, arr=toAssume(uri, extns);
  	let abs, stats, name, headers;
  	for (; i < arr.length; i++) {
  		abs = normalize(join(dir, name=arr[i]));
  		if (abs.startsWith(dir) && fs.existsSync(abs)) {
  			stats = fs.statSync(abs);
  			if (stats.isDirectory()) continue;
  			headers = toHeaders(name, stats, isEtag);
  			headers['Cache-Control'] = 'no-store';
  			return { abs, stats, headers };
  		}
  	}
  }
  
  function is404(req, res) {
  	return (res.statusCode=404,res.end());
  }
  
  function send(req, res, file, stats, headers) {
  	let code=200, tmp, opts={};
  	headers = { ...headers };
  
  	for (let key in headers) {
  		tmp = res.getHeader(key);
  		if (tmp) headers[key] = tmp;
  	}
  
  	if (tmp = res.getHeader('content-type')) {
  		headers['Content-Type'] = tmp;
  	}
  
  	if (req.headers.range) {
  		code = 206;
  		let [x, y] = req.headers.range.replace('bytes=', '').split('-');
  		let end = opts.end = parseInt(y, 10) || stats.size - 1;
  		let start = opts.start = parseInt(x, 10) || 0;
  
  		if (start >= stats.size || end >= stats.size) {
  			res.setHeader('Content-Range', `bytes */${stats.size}`);
  			res.statusCode = 416;
  			return res.end();
  		}
  
  		headers['Content-Range'] = `bytes ${start}-${end}/${stats.size}`;
  		headers['Content-Length'] = (end - start + 1);
  		headers['Accept-Ranges'] = 'bytes';
  	}
  
  	res.writeHead(code, headers);
  	fs.createReadStream(file, opts).pipe(res);
  }
  
  function isEncoding(name, type, headers) {
  	headers['Content-Encoding'] = type;
  	headers['Content-Type'] = mime.getType(name.replace(/\.([^.]*)$/, '')) || '';
  }
  
  function toHeaders(name, stats, isEtag) {
  	let headers = {
  		'Content-Length': stats.size,
  		'Content-Type': mime.getType(name) || '',
  		'Last-Modified': stats.mtime.toUTCString(),
  	};
  	if (isEtag) headers['ETag'] = `W/"${stats.size}-${stats.mtime.getTime()}"`;
  	if (/\.br$/.test(name)) isEncoding(name, 'br', headers);
  	if (/\.gz$/.test(name)) isEncoding(name, 'gzip', headers);
  	return headers;
  }
  
  export default function (dir, opts={}) {
  	dir = resolve(dir || '.');
  
  	let isNotFound = opts.onNoMatch || is404;
  	let setHeaders = opts.setHeaders || noop;
  
  	let extensions = opts.extensions || ['html', 'htm'];
  	let gzips = opts.gzip && extensions.map(x => `${x}.gz`).concat('gz');
  	let brots = opts.brotli && extensions.map(x => `${x}.br`).concat('br');
  
  	let fallback = '/';
  	let isEtag = !!opts.etag;
  	let isSPA = !!opts.single;
  	if (typeof opts.single === 'string') {
  		let idx = opts.single.lastIndexOf('.');
  		fallback += !!~idx ? opts.single.substring(0, idx) : opts.single;
  	}
  
  	let ignores = [];
  	if (opts.ignores !== false) {
  		ignores.push(/\w\.\w+$/); // any extn
  		if (opts.dotfiles) ignores.push(/\/\.\w/);
  		else ignores.push(/\/\.well-known/);
  		[].concat(opts.ignores || []).forEach(x => {
  			ignores.push(new RegExp(x, 'i'));
  		});
  	}
  
  	let cc = opts.maxAge != null && `public,max-age=${opts.maxAge}`;
  	if (cc && opts.immutable) cc += ',immutable';
  
  	if (!opts.dev) {
  		list(dir, (name, abs, stats) => {
  			if (/\.well-known[\\+\/]/.test(name)) {} // keep
  			else if (!opts.dotfiles && /(^\.|[\\+|\/+]\.)/.test(name)) return;
  
  			let headers = toHeaders(name, stats, isEtag);
  			if (cc) headers['Cache-Control'] = cc;
  
  			FILES['/' + name.normalize().replace(/\\+/g, '/')] = { abs, stats, headers };
  		});
  	}
  
  	let lookup = opts.dev ? viaLocal.bind(0, dir, isEtag) : viaCache;
  
  	return function (req, res, next) {
  		let extns = [''];
  		let val = req.headers['accept-encoding'] || '';
  		if (gzips && val.includes('gzip')) extns.unshift(...gzips);
  		if (brots && /(br|brotli)/i.test(val)) extns.unshift(...brots);
  		extns.push(...extensions); // [...br, ...gz, orig, ...exts]
  
  		let pathname = req.path || parser(req, true).pathname;
  		let data = lookup(pathname, extns) || isSPA && !isMatch(pathname, ignores) && lookup(fallback, extns);
  		if (!data) return next ? next() : isNotFound(req, res);
  
  		if (isEtag && req.headers['if-none-match'] === data.headers['ETag']) {
  			res.writeHead(304);
  			return res.end();
  		}
  
  		setHeaders(res, pathname, data.stats);
  		send(req, res, data.abs, data.stats, data.headers);
  	};
  }
  