import cors from 'cors';
import express from 'express';
import ejs from 'ejs';
import os from "os";
import serveDirectoryMetadata, { getMetadataMoreEasier } from './actions/serveDirectoryMetadata.js';
import serveFileMetadata from './actions/serveFileMetadata.js';
import serveFile from './actions/serveFile.js';
import serveModule from './actions/serveModule.js';
import allowQuery from './middleware/allowQuery.js';
import findEntry from './middleware/findEntry.js';
import noQuery from './middleware/noQuery.js';
import redirectLegacyURLs from './middleware/redirectLegacyURLs.js';
import requestLog from './middleware/requestLog.js';
import validateFilename from './middleware/validateFilename.js';
import validatePackagePathname from './middleware/validatePackagePathname.js';
import validatePackageName from './middleware/validatePackageName.js';
import validatePackageVersion from './middleware/validatePackageVersion.js';
const renderFolderBrowser = async (req, res, next) => {
res.set({
'Cache-Control': 'public, max-age=14400', // 4 hours
'Cache-Tag': 'browse'
});
const html = await ejs.render(`<%if(path!=="/"){path+="/"}%>
Index of <%= path %>
Index of <%= path %>
Name |
Type |
Size |
Last Modified |
<%
files.sort((fileA,fileB) => {
let nameA = fileA.path.toUpperCase();
let nameB = fileB.path.toUpperCase();
if(fileA.type === "directory") return -1;
else if(fileB.type === "directory") return 1;
else if(nameAnameB) return 1;
else return 0;
})
if(path!=="/"){
files.splice(0,0,{
path: "..",
type: "directory",
});
}
%>
<% files.forEach((file,index) => { let name = file.path.replace(path,"")+(file.type==="directory"?"/":""); %>
">
<%= name %> |
<%= file.type==="directory"?"-":file.contentType %> |
<%= file.type==="directory"?"-":(()=>{
if(file.size<=1024) return file.size+" B";
else if(file.size<=1024*1024) return (file.size/1024).toFixed(2)+" KiB";
else return (file.size/1024/1024).toFixed(2)+" MB";
})() %> |
<%= file.type==="directory"?"-":new Date(Date.parse(file.lastModified)).toISOString()
%> |
<% }) %>
<%= package %>
186526 NPM Edge Network #d9e588d
`, Object.assign({ package: `${req.packageName}@${req.packageVersion}` }, await getMetadataMoreEasier(req, res)), { async: true });
res.send(html);
};
function createApp(callback) {
const app = express();
callback(app);
return app;
}
const hostname = os.hostname();
export default function createServer() {
return createApp(app => {
app.disable('x-powered-by');
app.enable('trust proxy');
app.enable('strict routing');
app.use(cors());
app.use(express.static('public', { maxAge: '1y' }));
app.use((req, res, next) => {
res.set({
'x-delivery-by': hostname,
'timing-allow-origin': '*',
'x-powered-by': '186526 NPM Edge Network',
'x-version': 'd9e588d'
});
next();
})
app.use(requestLog);
app.use(redirectLegacyURLs);
app.all('/', (req, res) => {
res.send("To infinity and beyond!");
})
// app.use(
// '/browse',
// createApp(app => {
// app.enable('strict routing');
// app.get(
// '*/',
// noQuery(),
// validatePackagePathname,
// validatePackageName,
// validatePackageVersion,
// renderFolderBrowser,
// );
// app.get(
// '*',
// (req, res, next) => {
// res.redirect(req.path.replace("/browser", ""));
// }
// );
// })
// );
// We need to route in this weird way because Express
// doesn't have a way to route based on query params.
const metadataApp = createApp(app => {
app.enable('strict routing');
app.get(
'*/',
allowQuery('meta'),
validatePackagePathname,
validatePackageName,
validatePackageVersion,
validateFilename,
serveDirectoryMetadata
);
app.get(
'*',
allowQuery('meta'),
validatePackagePathname,
validatePackageName,
validatePackageVersion,
validateFilename,
serveFileMetadata
);
});
app.use((req, res, next) => {
if (req.query.meta != null) {
metadataApp(req, res);
} else {
next();
}
});
// We need to route in this weird way because Express
// doesn't have a way to route based on query params.
const moduleApp = createApp(app => {
app.enable('strict routing');
app.get(
'*',
allowQuery('module'),
validatePackagePathname,
validatePackageName,
validatePackageVersion,
validateFilename,
findEntry,
serveModule
);
});
app.use((req, res, next) => {
if (req.query.module != null) {
moduleApp(req, res);
} else {
next();
}
});
app.get('*/', noQuery(),
validatePackagePathname,
validatePackageName,
validatePackageVersion,
renderFolderBrowser
);
app.get(
'*',
noQuery(),
validatePackagePathname,
validatePackageName,
validatePackageVersion,
validateFilename,
findEntry,
serveFile
);
});
}