Skip to content

Instantly share code, notes, and snippets.

@friendlyanon
Last active September 19, 2018 18:55
Show Gist options
  • Save friendlyanon/2dbaacb858bab49e0e6b1ac2ce8d1f51 to your computer and use it in GitHub Desktop.
Save friendlyanon/2dbaacb858bab49e0e6b1ac2ce8d1f51 to your computer and use it in GitHub Desktop.
import { Server } from "_http_server";
const Aya = class Aya {
constructor() {
this.routes = {
GET: [],
HEAD: [],
POST: [],
PUT: [],
DELETE: [],
CONNECT: [],
OPTIONS: [],
TRACE: [],
PATCH: [],
};
this.middleware = [];
}
use(func) {
return this.middleware.push(func), this;
}
route(method, route, ...func) {
const upper = method.toUpperCase();
if (
!this.routes.hasOwnProperty(upper) ||
typeof route !== "string"
) throw new Error("Invalid route setup");
this.routes[upper].push([
route.split("/").slice(1).filter(this._validateRoute),
func
]);
return this;
}
start(port) {
this.server = new this._Server(this._serverHandler).listen({ port });
this.server.__ayaInstance = this;
console.log("Listening on port %i", port);
}
_serverHandler(req, res) {
const self = this.__ayaInstance;
self._handler(req, res, self.routes, self.middleware);
}
_validateRoute(str) {
return str.length > 0;
}
async _handler(req, res, routes, middleware) {
try { for (const f of middleware) await f(req, res); }
catch (err) { return res.end(err.message); }
const path = req.url.split("/").filter(this._validateRoute);
const pathLen = path.length;
let fns;
for (const { 0: info, 1: funcs } of routes[req.method]) {
if (pathLen !== info.length) continue;
const params = {};
let j = 0;
for (let len = info.length; j < len; ++j) {
const part = info[j];
if (part.charCodeAt() === 58) params[part.substring(1)] = path[j];
else if (path[j] !== part) break;
}
if (j !== info.length) continue;
req.params = params;
fns = funcs;
break;
}
if (fns == null) return res.end("Invalid route");
try {
const { hasOwnProperty: has } = arguments;
for (const f of fns) {
if (typeof f === "function") await f(req, res);
else for (const k in f) if (has.call(f, k)) req[k] = f[k];
}
}
catch (err) { res.end(err.message); }
}
}; // class Aya
// enumerable properties in the prototype chain are verboten
Object.defineProperties(Aya.prototype, {
_Server: {
value: Server,
writable: true,
configurable: true,
},
});
Object.defineProperties(Aya, {
Aya: {
value: Aya,
writable: true,
configurable: true,
},
});
export default Aya;
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment