Socket
Socket
Sign inDemoInstall

serve

Package Overview
Dependencies
Maintainers
4
Versions
152
Alerts
File Explorer

Advanced tools

Socket logo

Install Socket

Detect and block malicious and high-risk dependencies

Install

serve - npm Package Compare versions

Comparing version 6.5.8 to 7.0.0

LICENSE

326

bin/serve.js

@@ -5,140 +5,258 @@ #!/usr/bin/env node

const path = require('path');
const https = require('https');
// Packages
const Ajv = require('ajv');
const dotProp = require('dot-prop');
const checkForUpdate = require('update-check');
const chalk = require('chalk');
const micro = require('micro');
const args = require('args');
const compress = require('micro-compress');
const detect = require('detect-port');
const {coroutine} = require('bluebird');
const checkForUpdate = require('update-check');
const {red, bold} = require('chalk');
const nodeVersion = require('node-version');
const cert = require('openssl-self-signed-certificate');
const boxen = require('boxen');
const arg = require('arg');
const handler = require('serve-handler');
const schema = require('@zeit/schemas/deployment/config-static');
const fs = require('fs-extra');
// Utilities
const pkg = require('../package');
const listening = require('../lib/listening');
const serverHandler = require('../lib/server');
const {options, minimist} = require('../lib/options');
// Throw an error if node version is too low
if (nodeVersion.major < 6) {
console.error(
`${red(
'Error!'
)} Serve requires at least version 6 of Node. Please upgrade!`
);
process.exit(1);
}
const warning = message => chalk`{yellow WARNING:} ${message}`;
const info = message => chalk`{magenta INFO:} ${message}`;
const error = message => chalk`{red ERROR:} ${message}`;
// Register the list of options
args.options(options);
const updateCheck = async isDebugging => {
let update = null;
// And initialize `args`
const flags = args.parse(process.argv, {minimist});
try {
update = await checkForUpdate(pkg);
} catch (err) {
const suffix = isDebugging ? ':' : ' (use `--debug` to see full error)';
console.error(warning(`Checking for updates failed${suffix}`));
// Figure out the content directory
const [directory] = args.sub;
if (isDebugging) {
console.error(err);
}
}
// Don't log anything to the console if silent mode is enabled
if (flags.silent) {
console.log = () => {};
}
if (!update) {
return;
}
process.env.ASSET_DIR = Math.random()
.toString(36)
.substr(2, 10);
console.log(`${chalk.bgRed('UPDATE AVAILABLE')} The latest version of \`serve\` is ${update.latest}`);
};
let current = process.cwd();
const getHelp = () => chalk`
{bold.cyan serve} - Static file serving and directory listing
if (directory) {
current = path.resolve(process.cwd(), directory);
}
{bold USAGE}
let ignoredFiles = ['.DS_Store', '.git/'];
{bold $} {cyan serve} --help
{bold $} {cyan serve} --version
{bold $} {cyan serve} [-l {underline listen_uri} [-l ...]] [{underline directory}]
if (flags.ignore && flags.ignore.length > 0) {
ignoredFiles = ignoredFiles.concat(flags.ignore.split(','));
}
By default, {cyan serve} will listen on {bold 0.0.0.0:3000} and serve the
current working directory on that address.
const handler = coroutine(function *run(req, res) {
yield serverHandler(req, res, flags, current, ignoredFiles);
});
Specifying a single {bold --listen} argument will overwrite the default, not supplement it.
const httpsOpts = {
key: cert.key,
cert: cert.cert
{bold OPTIONS}
--help Shows this help message
-v, --version Displays the current version of serve
-l, --listen {underline listen_uri} Specify a URI endpoint on which to listen (see below) -
more than one may be specified to listen in multiple places
-d, --debug Show debugging information
{bold ENDPOINTS}
Listen endpoints (specified by the {bold --listen} or {bold -l} options above) instruct {cyan micro}
to listen on one or more interfaces/ports, UNIX domain sockets, or Windows named pipes.
For TCP (traditional host/port) endpoints:
{bold $} {cyan serve} -l tcp://{underline hostname}:{underline 1234}
For UNIX domain socket endpoints:
{bold $} {cyan serve} -l unix:{underline /path/to/socket.sock}
For Windows named pipe endpoints:
{bold $} {cyan serve} -l pipe:\\\\.\\pipe\\{underline PipeName}
`;
const parseEndpoint = str => {
const url = new URL(str);
switch (url.protocol) {
case 'pipe:': {
// some special handling
const cutStr = str.replace(/^pipe:/, '');
if (cutStr.slice(0, 4) !== '\\\\.\\') {
throw new Error(`Invalid Windows named pipe endpoint: ${str}`);
}
return [cutStr];
}
case 'unix:':
if (!url.pathname) {
throw new Error(`Invalid UNIX domain socket endpoint: ${str}`);
}
return [url.pathname];
case 'tcp:':
url.port = url.port || '3000';
return [parseInt(url.port, 10), url.hostname];
default:
throw new Error(`Unknown --listen endpoint scheme (protocol): ${url.protocol}`);
}
};
const microHttps = fn =>
https.createServer(httpsOpts, (req, res) => micro.run(req, res, fn));
const server = flags.ssl
? microHttps(flags.unzipped ? handler : compress(handler))
: micro(flags.unzipped ? handler : compress(handler));
const registerShutdown = fn => {
let run = false;
let {port} = flags;
const wrapper = () => {
if (!run) {
run = true;
fn();
}
};
detect(port).then(async open => {
const {NODE_ENV} = process.env;
process.on('SIGINT', wrapper);
process.on('SIGTERM', wrapper);
process.on('exit', wrapper);
};
if (NODE_ENV !== 'production') {
try {
const update = await checkForUpdate(pkg);
const startEndpoint = (endpoint, config) => {
const server = micro(async (request, response) => handler(request, response, config));
if (update) {
const message = `${bold(
'UPDATE AVAILABLE:'
)} The latest version of \`serve\` is ${update.latest}`;
server.on('error', err => {
console.error('serve:', err.stack);
process.exit(1);
});
console.log(
boxen(message, {
padding: 1,
borderColor: 'green',
margin: 1
})
);
}
server.listen(...endpoint, () => {
const details = server.address();
registerShutdown(() => server.close());
// `micro` is designed to run only in production, so
// this message is perfectly for prod
if (typeof details === 'string') {
console.log(info(`Accepting connections at ${details}`));
} else if (typeof details === 'object' && details.port) {
console.log(info(`Accepting connections at http://localhost:${details.port}`));
} else {
console.log(info('Accepting connections'));
}
});
};
const loadConfig = async (cwd, entry) => {
const paths = {
'serve.json': null,
'now.json': 'static',
'package.json': 'now.static'
};
const config = {};
for (const file of Object.keys(paths)) {
const location = path.join(entry, file);
const prop = paths[file];
try {
const content = await fs.readJSON(location);
Object.assign(config, prop ? dotProp.get(content, prop) : content);
} catch (err) {
console.log(
boxen(
`${bold(
'UPDATE CHECK FAILED:'
)} ${err.message}`, {
padding: 1,
borderColor: 'red',
margin: 1
}
)
);
continue;
}
if (Object.keys(config).length !== 0) {
console.log(info(`Discovered configuration in \`${file}\``));
break;
}
}
let inUse = open !== port;
if (entry) {
const {public} = config;
config.public = path.relative(cwd, (public ? path.join(entry, public) : entry));
}
if (inUse) {
port = open;
if (Object.keys(config).length !== 0) {
const ajv = new Ajv();
const validateSchema = ajv.compile(schema);
inUse = {
old: flags.port,
open
};
if (!validateSchema(config)) {
const defaultMessage = error('The configuration you provided is wrong:');
const {message, params} = validateSchema.errors[0];
console.error(`${defaultMessage}\n${message}\n${JSON.stringify(params)}`);
process.exit(1);
}
}
const listenArgs = [
server,
current,
inUse,
flags.clipless !== true,
flags.open,
flags.ssl,
flags.local
];
return config;
};
if (flags.local) {
server.listen(port, 'localhost', listening.bind(this, ...listenArgs));
} else {
server.listen(port, listening.bind(this, ...listenArgs));
(async () => {
let args = null;
try {
args = arg({
'--help': Boolean,
'--version': Boolean,
'--listen': [parseEndpoint],
'--debug': Boolean,
'-h': '--help',
'-v': '--version',
'-l': '--listen',
'-d': '--debug'
});
} catch (err) {
console.error(error(err.message));
process.exit(1);
}
});
await updateCheck(args['--debug']);
if (args['--version']) {
console.log(pkg.version);
return;
}
if (args['--help']) {
console.log(getHelp());
return;
}
if (!args['--listen']) {
// Default endpoint
args['--listen'] = [[3000]];
}
if (args._.length > 1) {
console.error(error('Please provide one path argument at maximum'));
process.exit(1);
}
const cwd = process.cwd();
const entry = args._.length > 0 ? path.join(cwd, args._[0]) : cwd;
const config = await loadConfig(cwd, entry);
for (const endpoint of args['--listen']) {
startEndpoint(endpoint, config);
}
registerShutdown(() => {
console.log(`\n${info('Gracefully shutting down. Please wait...')}`);
process.on('SIGINT', () => {
console.log(`\n${warning('Force-closing all open sockets...')}`);
process.exit(0);
});
});
})();
{
"name": "serve",
"version": "6.5.8",
"version": "7.0.0",
"description": "Static file serving and directory listing",
"scripts": {
"test": "yarn lint && NODE_ENV=test nyc ava",
"test": "yarn lint",
"lint": "zeit-eslint --ext .jsx,.js .",

@@ -11,15 +11,8 @@ "lint-staged": "git diff --diff-filter=ACMRT --cached --name-only '*.js' '*.jsx' | xargs zeit-eslint"

"files": [
"bin",
"lib",
"assets",
"views"
"bin"
],
"repository": "zeit/serve",
"main": "./lib/api.js",
"bin": {
"serve": "./bin/serve.js"
},
"engines": {
"node": ">=7.6.0"
},
"keywords": [

@@ -36,32 +29,4 @@ "now",

"@zeit/git-hooks": "0.1.4",
"ava": "0.25.0",
"eslint": "4.19.1",
"node-fetch": "2.1.2",
"nyc": "11.8.0",
"test-listen": "1.1.0"
"eslint": "4.19.1"
},
"dependencies": {
"args": "4.0.0",
"basic-auth": "2.0.0",
"bluebird": "3.5.1",
"boxen": "1.3.0",
"chalk": "2.4.1",
"clipboardy": "1.2.3",
"dargs": "5.1.0",
"detect-port": "1.2.3",
"filesize": "3.6.1",
"fs-extra": "6.0.1",
"handlebars": "4.0.11",
"ip": "1.1.5",
"micro": "9.3.1",
"micro-compress": "1.0.0",
"mime-types": "2.1.18",
"node-version": "1.1.3",
"openssl-self-signed-certificate": "1.1.6",
"opn": "5.3.0",
"path-is-inside": "1.0.2",
"path-type": "3.0.0",
"send": "0.16.2",
"update-check": "1.5.1"
},
"eslintConfig": {

@@ -74,3 +39,14 @@ "extends": [

"pre-commit": "lint-staged"
},
"dependencies": {
"@zeit/schemas": "1.1.1",
"ajv": "6.5.0",
"arg": "2.0.0",
"chalk": "2.4.1",
"dot-prop": "4.2.0",
"fs-extra": "6.0.1",
"micro": "9.3.1",
"serve-handler": "2.3.10",
"update-check": "1.5.2"
}
}
SocketSocket SOC 2 Logo

Product

  • Package Alerts
  • Integrations
  • Docs
  • Pricing
  • FAQ
  • Roadmap
  • Changelog

Packages

npm

Stay in touch

Get open source security insights delivered straight into your inbox.


  • Terms
  • Privacy
  • Security

Made with ⚡️ by Socket Inc