serve
Advanced tools
Comparing version 14.0.1 to 14.1.0
#!/usr/bin/env node | ||
// source/main.ts | ||
import { cwd as getPwd, exit, env as env2, stdout } from "node:process"; | ||
import path from "node:path"; | ||
import chalk3 from "chalk"; | ||
import chalk4 from "chalk"; | ||
import boxen from "boxen"; | ||
import clipboard from "clipboardy"; | ||
import checkForUpdate from "update-check"; | ||
@@ -13,3 +13,3 @@ // package.json | ||
name: "serve", | ||
version: "14.0.1", | ||
version: "14.1.0", | ||
description: "Static file serving and directory listing", | ||
@@ -39,3 +39,5 @@ keywords: [ | ||
"test:tsc": "tsc --project tsconfig.json", | ||
test: "pnpm test:tsc", | ||
"test:unit": "vitest run --config config/vitest.ts", | ||
"test:watch": "vitest watch --config config/vitest.ts", | ||
test: "pnpm test:tsc && pnpm test:unit", | ||
"lint:code": "eslint --max-warnings 0 source/**/*.ts", | ||
@@ -52,2 +54,3 @@ "lint:style": "prettier --check --ignore-path .gitignore .", | ||
boxen: "7.0.0", | ||
c8: "7.11.3", | ||
chalk: "5.0.1", | ||
@@ -58,3 +61,3 @@ "chalk-template": "0.4.0", | ||
"is-port-reachable": "4.0.0", | ||
"serve-handler": "6.1.3", | ||
"serve-handler": "6.1.5", | ||
"update-check": "1.5.4" | ||
@@ -67,2 +70,3 @@ }, | ||
eslint: "8.19.0", | ||
got: "12.1.0", | ||
husky: "8.0.1", | ||
@@ -73,3 +77,4 @@ "lint-staged": "13.0.3", | ||
tsx: "3.7.1", | ||
typescript: "4.6.4" | ||
typescript: "4.6.4", | ||
vitest: "0.18.0" | ||
}, | ||
@@ -98,3 +103,7 @@ tsup: { | ||
"source/**/*.ts": [ | ||
"eslint --max-warnings 0 --fix" | ||
"eslint --max-warnings 0 --fix", | ||
"vitest related --run" | ||
], | ||
tests: [ | ||
"vitest --run" | ||
] | ||
@@ -106,6 +115,13 @@ } | ||
import { promisify } from "node:util"; | ||
var resolve = (promise) => promise.then((data) => [void 0, data]).catch((error2) => [error2, void 0]); | ||
var resolve = async (promiseLike) => { | ||
try { | ||
const data = await promiseLike; | ||
return [void 0, data]; | ||
} catch (error2) { | ||
return [error2, void 0]; | ||
} | ||
}; | ||
// source/utilities/server.ts | ||
import http from "node:http"; | ||
import http2 from "node:http"; | ||
import https from "node:https"; | ||
@@ -116,31 +132,7 @@ import { readFile } from "node:fs/promises"; | ||
import isPortReachable from "is-port-reachable"; | ||
import chalk2 from "chalk"; | ||
// source/utilities/http.ts | ||
import { parse } from "node:url"; | ||
import { networkInterfaces as getNetworkInterfaces } from "node:os"; | ||
var networkInterfaces = getNetworkInterfaces(); | ||
var parseEndpoint = (uriOrPort) => { | ||
if (!isNaN(Number(uriOrPort))) | ||
return [uriOrPort]; | ||
const endpoint = uriOrPort; | ||
const url = parse(endpoint); | ||
switch (url.protocol) { | ||
case "pipe:": { | ||
const pipe = endpoint.replace(/^pipe:/, ""); | ||
if (!pipe.startsWith("\\\\.\\")) | ||
throw new Error(`Invalid Windows named pipe endpoint: ${endpoint}`); | ||
return [pipe]; | ||
} | ||
case "unix:": | ||
if (!url.pathname) | ||
throw new Error(`Invalid UNIX domain socket endpoint: ${endpoint}`); | ||
return [url.pathname]; | ||
case "tcp:": | ||
url.port = url.port ?? "3000"; | ||
url.hostname = url.hostname ?? "localhost"; | ||
return [parseInt(url.port, 10), url.hostname]; | ||
default: | ||
throw new Error(`Unknown --listen endpoint scheme (protocol): ${url.protocol ?? "undefined"}`); | ||
} | ||
}; | ||
var registerCloseListener = (fn) => { | ||
@@ -170,2 +162,11 @@ let run = false; | ||
// source/utilities/logger.ts | ||
import chalk from "chalk"; | ||
var http = (...message) => console.info(chalk.bgBlue.bold(" HTTP "), ...message); | ||
var info = (...message) => console.info(chalk.bgMagenta.bold(" INFO "), ...message); | ||
var warn = (...message) => console.error(chalk.bgYellow.bold(" WARN "), ...message); | ||
var error = (...message) => console.error(chalk.bgRed.bold(" ERROR "), ...message); | ||
var log = console.log; | ||
var logger = { http, info, warn, error, log }; | ||
// source/utilities/server.ts | ||
@@ -176,2 +177,8 @@ var compress = promisify(compression()); | ||
const run = async () => { | ||
const requestTime = new Date(); | ||
const formattedTime = `${requestTime.toLocaleDateString()} ${requestTime.toLocaleTimeString()}`; | ||
const ipAddress = request.socket.remoteAddress?.replace("::ffff:", "") ?? "unknown"; | ||
const requestUrl = `${request.method ?? "GET"} ${request.url ?? "/"}`; | ||
if (!args2["--no-request-logging"]) | ||
logger.http(chalk2.dim(formattedTime), chalk2.yellow(ipAddress), chalk2.cyan(requestUrl)); | ||
if (args2["--cors"]) | ||
@@ -182,2 +189,5 @@ response.setHeader("Access-Control-Allow-Origin", "*"); | ||
await handler(request, response, config2); | ||
const responseTime = Date.now() - requestTime.getTime(); | ||
if (!args2["--no-request-logging"]) | ||
logger.http(chalk2.dim(formattedTime), chalk2.yellow(ipAddress), chalk2[response.statusCode < 400 ? "green" : "red"](`Returned ${response.statusCode} in ${responseTime} ms`)); | ||
}; | ||
@@ -188,11 +198,21 @@ run().catch((error2) => { | ||
}; | ||
const useSsl = args2["--ssl-cert"] && args2["--ssl-key"]; | ||
const httpMode = useSsl ? "https" : "http"; | ||
const sslCert = args2["--ssl-cert"]; | ||
const sslKey = args2["--ssl-key"]; | ||
const sslPass = args2["--ssl-pass"]; | ||
const serverConfig = httpMode === "https" && args2["--ssl-cert"] && args2["--ssl-key"] ? { | ||
key: await readFile(args2["--ssl-key"]), | ||
cert: await readFile(args2["--ssl-cert"]), | ||
passphrase: sslPass ? await readFile(sslPass, "utf8") : "" | ||
} : {}; | ||
const server = httpMode === "https" ? https.createServer(serverConfig, serverHandler) : http.createServer(serverHandler); | ||
const isPFXFormat = sslCert && /[.](?<extension>pfx|p12)$/.exec(sslCert) !== null; | ||
const useSsl = sslCert && (sslKey || sslPass || isPFXFormat); | ||
let serverConfig = {}; | ||
if (useSsl && sslCert && sslKey) { | ||
serverConfig = { | ||
key: await readFile(sslKey), | ||
cert: await readFile(sslCert), | ||
passphrase: sslPass ? await readFile(sslPass, "utf8") : "" | ||
}; | ||
} else if (useSsl && sslCert && isPFXFormat) { | ||
serverConfig = { | ||
pfx: await readFile(sslCert), | ||
passphrase: sslPass ? await readFile(sslPass, "utf8") : "" | ||
}; | ||
} | ||
const server = useSsl ? https.createServer(serverConfig, serverHandler) : http2.createServer(serverHandler); | ||
const getServerDetails = () => { | ||
@@ -214,4 +234,5 @@ registerCloseListener(() => server.close()); | ||
const ip = getNetworkAddress(); | ||
local = `${httpMode}://${address}:${details.port}`; | ||
network = ip ? `${httpMode}://${ip}:${details.port}` : void 0; | ||
const protocol = useSsl ? "https" : "http"; | ||
local = `${protocol}://${address}:${details.port}`; | ||
network = ip ? `${protocol}://${ip}:${details.port}` : void 0; | ||
} | ||
@@ -227,17 +248,17 @@ return { | ||
}); | ||
if (typeof endpoint[0] === "number" && !isNaN(endpoint[0]) && endpoint[0] !== 0) { | ||
const port = endpoint[0]; | ||
if (typeof endpoint.port === "number" && !isNaN(endpoint.port) && endpoint.port !== 0) { | ||
const port = endpoint.port; | ||
const isClosed = await isPortReachable(port, { | ||
host: endpoint[1] ?? "localhost" | ||
host: endpoint.host ?? "localhost" | ||
}); | ||
if (isClosed) | ||
return startServer([0], config2, args2, port); | ||
return startServer({ port: 0 }, config2, args2, port); | ||
} | ||
return new Promise((resolve2, _reject) => { | ||
if (endpoint.length === 1 && typeof endpoint[0] === "number") | ||
server.listen(endpoint[0], () => resolve2(getServerDetails())); | ||
else if (endpoint.length === 1 && typeof endpoint[0] === "string") | ||
server.listen(endpoint[0], () => resolve2(getServerDetails())); | ||
else if (endpoint.length === 2 && typeof endpoint[0] === "number" && typeof endpoint[1] === "string") | ||
server.listen(endpoint[0], endpoint[1], () => resolve2(getServerDetails())); | ||
if (typeof endpoint.port !== "undefined" && typeof endpoint.host === "undefined") | ||
server.listen(endpoint.port, () => resolve2(getServerDetails())); | ||
else if (typeof endpoint.port === "undefined" && typeof endpoint.host !== "undefined") | ||
server.listen(endpoint.host, () => resolve2(getServerDetails())); | ||
else if (typeof endpoint.port !== "undefined" && typeof endpoint.host !== "undefined") | ||
server.listen(endpoint.port, endpoint.host, () => resolve2(getServerDetails())); | ||
}); | ||
@@ -247,33 +268,9 @@ }; | ||
// source/utilities/cli.ts | ||
import chalk from "chalk-template"; | ||
import { parse as parseUrl } from "node:url"; | ||
import { env } from "node:process"; | ||
import chalk3 from "chalk"; | ||
import chalkTemplate from "chalk-template"; | ||
import parseArgv from "arg"; | ||
var options = { | ||
"--help": Boolean, | ||
"--version": Boolean, | ||
"--listen": [parseEndpoint], | ||
"--single": Boolean, | ||
"--debug": Boolean, | ||
"--config": String, | ||
"--no-clipboard": Boolean, | ||
"--no-compression": Boolean, | ||
"--no-etag": Boolean, | ||
"--symlinks": Boolean, | ||
"--cors": Boolean, | ||
"--no-port-switching": Boolean, | ||
"--ssl-cert": String, | ||
"--ssl-key": String, | ||
"--ssl-pass": String, | ||
"-h": "--help", | ||
"-v": "--version", | ||
"-l": "--listen", | ||
"-s": "--single", | ||
"-d": "--debug", | ||
"-c": "--config", | ||
"-n": "--no-clipboard", | ||
"-u": "--no-compression", | ||
"-S": "--symlinks", | ||
"-C": "--cors", | ||
"-p": "--listen" | ||
}; | ||
var helpText = chalk` | ||
import checkForUpdate from "update-check"; | ||
var helpText = chalkTemplate` | ||
{bold.cyan serve} - Static file serving and directory listing | ||
@@ -304,8 +301,10 @@ | ||
-s, --single Rewrite all not-found requests to \`index.html\` | ||
-d, --debug Show debugging information | ||
-s, --single Rewrite all not-found requests to \`index.html\` | ||
-c, --config Specify custom path to \`serve.json\` | ||
-L, --no-request-logging Do not log any request information to the console. | ||
-C, --cors Enable CORS, sets \`Access-Control-Allow-Origin\` to \`*\` | ||
@@ -322,4 +321,6 @@ | ||
--ssl-cert Optional path to an SSL/TLS certificate to serve with HTTPS | ||
{grey Supported formats: PEM (default) and PKCS12 (PFX)} | ||
--ssl-key Optional path to the SSL/TLS certificate\'s private key | ||
{grey Applicable only for PEM certificates} | ||
@@ -351,4 +352,69 @@ --ssl-pass Optional path to the SSL/TLS certificate\'s passphrase | ||
`; | ||
var getHelpText = () => helpText; | ||
var parseEndpoint = (uriOrPort) => { | ||
if (!isNaN(Number(uriOrPort))) | ||
return { port: Number(uriOrPort) }; | ||
const endpoint = uriOrPort; | ||
const url = parseUrl(endpoint); | ||
switch (url.protocol) { | ||
case "pipe:": { | ||
const pipe = endpoint.replace(/^pipe:/, ""); | ||
if (!pipe.startsWith("\\\\.\\")) | ||
throw new Error(`Invalid Windows named pipe endpoint: ${endpoint}`); | ||
return { host: pipe }; | ||
} | ||
case "unix:": | ||
if (!url.pathname) | ||
throw new Error(`Invalid UNIX domain socket endpoint: ${endpoint}`); | ||
return { host: url.pathname }; | ||
case "tcp:": | ||
url.port = url.port ?? "3000"; | ||
url.hostname = url.hostname ?? "localhost"; | ||
return { | ||
port: Number(url.port), | ||
host: url.hostname | ||
}; | ||
default: | ||
throw new Error(`Unknown --listen endpoint scheme (protocol): ${url.protocol ?? "undefined"}`); | ||
} | ||
}; | ||
var options = { | ||
"--help": Boolean, | ||
"--version": Boolean, | ||
"--listen": [parseEndpoint], | ||
"--single": Boolean, | ||
"--debug": Boolean, | ||
"--config": String, | ||
"--no-clipboard": Boolean, | ||
"--no-compression": Boolean, | ||
"--no-etag": Boolean, | ||
"--symlinks": Boolean, | ||
"--cors": Boolean, | ||
"--no-port-switching": Boolean, | ||
"--ssl-cert": String, | ||
"--ssl-key": String, | ||
"--ssl-pass": String, | ||
"-h": "--help", | ||
"-v": "--version", | ||
"-l": "--listen", | ||
"-s": "--single", | ||
"-d": "--debug", | ||
"-c": "--config", | ||
"-n": "--no-clipboard", | ||
"-u": "--no-compression", | ||
"-S": "--symlinks", | ||
"-C": "--cors", | ||
"-p": "--listen" | ||
}; | ||
var parseArguments = () => parseArgv(options); | ||
var getHelpText = () => helpText; | ||
var checkForUpdates = async (manifest) => { | ||
if (env.NO_UPDATE_CHECK) | ||
return; | ||
const [error2, update] = await resolve(checkForUpdate(manifest)); | ||
if (error2) | ||
throw error2; | ||
if (!update) | ||
return; | ||
logger.log(chalk3.bgRed.white(" UPDATE "), `The latest version of \`serve\` is ${update.latest}`); | ||
}; | ||
@@ -363,3 +429,3 @@ // source/utilities/config.ts | ||
import schema from "@zeit/schemas/deployment/config-static.js"; | ||
var loadConfiguration = async (cwd2, entry2, args2) => { | ||
var loadConfiguration = async (presentDirectory2, directoryToServe2, args2) => { | ||
const files = ["serve.json", "now.json", "package.json"]; | ||
@@ -370,3 +436,3 @@ if (args2["--config"]) | ||
for (const file of files) { | ||
const location = resolvePath(entry2, file); | ||
const location = resolvePath(directoryToServe2, file); | ||
const [error2, rawContents] = await resolve(readFile2(location, "utf8")); | ||
@@ -397,7 +463,9 @@ if (error2) { | ||
Object.assign(config2, parsedJson); | ||
if (file === "now.json" || file === "package.json") | ||
logger.warn("The config files `now.json` and `package.json` are deprecated. Please use `serve.json`."); | ||
break; | ||
} | ||
if (entry2) { | ||
if (directoryToServe2) { | ||
const staticDirectory = config2.public; | ||
config2.public = resolveRelativePath(cwd2, staticDirectory ? resolvePath(entry2, staticDirectory) : entry2); | ||
config2.public = resolveRelativePath(presentDirectory2, staticDirectory ? resolvePath(directoryToServe2, staticDirectory) : directoryToServe2); | ||
} | ||
@@ -420,53 +488,36 @@ if (Object.keys(config2).length !== 0) { | ||
// source/utilities/logger.ts | ||
import chalk2 from "chalk"; | ||
var info = (...message) => console.error(chalk2.magenta("INFO:", ...message)); | ||
var warn = (...message) => console.error(chalk2.yellow("WARNING:", ...message)); | ||
var error = (...message) => console.error(chalk2.red("ERROR:", ...message)); | ||
var log = console.log; | ||
var logger = { info, warn, error, log }; | ||
// source/main.ts | ||
var printUpdateNotification = async (debugMode) => { | ||
const [error2, update] = await resolve(checkForUpdate(package_default)); | ||
if (error2) { | ||
const suffix = debugMode ? ":" : " (use `--debug` to see full error)."; | ||
logger.warn(`Checking for updates failed${suffix}`); | ||
if (debugMode) | ||
logger.error(error2.message); | ||
} | ||
if (!update) | ||
return; | ||
logger.log(chalk3.bgRed.white(" UPDATE "), `The latest version of \`serve\` is ${update.latest}.`); | ||
}; | ||
var args; | ||
try { | ||
args = parseArguments(); | ||
} catch (error2) { | ||
logger.error(error2.message); | ||
process.exit(1); | ||
var [parseError, args] = await resolve(parseArguments()); | ||
if (parseError || !args) { | ||
logger.error(parseError.message); | ||
exit(1); | ||
} | ||
if (process.env.NO_UPDATE_CHECK !== "1") | ||
await printUpdateNotification(args["--debug"]); | ||
var [updateError] = await resolve(checkForUpdates(package_default)); | ||
if (updateError) { | ||
const suffix = args["--debug"] ? ":" : " (use `--debug` to see full error)"; | ||
logger.warn(`Checking for updates failed${suffix}`); | ||
if (args["--debug"]) | ||
logger.error(updateError.message); | ||
} | ||
if (args["--version"]) { | ||
logger.log(package_default.version); | ||
process.exit(0); | ||
exit(0); | ||
} | ||
if (args["--help"]) { | ||
logger.log(getHelpText()); | ||
process.exit(0); | ||
exit(0); | ||
} | ||
if (!args["--listen"]) | ||
args["--listen"] = [ | ||
[process.env.PORT ? parseInt(process.env.PORT, 10) : 3e3] | ||
]; | ||
args["--listen"] = [{ port: parseInt(env2.PORT ?? "3000", 10) }]; | ||
if (args._.length > 1) { | ||
logger.error("Please provide one path argument at maximum"); | ||
process.exit(1); | ||
exit(1); | ||
} | ||
if (args["--config"] === "now.json" || args["--config"] === "package.json") | ||
logger.warn("The config files `now.json` and `package.json` are deprecated. Please use `serve.json`."); | ||
var cwd = process.cwd(); | ||
var entry = args._[0] ? path.resolve(args._[0]) : cwd; | ||
var config = await loadConfiguration(cwd, entry, args); | ||
var presentDirectory = getPwd(); | ||
var directoryToServe = args._[0] ? path.resolve(args._[0]) : presentDirectory; | ||
var [configError, config] = await resolve(loadConfiguration(presentDirectory, directoryToServe, args)); | ||
if (configError || !config) { | ||
logger.error(configError.message); | ||
exit(1); | ||
} | ||
if (args["--single"]) { | ||
@@ -486,22 +537,22 @@ const { rewrites } = config; | ||
const copyAddress = !args["--no-clipboard"]; | ||
if (!process.stdout.isTTY || process.env.NODE_ENV === "production") { | ||
const suffix = local ? ` at ${local}.` : "."; | ||
if (!stdout.isTTY || env2.NODE_ENV === "production") { | ||
const suffix = local ? ` at ${local}` : ""; | ||
logger.info(`Accepting connections${suffix}`); | ||
continue; | ||
} | ||
let message = chalk3.green("Serving!"); | ||
let message = chalk4.green("Serving!"); | ||
if (local) { | ||
const prefix = network ? "- " : ""; | ||
const space = network ? " " : " "; | ||
const space = network ? " " : " "; | ||
message += ` | ||
${chalk3.bold(`${prefix}Local:`)}${space}${local}`; | ||
${chalk4.bold(`${prefix}Local:`)}${space}${local}`; | ||
} | ||
if (network) | ||
message += ` | ||
${chalk3.bold("- On Your Network:")} ${network}`; | ||
${chalk4.bold("- Network:")} ${network}`; | ||
if (previous) | ||
message += chalk3.red(` | ||
message += chalk4.red(` | ||
This port was picked because ${chalk3.underline(previous.toString())} is in use.`); | ||
This port was picked because ${chalk4.underline(previous.toString())} is in use.`); | ||
if (copyAddress && local) { | ||
@@ -512,3 +563,3 @@ try { | ||
${chalk3.grey("Copied local address to clipboard!")}`; | ||
${chalk4.grey("Copied local address to clipboard!")}`; | ||
} catch (error2) { | ||
@@ -530,4 +581,4 @@ logger.error(`Cannot copy server address to clipboard: ${error2.message}.`); | ||
logger.warn("Force-closing all open sockets..."); | ||
process.exit(0); | ||
exit(0); | ||
}); | ||
}); |
{ | ||
"name": "serve", | ||
"version": "14.0.1", | ||
"version": "14.1.0", | ||
"description": "Static file serving and directory listing", | ||
@@ -23,14 +23,2 @@ "keywords": [ | ||
}, | ||
"scripts": { | ||
"develop": "tsx watch ./source/main.ts", | ||
"start": "node ./build/main.js", | ||
"compile": "tsup ./source/main.ts", | ||
"test:tsc": "tsc --project tsconfig.json", | ||
"test": "pnpm test:tsc", | ||
"lint:code": "eslint --max-warnings 0 source/**/*.ts", | ||
"lint:style": "prettier --check --ignore-path .gitignore .", | ||
"lint": "pnpm lint:code && pnpm lint:style", | ||
"format": "prettier --write --ignore-path .gitignore .", | ||
"prepare": "husky install config/husky && pnpm compile" | ||
}, | ||
"dependencies": { | ||
@@ -41,2 +29,3 @@ "@zeit/schemas": "2.21.0", | ||
"boxen": "7.0.0", | ||
"c8": "7.11.3", | ||
"chalk": "5.0.1", | ||
@@ -47,3 +36,3 @@ "chalk-template": "0.4.0", | ||
"is-port-reachable": "4.0.0", | ||
"serve-handler": "6.1.3", | ||
"serve-handler": "6.1.5", | ||
"update-check": "1.5.4" | ||
@@ -56,2 +45,3 @@ }, | ||
"eslint": "8.19.0", | ||
"got": "12.1.0", | ||
"husky": "8.0.1", | ||
@@ -62,3 +52,4 @@ "lint-staged": "13.0.3", | ||
"tsx": "3.7.1", | ||
"typescript": "4.6.4" | ||
"typescript": "4.6.4", | ||
"vitest": "0.18.0" | ||
}, | ||
@@ -87,5 +78,22 @@ "tsup": { | ||
"source/**/*.ts": [ | ||
"eslint --max-warnings 0 --fix" | ||
"eslint --max-warnings 0 --fix", | ||
"vitest related --run" | ||
], | ||
"tests": [ | ||
"vitest --run" | ||
] | ||
}, | ||
"scripts": { | ||
"develop": "tsx watch ./source/main.ts", | ||
"start": "node ./build/main.js", | ||
"compile": "tsup ./source/main.ts", | ||
"test:tsc": "tsc --project tsconfig.json", | ||
"test:unit": "vitest run --config config/vitest.ts", | ||
"test:watch": "vitest watch --config config/vitest.ts", | ||
"test": "pnpm test:tsc && pnpm test:unit", | ||
"lint:code": "eslint --max-warnings 0 source/**/*.ts", | ||
"lint:style": "prettier --check --ignore-path .gitignore .", | ||
"lint": "pnpm lint:code && pnpm lint:style", | ||
"format": "prettier --write --ignore-path .gitignore ." | ||
} | ||
} | ||
} |
@@ -29,2 +29,4 @@ ![Serve Logo](https://raw.githubusercontent.com/vercel/serve/main/media/banner.png) | ||
> `serve` v14 onwards requires Node v14 to run. Please use `serve` v13 if you cannot upgrade to Node v14. | ||
The quickest way to get started is to just run `npx serve` in your project's directory. | ||
@@ -64,3 +66,3 @@ | ||
The core of `serve` is [serve-handler](https://github.com/vercel/serve-handler), which can be used as middleware in existing HTTP servers: | ||
The core of `serve` is [`serve-handler`](https://github.com/vercel/serve-handler), which can be used as middleware in existing HTTP servers: | ||
@@ -82,5 +84,3 @@ ```js | ||
> **Note** | ||
> | ||
> You can also replace `http.createServer` with [micro](https://github.com/vercel/micro). | ||
> You can also replace `http.createServer` with [`micro`](https://github.com/vercel/micro). | ||
@@ -95,3 +95,3 @@ ## Issues and Contributing | ||
This project used to be called "list" and "micro-list". But thanks to [TJ Holowaychuk](https://github.com/tj) handing us the new name, it's now called "serve" (which is much more definite). | ||
This project used to be called `list` and `micro-list`. But thanks to [TJ Holowaychuk](https://github.com/tj) handing us the new name, it's now called `serve` (which is much more definite). | ||
@@ -98,0 +98,0 @@ ## Author |
New author
Supply chain riskA new npm collaborator published a version of the package for the first time. New collaborators are usually benign additions to a project, but do indicate a change to the security surface area of a package.
Found 1 instance in 1 package
Environment variable access
Supply chain riskPackage accesses environment variables, which may be a sign of credential stuffing or data theft.
Found 3 instances in 1 package
24772
513
1
12
12
1
+ Addedc8@7.11.3
+ Added@bcoe/v8-coverage@0.2.3(transitive)
+ Added@istanbuljs/schema@0.1.3(transitive)
+ Added@jridgewell/resolve-uri@3.1.2(transitive)
+ Added@jridgewell/sourcemap-codec@1.5.0(transitive)
+ Added@jridgewell/trace-mapping@0.3.25(transitive)
+ Added@types/istanbul-lib-coverage@2.0.6(transitive)
+ Addedc8@7.11.3(transitive)
+ Addedcliui@7.0.4(transitive)
+ Addedconvert-source-map@2.0.0(transitive)
+ Addedescalade@3.1.2(transitive)
+ Addedfind-up@5.0.0(transitive)
+ Addedforeground-child@2.0.0(transitive)
+ Addedfs.realpath@1.0.0(transitive)
+ Addedget-caller-file@2.0.5(transitive)
+ Addedglob@7.2.3(transitive)
+ Addedhtml-escaper@2.0.2(transitive)
+ Addedinflight@1.0.6(transitive)
+ Addedinherits@2.0.4(transitive)
+ Addedistanbul-lib-coverage@3.2.2(transitive)
+ Addedistanbul-lib-report@3.0.1(transitive)
+ Addedistanbul-reports@3.1.7(transitive)
+ Addedlocate-path@6.0.0(transitive)
+ Addedmake-dir@4.0.0(transitive)
+ Addedminimatch@3.1.2(transitive)
+ Addedonce@1.4.0(transitive)
+ Addedp-limit@3.1.0(transitive)
+ Addedp-locate@5.0.0(transitive)
+ Addedpath-exists@4.0.0(transitive)
+ Addedpath-is-absolute@1.0.1(transitive)
+ Addedrequire-directory@2.1.1(transitive)
+ Addedrimraf@3.0.2(transitive)
+ Addedsemver@7.6.3(transitive)
+ Addedserve-handler@6.1.5(transitive)
+ Addedtest-exclude@6.0.0(transitive)
+ Addedv8-to-istanbul@9.3.0(transitive)
+ Addedwrap-ansi@7.0.0(transitive)
+ Addedwrappy@1.0.2(transitive)
+ Addedy18n@5.0.8(transitive)
+ Addedyargs@16.2.0(transitive)
+ Addedyargs-parser@20.2.9(transitive)
+ Addedyocto-queue@0.1.0(transitive)
- Removedminimatch@3.0.4(transitive)
- Removedserve-handler@6.1.3(transitive)
Updatedserve-handler@6.1.5