This commit is contained in:
186526 2021-10-05 12:54:12 +08:00
parent a7ebffaa49
commit 010fed101f
Signed by: 186526
GPG Key ID: C7EB1E6B8CC5E51D
14 changed files with 228013 additions and 2955 deletions

7
Dockerfile.unpkg Normal file
View File

@ -0,0 +1,7 @@
FROM docker.io/library/node:lts-alpine
COPY ./dist/main.js /app/main.js
WORKDIR /app
CMD NODE_ENV=production node main.js

222243
build/main.js Normal file

File diff suppressed because one or more lines are too long

1911
dist/main.js vendored Normal file

File diff suppressed because one or more lines are too long

295
dist/main.js.LICENSE.txt vendored Normal file
View File

@ -0,0 +1,295 @@
/*
object-assign
(c) Sindre Sorhus
@license MIT
*/
/*!
* accepts
* Copyright(c) 2014 Jonathan Ong
* Copyright(c) 2015 Douglas Christopher Wilson
* MIT Licensed
*/
/*!
* body-parser
* Copyright(c) 2014 Jonathan Ong
* Copyright(c) 2014-2015 Douglas Christopher Wilson
* MIT Licensed
*/
/*!
* body-parser
* Copyright(c) 2014-2015 Douglas Christopher Wilson
* MIT Licensed
*/
/*!
* bytes
* Copyright(c) 2012-2014 TJ Holowaychuk
* Copyright(c) 2015 Jed Watson
* MIT Licensed
*/
/*!
* content-disposition
* Copyright(c) 2014-2017 Douglas Christopher Wilson
* MIT Licensed
*/
/*!
* content-type
* Copyright(c) 2015 Douglas Christopher Wilson
* MIT Licensed
*/
/*!
* cookie
* Copyright(c) 2012-2014 Roman Shtylman
* Copyright(c) 2015 Douglas Christopher Wilson
* MIT Licensed
*/
/*!
* depd
* Copyright(c) 2014 Douglas Christopher Wilson
* MIT Licensed
*/
/*!
* depd
* Copyright(c) 2014-2015 Douglas Christopher Wilson
* MIT Licensed
*/
/*!
* depd
* Copyright(c) 2014-2017 Douglas Christopher Wilson
* MIT Licensed
*/
/*!
* depd
* Copyright(c) 2015 Douglas Christopher Wilson
* MIT Licensed
*/
/*!
* destroy
* Copyright(c) 2014 Jonathan Ong
* MIT Licensed
*/
/*!
* ee-first
* Copyright(c) 2014 Jonathan Ong
* MIT Licensed
*/
/*!
* encodeurl
* Copyright(c) 2016 Douglas Christopher Wilson
* MIT Licensed
*/
/*!
* escape-html
* Copyright(c) 2012-2013 TJ Holowaychuk
* Copyright(c) 2015 Andreas Lubbe
* Copyright(c) 2015 Tiancheng "Timothy" Gu
* MIT Licensed
*/
/*!
* etag
* Copyright(c) 2014-2016 Douglas Christopher Wilson
* MIT Licensed
*/
/*!
* express
* Copyright(c) 2009-2013 TJ Holowaychuk
* Copyright(c) 2013 Roman Shtylman
* Copyright(c) 2014-2015 Douglas Christopher Wilson
* MIT Licensed
*/
/*!
* express
* Copyright(c) 2009-2013 TJ Holowaychuk
* Copyright(c) 2014-2015 Douglas Christopher Wilson
* MIT Licensed
*/
/*!
* finalhandler
* Copyright(c) 2014-2017 Douglas Christopher Wilson
* MIT Licensed
*/
/*!
* forwarded
* Copyright(c) 2014-2017 Douglas Christopher Wilson
* MIT Licensed
*/
/*!
* fresh
* Copyright(c) 2012 TJ Holowaychuk
* Copyright(c) 2016-2017 Douglas Christopher Wilson
* MIT Licensed
*/
/*!
* http-errors
* Copyright(c) 2014 Jonathan Ong
* Copyright(c) 2016 Douglas Christopher Wilson
* MIT Licensed
*/
/*!
* media-typer
* Copyright(c) 2014 Douglas Christopher Wilson
* MIT Licensed
*/
/*!
* merge-descriptors
* Copyright(c) 2014 Jonathan Ong
* Copyright(c) 2015 Douglas Christopher Wilson
* MIT Licensed
*/
/*!
* methods
* Copyright(c) 2013-2014 TJ Holowaychuk
* Copyright(c) 2015-2016 Douglas Christopher Wilson
* MIT Licensed
*/
/*!
* mime-db
* Copyright(c) 2014 Jonathan Ong
* MIT Licensed
*/
/*!
* mime-types
* Copyright(c) 2014 Jonathan Ong
* Copyright(c) 2015 Douglas Christopher Wilson
* MIT Licensed
*/
/*!
* negotiator
* Copyright(c) 2012 Federico Romero
* Copyright(c) 2012-2014 Isaac Z. Schlueter
* Copyright(c) 2015 Douglas Christopher Wilson
* MIT Licensed
*/
/*!
* on-finished
* Copyright(c) 2013 Jonathan Ong
* Copyright(c) 2014 Douglas Christopher Wilson
* MIT Licensed
*/
/*!
* parseurl
* Copyright(c) 2014 Jonathan Ong
* Copyright(c) 2014-2017 Douglas Christopher Wilson
* MIT Licensed
*/
/*!
* proxy-addr
* Copyright(c) 2014-2016 Douglas Christopher Wilson
* MIT Licensed
*/
/*!
* range-parser
* Copyright(c) 2012-2014 TJ Holowaychuk
* Copyright(c) 2015-2016 Douglas Christopher Wilson
* MIT Licensed
*/
/*!
* raw-body
* Copyright(c) 2013-2014 Jonathan Ong
* Copyright(c) 2014-2015 Douglas Christopher Wilson
* MIT Licensed
*/
/*!
* send
* Copyright(c) 2012 TJ Holowaychuk
* Copyright(c) 2014-2016 Douglas Christopher Wilson
* MIT Licensed
*/
/*!
* serve-static
* Copyright(c) 2010 Sencha Inc.
* Copyright(c) 2011 TJ Holowaychuk
* Copyright(c) 2014-2016 Douglas Christopher Wilson
* MIT Licensed
*/
/*!
* statuses
* Copyright(c) 2014 Jonathan Ong
* Copyright(c) 2016 Douglas Christopher Wilson
* MIT Licensed
*/
/*!
* toidentifier
* Copyright(c) 2016 Douglas Christopher Wilson
* MIT Licensed
*/
/*!
* type-is
* Copyright(c) 2014 Jonathan Ong
* Copyright(c) 2014-2015 Douglas Christopher Wilson
* MIT Licensed
*/
/*!
* unpipe
* Copyright(c) 2015 Douglas Christopher Wilson
* MIT Licensed
*/
/*!
* vary
* Copyright(c) 2014-2017 Douglas Christopher Wilson
* MIT Licensed
*/
/*! *****************************************************************************
Copyright (c) Microsoft Corporation.
Permission to use, copy, modify, and/or distribute this software for any
purpose with or without fee is hereby granted.
THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES WITH
REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY
AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY SPECIAL, DIRECT,
INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM
LOSS OF USE, DATA OR PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE OR
OTHER TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR
PERFORMANCE OF THIS SOFTWARE.
***************************************************************************** */
/*! safe-buffer. MIT License. Feross Aboukhadijeh <https://feross.org/opensource> */
/**
* @file Embedded JavaScript templating engine. {@link http://ejs.co}
* @author Matthew Eernisse <mde@fleegix.org>
* @author Tiancheng "Timothy" Gu <timothygu99@gmail.com>
* @project EJS
* @license {@link http://www.apache.org/licenses/LICENSE-2.0 Apache License, Version 2.0}
*/

101
modules/actions/dir.ejs Normal file
View File

@ -0,0 +1,101 @@
<%if(path!=="/"){path+="/"}%>
<!DOCTYPE html>
<html>
<head>
<meta charset="utf-8" />
<title>Index of <%= path %></title>
<style>
body {
font-size: 16px;
font-family: -apple-system, BlinkMacSystemFont, "Segoe UI", Roboto, Helvetica, Arial, sans-serif;
line-height: 1.5;
padding: 0 10px 5px
}
table {
width: 100%;
border-collapse: collapse;
font: .85em Monaco, monospace
}
tr.even {
background-color: #eee
}
th {
text-align: left
}
td,
th {
padding: .1em .25em
}
.version-wrapper {
line-height: 2.25em;
float: right
}
#version {
font-size: 1em
}
address {
text-align: right
}
</style>
</head>
<body>
<h1>Index of <%= path %></h1>
<hr />
<table>
<thead>
<tr>
<th>Name</th>
<th>Type</th>
<th>Size</th>
<th>Last Modified</th>
</tr>
</thead>
<tbody>
<%
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(nameA<nameB) return -1;
else if(nameA>nameB) 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"?"/":""}` %>
<tr class="<%= index%2===0?"even":"odd" %> ">
<td><a title="<%= name %>" href="<%= name %>"><%= name %></a></td>
<td><%= file.type==="directory"?"-":file.contentType %></td>
<td><%= 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";
})() %></td>
<td><%= file.type==="directory"?"-":new Date(Date.parse(file.lastModified)).toISOString()
%></td>
</tr>
<% }) %>
</tbody>
</table>
<hr />
<address><%= package %> </address>
<address>186526 Edge/1.20.1</address>
</body>
</html>

View File

@ -99,4 +99,14 @@ async function serveDirectoryMetadata(req, res) {
res.send(metadata);
}
export async function getMetadataMoreEasier(req,res) {
const stream = await getPackage(req.packageName, req.packageVersion, req.log);
const filename = req.filename.slice(0, -1) || '/';
const entries = await findMatchingEntries(stream, filename);
const metadata = getMetadata(entries[filename], entries);
return metadata;
}
export default asyncHandler(serveDirectoryMetadata);

View File

@ -29,7 +29,6 @@ export default function serveMainPage(req, res) {
res
.set({
'Cache-Control': 'public, max-age=14400', // 4 hours
'Cache-Tag': 'main'
})
.send(html);

View File

@ -1,15 +1,11 @@
import cors from 'cors';
import express from 'express';
import morgan from 'morgan';
import ejs from 'ejs';
import serveDirectoryBrowser from './actions/serveDirectoryBrowser.js';
import serveDirectoryMetadata from './actions/serveDirectoryMetadata.js';
import serveFileBrowser from './actions/serveFileBrowser.js';
import serveDirectoryMetadata, { getMetadataMoreEasier } from './actions/serveDirectoryMetadata.js';
import serveFileMetadata from './actions/serveFileMetadata.js';
import serveFile from './actions/serveFile.js';
import serveMainPage from './actions/serveMainPage.js';
import serveModule from './actions/serveModule.js';
import serveStats from './actions/serveStats.js';
import allowQuery from './middleware/allowQuery.js';
import findEntry from './middleware/findEntry.js';
@ -21,6 +17,117 @@ 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+="/"}%>
<!DOCTYPE html>
<html>
<head>
<meta charset="utf-8" />
<title>Index of <%= path %></title>
<style>
body {
font-size: 16px;
font-family: -apple-system, BlinkMacSystemFont, "Segoe UI", Roboto, Helvetica, Arial, sans-serif;
line-height: 1.5;
padding: 0 10px 5px
}
table {
width: 100%;
border-collapse: collapse;
font: .85em Monaco, monospace
}
tr.even {
background-color: #eee
}
th {
text-align: left
}
td,
th {
padding: .1em .25em
}
.version-wrapper {
line-height: 2.25em;
float: right
}
#version {
font-size: 1em
}
address {
text-align: right
}
</style>
</head>
<body>
<h1>Index of <%= path %></h1>
<hr />
<table>
<thead>
<tr>
<th>Name</th>
<th>Type</th>
<th>Size</th>
<th>Last Modified</th>
</tr>
</thead>
<tbody>
<%
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(nameA<nameB) return -1;
else if(nameA>nameB) 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"?"/":""); %>
<tr class="<%= index%2===0?"even":"odd" %> ">
<td><a title="<%= name %>" href="<%= name %>"><%= name %></a></td>
<td><%= file.type==="directory"?"-":file.contentType %></td>
<td><%= 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";
})() %></td>
<td><%= file.type==="directory"?"-":new Date(Date.parse(file.lastModified)).toISOString()
%></td>
</tr>
<% }) %>
</tbody>
</table>
<hr />
<address><%= package %> </address>
<address>186526 Edge/1.20.1</address>
</body>
</html>`, Object.assign({ package: `${req.packageName}@${req.packageVersion}` }, await getMetadataMoreEasier(req, res)), { async: true });
res.send(html);
};
function createApp(callback) {
const app = express();
callback(app);
@ -33,20 +140,17 @@ export default function createServer() {
app.enable('trust proxy');
app.enable('strict routing');
if (process.env.NODE_ENV === 'development') {
app.use(morgan('dev'));
}
app.use(cors());
app.use(express.static('public', { maxAge: '1y' }));
app.use(requestLog);
app.get('/', serveMainPage);
app.get('/api/stats', serveStats);
app.use(redirectLegacyURLs);
app.all('/', (req, res) => {
res.send("To infinity and beyond!");
})
app.use(
'/browse',
createApp(app => {
@ -58,16 +162,13 @@ export default function createServer() {
validatePackagePathname,
validatePackageName,
validatePackageVersion,
serveDirectoryBrowser
renderFolderBrowser,
);
app.get(
'*',
noQuery(),
validatePackagePathname,
validatePackageName,
validatePackageVersion,
serveFileBrowser
(req, res, next) => {
res.redirect(req.path.replace("/browser", ""));
}
);
})
);
@ -132,9 +233,12 @@ export default function createServer() {
});
// Send old */ requests to the new /browse UI.
app.get('*/', (req, res) => {
res.redirect(302, '/browse' + req.url);
});
app.get('*/', noQuery(),
validatePackagePathname,
validatePackageName,
validatePackageVersion,
renderFolderBrowser
);
app.get(
'*',

View File

@ -5,8 +5,8 @@
export default function asyncHandler(handler) {
return (req, res, next) => {
Promise.resolve(handler(req, res, next)).catch(error => {
req.log.error(`Unexpected error in ${handler.name}!`);
req.log.error(error.stack);
console.error(`Unexpected error in ${handler.name}!`);
console.error(error.stack);
next(error);
});

View File

@ -1,6 +1,7 @@
{
"name": "unpkg",
"private": true,
"type":"module",
"description": "The CDN for everything on npm",
"scripts": {
"build": "rollup -c",
@ -22,9 +23,11 @@
"@babel/plugin-syntax-import-meta": "^7.2.0",
"@emotion/core": "^10.0.6",
"@reach/visually-hidden": "^0.1.4",
"@rollup/plugin-json": "^4.1.0",
"cheerio": "^1.0.0-rc.2",
"cors": "^2.8.5",
"date-fns": "^1.30.1",
"ejs": "^3.1.6",
"etag": "^1.8.1",
"express": "^4.16.4",
"gunzip-maybe": "^1.4.1",
@ -77,8 +80,5 @@
"rollup-plugin-replace": "^2.1.0",
"rollup-plugin-url": "^2.1.0",
"supertest": "^3.0.0"
},
"engines": {
"node": "12"
}
}

View File

@ -3,7 +3,7 @@ const execSync = require('child_process').execSync;
const babel = require('rollup-plugin-babel');
const commonjs = require('rollup-plugin-commonjs');
const compiler = require('@ampproject/rollup-plugin-closure-compiler');
//const compiler = require('@ampproject/rollup-plugin-closure-compiler');
const json = require('rollup-plugin-json');
const replace = require('rollup-plugin-replace');
const resolve = require('rollup-plugin-node-resolve');
@ -11,6 +11,7 @@ const url = require('rollup-plugin-url');
const entryManifest = require('./plugins/entryManifest');
const pkg = require('./package.json');
const progress = require('rollup-plugin-progress');
const buildId =
process.env.BUILD_ID ||
@ -40,6 +41,7 @@ const client = ['browse', 'main'].map(entryName => {
babel({ exclude: /node_modules/ }),
json(),
resolve(),
progress(),
commonjs({
namedExports: {
'node_modules/react/index.js': [
@ -61,7 +63,7 @@ const client = ['browse', 'main'].map(entryName => {
limit: 5 * 1024,
publicPath: '/_client/'
}),
compiler()
//compiler()
]
};
});

18
rollup.config.mjs Normal file
View File

@ -0,0 +1,18 @@
import progress from 'rollup-plugin-progress';
import cjs from "rollup-plugin-commonjs";
import node from "rollup-plugin-node-resolve";
import json from '@rollup/plugin-json';
export default {
input: './modules/server.js',
output: { file: "build/main.js", format: "cjs", },
plugins: [
cjs(),
progress({
clearLine: false // default: true
}),
node(),
json(),
]
}

3
webpack.config.js Normal file
View File

@ -0,0 +1,3 @@
module.exports = {
target: "node",
}

6213
yarn.lock

File diff suppressed because it is too large Load Diff