@worker-tools/deno-fetch-event-adapter
Version:
Dispatches global `fetch` events using Deno's native HTTP server.
349 lines (346 loc) • 11.4 kB
JavaScript
// deno-fmt-ignore-file
// deno-lint-ignore-file
// This code was bundled using `deno bundle` and it's not recommended to edit it manually
class DenoStdInternalError extends Error {
constructor(message){
super(message);
this.name = "DenoStdInternalError";
}
}
function assert(expr, msg = "") {
if (!expr) {
throw new DenoStdInternalError(msg);
}
}
const { hasOwn } = Object;
function get(obj, key) {
if (hasOwn(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((key)=>{
o = get(o, key) ?? {};
});
const key1 = keys[keys.length - 1];
return key1 in o;
}
function parse(args, { "--": doubleDash = false , alias: alias3 = {} , boolean: __boolean = false , default: defaults = {} , stopEarly =false , string =[] , unknown =(i)=>i
} = {}) {
const flags = {
bools: {},
strings: {},
unknownFn: unknown,
allBools: false
};
if (__boolean !== undefined) {
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 (alias3 !== undefined) {
for(const key in alias3){
const val = getForce(alias3, key);
if (typeof val === "string") {
aliases[key] = [
val
];
} else {
aliases[key] = val;
}
for (const alias1 of getForce(aliases, key)){
aliases[alias1] = [
key
].concat(aliases[key].filter((y)=>alias1 !== y
));
}
}
}
if (string !== undefined) {
const stringArgs = typeof string === "string" ? [
string
] : string;
for (const key of stringArgs.filter(Boolean)){
flags.strings[key] = true;
const alias = get(aliases, key);
if (alias) {
for (const al of alias){
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(key) {
if (get(o, key) === undefined) {
o[key] = {};
}
o = get(o, key);
});
const key4 = keys[keys.length - 1];
if (get(o, key4) === undefined || get(flags.bools, key4) || typeof get(o, key4) === "boolean") {
o[key4] = value;
} else if (Array.isArray(get(o, key4))) {
o[key4].push(value);
} else {
o[key4] = [
get(o, key4),
value
];
}
}
function setArg(key, val, arg = undefined) {
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 alias = get(aliases, key);
if (alias) {
for (const x of alias){
setKey(argv, x.split("."), value);
}
}
}
function aliasIsBoolean(key) {
return getForce(aliases, key).some((x)=>typeof get(flags.bools, x) === "boolean"
);
}
for (const key3 of Object.keys(flags.bools)){
setArg(key3, defaults[key3] === undefined ? false : defaults[key3]);
}
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 !== undefined && !/^-/.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 key2 of Object.keys(defaults)){
if (!hasKey(argv, key2.split("."))) {
setKey(argv, key2.split("."), defaults[key2]);
if (aliases[key2]) {
for (const x of aliases[key2]){
setKey(argv, x.split("."), defaults[key2]);
}
}
}
}
if (doubleDash) {
argv["--"] = [];
for (const key of notFlags){
argv["--"].push(key);
}
} else {
for (const key of notFlags){
argv._.push(key);
}
}
return argv;
}
const importMeta = {
url: "file:///home/runner/work/deno-fetch-event-adapter/deno-fetch-event-adapter/listen.ts",
main: import.meta.main
};
class AdaptedFetchEvent extends Event {
#event;
#request;
constructor(event, hostname){
super('fetch');
if (typeof event === 'string' || typeof hostname === 'object') throw Error('Overload not implemented');
this.#event = event;
const headers = new Headers([
...this.#event.request.headers,
...hostname ? [
[
'x-forwarded-for',
hostname
]
] : [],
]);
this.#request = new Proxy(this.#event.request, {
get (target, prop) {
return prop === 'headers' ? headers : Reflect.get(target, prop);
}
});
}
get request() {
return this.#request;
}
respondWith(r) {
this.#event.respondWith(r);
}
waitUntil(_f) {}
get clientId() {
return '';
}
get preloadResponse() {
return Promise.resolve();
}
get replacesClientId() {
return '';
}
get resultingClientId() {
return '';
}
}
Object.defineProperty(self, 'FetchEvent', {
configurable: false,
enumerable: false,
writable: false,
value: AdaptedFetchEvent
});
const NAME = 'Deno Fetch Event Adapter';
(async ()=>{
let server;
if (!self.location) {
throw new Error(`${NAME}: When using Deno Fetch Event Adapter, a --location is required.`);
}
if (self.location.protocol === 'https:' || self.location.port === '433') {
const { cert: certFile , key: keyFile } = parse(Deno.args, {
alias: {
cert: [
'c',
'cert-file'
],
key: [
'k',
'key-file'
]
}
});
if (!certFile || !keyFile) {
throw new Error(`${NAME}: When using HTTPS or port 443, a --cert and --key are required.`);
}
server = Deno.listenTls({
hostname: self.location.hostname,
port: Number(self.location.port || 443),
certFile,
keyFile
});
} else {
server = Deno.listen({
hostname: self.location.hostname,
port: Number(self.location.port || 80)
});
}
for await (const conn of server){
(async ()=>{
try {
for await (const event of Deno.serveHttp(conn)){
const { hostname } = conn.remoteAddr;
self.dispatchEvent(new AdaptedFetchEvent(event, hostname));
}
} catch (error) {
self.dispatchEvent(new ErrorEvent('error', {
message: error?.message,
filename: importMeta.url,
error
}));
}
})();
}
})();