feat(project) cleanup, removed dependencies, updated structure
This commit is contained in:
21
src/IO/LayRequest.js
Normal file
21
src/IO/LayRequest.js
Normal file
@@ -0,0 +1,21 @@
|
||||
import RequestParser from '../Utils/RequestParser';
|
||||
|
||||
export default class LayRequest extends Request {
|
||||
body = null;
|
||||
constructor(req) {
|
||||
super(req);
|
||||
|
||||
this.params = new Map();
|
||||
this.query = new Map();
|
||||
|
||||
this.parseBody(req);
|
||||
}
|
||||
|
||||
header(key) {
|
||||
this.headers?.get(key);
|
||||
}
|
||||
|
||||
async parseBody(req) {
|
||||
this.body = await RequestParser(req);
|
||||
}
|
||||
}
|
||||
102
src/IO/LayResponse.js
Normal file
102
src/IO/LayResponse.js
Normal file
@@ -0,0 +1,102 @@
|
||||
import MimeTypeMap from './MimeTypeMap';
|
||||
|
||||
export default class LayResponse {
|
||||
body;
|
||||
statusCode;
|
||||
headerList = new Map();
|
||||
mimeType;
|
||||
options = {
|
||||
disableFileCheck: false,
|
||||
};
|
||||
|
||||
constructor(router) {
|
||||
this.router = router;
|
||||
this.body = 'Not Implemented';
|
||||
this.statusCode = 502;
|
||||
this.headerList = new Map();
|
||||
this.mimeType = 'text/plain';
|
||||
}
|
||||
|
||||
async send(str) {
|
||||
this.type('text');
|
||||
this.body = str;
|
||||
|
||||
if (this.options.disableFileCheck) return;
|
||||
try {
|
||||
const temp = Bun.file(str);
|
||||
|
||||
if (await temp.exists()) {
|
||||
this.file = str;
|
||||
}
|
||||
} catch (err) {}
|
||||
}
|
||||
|
||||
json(data, options = {}) {
|
||||
let { replacer, space } = options;
|
||||
if (!Array.isArray(replacer) && typeof replacer != 'function') {
|
||||
replacer = null;
|
||||
}
|
||||
if (isNaN(space) || Math.floor(space) < 0) {
|
||||
space = 0;
|
||||
}
|
||||
this.type('json');
|
||||
this.body = JSON.stringify(data, replacer, space);
|
||||
}
|
||||
|
||||
type(key) {
|
||||
if (!MimeTypeMap.has(key)) {
|
||||
this.mimeType = MimeTypeMap.get('text');
|
||||
return;
|
||||
}
|
||||
this.mimeType = MimeTypeMap.get(key);
|
||||
}
|
||||
|
||||
status(value = null) {
|
||||
if (isNaN(value)) throw new Error('status has to be a number');
|
||||
this.statusCode = value || 502;
|
||||
}
|
||||
|
||||
text(value = null) {
|
||||
if (typeof value != 'string') {
|
||||
value = JSON.stringify(value);
|
||||
}
|
||||
|
||||
this.type('text');
|
||||
this.body = value;
|
||||
}
|
||||
|
||||
json(value = null) {
|
||||
this.text(value);
|
||||
this.type('json');
|
||||
}
|
||||
|
||||
redirect(value = null, status = 302) {
|
||||
if (value === null) {
|
||||
return this.redirectUrl;
|
||||
}
|
||||
|
||||
this.redirectUrl = value;
|
||||
this.status(status);
|
||||
}
|
||||
|
||||
headers() {
|
||||
if (!this.headerList.get('Content-Type')) {
|
||||
this.headerList.set('Content-Type', `${this.mimeType}`);
|
||||
}
|
||||
return this.headerList;
|
||||
}
|
||||
|
||||
header(key, value) {
|
||||
this.headerList.set(key, value);
|
||||
}
|
||||
|
||||
build(options = {}) {
|
||||
if (this.redirectUrl) {
|
||||
return Response.redirect(this.redirectUrl, this.status());
|
||||
}
|
||||
return new Response(this.body, {
|
||||
status: this.status(),
|
||||
headers: this.headers(),
|
||||
});
|
||||
}
|
||||
}
|
||||
24
src/IO/MimeTypeMap.js
Normal file
24
src/IO/MimeTypeMap.js
Normal file
@@ -0,0 +1,24 @@
|
||||
export default new Map([
|
||||
['text', 'text/plain'],
|
||||
['html', 'text/html'],
|
||||
['css', 'text/css'],
|
||||
['csv', 'text/csv'],
|
||||
['js', 'text/javascript'],
|
||||
['gif', 'image/gif'],
|
||||
['jpeg', 'image/jpeg'],
|
||||
['png', 'image/png'],
|
||||
['svg', 'image/svg+xml'],
|
||||
['midi', 'audio/midi'],
|
||||
['mp3', 'audio/mpeg'],
|
||||
['oga', 'audio/ogg'],
|
||||
['mp4', 'video/mp4'],
|
||||
['mpeg', 'video/mpeg'],
|
||||
['ogv', 'video/ogg'],
|
||||
['zip', 'application/zip'],
|
||||
['pdf', 'application/pdf'],
|
||||
['epub', 'application/epub+zip'],
|
||||
['gz', 'application/gzip'],
|
||||
['bin', 'application/octet-stream'],
|
||||
['json', 'application/json'],
|
||||
['jsonld', 'application/ld+json'],
|
||||
]);
|
||||
168
src/LayServer.js
Normal file
168
src/LayServer.js
Normal file
@@ -0,0 +1,168 @@
|
||||
import { resolve as resolvePath } from 'path';
|
||||
import Router from './Routing/Router';
|
||||
import LayRouting from './Routing/LayRouting';
|
||||
import HtmlEngine from './Views/HtmlEngine';
|
||||
|
||||
export default class LayServer {
|
||||
controllers = new Map();
|
||||
proc = null;
|
||||
router;
|
||||
publicFiles;
|
||||
options = new Map([
|
||||
['publicDir', undefined],
|
||||
['viewsPath', undefined],
|
||||
['viewsEngine', undefined],
|
||||
['onlySingleRoutes', true],
|
||||
['preferIndexFiles', false],
|
||||
['discoverPublicFiles', true],
|
||||
['enforceTrailingSlash', true],
|
||||
]);
|
||||
|
||||
constructor(options = {}) {
|
||||
if (typeof options == 'object') {
|
||||
const optionKeys = Object.getOwnPropertyNames(options);
|
||||
|
||||
for (const key of optionKeys) {
|
||||
if (!this.options.has(key)) continue;
|
||||
const valueType = typeof this.options.get(key);
|
||||
if (typeof options[key] == valueType)
|
||||
this.options.set(key, options[key]);
|
||||
}
|
||||
}
|
||||
|
||||
this.initRouting(options.router);
|
||||
|
||||
if (options.hasOwnProperty('controllers')) {
|
||||
this.registerControllers(options.controllers);
|
||||
}
|
||||
|
||||
if (options.publicFiles) {
|
||||
this.addPublicFileRoutes(options.publicFiles);
|
||||
}
|
||||
|
||||
if (
|
||||
!options.publicFiles &&
|
||||
this.options.discoverPublicFiles &&
|
||||
this.options.publicDir
|
||||
)
|
||||
this.indexPublicFiles(this.options.publicDir);
|
||||
|
||||
if (!this.options.viewsEngine && this.options.viewsPath) {
|
||||
this.options.viewsEngine = new HtmlEngine();
|
||||
}
|
||||
}
|
||||
|
||||
option(key, value = undefined) {
|
||||
if (!this.options.has(key)) return undefined;
|
||||
if (value !== undefined) this.option.set(key, value);
|
||||
return this.options.get(key);
|
||||
}
|
||||
|
||||
addPublicFileRoutes(filePaths) {
|
||||
if (!filePaths) return;
|
||||
if (!Array.isArray(filePaths))
|
||||
throw new Error(
|
||||
'publicFiles option has to be an array or undefined'
|
||||
);
|
||||
for (let path of filePaths) {
|
||||
}
|
||||
}
|
||||
|
||||
indexPublicFiles(publicDir) {}
|
||||
|
||||
initRouting(router = null) {
|
||||
if (router) this.router = new router(this);
|
||||
if (typeof this.router == 'undefined') this.router = new Router(this);
|
||||
this.routeControl = new LayRouting(this.router);
|
||||
}
|
||||
|
||||
registerControllers(controllers) {
|
||||
if (!Array.isArray(controllers))
|
||||
throw new Error('controllers is not an Array');
|
||||
|
||||
for (let controller of controllers) {
|
||||
if (typeof controller != 'function') {
|
||||
console.log(`ignored ${controller} for not being a function`);
|
||||
continue;
|
||||
}
|
||||
|
||||
this.controllers.set(
|
||||
controller.name,
|
||||
this.instantiateController(controller)
|
||||
);
|
||||
}
|
||||
}
|
||||
|
||||
instantiateController(controller) {
|
||||
this.routeControl.setNamespace(controller.namespace);
|
||||
const _temp = new controller(this.routeControl);
|
||||
if (controller.namespace) this.routeControl.setNamespace(null);
|
||||
return _temp;
|
||||
}
|
||||
|
||||
isRunning() {
|
||||
proc != null;
|
||||
}
|
||||
|
||||
async handleRequest(req) {
|
||||
const url = new URL(req.url);
|
||||
|
||||
if (
|
||||
!url.pathname.endsWith('/') &&
|
||||
Array.isArray(this.publicFiles) &&
|
||||
this.publicFiles.length > 0
|
||||
) {
|
||||
let path = this.publicFiles.find(
|
||||
(v) => url.pathname.substring(1) === v
|
||||
);
|
||||
if (path) {
|
||||
try {
|
||||
return new Response(
|
||||
Bun.file(resolvePath(import.meta.dir, 'public', path))
|
||||
);
|
||||
} catch (err) {
|
||||
console.log(err);
|
||||
return new Response('Internal Server Error', {
|
||||
status: 500,
|
||||
});
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
if (this.options.enforceTrailingSlash && !url.pathname.endsWith('/')) {
|
||||
return Response.redirect(`${url.toString()}/`, 302);
|
||||
}
|
||||
|
||||
return await this.router.handle(req);
|
||||
}
|
||||
|
||||
listen(port = 3000) {
|
||||
try {
|
||||
this.proc = Bun.serve({
|
||||
port,
|
||||
development: Bun.env.BUN_ENV != 'production',
|
||||
fetch: this.handleRequest.bind(this),
|
||||
error(err) {
|
||||
console.log(err.stack);
|
||||
return new Response(`<pre>${err}\n${err.stack}</pre>`, {
|
||||
headers: {
|
||||
'Content-Type': 'text/html',
|
||||
},
|
||||
});
|
||||
},
|
||||
});
|
||||
|
||||
if (!this.proc) {
|
||||
throw new Error('something went wrong');
|
||||
}
|
||||
|
||||
console.log(
|
||||
this.proc,
|
||||
`listening on ${this.proc.hostname} with port ${this.proc.port}`
|
||||
);
|
||||
} catch (err) {
|
||||
console.log('where', err.stack);
|
||||
console.error(err);
|
||||
}
|
||||
}
|
||||
}
|
||||
3
src/Routing/BaseController.js
Normal file
3
src/Routing/BaseController.js
Normal file
@@ -0,0 +1,3 @@
|
||||
export default class BaseController {
|
||||
constructor() {}
|
||||
}
|
||||
84
src/Routing/LayRouting.js
Normal file
84
src/Routing/LayRouting.js
Normal file
@@ -0,0 +1,84 @@
|
||||
export default class LayRouting {
|
||||
router;
|
||||
namespace;
|
||||
constructor(router, namespace = null) {
|
||||
this.router = router;
|
||||
|
||||
if (namespace !== null) this.namespace = namespace;
|
||||
}
|
||||
|
||||
setNamespace(ns) {
|
||||
if (!ns || typeof ns != 'string') this.namespace = null;
|
||||
this.namespace = ns;
|
||||
}
|
||||
|
||||
routes() {
|
||||
return this.router.routes;
|
||||
}
|
||||
|
||||
add(path, cb, method) {
|
||||
if (this.namespace) {
|
||||
if (!path.startsWith('/')) path = '/' + path;
|
||||
path = this.namespace + path;
|
||||
}
|
||||
|
||||
this.router.add(path, cb, method);
|
||||
}
|
||||
|
||||
route(config = {}) {
|
||||
if (typeof config != 'object')
|
||||
throw new Error('route config is not an object');
|
||||
|
||||
const { path, handle, method = 'get' } = config;
|
||||
if (typeof path != 'string')
|
||||
throw new Error('route path is not a string');
|
||||
if (typeof handle != 'function')
|
||||
throw new Error('route handle is not a function');
|
||||
this.add(path, handle, method);
|
||||
return this;
|
||||
}
|
||||
|
||||
any(path, cb) {
|
||||
this.all(path, cb);
|
||||
}
|
||||
|
||||
all(path, cb) {
|
||||
this.add(path, cb, 'all');
|
||||
return this;
|
||||
}
|
||||
|
||||
get(path, cb) {
|
||||
this.add(path, cb, 'get');
|
||||
return this;
|
||||
}
|
||||
|
||||
post(path, cb) {
|
||||
this.add(path, cb, 'post');
|
||||
return this;
|
||||
}
|
||||
|
||||
put(path, cb) {
|
||||
this.add(path, cb, 'put');
|
||||
return this;
|
||||
}
|
||||
|
||||
patch(path, cb) {
|
||||
this.add(path, cb, 'patch');
|
||||
return this;
|
||||
}
|
||||
|
||||
delete(path, cb) {
|
||||
this.add(path, cb, 'delete');
|
||||
return this;
|
||||
}
|
||||
|
||||
head(path, cb) {
|
||||
this.add(path, cb, 'head');
|
||||
return this;
|
||||
}
|
||||
|
||||
options(path, cb) {
|
||||
this.add(path, cb, 'options');
|
||||
return this;
|
||||
}
|
||||
}
|
||||
251
src/Routing/Router.js
Normal file
251
src/Routing/Router.js
Normal file
@@ -0,0 +1,251 @@
|
||||
import LayRequest from '../IO/LayRequest';
|
||||
import LayResponse from '../IO/LayResponse';
|
||||
import RequestParser from '../Utils/RequestParser';
|
||||
|
||||
export default class Router {
|
||||
server = undefined;
|
||||
routes = new Map();
|
||||
static allMethodKey = '$all';
|
||||
static methods = ['all', 'get', 'post', 'put', 'patch', 'head', 'options'];
|
||||
headerList = new Map();
|
||||
|
||||
constructor(server) {
|
||||
this.server = server;
|
||||
}
|
||||
|
||||
async handle(req) {
|
||||
if (!(req instanceof Request)) {
|
||||
throw new Error('`req` is not a proper Request');
|
||||
}
|
||||
|
||||
let method = (req.method || '').toString().toLowerCase();
|
||||
const methodKey = `$${method.toLowerCase()}`;
|
||||
let path;
|
||||
let url = req.url;
|
||||
|
||||
if (!(url instanceof URL) && typeof url == 'string') {
|
||||
url = new URL(url);
|
||||
path = url.pathname;
|
||||
}
|
||||
if (path.startsWith('/')) path = path.substring(1);
|
||||
if (path.endsWith('/')) path = path.substring(0, path.length - 1);
|
||||
|
||||
let currentNode = this.routes;
|
||||
let paramsList = [];
|
||||
|
||||
if (path != '') {
|
||||
let segments = path.split('/');
|
||||
for (let index = 0; index < segments.length; index++) {
|
||||
const segment = segments[index];
|
||||
|
||||
if (currentNode.has(segment)) {
|
||||
currentNode = currentNode.get(segment);
|
||||
continue;
|
||||
}
|
||||
|
||||
if (currentNode.has(':') || currentNode.has('?')) {
|
||||
paramsList.push(segment);
|
||||
currentNode = currentNode.get(':') ?? currentNode.get('?');
|
||||
continue;
|
||||
}
|
||||
|
||||
currentNode = null;
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
if (
|
||||
!(currentNode instanceof Map) ||
|
||||
(['get', 'head'].indexOf(method) < 0 &&
|
||||
!currentNode.has(methodKey) &&
|
||||
!currentNode.has(Router.allMethodKey))
|
||||
) {
|
||||
return new Response(`[${method}] Method Not Allowed`, {
|
||||
status: 405,
|
||||
});
|
||||
}
|
||||
|
||||
if (
|
||||
!currentNode.has(methodKey) &&
|
||||
!currentNode.get(Router.allMethodKey)
|
||||
) {
|
||||
return new Response(`Not Implemented: [${method}, ${req.url}]`, {
|
||||
status: 501,
|
||||
});
|
||||
}
|
||||
|
||||
const reqContext = {
|
||||
request: null,
|
||||
response: null,
|
||||
};
|
||||
try {
|
||||
reqContext.request = new LayRequest(req);
|
||||
reqContext.response = new LayResponse(this);
|
||||
} catch (err) {
|
||||
console.log(err);
|
||||
}
|
||||
let handle =
|
||||
currentNode.get(methodKey) || currentNode.get(Router.allMethodKey);
|
||||
|
||||
if (typeof handle == 'object' && typeof handle.callback == 'function') {
|
||||
if (Array.isArray(handle.params)) {
|
||||
for (const name of handle.params) {
|
||||
let value = paramsList[reqContext.request.params.size];
|
||||
if (reqContext.request.params.has(name)) {
|
||||
let yet = reqContext.request.params.get(name);
|
||||
if (!Array.isArray(yet)) {
|
||||
yet = [yet];
|
||||
}
|
||||
yet.push(value);
|
||||
value = yet;
|
||||
}
|
||||
reqContext.request.params.set(name, value);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
try {
|
||||
const retVal = await handle.callback(
|
||||
reqContext.request,
|
||||
reqContext.response
|
||||
);
|
||||
if (typeof retVal != 'undefined') {
|
||||
if (retVal instanceof Response) {
|
||||
return retVal;
|
||||
} else if (typeof retVal == 'string') {
|
||||
reqContext.response.send(retVal);
|
||||
} else {
|
||||
reqContext.response.json(retVal);
|
||||
}
|
||||
}
|
||||
} catch (err) {
|
||||
console.log(err);
|
||||
return new Response('Error', { status: 500 });
|
||||
}
|
||||
|
||||
if (reqContext.response.redirect()) {
|
||||
return Response.redirect(
|
||||
reqContext.response.redirect,
|
||||
reqContext.response.status || 302
|
||||
);
|
||||
}
|
||||
|
||||
return new Response(reqContext.response.body, {
|
||||
status: reqContext.response.status() || 200,
|
||||
headers: reqContext.response.headers() || {},
|
||||
});
|
||||
}
|
||||
|
||||
add(route, callback, method = 'get', middleware = null) {
|
||||
if (typeof callback != 'function')
|
||||
throw new Error('`callback` is not a function');
|
||||
if (typeof route != 'string')
|
||||
throw new Error('`route` is not a string');
|
||||
if (Router.methods.indexOf(method) < 0)
|
||||
throw new Error(
|
||||
`invalid \`method\` (${method}) given`,
|
||||
Router.methods
|
||||
);
|
||||
if (!Array.isArray(middleware)) {
|
||||
middleware = typeof middleware == 'function' ? [middleware] : null;
|
||||
}
|
||||
|
||||
const methodKey = `$${method.toLowerCase()}`;
|
||||
if (route.startsWith('/')) route = route.substring(1);
|
||||
if (route.endsWith('/')) route = route.substring(0, route.length - 1);
|
||||
|
||||
let params = [];
|
||||
let segments = route.split('/');
|
||||
let currentNode = this.routes;
|
||||
|
||||
if (route == '') {
|
||||
if (currentNode.get(methodKey)) {
|
||||
if (!this.server.option('allowOverwrite')) {
|
||||
console.log(
|
||||
`overwriting of routes is prohibited: [${method}] \`${route}\``
|
||||
);
|
||||
return;
|
||||
}
|
||||
|
||||
console.log(`overwriting route for \`${route}\``);
|
||||
}
|
||||
currentNode.set(methodKey, { callback, middleware, params: [] });
|
||||
return;
|
||||
}
|
||||
|
||||
// add method to the segments to store the callback with
|
||||
// and to allow different methods for the same route
|
||||
for (let index = 0; index < segments.length; index++) {
|
||||
let segment = segments[index];
|
||||
let varName = null;
|
||||
|
||||
if (segment.startsWith(':')) {
|
||||
let newSegment = ':';
|
||||
varName = segment.substring(1);
|
||||
if (segment.endsWith('?')) {
|
||||
// optional param
|
||||
newSegment = '?';
|
||||
varName = varName.substring(0, -1);
|
||||
}
|
||||
segment = newSegment;
|
||||
params.push(varName);
|
||||
}
|
||||
|
||||
if (!currentNode.has(segment)) currentNode.set(segment, new Map());
|
||||
|
||||
currentNode = currentNode.get(segment);
|
||||
}
|
||||
|
||||
if (currentNode.has(methodKey)) {
|
||||
if (!this.server.option('allowOverwrite')) {
|
||||
console.log(
|
||||
`overwriting of routes is prohibited: [${method}] \`${route}\``
|
||||
);
|
||||
return;
|
||||
}
|
||||
|
||||
console.log(`overwriting route for \`${route}\``);
|
||||
}
|
||||
|
||||
currentNode.set(methodKey, { callback, middleware, params });
|
||||
}
|
||||
|
||||
remove(route, method, cb = null) {
|
||||
const methodKey = `$${method.toLowerCase()}`;
|
||||
if (route.startsWith('/')) route = route.substring(1);
|
||||
if (route.endsWith('/')) route = route.substring(0, route.length - 1);
|
||||
|
||||
let currentNode = this.routes;
|
||||
|
||||
if (route != '') {
|
||||
let segments = route.toString().split('/');
|
||||
|
||||
for (let index = 0; index < segments.length; index++) {
|
||||
const segment = segments[index];
|
||||
|
||||
if (currentNode.has(segment)) {
|
||||
currentNode = currentNode.get(segment);
|
||||
continue;
|
||||
}
|
||||
|
||||
if (currentNode.has(':') || currentNode.has('?')) {
|
||||
currentNode = currentNode.get(':') ?? currentNode.get('?');
|
||||
continue;
|
||||
}
|
||||
|
||||
currentNode = null;
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
if (
|
||||
!(currentNode instanceof Map) ||
|
||||
!currentNode.has(methodKey) ||
|
||||
(typeof cb == 'function' && currentNode.get(methodKey) != cb)
|
||||
) {
|
||||
return false;
|
||||
}
|
||||
|
||||
return currentNode.delete(methodKey);
|
||||
}
|
||||
}
|
||||
5
src/Utils/Logger.js
Normal file
5
src/Utils/Logger.js
Normal file
@@ -0,0 +1,5 @@
|
||||
export class Logger {
|
||||
static info() {
|
||||
const [message, data] = arguments;
|
||||
}
|
||||
}
|
||||
46
src/Utils/RequestParser.js
Normal file
46
src/Utils/RequestParser.js
Normal file
@@ -0,0 +1,46 @@
|
||||
export async function parseFormData(req, multipart = false) {
|
||||
const data = await req.formData();
|
||||
|
||||
// console.log(tempFile, new Response(tempFile).headers.get('Content-Type'));
|
||||
// console.log(upload.type, upload.type == tempFile.type);
|
||||
|
||||
for (const key of data.keys()) {
|
||||
const value = data.get(key);
|
||||
if (value.constructor.name == 'Blob' && multipart) {
|
||||
// const ext = value.name.toString().split('.').pop().toLowerCase();
|
||||
const tempFilePath = `/tmp/${Date.now().toString(36)}`;
|
||||
await Bun.write(tempFilePath, value);
|
||||
let tempFile = Bun.file(tempFilePath, { type: value.type });
|
||||
console.log(
|
||||
tempFile,
|
||||
new Response(tempFile).headers.get('Content-Type')
|
||||
);
|
||||
console.log(value.type, value.type == tempFile.type);
|
||||
// data.set(key, await Bun.write())
|
||||
}
|
||||
}
|
||||
|
||||
return data;
|
||||
}
|
||||
|
||||
export default async function RequestParser(req) {
|
||||
try {
|
||||
const contentType = req.headers.get('Content-Type')?.toLowerCase();
|
||||
|
||||
let val = await req.text();
|
||||
console.log(val);
|
||||
return {};
|
||||
|
||||
if (!contentType) return await req.text();
|
||||
|
||||
if (contentType.startsWith('multipart/form-data'))
|
||||
return await parseFormData(req, true);
|
||||
if (contentType == 'application/x-www-form-urlencoded')
|
||||
return await parseFormData(req);
|
||||
if (contentType == 'application/json') return await req.json();
|
||||
|
||||
return await req.text();
|
||||
} catch (err) {
|
||||
console.log(err, typeof req, req.constructor.name);
|
||||
}
|
||||
}
|
||||
7
src/Views/HtmlEngine.js
Normal file
7
src/Views/HtmlEngine.js
Normal file
@@ -0,0 +1,7 @@
|
||||
export default class HtmlEngine {
|
||||
constructor() {}
|
||||
|
||||
render(tpl, context = {}) {
|
||||
return tpl;
|
||||
}
|
||||
}
|
||||
1
src/index.js
Normal file
1
src/index.js
Normal file
@@ -0,0 +1 @@
|
||||
export { default as LayServer } from './LayServer';
|
||||
Reference in New Issue
Block a user