enh(LayServer) allow multiple view Paths; Docs; Improvements

This commit is contained in:
gh0sTedBuddy
2024-04-01 22:46:03 +01:00
parent 9addad2a9d
commit 802633353a

View File

@@ -10,20 +10,20 @@ import Logger from './Utils/Logger';
/**
* Represents a LayServer instance that handles routing and server configuration.
* @todo add multi domain support
* @class
*/
export default class LayServer extends BaseRouter {
#controllers = new Map();
#cookieHandle = undefined;
#loaders = new Map();
#proc = null;
#publicFiles;
#viewPaths = new Set();
#routing = null;
#options = new Map([
['layout', undefined],
['loaders', undefined],
['publicDir', undefined],
['viewsPath', undefined],
['preferIndexFiles', false],
['discoverPublicFiles', false],
['enforceTrailingSlash', false],
@@ -57,6 +57,21 @@ export default class LayServer extends BaseRouter {
this.loaders = options.loaders;
}
}
if(options.hasOwnProperty('viewPaths')) {
if(typeof(options.viewPaths) == 'string') {
this.#viewPaths.add(options.viewPaths);
} else if (Array.isArray(options.viewPaths) || options.viewPaths instanceof Set) {
this.#viewPaths = new Set([...this.#viewPaths, ...options.viewPaths]);
}
}
if (options.hasOwnProperty('cookieHandle')) {
if(!options.cookieHandle.hasOwnProperty('read') || options.cookieHandle.hasOwnProperty('write')) {
Logger.debug('cookie handling offers no read/write methods');
}
this.#cookieHandle = options.cookieHandle;
}
}
this.#routing = new LayRouting(this);
@@ -77,10 +92,6 @@ export default class LayServer extends BaseRouter {
this.#options.publicDir
)
this.indexPublicFiles(this.#options.publicDir);
if (!this.#options.viewsEngine && this.#options.viewsPath) {
this.#options.viewsEngine = new HtmlEngine();
}
}
/**
@@ -180,13 +191,27 @@ export default class LayServer extends BaseRouter {
async handleRequest(req) {
const url = new URL(req.url);
if(this.#cookieHandle) {
const cookie = this.#cookieHandle.read(req, {
Domain: url.hostname,
Path: '/',
SameSite: 'Strict',
Secure: url.protocol.indexOf('https') >= 0
});
/**
* Retrieves the layout of the LayServer instance.
* @returns {string|undefined} - The layout of the LayServer instance, or undefined if not set.
*/
cookie.set('visits', Number(cookie.get('visits') || '') + 1);
}
if (
!url.pathname.endsWith('/') &&
Array.isArray(this.#publicFiles) &&
this.#publicFiles.length > 0
) {
let path = this.#publicFiles.find(
(v) => url.pathname.substring(1) === v
(v) => v === url.pathname.substring(1) || v.endsWith(url.pathname.substring(1))
);
if (path) {
try {
@@ -208,12 +233,19 @@ export default class LayServer extends BaseRouter {
}
}
if (this.#options.get('publicDir')) {
// console.log('LayServer.js', 'publicDir', this.#options.get('publicDir'));
}
if (this.#options.enforceTrailingSlash && !url.pathname.endsWith('/')) {
return Response.redirect(`${url.toString()}/`, 302);
}
let resp = await this.#routing.handle(req);
if (resp instanceof Response) return resp;
if (resp instanceof Response) {
if(this.#cookieHandle && cookie instanceof Map) this.#cookieHandle.write(resp, cookie);
return resp;
}
return new Response('Not Found', { status: 404 });
}
@@ -255,27 +287,12 @@ export default class LayServer extends BaseRouter {
* @returns {Promise<string|null>} - The path of the view file, or null if not found.
*/
async getViewPath(filepath) {
let path = this.#options.get('viewsPath');
if (!path.endsWith('/')) path += '/';
const filename = filepath.split('/').pop().toString();
const basedir = filepath.substring(0, filepath.indexOf(filename));
path += basedir;
if (!path.endsWith('/')) path += '/';
const files = await readdir(path);
for (let file of files) {
Logger(
file,
file.substring(0, file.indexOf('.')),
filename.substring(0, filename.indexOf('.')) || filename
);
if (
(file.substring(0, file.indexOf('.')) || file) !=
(filename.substring(0, filename.indexOf('.')) || filename)
)
continue;
return `${path}${file}`;
for(const viewPath of this.#viewPaths) {
const realPath = resolvePath(__dirname, viewPath, filepath);
const file = Bun.file(realPath);
if(await file.exists()) {
return realPath;
}
}
return null;
@@ -303,18 +320,35 @@ export default class LayServer extends BaseRouter {
return new DefaultLoader(filepath);
}
/**
* Adds a route to the LayServer instance.
* @param {string} path - The path of the route.
* @param {Function} cb - The callback function for the route.
*/
add(path, cb) {
this.#routing.add(...arguments)
}
/**
* Adds a middleware to the LayServer instance.
* @param {Function} cb - The middleware function.
*/
use (cb) {
this.add('*', cb, arguments[1]);
}
/**
* Checks if the LayServer instance has a layout.
* @returns {boolean} - True if the LayServer instance has a layout, false otherwise.
*/
hasLayout() {
return typeof(this.#options.get('layout')) == 'string' && this.#options.get('layout').length > 0;
}
/**
* Retrieves the layout of the LayServer instance.
* @returns {string|undefined} - The layout of the LayServer instance, or undefined if not set.
*/
getLayout() {
if(!this.#options.has('layout')) return undefined;