Move utilities into middleware/utils
This commit is contained in:
parent
2d03ed9be6
commit
7408b24adf
|
@ -1,49 +0,0 @@
|
|||
const fs = require('fs')
|
||||
const mime = require('mime')
|
||||
|
||||
mime.define({
|
||||
'text/plain': [
|
||||
'license',
|
||||
'readme',
|
||||
'changes',
|
||||
'authors',
|
||||
'makefile',
|
||||
'ts',
|
||||
'flow'
|
||||
]
|
||||
})
|
||||
|
||||
const TextFiles = /\/?(\.[a-z]*rc|\.git[a-z]*|\.[a-z]*ignore)$/i
|
||||
|
||||
function getContentType(file) {
|
||||
return TextFiles.test(file) ? 'text/plain' : mime.lookup(file)
|
||||
}
|
||||
|
||||
function getStats(file) {
|
||||
return new Promise((resolve, reject) => {
|
||||
fs.lstat(file, (error, stats) => {
|
||||
if (error) {
|
||||
reject(error)
|
||||
} else {
|
||||
resolve(stats)
|
||||
}
|
||||
})
|
||||
})
|
||||
}
|
||||
|
||||
function getFileType(stats) {
|
||||
if (stats.isFile()) return 'file'
|
||||
if (stats.isDirectory()) return 'directory'
|
||||
if (stats.isBlockDevice()) return 'blockDevice'
|
||||
if (stats.isCharacterDevice()) return 'characterDevice'
|
||||
if (stats.isSymbolicLink()) return 'symlink'
|
||||
if (stats.isSocket()) return 'socket'
|
||||
if (stats.isFIFO()) return 'fifo'
|
||||
return 'unknown'
|
||||
}
|
||||
|
||||
module.exports = {
|
||||
getContentType,
|
||||
getStats,
|
||||
getFileType
|
||||
}
|
|
@ -1,34 +0,0 @@
|
|||
const { getContentType, getStats, getFileType } = require('./FileUtils')
|
||||
|
||||
it('gets a content type of text/plain for LICENSE|README|CHANGES|AUTHORS|Makefile', () => {
|
||||
expect(getContentType('LICENSE')).toBe('text/plain')
|
||||
expect(getContentType('README')).toBe('text/plain')
|
||||
expect(getContentType('CHANGES')).toBe('text/plain')
|
||||
expect(getContentType('AUTHORS')).toBe('text/plain')
|
||||
expect(getContentType('Makefile')).toBe('text/plain')
|
||||
})
|
||||
|
||||
it('gets a content type of text/plain for .*rc files', () => {
|
||||
expect(getContentType('.eslintrc')).toBe('text/plain')
|
||||
expect(getContentType('.babelrc')).toBe('text/plain')
|
||||
expect(getContentType('.anythingrc')).toBe('text/plain')
|
||||
})
|
||||
|
||||
it('gets a content type of text/plain for .git* files', () => {
|
||||
expect(getContentType('.gitignore')).toBe('text/plain')
|
||||
expect(getContentType('.gitanything')).toBe('text/plain')
|
||||
})
|
||||
|
||||
it('gets a content type of text/plain for .*ignore files', () => {
|
||||
expect(getContentType('.eslintignore')).toBe('text/plain')
|
||||
expect(getContentType('.anythingignore')).toBe('text/plain')
|
||||
})
|
||||
|
||||
it('gets a content type of text/plain for .ts files', () => {
|
||||
expect(getContentType('app.ts')).toBe('text/plain')
|
||||
expect(getContentType('app.d.ts')).toBe('text/plain')
|
||||
})
|
||||
|
||||
it('gets a content type of text/plain for .flow files', () => {
|
||||
expect(getContentType('app.js.flow')).toBe('text/plain')
|
||||
})
|
|
@ -1,41 +0,0 @@
|
|||
const fs = require('fs')
|
||||
const path = require('path')
|
||||
const React = require('react')
|
||||
const ReactDOMServer = require('react-dom/server')
|
||||
const IndexPage = require('./components/IndexPage')
|
||||
const { getStats } = require('./FileUtils')
|
||||
|
||||
const e = React.createElement
|
||||
|
||||
const getEntries = (dir) =>
|
||||
new Promise((resolve, reject) => {
|
||||
fs.readdir(dir, (error, files) => {
|
||||
if (error) {
|
||||
reject(error)
|
||||
} else {
|
||||
resolve(
|
||||
Promise.all(
|
||||
files.map(file => getStats(path.join(dir, file)))
|
||||
).then(
|
||||
statsArray => statsArray.map(
|
||||
(stats, index) => ({ file: files[index], stats })
|
||||
)
|
||||
)
|
||||
)
|
||||
}
|
||||
})
|
||||
})
|
||||
|
||||
const DOCTYPE = '<!DOCTYPE html>'
|
||||
|
||||
const generateIndexPage = (props) =>
|
||||
DOCTYPE + ReactDOMServer.renderToStaticMarkup(e(IndexPage, props))
|
||||
|
||||
const generateDirectoryIndexHTML = (packageInfo, version, baseDir, dir, callback) =>
|
||||
getEntries(path.join(baseDir, dir))
|
||||
.then(entries => generateIndexPage({ packageInfo, version, dir, entries }))
|
||||
.then(html => callback(null, html), callback)
|
||||
|
||||
module.exports = {
|
||||
generateDirectoryIndexHTML
|
||||
}
|
|
@ -1,14 +0,0 @@
|
|||
const fs = require('fs')
|
||||
const path = require('path')
|
||||
const csso = require('csso')
|
||||
|
||||
const minifyCSS = (css) =>
|
||||
csso.minify(css).css
|
||||
|
||||
const readCSS = (...args) =>
|
||||
minifyCSS(fs.readFileSync(path.resolve(...args), 'utf8'))
|
||||
|
||||
module.exports = {
|
||||
minifyCSS,
|
||||
readCSS
|
||||
}
|
|
@ -1,6 +1,6 @@
|
|||
const React = require('react')
|
||||
const prettyBytes = require('pretty-bytes')
|
||||
const { getContentType } = require('../FileUtils')
|
||||
const getFileContentType = require('../utils/getFileContentType')
|
||||
|
||||
const e = React.createElement
|
||||
|
||||
|
@ -15,7 +15,7 @@ const DirectoryListing = ({ dir, entries }) => {
|
|||
return (
|
||||
e('tr', { key: file, className: index % 2 ? 'odd' : 'even' },
|
||||
e('td', null, e('a', { title: file, href }, file)),
|
||||
e('td', null, isDir ? '-' : getContentType(file)),
|
||||
e('td', null, isDir ? '-' : getFileContentType(file)),
|
||||
e('td', null, isDir ? '-' : prettyBytes(stats.size)),
|
||||
e('td', null, isDir ? '-' : formatTime(stats.mtime))
|
||||
)
|
||||
|
|
|
@ -1,7 +1,7 @@
|
|||
const React = require('react')
|
||||
const semver = require('semver')
|
||||
const DirectoryListing = require('./DirectoryListing')
|
||||
const { readCSS } = require('../StyleUtils')
|
||||
const readCSS = require('../utils/readCSS')
|
||||
|
||||
const e = React.createElement
|
||||
|
||||
|
|
|
@ -2,8 +2,8 @@ const fs = require('fs')
|
|||
const path = require('path')
|
||||
const qs = require('querystring')
|
||||
const etag = require('etag')
|
||||
const { generateDirectoryIndexHTML } = require('./IndexUtils')
|
||||
const { getContentType } = require('./FileUtils')
|
||||
const getFileContentType = require('./utils/getFileContentType')
|
||||
const getIndexHTML = require('./utils/getIndexHTML')
|
||||
|
||||
/**
|
||||
* Automatically generate HTML pages that show package contents.
|
||||
|
@ -11,7 +11,7 @@ const { getContentType } = require('./FileUtils')
|
|||
const AutoIndex = !process.env.DISABLE_INDEX
|
||||
|
||||
function sendFile(res, file, stats) {
|
||||
let contentType = getContentType(file)
|
||||
let contentType = getFileContentType(file)
|
||||
|
||||
if (contentType === 'text/html')
|
||||
contentType = 'text/plain' // We can't serve HTML because bad people :(
|
||||
|
@ -52,7 +52,7 @@ function serveFile(req, res, next) {
|
|||
// TODO: use res.sendFile instead of our own sendFile?
|
||||
sendFile(res, path.join(req.packageDir, req.file), req.stats)
|
||||
} else if (AutoIndex && req.stats.isDirectory()) {
|
||||
generateDirectoryIndexHTML(req.packageInfo, req.packageVersion, req.packageDir, req.file, function (error, html) {
|
||||
getIndexHTML(req.packageInfo, req.packageVersion, req.packageDir, req.file, function (error, html) {
|
||||
if (error) {
|
||||
console.error(error)
|
||||
res.status(500).type('text').send(`Cannot generate index page for ${req.packageSpec}${req.filename}`)
|
||||
|
|
|
@ -1,12 +1,12 @@
|
|||
const Metadata = require('./MetadataUtils')
|
||||
const getMetadata = require('./utils/getMetadata')
|
||||
|
||||
/**
|
||||
* Maximum recursion depth for ?meta listings.
|
||||
* Maximum recursion depth for meta listings.
|
||||
*/
|
||||
const MaximumDepth = 128
|
||||
|
||||
function serveMetadata(req, res) {
|
||||
Metadata.get(req.packageDir, req.file, req.stats, MaximumDepth, function (error, metadata) {
|
||||
getMetadata(req.packageDir, req.file, req.stats, MaximumDepth, function (error, metadata) {
|
||||
if (error) {
|
||||
console.error(error)
|
||||
res.status(500).type('text').send(`Cannot generate metadata for ${req.packageSpec}${req.filename}`)
|
||||
|
|
|
@ -0,0 +1,21 @@
|
|||
const mime = require('mime')
|
||||
|
||||
mime.define({
|
||||
'text/plain': [
|
||||
'license',
|
||||
'readme',
|
||||
'changes',
|
||||
'authors',
|
||||
'makefile',
|
||||
'ts',
|
||||
'flow'
|
||||
]
|
||||
})
|
||||
|
||||
const TextFiles = /\/?(\.[a-z]*rc|\.git[a-z]*|\.[a-z]*ignore)$/i
|
||||
|
||||
function getFileContentType(file) {
|
||||
return TextFiles.test(file) ? 'text/plain' : mime.lookup(file)
|
||||
}
|
||||
|
||||
module.exports = getFileContentType
|
|
@ -0,0 +1,34 @@
|
|||
const getFileContentType = require('./getFileContentType')
|
||||
|
||||
it('gets a content type of text/plain for LICENSE|README|CHANGES|AUTHORS|Makefile', () => {
|
||||
expect(getFileContentType('LICENSE')).toBe('text/plain')
|
||||
expect(getFileContentType('README')).toBe('text/plain')
|
||||
expect(getFileContentType('CHANGES')).toBe('text/plain')
|
||||
expect(getFileContentType('AUTHORS')).toBe('text/plain')
|
||||
expect(getFileContentType('Makefile')).toBe('text/plain')
|
||||
})
|
||||
|
||||
it('gets a content type of text/plain for .*rc files', () => {
|
||||
expect(getFileContentType('.eslintrc')).toBe('text/plain')
|
||||
expect(getFileContentType('.babelrc')).toBe('text/plain')
|
||||
expect(getFileContentType('.anythingrc')).toBe('text/plain')
|
||||
})
|
||||
|
||||
it('gets a content type of text/plain for .git* files', () => {
|
||||
expect(getFileContentType('.gitignore')).toBe('text/plain')
|
||||
expect(getFileContentType('.gitanything')).toBe('text/plain')
|
||||
})
|
||||
|
||||
it('gets a content type of text/plain for .*ignore files', () => {
|
||||
expect(getFileContentType('.eslintignore')).toBe('text/plain')
|
||||
expect(getFileContentType('.anythingignore')).toBe('text/plain')
|
||||
})
|
||||
|
||||
it('gets a content type of text/plain for .ts files', () => {
|
||||
expect(getFileContentType('app.ts')).toBe('text/plain')
|
||||
expect(getFileContentType('app.d.ts')).toBe('text/plain')
|
||||
})
|
||||
|
||||
it('gets a content type of text/plain for .flow files', () => {
|
||||
expect(getFileContentType('app.js.flow')).toBe('text/plain')
|
||||
})
|
|
@ -0,0 +1,15 @@
|
|||
const fs = require('fs')
|
||||
|
||||
function getFileStats(file) {
|
||||
return new Promise((resolve, reject) => {
|
||||
fs.lstat(file, (error, stats) => {
|
||||
if (error) {
|
||||
reject(error)
|
||||
} else {
|
||||
resolve(stats)
|
||||
}
|
||||
})
|
||||
})
|
||||
}
|
||||
|
||||
module.exports = getFileStats
|
|
@ -0,0 +1,12 @@
|
|||
function getFileType(stats) {
|
||||
if (stats.isFile()) return 'file'
|
||||
if (stats.isDirectory()) return 'directory'
|
||||
if (stats.isBlockDevice()) return 'blockDevice'
|
||||
if (stats.isCharacterDevice()) return 'characterDevice'
|
||||
if (stats.isSymbolicLink()) return 'symlink'
|
||||
if (stats.isSocket()) return 'socket'
|
||||
if (stats.isFIFO()) return 'fifo'
|
||||
return 'unknown'
|
||||
}
|
||||
|
||||
module.exports = getFileType
|
|
@ -0,0 +1,42 @@
|
|||
const fs = require('fs')
|
||||
const path = require('path')
|
||||
const React = require('react')
|
||||
const ReactDOMServer = require('react-dom/server')
|
||||
const getFileStats = require('./getFileStats')
|
||||
const IndexPage = require('../components/IndexPage')
|
||||
|
||||
const e = React.createElement
|
||||
|
||||
function getEntries(dir) {
|
||||
return new Promise(function (resolve, reject) {
|
||||
fs.readdir(dir, function (error, files) {
|
||||
if (error) {
|
||||
reject(error)
|
||||
} else {
|
||||
resolve(
|
||||
Promise.all(
|
||||
files.map(file => getFileStats(path.join(dir, file)))
|
||||
).then(function (statsArray) {
|
||||
return statsArray.map(function (stats, index) {
|
||||
return { file: files[index], stats }
|
||||
})
|
||||
})
|
||||
)
|
||||
}
|
||||
})
|
||||
})
|
||||
}
|
||||
|
||||
const DOCTYPE = '<!DOCTYPE html>'
|
||||
|
||||
function createHTML(props) {
|
||||
return DOCTYPE + ReactDOMServer.renderToStaticMarkup(e(IndexPage, props))
|
||||
}
|
||||
|
||||
function getIndexHTML(packageInfo, version, baseDir, dir, callback) {
|
||||
getEntries(path.join(baseDir, dir))
|
||||
.then(entries => createHTML({ packageInfo, version, dir, entries }))
|
||||
.then(html => callback(null, html), callback)
|
||||
}
|
||||
|
||||
module.exports = getIndexHTML
|
|
@ -1,7 +1,9 @@
|
|||
const fs = require('fs')
|
||||
const path = require('path')
|
||||
const SRIToolbox = require('sri-toolbox')
|
||||
const { getContentType, getStats, getFileType } = require('./FileUtils')
|
||||
const getFileContentType = require('./getFileContentType')
|
||||
const getFileStats = require('./getFileStats')
|
||||
const getFileType = require('./getFileType')
|
||||
|
||||
function getEntries(dir, file, maximumDepth) {
|
||||
return new Promise(function (resolve, reject) {
|
||||
|
@ -12,7 +14,7 @@ function getEntries(dir, file, maximumDepth) {
|
|||
resolve(
|
||||
Promise.all(
|
||||
files.map(function (f) {
|
||||
return getStats(path.join(dir, file, f))
|
||||
return getFileStats(path.join(dir, file, f))
|
||||
})
|
||||
).then(function (statsArray) {
|
||||
return Promise.all(statsArray.map(function (stats, index) {
|
||||
|
@ -44,7 +46,7 @@ function getIntegrity(file) {
|
|||
function getMetadataRecursive(dir, file, stats, maximumDepth) {
|
||||
const metadata = {
|
||||
lastModified: formatTime(stats.mtime),
|
||||
contentType: getContentType(file),
|
||||
contentType: getFileContentType(file),
|
||||
path: file,
|
||||
size: stats.size,
|
||||
type: getFileType(stats)
|
||||
|
@ -72,6 +74,4 @@ function getMetadata(baseDir, path, stats, maximumDepth, callback) {
|
|||
}, callback)
|
||||
}
|
||||
|
||||
module.exports = {
|
||||
get: getMetadata
|
||||
}
|
||||
module.exports = getMetadata
|
|
@ -0,0 +1,9 @@
|
|||
const fs = require('fs')
|
||||
const path = require('path')
|
||||
const csso = require('csso')
|
||||
|
||||
function readCSS(...args) {
|
||||
return csso.minify(fs.readFileSync(path.resolve(...args), 'utf8')).css
|
||||
}
|
||||
|
||||
module.exports = readCSS
|
Loading…
Reference in New Issue