Skip to content

Instantly share code, notes, and snippets.

@wperron
Created February 16, 2021 18:20
Show Gist options
  • Save wperron/b332352f3efcce07971f25c44520658a to your computer and use it in GitHub Desktop.
Save wperron/b332352f3efcce07971f25c44520658a to your computer and use it in GitHub Desktop.
Deno Run Esbuild output
#!/usr/bin/env -S deno run --allow-net --allow-read
(() => {
var __defProp = Object.defineProperty;
var __export = (target2, all) => {
for (var name in all)
__defProp(target2, name, {get: all[name], enumerable: true});
};
// _util/os.ts
var osType = (() => {
if (globalThis.Deno != null) {
return Deno.build.os;
}
const navigator = globalThis.navigator;
if (navigator?.appVersion?.includes?.("Win") ?? false) {
return "windows";
}
return "linux";
})();
var isWindows = osType === "windows";
// path/win32.ts
var win32_exports = {};
__export(win32_exports, {
basename: () => basename,
delimiter: () => delimiter,
dirname: () => dirname,
extname: () => extname,
format: () => format,
fromFileUrl: () => fromFileUrl,
isAbsolute: () => isAbsolute,
join: () => join,
normalize: () => normalize,
parse: () => parse,
relative: () => relative,
resolve: () => resolve,
sep: () => sep,
toFileUrl: () => toFileUrl,
toNamespacedPath: () => toNamespacedPath
});
// path/_constants.ts
var CHAR_UPPERCASE_A = 65;
var CHAR_LOWERCASE_A = 97;
var CHAR_UPPERCASE_Z = 90;
var CHAR_LOWERCASE_Z = 122;
var CHAR_DOT = 46;
var CHAR_FORWARD_SLASH = 47;
var CHAR_BACKWARD_SLASH = 92;
var CHAR_COLON = 58;
var CHAR_QUESTION_MARK = 63;
// path/_util.ts
function assertPath(path2) {
if (typeof path2 !== "string") {
throw new TypeError(`Path must be a string. Received ${JSON.stringify(path2)}`);
}
}
function isPosixPathSeparator(code) {
return code === CHAR_FORWARD_SLASH;
}
function isPathSeparator(code) {
return isPosixPathSeparator(code) || code === CHAR_BACKWARD_SLASH;
}
function isWindowsDeviceRoot(code) {
return code >= CHAR_LOWERCASE_A && code <= CHAR_LOWERCASE_Z || code >= CHAR_UPPERCASE_A && code <= CHAR_UPPERCASE_Z;
}
function normalizeString(path2, allowAboveRoot, separator, isPathSeparator2) {
let res = "";
let lastSegmentLength = 0;
let lastSlash = -1;
let dots = 0;
let code;
for (let i = 0, len = path2.length; i <= len; ++i) {
if (i < len)
code = path2.charCodeAt(i);
else if (isPathSeparator2(code))
break;
else
code = CHAR_FORWARD_SLASH;
if (isPathSeparator2(code)) {
if (lastSlash === i - 1 || dots === 1) {
} else if (lastSlash !== i - 1 && dots === 2) {
if (res.length < 2 || lastSegmentLength !== 2 || res.charCodeAt(res.length - 1) !== CHAR_DOT || res.charCodeAt(res.length - 2) !== CHAR_DOT) {
if (res.length > 2) {
const lastSlashIndex = res.lastIndexOf(separator);
if (lastSlashIndex === -1) {
res = "";
lastSegmentLength = 0;
} else {
res = res.slice(0, lastSlashIndex);
lastSegmentLength = res.length - 1 - res.lastIndexOf(separator);
}
lastSlash = i;
dots = 0;
continue;
} else if (res.length === 2 || res.length === 1) {
res = "";
lastSegmentLength = 0;
lastSlash = i;
dots = 0;
continue;
}
}
if (allowAboveRoot) {
if (res.length > 0)
res += `${separator}..`;
else
res = "..";
lastSegmentLength = 2;
}
} else {
if (res.length > 0)
res += separator + path2.slice(lastSlash + 1, i);
else
res = path2.slice(lastSlash + 1, i);
lastSegmentLength = i - lastSlash - 1;
}
lastSlash = i;
dots = 0;
} else if (code === CHAR_DOT && dots !== -1) {
++dots;
} else {
dots = -1;
}
}
return res;
}
function _format(sep4, pathObject) {
const dir = pathObject.dir || pathObject.root;
const base = pathObject.base || (pathObject.name || "") + (pathObject.ext || "");
if (!dir)
return base;
if (dir === pathObject.root)
return dir + base;
return dir + sep4 + base;
}
// _util/assert.ts
var DenoStdInternalError = class extends Error {
constructor(message) {
super(message);
this.name = "DenoStdInternalError";
}
};
function assert(expr, msg = "") {
if (!expr) {
throw new DenoStdInternalError(msg);
}
}
// path/win32.ts
var sep = "\\";
var delimiter = ";";
function resolve(...pathSegments) {
let resolvedDevice = "";
let resolvedTail = "";
let resolvedAbsolute = false;
for (let i = pathSegments.length - 1; i >= -1; i--) {
let path2;
if (i >= 0) {
path2 = pathSegments[i];
} else if (!resolvedDevice) {
if (globalThis.Deno == null) {
throw new TypeError("Resolved a drive-letter-less path without a CWD.");
}
path2 = Deno.cwd();
} else {
if (globalThis.Deno == null) {
throw new TypeError("Resolved a relative path without a CWD.");
}
path2 = Deno.env.get(`=${resolvedDevice}`) || Deno.cwd();
if (path2 === void 0 || path2.slice(0, 3).toLowerCase() !== `${resolvedDevice.toLowerCase()}\\`) {
path2 = `${resolvedDevice}\\`;
}
}
assertPath(path2);
const len = path2.length;
if (len === 0)
continue;
let rootEnd = 0;
let device = "";
let isAbsolute4 = false;
const code = path2.charCodeAt(0);
if (len > 1) {
if (isPathSeparator(code)) {
isAbsolute4 = true;
if (isPathSeparator(path2.charCodeAt(1))) {
let j = 2;
let last = j;
for (; j < len; ++j) {
if (isPathSeparator(path2.charCodeAt(j)))
break;
}
if (j < len && j !== last) {
const firstPart = path2.slice(last, j);
last = j;
for (; j < len; ++j) {
if (!isPathSeparator(path2.charCodeAt(j)))
break;
}
if (j < len && j !== last) {
last = j;
for (; j < len; ++j) {
if (isPathSeparator(path2.charCodeAt(j)))
break;
}
if (j === len) {
device = `\\\\${firstPart}\\${path2.slice(last)}`;
rootEnd = j;
} else if (j !== last) {
device = `\\\\${firstPart}\\${path2.slice(last, j)}`;
rootEnd = j;
}
}
}
} else {
rootEnd = 1;
}
} else if (isWindowsDeviceRoot(code)) {
if (path2.charCodeAt(1) === CHAR_COLON) {
device = path2.slice(0, 2);
rootEnd = 2;
if (len > 2) {
if (isPathSeparator(path2.charCodeAt(2))) {
isAbsolute4 = true;
rootEnd = 3;
}
}
}
}
} else if (isPathSeparator(code)) {
rootEnd = 1;
isAbsolute4 = true;
}
if (device.length > 0 && resolvedDevice.length > 0 && device.toLowerCase() !== resolvedDevice.toLowerCase()) {
continue;
}
if (resolvedDevice.length === 0 && device.length > 0) {
resolvedDevice = device;
}
if (!resolvedAbsolute) {
resolvedTail = `${path2.slice(rootEnd)}\\${resolvedTail}`;
resolvedAbsolute = isAbsolute4;
}
if (resolvedAbsolute && resolvedDevice.length > 0)
break;
}
resolvedTail = normalizeString(resolvedTail, !resolvedAbsolute, "\\", isPathSeparator);
return resolvedDevice + (resolvedAbsolute ? "\\" : "") + resolvedTail || ".";
}
function normalize(path2) {
assertPath(path2);
const len = path2.length;
if (len === 0)
return ".";
let rootEnd = 0;
let device;
let isAbsolute4 = false;
const code = path2.charCodeAt(0);
if (len > 1) {
if (isPathSeparator(code)) {
isAbsolute4 = true;
if (isPathSeparator(path2.charCodeAt(1))) {
let j = 2;
let last = j;
for (; j < len; ++j) {
if (isPathSeparator(path2.charCodeAt(j)))
break;
}
if (j < len && j !== last) {
const firstPart = path2.slice(last, j);
last = j;
for (; j < len; ++j) {
if (!isPathSeparator(path2.charCodeAt(j)))
break;
}
if (j < len && j !== last) {
last = j;
for (; j < len; ++j) {
if (isPathSeparator(path2.charCodeAt(j)))
break;
}
if (j === len) {
return `\\\\${firstPart}\\${path2.slice(last)}\\`;
} else if (j !== last) {
device = `\\\\${firstPart}\\${path2.slice(last, j)}`;
rootEnd = j;
}
}
}
} else {
rootEnd = 1;
}
} else if (isWindowsDeviceRoot(code)) {
if (path2.charCodeAt(1) === CHAR_COLON) {
device = path2.slice(0, 2);
rootEnd = 2;
if (len > 2) {
if (isPathSeparator(path2.charCodeAt(2))) {
isAbsolute4 = true;
rootEnd = 3;
}
}
}
}
} else if (isPathSeparator(code)) {
return "\\";
}
let tail;
if (rootEnd < len) {
tail = normalizeString(path2.slice(rootEnd), !isAbsolute4, "\\", isPathSeparator);
} else {
tail = "";
}
if (tail.length === 0 && !isAbsolute4)
tail = ".";
if (tail.length > 0 && isPathSeparator(path2.charCodeAt(len - 1))) {
tail += "\\";
}
if (device === void 0) {
if (isAbsolute4) {
if (tail.length > 0)
return `\\${tail}`;
else
return "\\";
} else if (tail.length > 0) {
return tail;
} else {
return "";
}
} else if (isAbsolute4) {
if (tail.length > 0)
return `${device}\\${tail}`;
else
return `${device}\\`;
} else if (tail.length > 0) {
return device + tail;
} else {
return device;
}
}
function isAbsolute(path2) {
assertPath(path2);
const len = path2.length;
if (len === 0)
return false;
const code = path2.charCodeAt(0);
if (isPathSeparator(code)) {
return true;
} else if (isWindowsDeviceRoot(code)) {
if (len > 2 && path2.charCodeAt(1) === CHAR_COLON) {
if (isPathSeparator(path2.charCodeAt(2)))
return true;
}
}
return false;
}
function join(...paths) {
const pathsCount = paths.length;
if (pathsCount === 0)
return ".";
let joined;
let firstPart = null;
for (let i = 0; i < pathsCount; ++i) {
const path2 = paths[i];
assertPath(path2);
if (path2.length > 0) {
if (joined === void 0)
joined = firstPart = path2;
else
joined += `\\${path2}`;
}
}
if (joined === void 0)
return ".";
let needsReplace = true;
let slashCount = 0;
assert(firstPart != null);
if (isPathSeparator(firstPart.charCodeAt(0))) {
++slashCount;
const firstLen = firstPart.length;
if (firstLen > 1) {
if (isPathSeparator(firstPart.charCodeAt(1))) {
++slashCount;
if (firstLen > 2) {
if (isPathSeparator(firstPart.charCodeAt(2)))
++slashCount;
else {
needsReplace = false;
}
}
}
}
}
if (needsReplace) {
for (; slashCount < joined.length; ++slashCount) {
if (!isPathSeparator(joined.charCodeAt(slashCount)))
break;
}
if (slashCount >= 2)
joined = `\\${joined.slice(slashCount)}`;
}
return normalize(joined);
}
function relative(from, to) {
assertPath(from);
assertPath(to);
if (from === to)
return "";
const fromOrig = resolve(from);
const toOrig = resolve(to);
if (fromOrig === toOrig)
return "";
from = fromOrig.toLowerCase();
to = toOrig.toLowerCase();
if (from === to)
return "";
let fromStart = 0;
let fromEnd = from.length;
for (; fromStart < fromEnd; ++fromStart) {
if (from.charCodeAt(fromStart) !== CHAR_BACKWARD_SLASH)
break;
}
for (; fromEnd - 1 > fromStart; --fromEnd) {
if (from.charCodeAt(fromEnd - 1) !== CHAR_BACKWARD_SLASH)
break;
}
const fromLen = fromEnd - fromStart;
let toStart = 0;
let toEnd = to.length;
for (; toStart < toEnd; ++toStart) {
if (to.charCodeAt(toStart) !== CHAR_BACKWARD_SLASH)
break;
}
for (; toEnd - 1 > toStart; --toEnd) {
if (to.charCodeAt(toEnd - 1) !== CHAR_BACKWARD_SLASH)
break;
}
const toLen = toEnd - toStart;
const length = fromLen < toLen ? fromLen : toLen;
let lastCommonSep = -1;
let i = 0;
for (; i <= length; ++i) {
if (i === length) {
if (toLen > length) {
if (to.charCodeAt(toStart + i) === CHAR_BACKWARD_SLASH) {
return toOrig.slice(toStart + i + 1);
} else if (i === 2) {
return toOrig.slice(toStart + i);
}
}
if (fromLen > length) {
if (from.charCodeAt(fromStart + i) === CHAR_BACKWARD_SLASH) {
lastCommonSep = i;
} else if (i === 2) {
lastCommonSep = 3;
}
}
break;
}
const fromCode = from.charCodeAt(fromStart + i);
const toCode = to.charCodeAt(toStart + i);
if (fromCode !== toCode)
break;
else if (fromCode === CHAR_BACKWARD_SLASH)
lastCommonSep = i;
}
if (i !== length && lastCommonSep === -1) {
return toOrig;
}
let out = "";
if (lastCommonSep === -1)
lastCommonSep = 0;
for (i = fromStart + lastCommonSep + 1; i <= fromEnd; ++i) {
if (i === fromEnd || from.charCodeAt(i) === CHAR_BACKWARD_SLASH) {
if (out.length === 0)
out += "..";
else
out += "\\..";
}
}
if (out.length > 0) {
return out + toOrig.slice(toStart + lastCommonSep, toEnd);
} else {
toStart += lastCommonSep;
if (toOrig.charCodeAt(toStart) === CHAR_BACKWARD_SLASH)
++toStart;
return toOrig.slice(toStart, toEnd);
}
}
function toNamespacedPath(path2) {
if (typeof path2 !== "string")
return path2;
if (path2.length === 0)
return "";
const resolvedPath = resolve(path2);
if (resolvedPath.length >= 3) {
if (resolvedPath.charCodeAt(0) === CHAR_BACKWARD_SLASH) {
if (resolvedPath.charCodeAt(1) === CHAR_BACKWARD_SLASH) {
const code = resolvedPath.charCodeAt(2);
if (code !== CHAR_QUESTION_MARK && code !== CHAR_DOT) {
return `\\\\?\\UNC\\${resolvedPath.slice(2)}`;
}
}
} else if (isWindowsDeviceRoot(resolvedPath.charCodeAt(0))) {
if (resolvedPath.charCodeAt(1) === CHAR_COLON && resolvedPath.charCodeAt(2) === CHAR_BACKWARD_SLASH) {
return `\\\\?\\${resolvedPath}`;
}
}
}
return path2;
}
function dirname(path2) {
assertPath(path2);
const len = path2.length;
if (len === 0)
return ".";
let rootEnd = -1;
let end = -1;
let matchedSlash = true;
let offset = 0;
const code = path2.charCodeAt(0);
if (len > 1) {
if (isPathSeparator(code)) {
rootEnd = offset = 1;
if (isPathSeparator(path2.charCodeAt(1))) {
let j = 2;
let last = j;
for (; j < len; ++j) {
if (isPathSeparator(path2.charCodeAt(j)))
break;
}
if (j < len && j !== last) {
last = j;
for (; j < len; ++j) {
if (!isPathSeparator(path2.charCodeAt(j)))
break;
}
if (j < len && j !== last) {
last = j;
for (; j < len; ++j) {
if (isPathSeparator(path2.charCodeAt(j)))
break;
}
if (j === len) {
return path2;
}
if (j !== last) {
rootEnd = offset = j + 1;
}
}
}
}
} else if (isWindowsDeviceRoot(code)) {
if (path2.charCodeAt(1) === CHAR_COLON) {
rootEnd = offset = 2;
if (len > 2) {
if (isPathSeparator(path2.charCodeAt(2)))
rootEnd = offset = 3;
}
}
}
} else if (isPathSeparator(code)) {
return path2;
}
for (let i = len - 1; i >= offset; --i) {
if (isPathSeparator(path2.charCodeAt(i))) {
if (!matchedSlash) {
end = i;
break;
}
} else {
matchedSlash = false;
}
}
if (end === -1) {
if (rootEnd === -1)
return ".";
else
end = rootEnd;
}
return path2.slice(0, end);
}
function basename(path2, ext = "") {
if (ext !== void 0 && typeof ext !== "string") {
throw new TypeError('"ext" argument must be a string');
}
assertPath(path2);
let start = 0;
let end = -1;
let matchedSlash = true;
let i;
if (path2.length >= 2) {
const drive = path2.charCodeAt(0);
if (isWindowsDeviceRoot(drive)) {
if (path2.charCodeAt(1) === CHAR_COLON)
start = 2;
}
}
if (ext !== void 0 && ext.length > 0 && ext.length <= path2.length) {
if (ext.length === path2.length && ext === path2)
return "";
let extIdx = ext.length - 1;
let firstNonSlashEnd = -1;
for (i = path2.length - 1; i >= start; --i) {
const code = path2.charCodeAt(i);
if (isPathSeparator(code)) {
if (!matchedSlash) {
start = i + 1;
break;
}
} else {
if (firstNonSlashEnd === -1) {
matchedSlash = false;
firstNonSlashEnd = i + 1;
}
if (extIdx >= 0) {
if (code === ext.charCodeAt(extIdx)) {
if (--extIdx === -1) {
end = i;
}
} else {
extIdx = -1;
end = firstNonSlashEnd;
}
}
}
}
if (start === end)
end = firstNonSlashEnd;
else if (end === -1)
end = path2.length;
return path2.slice(start, end);
} else {
for (i = path2.length - 1; i >= start; --i) {
if (isPathSeparator(path2.charCodeAt(i))) {
if (!matchedSlash) {
start = i + 1;
break;
}
} else if (end === -1) {
matchedSlash = false;
end = i + 1;
}
}
if (end === -1)
return "";
return path2.slice(start, end);
}
}
function extname(path2) {
assertPath(path2);
let start = 0;
let startDot = -1;
let startPart = 0;
let end = -1;
let matchedSlash = true;
let preDotState = 0;
if (path2.length >= 2 && path2.charCodeAt(1) === CHAR_COLON && isWindowsDeviceRoot(path2.charCodeAt(0))) {
start = startPart = 2;
}
for (let i = path2.length - 1; i >= start; --i) {
const code = path2.charCodeAt(i);
if (isPathSeparator(code)) {
if (!matchedSlash) {
startPart = i + 1;
break;
}
continue;
}
if (end === -1) {
matchedSlash = false;
end = i + 1;
}
if (code === CHAR_DOT) {
if (startDot === -1)
startDot = i;
else if (preDotState !== 1)
preDotState = 1;
} else if (startDot !== -1) {
preDotState = -1;
}
}
if (startDot === -1 || end === -1 || preDotState === 0 || preDotState === 1 && startDot === end - 1 && startDot === startPart + 1) {
return "";
}
return path2.slice(startDot, end);
}
function format(pathObject) {
if (pathObject === null || typeof pathObject !== "object") {
throw new TypeError(`The "pathObject" argument must be of type Object. Received type ${typeof pathObject}`);
}
return _format("\\", pathObject);
}
function parse(path2) {
assertPath(path2);
const ret = {root: "", dir: "", base: "", ext: "", name: ""};
const len = path2.length;
if (len === 0)
return ret;
let rootEnd = 0;
let code = path2.charCodeAt(0);
if (len > 1) {
if (isPathSeparator(code)) {
rootEnd = 1;
if (isPathSeparator(path2.charCodeAt(1))) {
let j = 2;
let last = j;
for (; j < len; ++j) {
if (isPathSeparator(path2.charCodeAt(j)))
break;
}
if (j < len && j !== last) {
last = j;
for (; j < len; ++j) {
if (!isPathSeparator(path2.charCodeAt(j)))
break;
}
if (j < len && j !== last) {
last = j;
for (; j < len; ++j) {
if (isPathSeparator(path2.charCodeAt(j)))
break;
}
if (j === len) {
rootEnd = j;
} else if (j !== last) {
rootEnd = j + 1;
}
}
}
}
} else if (isWindowsDeviceRoot(code)) {
if (path2.charCodeAt(1) === CHAR_COLON) {
rootEnd = 2;
if (len > 2) {
if (isPathSeparator(path2.charCodeAt(2))) {
if (len === 3) {
ret.root = ret.dir = path2;
return ret;
}
rootEnd = 3;
}
} else {
ret.root = ret.dir = path2;
return ret;
}
}
}
} else if (isPathSeparator(code)) {
ret.root = ret.dir = path2;
return ret;
}
if (rootEnd > 0)
ret.root = path2.slice(0, rootEnd);
let startDot = -1;
let startPart = rootEnd;
let end = -1;
let matchedSlash = true;
let i = path2.length - 1;
let preDotState = 0;
for (; i >= rootEnd; --i) {
code = path2.charCodeAt(i);
if (isPathSeparator(code)) {
if (!matchedSlash) {
startPart = i + 1;
break;
}
continue;
}
if (end === -1) {
matchedSlash = false;
end = i + 1;
}
if (code === CHAR_DOT) {
if (startDot === -1)
startDot = i;
else if (preDotState !== 1)
preDotState = 1;
} else if (startDot !== -1) {
preDotState = -1;
}
}
if (startDot === -1 || end === -1 || preDotState === 0 || preDotState === 1 && startDot === end - 1 && startDot === startPart + 1) {
if (end !== -1) {
ret.base = ret.name = path2.slice(startPart, end);
}
} else {
ret.name = path2.slice(startPart, startDot);
ret.base = path2.slice(startPart, end);
ret.ext = path2.slice(startDot, end);
}
if (startPart > 0 && startPart !== rootEnd) {
ret.dir = path2.slice(0, startPart - 1);
} else
ret.dir = ret.root;
return ret;
}
function fromFileUrl(url) {
url = url instanceof URL ? url : new URL(url);
if (url.protocol != "file:") {
throw new TypeError("Must be a file URL.");
}
let path2 = decodeURIComponent(url.pathname.replace(/\//g, "\\").replace(/%(?![0-9A-Fa-f]{2})/g, "%25")).replace(/^\\*([A-Za-z]:)(\\|$)/, "$1\\");
if (url.hostname != "") {
path2 = `\\\\${url.hostname}${path2}`;
}
return path2;
}
function toFileUrl(path2) {
if (!isAbsolute(path2)) {
throw new TypeError("Must be an absolute path.");
}
const [, hostname, pathname] = path2.match(/^(?:[/\\]{2}([^/\\]+)(?=[/\\][^/\\]))?(.*)/);
const url = new URL("file:///");
url.pathname = pathname.replace(/%/g, "%25");
if (hostname != null) {
url.hostname = hostname;
if (!url.hostname) {
throw new TypeError("Invalid hostname.");
}
}
return url;
}
// path/posix.ts
var posix_exports = {};
__export(posix_exports, {
basename: () => basename2,
delimiter: () => delimiter2,
dirname: () => dirname2,
extname: () => extname2,
format: () => format2,
fromFileUrl: () => fromFileUrl2,
isAbsolute: () => isAbsolute2,
join: () => join2,
normalize: () => normalize2,
parse: () => parse2,
relative: () => relative2,
resolve: () => resolve2,
sep: () => sep2,
toFileUrl: () => toFileUrl2,
toNamespacedPath: () => toNamespacedPath2
});
var sep2 = "/";
var delimiter2 = ":";
function resolve2(...pathSegments) {
let resolvedPath = "";
let resolvedAbsolute = false;
for (let i = pathSegments.length - 1; i >= -1 && !resolvedAbsolute; i--) {
let path2;
if (i >= 0)
path2 = pathSegments[i];
else {
if (globalThis.Deno == null) {
throw new TypeError("Resolved a relative path without a CWD.");
}
path2 = Deno.cwd();
}
assertPath(path2);
if (path2.length === 0) {
continue;
}
resolvedPath = `${path2}/${resolvedPath}`;
resolvedAbsolute = path2.charCodeAt(0) === CHAR_FORWARD_SLASH;
}
resolvedPath = normalizeString(resolvedPath, !resolvedAbsolute, "/", isPosixPathSeparator);
if (resolvedAbsolute) {
if (resolvedPath.length > 0)
return `/${resolvedPath}`;
else
return "/";
} else if (resolvedPath.length > 0)
return resolvedPath;
else
return ".";
}
function normalize2(path2) {
assertPath(path2);
if (path2.length === 0)
return ".";
const isAbsolute4 = path2.charCodeAt(0) === CHAR_FORWARD_SLASH;
const trailingSeparator = path2.charCodeAt(path2.length - 1) === CHAR_FORWARD_SLASH;
path2 = normalizeString(path2, !isAbsolute4, "/", isPosixPathSeparator);
if (path2.length === 0 && !isAbsolute4)
path2 = ".";
if (path2.length > 0 && trailingSeparator)
path2 += "/";
if (isAbsolute4)
return `/${path2}`;
return path2;
}
function isAbsolute2(path2) {
assertPath(path2);
return path2.length > 0 && path2.charCodeAt(0) === CHAR_FORWARD_SLASH;
}
function join2(...paths) {
if (paths.length === 0)
return ".";
let joined;
for (let i = 0, len = paths.length; i < len; ++i) {
const path2 = paths[i];
assertPath(path2);
if (path2.length > 0) {
if (!joined)
joined = path2;
else
joined += `/${path2}`;
}
}
if (!joined)
return ".";
return normalize2(joined);
}
function relative2(from, to) {
assertPath(from);
assertPath(to);
if (from === to)
return "";
from = resolve2(from);
to = resolve2(to);
if (from === to)
return "";
let fromStart = 1;
const fromEnd = from.length;
for (; fromStart < fromEnd; ++fromStart) {
if (from.charCodeAt(fromStart) !== CHAR_FORWARD_SLASH)
break;
}
const fromLen = fromEnd - fromStart;
let toStart = 1;
const toEnd = to.length;
for (; toStart < toEnd; ++toStart) {
if (to.charCodeAt(toStart) !== CHAR_FORWARD_SLASH)
break;
}
const toLen = toEnd - toStart;
const length = fromLen < toLen ? fromLen : toLen;
let lastCommonSep = -1;
let i = 0;
for (; i <= length; ++i) {
if (i === length) {
if (toLen > length) {
if (to.charCodeAt(toStart + i) === CHAR_FORWARD_SLASH) {
return to.slice(toStart + i + 1);
} else if (i === 0) {
return to.slice(toStart + i);
}
} else if (fromLen > length) {
if (from.charCodeAt(fromStart + i) === CHAR_FORWARD_SLASH) {
lastCommonSep = i;
} else if (i === 0) {
lastCommonSep = 0;
}
}
break;
}
const fromCode = from.charCodeAt(fromStart + i);
const toCode = to.charCodeAt(toStart + i);
if (fromCode !== toCode)
break;
else if (fromCode === CHAR_FORWARD_SLASH)
lastCommonSep = i;
}
let out = "";
for (i = fromStart + lastCommonSep + 1; i <= fromEnd; ++i) {
if (i === fromEnd || from.charCodeAt(i) === CHAR_FORWARD_SLASH) {
if (out.length === 0)
out += "..";
else
out += "/..";
}
}
if (out.length > 0)
return out + to.slice(toStart + lastCommonSep);
else {
toStart += lastCommonSep;
if (to.charCodeAt(toStart) === CHAR_FORWARD_SLASH)
++toStart;
return to.slice(toStart);
}
}
function toNamespacedPath2(path2) {
return path2;
}
function dirname2(path2) {
assertPath(path2);
if (path2.length === 0)
return ".";
const hasRoot = path2.charCodeAt(0) === CHAR_FORWARD_SLASH;
let end = -1;
let matchedSlash = true;
for (let i = path2.length - 1; i >= 1; --i) {
if (path2.charCodeAt(i) === CHAR_FORWARD_SLASH) {
if (!matchedSlash) {
end = i;
break;
}
} else {
matchedSlash = false;
}
}
if (end === -1)
return hasRoot ? "/" : ".";
if (hasRoot && end === 1)
return "//";
return path2.slice(0, end);
}
function basename2(path2, ext = "") {
if (ext !== void 0 && typeof ext !== "string") {
throw new TypeError('"ext" argument must be a string');
}
assertPath(path2);
let start = 0;
let end = -1;
let matchedSlash = true;
let i;
if (ext !== void 0 && ext.length > 0 && ext.length <= path2.length) {
if (ext.length === path2.length && ext === path2)
return "";
let extIdx = ext.length - 1;
let firstNonSlashEnd = -1;
for (i = path2.length - 1; i >= 0; --i) {
const code = path2.charCodeAt(i);
if (code === CHAR_FORWARD_SLASH) {
if (!matchedSlash) {
start = i + 1;
break;
}
} else {
if (firstNonSlashEnd === -1) {
matchedSlash = false;
firstNonSlashEnd = i + 1;
}
if (extIdx >= 0) {
if (code === ext.charCodeAt(extIdx)) {
if (--extIdx === -1) {
end = i;
}
} else {
extIdx = -1;
end = firstNonSlashEnd;
}
}
}
}
if (start === end)
end = firstNonSlashEnd;
else if (end === -1)
end = path2.length;
return path2.slice(start, end);
} else {
for (i = path2.length - 1; i >= 0; --i) {
if (path2.charCodeAt(i) === CHAR_FORWARD_SLASH) {
if (!matchedSlash) {
start = i + 1;
break;
}
} else if (end === -1) {
matchedSlash = false;
end = i + 1;
}
}
if (end === -1)
return "";
return path2.slice(start, end);
}
}
function extname2(path2) {
assertPath(path2);
let startDot = -1;
let startPart = 0;
let end = -1;
let matchedSlash = true;
let preDotState = 0;
for (let i = path2.length - 1; i >= 0; --i) {
const code = path2.charCodeAt(i);
if (code === CHAR_FORWARD_SLASH) {
if (!matchedSlash) {
startPart = i + 1;
break;
}
continue;
}
if (end === -1) {
matchedSlash = false;
end = i + 1;
}
if (code === CHAR_DOT) {
if (startDot === -1)
startDot = i;
else if (preDotState !== 1)
preDotState = 1;
} else if (startDot !== -1) {
preDotState = -1;
}
}
if (startDot === -1 || end === -1 || preDotState === 0 || preDotState === 1 && startDot === end - 1 && startDot === startPart + 1) {
return "";
}
return path2.slice(startDot, end);
}
function format2(pathObject) {
if (pathObject === null || typeof pathObject !== "object") {
throw new TypeError(`The "pathObject" argument must be of type Object. Received type ${typeof pathObject}`);
}
return _format("/", pathObject);
}
function parse2(path2) {
assertPath(path2);
const ret = {root: "", dir: "", base: "", ext: "", name: ""};
if (path2.length === 0)
return ret;
const isAbsolute4 = path2.charCodeAt(0) === CHAR_FORWARD_SLASH;
let start;
if (isAbsolute4) {
ret.root = "/";
start = 1;
} else {
start = 0;
}
let startDot = -1;
let startPart = 0;
let end = -1;
let matchedSlash = true;
let i = path2.length - 1;
let preDotState = 0;
for (; i >= start; --i) {
const code = path2.charCodeAt(i);
if (code === CHAR_FORWARD_SLASH) {
if (!matchedSlash) {
startPart = i + 1;
break;
}
continue;
}
if (end === -1) {
matchedSlash = false;
end = i + 1;
}
if (code === CHAR_DOT) {
if (startDot === -1)
startDot = i;
else if (preDotState !== 1)
preDotState = 1;
} else if (startDot !== -1) {
preDotState = -1;
}
}
if (startDot === -1 || end === -1 || preDotState === 0 || preDotState === 1 && startDot === end - 1 && startDot === startPart + 1) {
if (end !== -1) {
if (startPart === 0 && isAbsolute4) {
ret.base = ret.name = path2.slice(1, end);
} else {
ret.base = ret.name = path2.slice(startPart, end);
}
}
} else {
if (startPart === 0 && isAbsolute4) {
ret.name = path2.slice(1, startDot);
ret.base = path2.slice(1, end);
} else {
ret.name = path2.slice(startPart, startDot);
ret.base = path2.slice(startPart, end);
}
ret.ext = path2.slice(startDot, end);
}
if (startPart > 0)
ret.dir = path2.slice(0, startPart - 1);
else if (isAbsolute4)
ret.dir = "/";
return ret;
}
function fromFileUrl2(url) {
url = url instanceof URL ? url : new URL(url);
if (url.protocol != "file:") {
throw new TypeError("Must be a file URL.");
}
return decodeURIComponent(url.pathname.replace(/%(?![0-9A-Fa-f]{2})/g, "%25"));
}
function toFileUrl2(path2) {
if (!isAbsolute2(path2)) {
throw new TypeError("Must be an absolute path.");
}
const url = new URL("file:///");
url.pathname = path2.replace(/%/g, "%25").replace(/\\/g, "%5C");
return url;
}
// path/mod.ts
var path = isWindows ? win32_exports : posix_exports;
var posix = posix_exports;
var {
basename: basename3,
delimiter: delimiter3,
dirname: dirname3,
extname: extname3,
format: format3,
fromFileUrl: fromFileUrl3,
isAbsolute: isAbsolute3,
join: join3,
normalize: normalize3,
parse: parse3,
relative: relative3,
resolve: resolve3,
sep: sep3,
toFileUrl: toFileUrl3,
toNamespacedPath: toNamespacedPath3
} = path;
// bytes/mod.ts
function concat(...buf) {
let length = 0;
for (const b of buf) {
length += b.length;
}
const output = new Uint8Array(length);
let index = 0;
for (const b of buf) {
output.set(b, index);
index += b.length;
}
return output;
}
function copy(src, dst, off = 0) {
off = Math.max(0, Math.min(off, dst.byteLength));
const dstBytesAvailable = dst.byteLength - off;
if (src.byteLength > dstBytesAvailable) {
src = src.subarray(0, dstBytesAvailable);
}
dst.set(src, off);
return src.byteLength;
}
// io/bufio.ts
var DEFAULT_BUF_SIZE = 4096;
var MIN_BUF_SIZE = 16;
var MAX_CONSECUTIVE_EMPTY_READS = 100;
var CR = "\r".charCodeAt(0);
var LF = "\n".charCodeAt(0);
var BufferFullError = class extends Error {
constructor(partial) {
super("Buffer full");
this.partial = partial;
this.name = "BufferFullError";
}
};
var PartialReadError = class extends Deno.errors.UnexpectedEof {
constructor() {
super("Encountered UnexpectedEof, data only partially read");
this.name = "PartialReadError";
}
};
var BufReader = class {
constructor(rd, size = DEFAULT_BUF_SIZE) {
this.r = 0;
this.w = 0;
this.eof = false;
if (size < MIN_BUF_SIZE) {
size = MIN_BUF_SIZE;
}
this._reset(new Uint8Array(size), rd);
}
static create(r, size = DEFAULT_BUF_SIZE) {
return r instanceof BufReader ? r : new BufReader(r, size);
}
size() {
return this.buf.byteLength;
}
buffered() {
return this.w - this.r;
}
async _fill() {
if (this.r > 0) {
this.buf.copyWithin(0, this.r, this.w);
this.w -= this.r;
this.r = 0;
}
if (this.w >= this.buf.byteLength) {
throw Error("bufio: tried to fill full buffer");
}
for (let i = MAX_CONSECUTIVE_EMPTY_READS; i > 0; i--) {
const rr = await this.rd.read(this.buf.subarray(this.w));
if (rr === null) {
this.eof = true;
return;
}
assert(rr >= 0, "negative read");
this.w += rr;
if (rr > 0) {
return;
}
}
throw new Error(`No progress after ${MAX_CONSECUTIVE_EMPTY_READS} read() calls`);
}
reset(r) {
this._reset(this.buf, r);
}
_reset(buf, rd) {
this.buf = buf;
this.rd = rd;
this.eof = false;
}
async read(p) {
let rr = p.byteLength;
if (p.byteLength === 0)
return rr;
if (this.r === this.w) {
if (p.byteLength >= this.buf.byteLength) {
const rr2 = await this.rd.read(p);
const nread = rr2 ?? 0;
assert(nread >= 0, "negative read");
return rr2;
}
this.r = 0;
this.w = 0;
rr = await this.rd.read(this.buf);
if (rr === 0 || rr === null)
return rr;
assert(rr >= 0, "negative read");
this.w += rr;
}
const copied = copy(this.buf.subarray(this.r, this.w), p, 0);
this.r += copied;
return copied;
}
async readFull(p) {
let bytesRead = 0;
while (bytesRead < p.length) {
try {
const rr = await this.read(p.subarray(bytesRead));
if (rr === null) {
if (bytesRead === 0) {
return null;
} else {
throw new PartialReadError();
}
}
bytesRead += rr;
} catch (err) {
err.partial = p.subarray(0, bytesRead);
throw err;
}
}
return p;
}
async readByte() {
while (this.r === this.w) {
if (this.eof)
return null;
await this._fill();
}
const c = this.buf[this.r];
this.r++;
return c;
}
async readString(delim) {
if (delim.length !== 1) {
throw new Error("Delimiter should be a single character");
}
const buffer = await this.readSlice(delim.charCodeAt(0));
if (buffer === null)
return null;
return new TextDecoder().decode(buffer);
}
async readLine() {
let line;
try {
line = await this.readSlice(LF);
} catch (err) {
let {partial} = err;
assert(partial instanceof Uint8Array, "bufio: caught error from `readSlice()` without `partial` property");
if (!(err instanceof BufferFullError)) {
throw err;
}
if (!this.eof && partial.byteLength > 0 && partial[partial.byteLength - 1] === CR) {
assert(this.r > 0, "bufio: tried to rewind past start of buffer");
this.r--;
partial = partial.subarray(0, partial.byteLength - 1);
}
return {line: partial, more: !this.eof};
}
if (line === null) {
return null;
}
if (line.byteLength === 0) {
return {line, more: false};
}
if (line[line.byteLength - 1] == LF) {
let drop = 1;
if (line.byteLength > 1 && line[line.byteLength - 2] === CR) {
drop = 2;
}
line = line.subarray(0, line.byteLength - drop);
}
return {line, more: false};
}
async readSlice(delim) {
let s = 0;
let slice;
while (true) {
let i = this.buf.subarray(this.r + s, this.w).indexOf(delim);
if (i >= 0) {
i += s;
slice = this.buf.subarray(this.r, this.r + i + 1);
this.r += i + 1;
break;
}
if (this.eof) {
if (this.r === this.w) {
return null;
}
slice = this.buf.subarray(this.r, this.w);
this.r = this.w;
break;
}
if (this.buffered() >= this.buf.byteLength) {
this.r = this.w;
const oldbuf = this.buf;
const newbuf = this.buf.slice(0);
this.buf = newbuf;
throw new BufferFullError(oldbuf);
}
s = this.w - this.r;
try {
await this._fill();
} catch (err) {
err.partial = slice;
throw err;
}
}
return slice;
}
async peek(n) {
if (n < 0) {
throw Error("negative count");
}
let avail = this.w - this.r;
while (avail < n && avail < this.buf.byteLength && !this.eof) {
try {
await this._fill();
} catch (err) {
err.partial = this.buf.subarray(this.r, this.w);
throw err;
}
avail = this.w - this.r;
}
if (avail === 0 && this.eof) {
return null;
} else if (avail < n && this.eof) {
return this.buf.subarray(this.r, this.r + avail);
} else if (avail < n) {
throw new BufferFullError(this.buf.subarray(this.r, this.w));
}
return this.buf.subarray(this.r, this.r + n);
}
};
var AbstractBufBase = class {
constructor() {
this.usedBufferBytes = 0;
this.err = null;
}
size() {
return this.buf.byteLength;
}
available() {
return this.buf.byteLength - this.usedBufferBytes;
}
buffered() {
return this.usedBufferBytes;
}
};
var BufWriter = class extends AbstractBufBase {
constructor(writer, size = DEFAULT_BUF_SIZE) {
super();
this.writer = writer;
if (size <= 0) {
size = DEFAULT_BUF_SIZE;
}
this.buf = new Uint8Array(size);
}
static create(writer, size = DEFAULT_BUF_SIZE) {
return writer instanceof BufWriter ? writer : new BufWriter(writer, size);
}
reset(w) {
this.err = null;
this.usedBufferBytes = 0;
this.writer = w;
}
async flush() {
if (this.err !== null)
throw this.err;
if (this.usedBufferBytes === 0)
return;
try {
await Deno.writeAll(this.writer, this.buf.subarray(0, this.usedBufferBytes));
} catch (e) {
this.err = e;
throw e;
}
this.buf = new Uint8Array(this.buf.length);
this.usedBufferBytes = 0;
}
async write(data) {
if (this.err !== null)
throw this.err;
if (data.length === 0)
return 0;
let totalBytesWritten = 0;
let numBytesWritten = 0;
while (data.byteLength > this.available()) {
if (this.buffered() === 0) {
try {
numBytesWritten = await this.writer.write(data);
} catch (e) {
this.err = e;
throw e;
}
} else {
numBytesWritten = copy(data, this.buf, this.usedBufferBytes);
this.usedBufferBytes += numBytesWritten;
await this.flush();
}
totalBytesWritten += numBytesWritten;
data = data.subarray(numBytesWritten);
}
numBytesWritten = copy(data, this.buf, this.usedBufferBytes);
this.usedBufferBytes += numBytesWritten;
totalBytesWritten += numBytesWritten;
return totalBytesWritten;
}
};
// async/deferred.ts
function deferred() {
let methods;
const promise = new Promise((resolve4, reject) => {
methods = {resolve: resolve4, reject};
});
return Object.assign(promise, methods);
}
// async/mux_async_iterator.ts
var MuxAsyncIterator = class {
constructor() {
this.iteratorCount = 0;
this.yields = [];
this.throws = [];
this.signal = deferred();
}
add(iterator) {
++this.iteratorCount;
this.callIteratorNext(iterator);
}
async callIteratorNext(iterator) {
try {
const {value, done} = await iterator.next();
if (done) {
--this.iteratorCount;
} else {
this.yields.push({iterator, value});
}
} catch (e) {
this.throws.push(e);
}
this.signal.resolve();
}
async *iterate() {
while (this.iteratorCount > 0) {
await this.signal;
for (let i = 0; i < this.yields.length; i++) {
const {iterator, value} = this.yields[i];
yield value;
this.callIteratorNext(iterator);
}
if (this.throws.length) {
for (const e of this.throws) {
throw e;
}
this.throws.length = 0;
}
this.yields.length = 0;
this.signal = deferred();
}
}
[Symbol.asyncIterator]() {
return this.iterate();
}
};
// textproto/mod.ts
var invalidHeaderCharRegex = /[^\t\x20-\x7e\x80-\xff]/g;
function str(buf) {
if (buf == null) {
return "";
} else {
return new TextDecoder().decode(buf);
}
}
function charCode(s) {
return s.charCodeAt(0);
}
var TextProtoReader = class {
constructor(r) {
this.r = r;
}
async readLine() {
const s = await this.readLineSlice();
if (s === null)
return null;
return str(s);
}
async readMIMEHeader() {
const m = new Headers();
let line;
let buf = await this.r.peek(1);
if (buf === null) {
return null;
} else if (buf[0] == charCode(" ") || buf[0] == charCode(" ")) {
line = await this.readLineSlice();
}
buf = await this.r.peek(1);
if (buf === null) {
throw new Deno.errors.UnexpectedEof();
} else if (buf[0] == charCode(" ") || buf[0] == charCode(" ")) {
throw new Deno.errors.InvalidData(`malformed MIME header initial line: ${str(line)}`);
}
while (true) {
const kv = await this.readLineSlice();
if (kv === null)
throw new Deno.errors.UnexpectedEof();
if (kv.byteLength === 0)
return m;
let i = kv.indexOf(charCode(":"));
if (i < 0) {
throw new Deno.errors.InvalidData(`malformed MIME header line: ${str(kv)}`);
}
const key = str(kv.subarray(0, i));
if (key == "") {
continue;
}
i++;
while (i < kv.byteLength && (kv[i] == charCode(" ") || kv[i] == charCode(" "))) {
i++;
}
const value = str(kv.subarray(i)).replace(invalidHeaderCharRegex, encodeURI);
try {
m.append(key, value);
} catch {
}
}
}
async readLineSlice() {
let line;
while (true) {
const r = await this.r.readLine();
if (r === null)
return null;
const {line: l, more} = r;
if (!line && !more) {
if (this.skipSpace(l) === 0) {
return new Uint8Array(0);
}
return l;
}
line = line ? concat(line, l) : l;
if (!more) {
break;
}
}
return line;
}
skipSpace(l) {
let n = 0;
for (let i = 0; i < l.length; i++) {
if (l[i] === charCode(" ") || l[i] === charCode(" ")) {
continue;
}
n++;
}
return n;
}
};
// http/http_status.ts
var Status;
(function(Status2) {
Status2[Status2["Continue"] = 100] = "Continue";
Status2[Status2["SwitchingProtocols"] = 101] = "SwitchingProtocols";
Status2[Status2["Processing"] = 102] = "Processing";
Status2[Status2["EarlyHints"] = 103] = "EarlyHints";
Status2[Status2["OK"] = 200] = "OK";
Status2[Status2["Created"] = 201] = "Created";
Status2[Status2["Accepted"] = 202] = "Accepted";
Status2[Status2["NonAuthoritativeInfo"] = 203] = "NonAuthoritativeInfo";
Status2[Status2["NoContent"] = 204] = "NoContent";
Status2[Status2["ResetContent"] = 205] = "ResetContent";
Status2[Status2["PartialContent"] = 206] = "PartialContent";
Status2[Status2["MultiStatus"] = 207] = "MultiStatus";
Status2[Status2["AlreadyReported"] = 208] = "AlreadyReported";
Status2[Status2["IMUsed"] = 226] = "IMUsed";
Status2[Status2["MultipleChoices"] = 300] = "MultipleChoices";
Status2[Status2["MovedPermanently"] = 301] = "MovedPermanently";
Status2[Status2["Found"] = 302] = "Found";
Status2[Status2["SeeOther"] = 303] = "SeeOther";
Status2[Status2["NotModified"] = 304] = "NotModified";
Status2[Status2["UseProxy"] = 305] = "UseProxy";
Status2[Status2["TemporaryRedirect"] = 307] = "TemporaryRedirect";
Status2[Status2["PermanentRedirect"] = 308] = "PermanentRedirect";
Status2[Status2["BadRequest"] = 400] = "BadRequest";
Status2[Status2["Unauthorized"] = 401] = "Unauthorized";
Status2[Status2["PaymentRequired"] = 402] = "PaymentRequired";
Status2[Status2["Forbidden"] = 403] = "Forbidden";
Status2[Status2["NotFound"] = 404] = "NotFound";
Status2[Status2["MethodNotAllowed"] = 405] = "MethodNotAllowed";
Status2[Status2["NotAcceptable"] = 406] = "NotAcceptable";
Status2[Status2["ProxyAuthRequired"] = 407] = "ProxyAuthRequired";
Status2[Status2["RequestTimeout"] = 408] = "RequestTimeout";
Status2[Status2["Conflict"] = 409] = "Conflict";
Status2[Status2["Gone"] = 410] = "Gone";
Status2[Status2["LengthRequired"] = 411] = "LengthRequired";
Status2[Status2["PreconditionFailed"] = 412] = "PreconditionFailed";
Status2[Status2["RequestEntityTooLarge"] = 413] = "RequestEntityTooLarge";
Status2[Status2["RequestURITooLong"] = 414] = "RequestURITooLong";
Status2[Status2["UnsupportedMediaType"] = 415] = "UnsupportedMediaType";
Status2[Status2["RequestedRangeNotSatisfiable"] = 416] = "RequestedRangeNotSatisfiable";
Status2[Status2["ExpectationFailed"] = 417] = "ExpectationFailed";
Status2[Status2["Teapot"] = 418] = "Teapot";
Status2[Status2["MisdirectedRequest"] = 421] = "MisdirectedRequest";
Status2[Status2["UnprocessableEntity"] = 422] = "UnprocessableEntity";
Status2[Status2["Locked"] = 423] = "Locked";
Status2[Status2["FailedDependency"] = 424] = "FailedDependency";
Status2[Status2["TooEarly"] = 425] = "TooEarly";
Status2[Status2["UpgradeRequired"] = 426] = "UpgradeRequired";
Status2[Status2["PreconditionRequired"] = 428] = "PreconditionRequired";
Status2[Status2["TooManyRequests"] = 429] = "TooManyRequests";
Status2[Status2["RequestHeaderFieldsTooLarge"] = 431] = "RequestHeaderFieldsTooLarge";
Status2[Status2["UnavailableForLegalReasons"] = 451] = "UnavailableForLegalReasons";
Status2[Status2["InternalServerError"] = 500] = "InternalServerError";
Status2[Status2["NotImplemented"] = 501] = "NotImplemented";
Status2[Status2["BadGateway"] = 502] = "BadGateway";
Status2[Status2["ServiceUnavailable"] = 503] = "ServiceUnavailable";
Status2[Status2["GatewayTimeout"] = 504] = "GatewayTimeout";
Status2[Status2["HTTPVersionNotSupported"] = 505] = "HTTPVersionNotSupported";
Status2[Status2["VariantAlsoNegotiates"] = 506] = "VariantAlsoNegotiates";
Status2[Status2["InsufficientStorage"] = 507] = "InsufficientStorage";
Status2[Status2["LoopDetected"] = 508] = "LoopDetected";
Status2[Status2["NotExtended"] = 510] = "NotExtended";
Status2[Status2["NetworkAuthenticationRequired"] = 511] = "NetworkAuthenticationRequired";
})(Status || (Status = {}));
var STATUS_TEXT = new Map([
[100, "Continue"],
[101, "Switching Protocols"],
[102, "Processing"],
[103, "Early Hints"],
[200, "OK"],
[201, "Created"],
[202, "Accepted"],
[203, "Non-Authoritative Information"],
[204, "No Content"],
[205, "Reset Content"],
[206, "Partial Content"],
[207, "Multi-Status"],
[208, "Already Reported"],
[226, "IM Used"],
[300, "Multiple Choices"],
[301, "Moved Permanently"],
[302, "Found"],
[303, "See Other"],
[304, "Not Modified"],
[305, "Use Proxy"],
[307, "Temporary Redirect"],
[308, "Permanent Redirect"],
[400, "Bad Request"],
[401, "Unauthorized"],
[402, "Payment Required"],
[403, "Forbidden"],
[404, "Not Found"],
[405, "Method Not Allowed"],
[406, "Not Acceptable"],
[407, "Proxy Authentication Required"],
[408, "Request Timeout"],
[409, "Conflict"],
[410, "Gone"],
[411, "Length Required"],
[412, "Precondition Failed"],
[413, "Request Entity Too Large"],
[414, "Request URI Too Long"],
[415, "Unsupported Media Type"],
[416, "Requested Range Not Satisfiable"],
[417, "Expectation Failed"],
[418, "I'm a teapot"],
[421, "Misdirected Request"],
[422, "Unprocessable Entity"],
[423, "Locked"],
[424, "Failed Dependency"],
[425, "Too Early"],
[426, "Upgrade Required"],
[428, "Precondition Required"],
[429, "Too Many Requests"],
[431, "Request Header Fields Too Large"],
[451, "Unavailable For Legal Reasons"],
[500, "Internal Server Error"],
[501, "Not Implemented"],
[502, "Bad Gateway"],
[503, "Service Unavailable"],
[504, "Gateway Timeout"],
[505, "HTTP Version Not Supported"],
[506, "Variant Also Negotiates"],
[507, "Insufficient Storage"],
[508, "Loop Detected"],
[510, "Not Extended"],
[511, "Network Authentication Required"]
]);
// http/_io.ts
function emptyReader() {
return {
read(_) {
return Promise.resolve(null);
}
};
}
function bodyReader(contentLength, r) {
let totalRead = 0;
let finished = false;
async function read(buf) {
if (finished)
return null;
let result;
const remaining = contentLength - totalRead;
if (remaining >= buf.byteLength) {
result = await r.read(buf);
} else {
const readBuf = buf.subarray(0, remaining);
result = await r.read(readBuf);
}
if (result !== null) {
totalRead += result;
}
finished = totalRead === contentLength;
return result;
}
return {read};
}
function chunkedBodyReader(h, r) {
const tp = new TextProtoReader(r);
let finished = false;
const chunks = [];
async function read(buf) {
if (finished)
return null;
const [chunk] = chunks;
if (chunk) {
const chunkRemaining = chunk.data.byteLength - chunk.offset;
const readLength = Math.min(chunkRemaining, buf.byteLength);
for (let i = 0; i < readLength; i++) {
buf[i] = chunk.data[chunk.offset + i];
}
chunk.offset += readLength;
if (chunk.offset === chunk.data.byteLength) {
chunks.shift();
if (await tp.readLine() === null) {
throw new Deno.errors.UnexpectedEof();
}
}
return readLength;
}
const line = await tp.readLine();
if (line === null)
throw new Deno.errors.UnexpectedEof();
const [chunkSizeString] = line.split(";");
const chunkSize = parseInt(chunkSizeString, 16);
if (Number.isNaN(chunkSize) || chunkSize < 0) {
throw new Deno.errors.InvalidData("Invalid chunk size");
}
if (chunkSize > 0) {
if (chunkSize > buf.byteLength) {
let eof = await r.readFull(buf);
if (eof === null) {
throw new Deno.errors.UnexpectedEof();
}
const restChunk = new Uint8Array(chunkSize - buf.byteLength);
eof = await r.readFull(restChunk);
if (eof === null) {
throw new Deno.errors.UnexpectedEof();
} else {
chunks.push({
offset: 0,
data: restChunk
});
}
return buf.byteLength;
} else {
const bufToFill = buf.subarray(0, chunkSize);
const eof = await r.readFull(bufToFill);
if (eof === null) {
throw new Deno.errors.UnexpectedEof();
}
if (await tp.readLine() === null) {
throw new Deno.errors.UnexpectedEof();
}
return chunkSize;
}
} else {
assert(chunkSize === 0);
if (await r.readLine() === null) {
throw new Deno.errors.UnexpectedEof();
}
await readTrailers(h, r);
finished = true;
return null;
}
}
return {read};
}
function isProhibidedForTrailer(key) {
const s = new Set(["transfer-encoding", "content-length", "trailer"]);
return s.has(key.toLowerCase());
}
async function readTrailers(headers, r) {
const trailers = parseTrailer(headers.get("trailer"));
if (trailers == null)
return;
const trailerNames = [...trailers.keys()];
const tp = new TextProtoReader(r);
const result = await tp.readMIMEHeader();
if (result == null) {
throw new Deno.errors.InvalidData("Missing trailer header.");
}
const undeclared = [...result.keys()].filter((k) => !trailerNames.includes(k));
if (undeclared.length > 0) {
throw new Deno.errors.InvalidData(`Undeclared trailers: ${Deno.inspect(undeclared)}.`);
}
for (const [k, v] of result) {
headers.append(k, v);
}
const missingTrailers = trailerNames.filter((k) => !result.has(k));
if (missingTrailers.length > 0) {
throw new Deno.errors.InvalidData(`Missing trailers: ${Deno.inspect(missingTrailers)}.`);
}
headers.delete("trailer");
}
function parseTrailer(field) {
if (field == null) {
return void 0;
}
const trailerNames = field.split(",").map((v) => v.trim().toLowerCase());
if (trailerNames.length === 0) {
throw new Deno.errors.InvalidData("Empty trailer header.");
}
const prohibited = trailerNames.filter((k) => isProhibidedForTrailer(k));
if (prohibited.length > 0) {
throw new Deno.errors.InvalidData(`Prohibited trailer names: ${Deno.inspect(prohibited)}.`);
}
return new Headers(trailerNames.map((key) => [key, ""]));
}
async function writeChunkedBody(w, r) {
const encoder2 = new TextEncoder();
for await (const chunk of Deno.iter(r)) {
if (chunk.byteLength <= 0)
continue;
const start = encoder2.encode(`${chunk.byteLength.toString(16)}\r
`);
const end = encoder2.encode("\r\n");
await w.write(start);
await w.write(chunk);
await w.write(end);
await w.flush();
}
const endChunk = encoder2.encode("0\r\n\r\n");
await w.write(endChunk);
}
async function writeTrailers(w, headers, trailers) {
const trailer = headers.get("trailer");
if (trailer === null) {
throw new TypeError("Missing trailer header.");
}
const transferEncoding = headers.get("transfer-encoding");
if (transferEncoding === null || !transferEncoding.match(/^chunked/)) {
throw new TypeError(`Trailers are only allowed for "transfer-encoding: chunked", got "transfer-encoding: ${transferEncoding}".`);
}
const writer = BufWriter.create(w);
const trailerNames = trailer.split(",").map((s) => s.trim().toLowerCase());
const prohibitedTrailers = trailerNames.filter((k) => isProhibidedForTrailer(k));
if (prohibitedTrailers.length > 0) {
throw new TypeError(`Prohibited trailer names: ${Deno.inspect(prohibitedTrailers)}.`);
}
const undeclared = [...trailers.keys()].filter((k) => !trailerNames.includes(k));
if (undeclared.length > 0) {
throw new TypeError(`Undeclared trailers: ${Deno.inspect(undeclared)}.`);
}
const encoder2 = new TextEncoder();
for (const [key, value] of trailers) {
await writer.write(encoder2.encode(`${key}: ${value}\r
`));
}
await writer.write(encoder2.encode("\r\n"));
await writer.flush();
}
async function writeResponse(w, r) {
const protoMajor = 1;
const protoMinor = 1;
const statusCode = r.status || 200;
const statusText = STATUS_TEXT.get(statusCode);
const writer = BufWriter.create(w);
const encoder2 = new TextEncoder();
if (!statusText) {
throw new Deno.errors.InvalidData("Bad status code");
}
if (!r.body) {
r.body = new Uint8Array();
}
if (typeof r.body === "string") {
r.body = encoder2.encode(r.body);
}
let out = `HTTP/${protoMajor}.${protoMinor} ${statusCode} ${statusText}\r
`;
const headers = r.headers ?? new Headers();
if (r.body && !headers.get("content-length")) {
if (r.body instanceof Uint8Array) {
out += `content-length: ${r.body.byteLength}\r
`;
} else if (!headers.get("transfer-encoding")) {
out += "transfer-encoding: chunked\r\n";
}
}
for (const [key, value] of headers) {
out += `${key}: ${value}\r
`;
}
out += `\r
`;
const header = encoder2.encode(out);
const n = await writer.write(header);
assert(n === header.byteLength);
if (r.body instanceof Uint8Array) {
const n2 = await writer.write(r.body);
assert(n2 === r.body.byteLength);
} else if (headers.has("content-length")) {
const contentLength = headers.get("content-length");
assert(contentLength != null);
const bodyLength = parseInt(contentLength);
const n2 = await Deno.copy(r.body, writer);
assert(n2 === bodyLength);
} else {
await writeChunkedBody(writer, r.body);
}
if (r.trailers) {
const t = await r.trailers();
await writeTrailers(writer, headers, t);
}
await writer.flush();
}
function parseHTTPVersion(vers) {
switch (vers) {
case "HTTP/1.1":
return [1, 1];
case "HTTP/1.0":
return [1, 0];
default: {
const Big = 1e6;
if (!vers.startsWith("HTTP/")) {
break;
}
const dot = vers.indexOf(".");
if (dot < 0) {
break;
}
const majorStr = vers.substring(vers.indexOf("/") + 1, dot);
const major = Number(majorStr);
if (!Number.isInteger(major) || major < 0 || major > Big) {
break;
}
const minorStr = vers.substring(dot + 1);
const minor = Number(minorStr);
if (!Number.isInteger(minor) || minor < 0 || minor > Big) {
break;
}
return [major, minor];
}
}
throw new Error(`malformed HTTP version ${vers}`);
}
async function readRequest(conn, bufr) {
const tp = new TextProtoReader(bufr);
const firstLine = await tp.readLine();
if (firstLine === null)
return null;
const headers = await tp.readMIMEHeader();
if (headers === null)
throw new Deno.errors.UnexpectedEof();
const req = new ServerRequest();
req.conn = conn;
req.r = bufr;
[req.method, req.url, req.proto] = firstLine.split(" ", 3);
[req.protoMajor, req.protoMinor] = parseHTTPVersion(req.proto);
req.headers = headers;
fixLength(req);
return req;
}
function fixLength(req) {
const contentLength = req.headers.get("Content-Length");
if (contentLength) {
const arrClen = contentLength.split(",");
if (arrClen.length > 1) {
const distinct = [...new Set(arrClen.map((e) => e.trim()))];
if (distinct.length > 1) {
throw Error("cannot contain multiple Content-Length headers");
} else {
req.headers.set("Content-Length", distinct[0]);
}
}
const c = req.headers.get("Content-Length");
if (req.method === "HEAD" && c && c !== "0") {
throw Error("http: method cannot contain a Content-Length");
}
if (c && req.headers.has("transfer-encoding")) {
throw new Error("http: Transfer-Encoding and Content-Length cannot be send together");
}
}
}
// http/server.ts
var ServerRequest = class {
constructor() {
this.#done = deferred();
this.#contentLength = void 0;
this.#body = void 0;
this.#finalized = false;
}
#done;
#contentLength;
#body;
#finalized;
get done() {
return this.#done.then((e) => e);
}
get contentLength() {
if (this.#contentLength === void 0) {
const cl = this.headers.get("content-length");
if (cl) {
this.#contentLength = parseInt(cl);
if (Number.isNaN(this.#contentLength)) {
this.#contentLength = null;
}
} else {
this.#contentLength = null;
}
}
return this.#contentLength;
}
get body() {
if (!this.#body) {
if (this.contentLength != null) {
this.#body = bodyReader(this.contentLength, this.r);
} else {
const transferEncoding = this.headers.get("transfer-encoding");
if (transferEncoding != null) {
const parts = transferEncoding.split(",").map((e) => e.trim().toLowerCase());
assert(parts.includes("chunked"), 'transfer-encoding must include "chunked" if content-length is not set');
this.#body = chunkedBodyReader(this.headers, this.r);
} else {
this.#body = emptyReader();
}
}
}
return this.#body;
}
async respond(r) {
let err;
try {
await writeResponse(this.w, r);
} catch (e) {
try {
this.conn.close();
} catch {
}
err = e;
}
this.#done.resolve(err);
if (err) {
throw err;
}
}
async finalize() {
if (this.#finalized)
return;
const body = this.body;
const buf = new Uint8Array(1024);
while (await body.read(buf) !== null) {
}
this.#finalized = true;
}
};
var Server = class {
constructor(listener) {
this.listener = listener;
this.#closing = false;
this.#connections = [];
}
#closing;
#connections;
close() {
this.#closing = true;
this.listener.close();
for (const conn of this.#connections) {
try {
conn.close();
} catch (e) {
if (!(e instanceof Deno.errors.BadResource)) {
throw e;
}
}
}
}
async *iterateHttpRequests(conn) {
const reader = new BufReader(conn);
const writer = new BufWriter(conn);
while (!this.#closing) {
let request;
try {
request = await readRequest(conn, reader);
} catch (error) {
if (error instanceof Deno.errors.InvalidData || error instanceof Deno.errors.UnexpectedEof) {
try {
await writeResponse(writer, {
status: 400,
body: new TextEncoder().encode(`${error.message}\r
\r
`)
});
} catch (error2) {
}
}
break;
}
if (request === null) {
break;
}
request.w = writer;
yield request;
const responseError = await request.done;
if (responseError) {
this.untrackConnection(request.conn);
return;
}
try {
await request.finalize();
} catch (error) {
break;
}
}
this.untrackConnection(conn);
try {
conn.close();
} catch (e) {
}
}
trackConnection(conn) {
this.#connections.push(conn);
}
untrackConnection(conn) {
const index = this.#connections.indexOf(conn);
if (index !== -1) {
this.#connections.splice(index, 1);
}
}
async *acceptConnAndIterateHttpRequests(mux) {
if (this.#closing)
return;
let conn;
try {
conn = await this.listener.accept();
} catch (error) {
if (error instanceof Deno.errors.BadResource || error instanceof Deno.errors.InvalidData || error instanceof Deno.errors.UnexpectedEof || error instanceof Deno.errors.ConnectionReset) {
return mux.add(this.acceptConnAndIterateHttpRequests(mux));
}
throw error;
}
this.trackConnection(conn);
mux.add(this.acceptConnAndIterateHttpRequests(mux));
yield* this.iterateHttpRequests(conn);
}
[Symbol.asyncIterator]() {
const mux = new MuxAsyncIterator();
mux.add(this.acceptConnAndIterateHttpRequests(mux));
return mux.iterate();
}
};
function _parseAddrFromStr(addr) {
let url;
try {
const host = addr.startsWith(":") ? `0.0.0.0${addr}` : addr;
url = new URL(`http://${host}`);
} catch {
throw new TypeError("Invalid address.");
}
if (url.username || url.password || url.pathname != "/" || url.search || url.hash) {
throw new TypeError("Invalid address.");
}
return {
hostname: url.hostname,
port: url.port === "" ? 80 : Number(url.port)
};
}
function serve(addr) {
if (typeof addr === "string") {
addr = _parseAddrFromStr(addr);
}
const listener = Deno.listen(addr);
return new Server(listener);
}
async function listenAndServe(addr, handler) {
const server = serve(addr);
for await (const request of server) {
handler(request);
}
}
function serveTLS(options) {
const tlsOptions = {
...options,
transport: "tcp"
};
const listener = Deno.listenTls(tlsOptions);
return new Server(listener);
}
async function listenAndServeTLS(options, handler) {
const server = serveTLS(options);
for await (const request of server) {
handler(request);
}
}
// flags/mod.ts
function get(obj, key) {
if (Object.prototype.hasOwnProperty.call(obj, key)) {
return obj[key];
}
}
function getForce(obj, key) {
const v = get(obj, key);
assert(v != null);
return v;
}
function isNumber(x) {
if (typeof x === "number")
return true;
if (/^0x[0-9a-f]+$/i.test(String(x)))
return true;
return /^[-+]?(?:\d+(?:\.\d*)?|\.\d+)(e[-+]?\d+)?$/.test(String(x));
}
function hasKey(obj, keys) {
let o = obj;
keys.slice(0, -1).forEach((key2) => {
o = get(o, key2) ?? {};
});
const key = keys[keys.length - 1];
return key in o;
}
function parse4(args, {
"--": doubleDash = false,
alias = {},
boolean = false,
default: defaults = {},
stopEarly = false,
string = [],
unknown = (i) => i
} = {}) {
const flags = {
bools: {},
strings: {},
unknownFn: unknown,
allBools: false
};
if (boolean !== void 0) {
if (typeof boolean === "boolean") {
flags.allBools = !!boolean;
} else {
const booleanArgs = typeof boolean === "string" ? [boolean] : boolean;
for (const key of booleanArgs.filter(Boolean)) {
flags.bools[key] = true;
}
}
}
const aliases = {};
if (alias !== void 0) {
for (const key in alias) {
const val = getForce(alias, key);
if (typeof val === "string") {
aliases[key] = [val];
} else {
aliases[key] = val;
}
for (const alias2 of getForce(aliases, key)) {
aliases[alias2] = [key].concat(aliases[key].filter((y) => alias2 !== y));
}
}
}
if (string !== void 0) {
const stringArgs = typeof string === "string" ? [string] : string;
for (const key of stringArgs.filter(Boolean)) {
flags.strings[key] = true;
const alias2 = get(aliases, key);
if (alias2) {
for (const al of alias2) {
flags.strings[al] = true;
}
}
}
}
const argv = {_: []};
function argDefined(key, arg) {
return flags.allBools && /^--[^=]+$/.test(arg) || get(flags.bools, key) || !!get(flags.strings, key) || !!get(aliases, key);
}
function setKey(obj, keys, value) {
let o = obj;
keys.slice(0, -1).forEach(function(key2) {
if (get(o, key2) === void 0) {
o[key2] = {};
}
o = get(o, key2);
});
const key = keys[keys.length - 1];
if (get(o, key) === void 0 || get(flags.bools, key) || typeof get(o, key) === "boolean") {
o[key] = value;
} else if (Array.isArray(get(o, key))) {
o[key].push(value);
} else {
o[key] = [get(o, key), value];
}
}
function setArg(key, val, arg = void 0) {
if (arg && flags.unknownFn && !argDefined(key, arg)) {
if (flags.unknownFn(arg, key, val) === false)
return;
}
const value = !get(flags.strings, key) && isNumber(val) ? Number(val) : val;
setKey(argv, key.split("."), value);
const alias2 = get(aliases, key);
if (alias2) {
for (const x of alias2) {
setKey(argv, x.split("."), value);
}
}
}
function aliasIsBoolean(key) {
return getForce(aliases, key).some((x) => typeof get(flags.bools, x) === "boolean");
}
for (const key of Object.keys(flags.bools)) {
setArg(key, defaults[key] === void 0 ? false : defaults[key]);
}
let notFlags = [];
if (args.includes("--")) {
notFlags = args.slice(args.indexOf("--") + 1);
args = args.slice(0, args.indexOf("--"));
}
for (let i = 0; i < args.length; i++) {
const arg = args[i];
if (/^--.+=/.test(arg)) {
const m = arg.match(/^--([^=]+)=(.*)$/s);
assert(m != null);
const [, key, value] = m;
if (flags.bools[key]) {
const booleanValue = value !== "false";
setArg(key, booleanValue, arg);
} else {
setArg(key, value, arg);
}
} else if (/^--no-.+/.test(arg)) {
const m = arg.match(/^--no-(.+)/);
assert(m != null);
setArg(m[1], false, arg);
} else if (/^--.+/.test(arg)) {
const m = arg.match(/^--(.+)/);
assert(m != null);
const [, key] = m;
const next = args[i + 1];
if (next !== void 0 && !/^-/.test(next) && !get(flags.bools, key) && !flags.allBools && (get(aliases, key) ? !aliasIsBoolean(key) : true)) {
setArg(key, next, arg);
i++;
} else if (/^(true|false)$/.test(next)) {
setArg(key, next === "true", arg);
i++;
} else {
setArg(key, get(flags.strings, key) ? "" : true, arg);
}
} else if (/^-[^-]+/.test(arg)) {
const letters = arg.slice(1, -1).split("");
let broken = false;
for (let j = 0; j < letters.length; j++) {
const next = arg.slice(j + 2);
if (next === "-") {
setArg(letters[j], next, arg);
continue;
}
if (/[A-Za-z]/.test(letters[j]) && /=/.test(next)) {
setArg(letters[j], next.split(/=(.+)/)[1], arg);
broken = true;
break;
}
if (/[A-Za-z]/.test(letters[j]) && /-?\d+(\.\d*)?(e-?\d+)?$/.test(next)) {
setArg(letters[j], next, arg);
broken = true;
break;
}
if (letters[j + 1] && letters[j + 1].match(/\W/)) {
setArg(letters[j], arg.slice(j + 2), arg);
broken = true;
break;
} else {
setArg(letters[j], get(flags.strings, letters[j]) ? "" : true, arg);
}
}
const [key] = arg.slice(-1);
if (!broken && key !== "-") {
if (args[i + 1] && !/^(-|--)[^-]/.test(args[i + 1]) && !get(flags.bools, key) && (get(aliases, key) ? !aliasIsBoolean(key) : true)) {
setArg(key, args[i + 1], arg);
i++;
} else if (args[i + 1] && /^(true|false)$/.test(args[i + 1])) {
setArg(key, args[i + 1] === "true", arg);
i++;
} else {
setArg(key, get(flags.strings, key) ? "" : true, arg);
}
}
} else {
if (!flags.unknownFn || flags.unknownFn(arg) !== false) {
argv._.push(flags.strings["_"] ?? !isNumber(arg) ? arg : Number(arg));
}
if (stopEarly) {
argv._.push(...args.slice(i + 1));
break;
}
}
}
for (const key of Object.keys(defaults)) {
if (!hasKey(argv, key.split("."))) {
setKey(argv, key.split("."), defaults[key]);
if (aliases[key]) {
for (const x of aliases[key]) {
setKey(argv, x.split("."), defaults[key]);
}
}
}
}
if (doubleDash) {
argv["--"] = [];
for (const key of notFlags) {
argv["--"].push(key);
}
} else {
for (const key of notFlags) {
argv._.push(key);
}
}
return argv;
}
// http/file_server.ts
var import_meta = {};
var encoder = new TextEncoder();
var serverArgs = parse4(Deno.args);
var target = posix.resolve(serverArgs._[0] ?? "");
var MEDIA_TYPES = {
".md": "text/markdown",
".html": "text/html",
".htm": "text/html",
".json": "application/json",
".map": "application/json",
".txt": "text/plain",
".ts": "text/typescript",
".tsx": "text/tsx",
".js": "application/javascript",
".jsx": "text/jsx",
".gz": "application/gzip",
".css": "text/css",
".wasm": "application/wasm",
".mjs": "application/javascript",
".svg": "image/svg+xml"
};
function contentType(path2) {
return MEDIA_TYPES[extname3(path2)];
}
function modeToString(isDir, maybeMode) {
const modeMap = ["---", "--x", "-w-", "-wx", "r--", "r-x", "rw-", "rwx"];
if (maybeMode === null) {
return "(unknown mode)";
}
const mode = maybeMode.toString(8);
if (mode.length < 3) {
return "(unknown mode)";
}
let output = "";
mode.split("").reverse().slice(0, 3).forEach((v) => {
output = modeMap[+v] + output;
});
output = `(${isDir ? "d" : "-"}${output})`;
return output;
}
function fileLenToString(len) {
const multiplier = 1024;
let base = 1;
const suffix = ["B", "K", "M", "G", "T"];
let suffixIndex = 0;
while (base * multiplier < len) {
if (suffixIndex >= suffix.length - 1) {
break;
}
base *= multiplier;
suffixIndex++;
}
return `${(len / base).toFixed(2)}${suffix[suffixIndex]}`;
}
async function serveFile(req, filePath) {
const [file, fileInfo] = await Promise.all([
Deno.open(filePath),
Deno.stat(filePath)
]);
const headers = new Headers();
headers.set("content-length", fileInfo.size.toString());
const contentTypeValue = contentType(filePath);
if (contentTypeValue) {
headers.set("content-type", contentTypeValue);
}
req.done.then(() => {
file.close();
});
return {
status: 200,
body: file,
headers
};
}
async function serveDir(req, dirPath) {
const showDotfiles = serverArgs.dotfiles ?? true;
const dirUrl = `/${posix.relative(target, dirPath)}`;
const listEntry = [];
if (dirUrl !== "/") {
const prevPath = posix.join(dirPath, "..");
const fileInfo = await Deno.stat(prevPath);
listEntry.push({
mode: modeToString(true, fileInfo.mode),
size: "",
name: "../",
url: posix.join(dirUrl, "..")
});
}
for await (const entry of Deno.readDir(dirPath)) {
if (!showDotfiles && entry.name[0] === ".") {
continue;
}
const filePath = posix.join(dirPath, entry.name);
const fileUrl = posix.join(dirUrl, entry.name);
if (entry.name === "index.html" && entry.isFile) {
return serveFile(req, filePath);
}
const fileInfo = await Deno.stat(filePath);
listEntry.push({
mode: modeToString(entry.isDirectory, fileInfo.mode),
size: entry.isFile ? fileLenToString(fileInfo.size ?? 0) : "",
name: `${entry.name}${entry.isDirectory ? "/" : ""}`,
url: fileUrl
});
}
listEntry.sort((a, b) => a.name.toLowerCase() > b.name.toLowerCase() ? 1 : -1);
const formattedDirUrl = `${dirUrl.replace(/\/$/, "")}/`;
const page = encoder.encode(dirViewerTemplate(formattedDirUrl, listEntry));
const headers = new Headers();
headers.set("content-type", "text/html");
const res = {
status: 200,
body: page,
headers
};
return res;
}
function serveFallback(req, e) {
if (e instanceof URIError) {
return Promise.resolve({
status: 400,
body: encoder.encode("Bad Request")
});
} else if (e instanceof Deno.errors.NotFound) {
return Promise.resolve({
status: 404,
body: encoder.encode("Not Found")
});
} else {
return Promise.resolve({
status: 500,
body: encoder.encode("Internal server error")
});
}
}
function serverLog(req, res) {
const d = new Date().toISOString();
const dateFmt = `[${d.slice(0, 10)} ${d.slice(11, 19)}]`;
const s = `${dateFmt} "${req.method} ${req.url} ${req.proto}" ${res.status}`;
console.log(s);
}
function setCORS(res) {
if (!res.headers) {
res.headers = new Headers();
}
res.headers.append("access-control-allow-origin", "*");
res.headers.append("access-control-allow-headers", "Origin, X-Requested-With, Content-Type, Accept, Range");
}
function dirViewerTemplate(dirname4, entries) {
return html`
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8" />
<meta name="viewport" content="width=device-width, initial-scale=1.0" />
<meta http-equiv="X-UA-Compatible" content="ie=edge" />
<title>Deno File Server</title>
<style>
:root {
--background-color: #fafafa;
--color: rgba(0, 0, 0, 0.87);
}
@media (prefers-color-scheme: dark) {
:root {
--background-color: #303030;
--color: #fff;
}
}
@media (min-width: 960px) {
main {
max-width: 960px;
}
body {
padding-left: 32px;
padding-right: 32px;
}
}
@media (min-width: 600px) {
main {
padding-left: 24px;
padding-right: 24px;
}
}
body {
background: var(--background-color);
color: var(--color);
font-family: "Roboto", "Helvetica", "Arial", sans-serif;
font-weight: 400;
line-height: 1.43;
font-size: 0.875rem;
}
a {
color: #2196f3;
text-decoration: none;
}
a:hover {
text-decoration: underline;
}
table th {
text-align: left;
}
table td {
padding: 12px 24px 0 0;
}
</style>
</head>
<body>
<main>
<h1>Index of ${dirname4}</h1>
<table>
<tr>
<th>Mode</th>
<th>Size</th>
<th>Name</th>
</tr>
${entries.map((entry) => html`
<tr>
<td class="mode">
${entry.mode}
</td>
<td>
${entry.size}
</td>
<td>
<a href="${entry.url}">${entry.name}</a>
</td>
</tr>
`)}
</table>
</main>
</body>
</html>
`;
}
function html(strings, ...values) {
const l = strings.length - 1;
let html2 = "";
for (let i = 0; i < l; i++) {
let v = values[i];
if (v instanceof Array) {
v = v.join("");
}
const s = strings[i] + v;
html2 += s;
}
html2 += strings[l];
return html2;
}
function normalizeURL(url) {
let normalizedUrl = url;
try {
normalizedUrl = decodeURI(normalizedUrl);
} catch (e) {
if (!(e instanceof URIError)) {
throw e;
}
}
try {
const absoluteURI = new URL(normalizedUrl);
normalizedUrl = absoluteURI.pathname;
} catch (e) {
if (!(e instanceof TypeError)) {
throw e;
}
}
if (normalizedUrl[0] !== "/") {
throw new URIError("The request URI is malformed.");
}
normalizedUrl = posix.normalize(normalizedUrl);
const startOfParams = normalizedUrl.indexOf("?");
return startOfParams > -1 ? normalizedUrl.slice(0, startOfParams) : normalizedUrl;
}
function main() {
const CORSEnabled = serverArgs.cors ? true : false;
const port = serverArgs.port ?? serverArgs.p ?? 4507;
const host = serverArgs.host ?? "0.0.0.0";
const addr = `${host}:${port}`;
const tlsOpts = {};
tlsOpts.certFile = serverArgs.cert ?? serverArgs.c ?? "";
tlsOpts.keyFile = serverArgs.key ?? serverArgs.k ?? "";
const dirListingEnabled = serverArgs["dir-listing"] ?? true;
if (tlsOpts.keyFile || tlsOpts.certFile) {
if (tlsOpts.keyFile === "" || tlsOpts.certFile === "") {
console.log("--key and --cert are required for TLS");
serverArgs.h = true;
}
}
if (serverArgs.h ?? serverArgs.help) {
console.log(`Deno File Server
Serves a local directory in HTTP.
INSTALL:
deno install --allow-net --allow-read https://deno.land/std/http/file_server.ts
USAGE:
file_server [path] [options]
OPTIONS:
-h, --help Prints help information
-p, --port <PORT> Set port
--cors Enable CORS via the "Access-Control-Allow-Origin" header
--host <HOST> Hostname (default is 0.0.0.0)
-c, --cert <FILE> TLS certificate file (enables TLS)
-k, --key <FILE> TLS key file (enables TLS)
--no-dir-listing Disable directory listing
--no-dotfiles Do not show dotfiles
All TLS options are required when one is provided.`);
Deno.exit();
}
const handler = async (req) => {
let response;
try {
const normalizedUrl = normalizeURL(req.url);
let fsPath = posix.join(target, normalizedUrl);
if (fsPath.indexOf(target) !== 0) {
fsPath = target;
}
const fileInfo = await Deno.stat(fsPath);
if (fileInfo.isDirectory) {
if (dirListingEnabled) {
response = await serveDir(req, fsPath);
} else {
throw new Deno.errors.NotFound();
}
} else {
response = await serveFile(req, fsPath);
}
} catch (e) {
console.error(e.message);
response = await serveFallback(req, e);
} finally {
if (CORSEnabled) {
assert(response);
setCORS(response);
}
serverLog(req, response);
try {
await req.respond(response);
} catch (e) {
console.error(e.message);
}
}
};
let proto = "http";
if (tlsOpts.keyFile || tlsOpts.certFile) {
proto += "s";
tlsOpts.hostname = host;
tlsOpts.port = port;
listenAndServeTLS(tlsOpts, handler);
} else {
listenAndServe(addr, handler);
}
console.log(`${proto.toUpperCase()} server listening on ${proto}://${addr}/`);
}
// with the if statement uncommented, `deno run` simply exits
// if (import_meta.main) {
main();
// }
})();
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment