|
|
|
@ -2,6 +2,7 @@ import cors from 'cors';
|
|
|
|
|
import express from 'express'; |
|
|
|
|
import ejs from 'ejs'; |
|
|
|
|
import os from "os"; |
|
|
|
|
import semver from 'semver'; |
|
|
|
|
|
|
|
|
|
import serveDirectoryMetadata, { getMetadataMoreEasier } from './actions/serveDirectoryMetadata.js'; |
|
|
|
|
import serveFileMetadata from './actions/serveFileMetadata.js'; |
|
|
|
@ -18,13 +19,30 @@ import validatePackagePathname from './middleware/validatePackagePathname.js';
|
|
|
|
|
import validatePackageName from './middleware/validatePackageName.js'; |
|
|
|
|
import validatePackageVersion from './middleware/validatePackageVersion.js'; |
|
|
|
|
|
|
|
|
|
import { getVersionsAndTags } from './utils/npm.js'; |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
const renderFolderBrowser = async (req, res, next) => { |
|
|
|
|
|
|
|
|
|
function byVersion(a, b) { |
|
|
|
|
return semver.lt(a, b) ? -1 : semver.gt(a, b) ? 1 : 0; |
|
|
|
|
} |
|
|
|
|
|
|
|
|
|
async function getAvailableVersions(packageName, log) { |
|
|
|
|
const versionsAndTags = await getVersionsAndTags(packageName, log); |
|
|
|
|
return versionsAndTags ? versionsAndTags.versions.sort(byVersion) : []; |
|
|
|
|
} |
|
|
|
|
|
|
|
|
|
res.set({ |
|
|
|
|
'Cache-Control': 'public, max-age=14400', // 4 hours
|
|
|
|
|
'Cache-Tag': 'browse' |
|
|
|
|
}); |
|
|
|
|
|
|
|
|
|
const availableVersions = await getAvailableVersions( |
|
|
|
|
req.packageName, |
|
|
|
|
req.log |
|
|
|
|
); |
|
|
|
|
|
|
|
|
|
const html = await ejs.render(`<%if(path!=="/"){path+="/"}%>
|
|
|
|
|
<!DOCTYPE html> |
|
|
|
|
<html> |
|
|
|
@ -75,6 +93,9 @@ const renderFolderBrowser = async (req, res, next) => {
|
|
|
|
|
</head> |
|
|
|
|
|
|
|
|
|
<body> |
|
|
|
|
<div class="version-wrapper"><select id="version"><% availableVersions.forEach(it=>{ %> |
|
|
|
|
<option value="<%= it %>" <%= it === version ? "selected" : "" %> ><%= packageName+"@"+it %></option> |
|
|
|
|
<% })%></select></div> |
|
|
|
|
<h1>Index of <%= path %></h1> |
|
|
|
|
<hr /> |
|
|
|
|
<table> |
|
|
|
@ -121,11 +142,24 @@ const renderFolderBrowser = async (req, res, next) => {
|
|
|
|
|
</tbody> |
|
|
|
|
</table> |
|
|
|
|
<hr /> |
|
|
|
|
<script> |
|
|
|
|
var s = document.getElementById('version'), v = s.value |
|
|
|
|
s.onchange = function () { |
|
|
|
|
window.location.href = window.location.href.replace('@' + v, '@' + s.value) |
|
|
|
|
} |
|
|
|
|
</script> |
|
|
|
|
<address><%= package %> </address> |
|
|
|
|
<address>186526 NPM Edge Network #d9e588d</address> |
|
|
|
|
<address>186526 UNPKG Network @sg-singapore-03 #<%= ((r=32)=>{ |
|
|
|
|
let s = "ABCDEFGHJKMNPQRSTWXYZabcdefhijkmnprstwxyz2345678" |
|
|
|
|
, n = s.length |
|
|
|
|
, t = ""; |
|
|
|
|
for (let o = 0; o < r; o++) |
|
|
|
|
t += s.charAt(Math.floor(Math.random() * n)); |
|
|
|
|
return t |
|
|
|
|
})(8) %></address> |
|
|
|
|
</body> |
|
|
|
|
|
|
|
|
|
</html>`, Object.assign({ package: `${req.packageName}@${req.packageVersion}` }, await getMetadataMoreEasier(req, res)), { async: true }); |
|
|
|
|
</html>`, Object.assign({ package: `${req.packageName}@${req.packageVersion}`, packageName: req.packageName, version: req.packageVersion, availableVersions: await getAvailableVersions(req.packageName, req.log) }, await getMetadataMoreEasier(req, res)), { async: true }); |
|
|
|
|
res.send(html); |
|
|
|
|
}; |
|
|
|
|
|
|
|
|
@ -161,6 +195,7 @@ export default function createServer() {
|
|
|
|
|
app.use(redirectLegacyURLs); |
|
|
|
|
|
|
|
|
|
app.all('/', (req, res) => { |
|
|
|
|
res.setHeader('Content-Type',"text/plain; charset=utf-8") |
|
|
|
|
res.send("To infinity and beyond!"); |
|
|
|
|
}) |
|
|
|
|
|
|
|
|
|