UNPKG

devlien

Version:

Devlien is a lightweight, zero-dependency Node.js framework with clean MVC structure, built-in ORM, and intuitive routing for rapid backend development.

120 lines (92 loc) 3.72 kB
export default class RouteServe { _ROUTES = {}; _ROUTE = {}; _REQUEST = {}; _RESPONSE = {}; #request; #response; #system; #routes; constructor({request, response, system, routes}){ this.#request = request; this.#response = response; this.#system = system; this.#routes = routes; } async setConfig(request, response){ var _ROUTES = {}; this.#routes.forEach(router=>{ for(const path in router._ROUTES){ _ROUTES[path] = router._ROUTES[path]; } }); this._ROUTES = _ROUTES; this._REQUEST = request; this._RESPONSE = response; return this._ROUTE = await this.getOrigin(); } async getOrigin(){ const url = (this._REQUEST.url).split('?')[0]; for (const pattern in this._ROUTES){ const match_route = this.matchRoute(pattern, url); if(match_route) { this._ROUTES[url] = this._ROUTES[pattern]; this._ROUTES[url].PARAMS = match_route; break; } } let _TARGET_PATH = this._ROUTES[url]; let _IS_ACCEPT = _TARGET_PATH && (_TARGET_PATH.REQUEST_METHOD.includes(this._REQUEST.method.toLocaleUpperCase()) || _TARGET_PATH.REQUEST_METHOD.includes('ANY')) if(_IS_ACCEPT){ return _TARGET_PATH; } return {}; } async route(){ return await this.setConfig(this.#request, this.#response, this.#system) } matchRoute(pattern, url) { const PATTERN_PARTS = pattern.split('/'); const urlParts = url.split('/'); // First, extract all parameter info const paramInfo = []; PATTERN_PARTS.forEach((part, index) => { if (part.startsWith(':')) { const PARAM_NAME = part.slice(1); const IS_OPTIONAL = PARAM_NAME.endsWith('?'); const CLEAN_NAME = IS_OPTIONAL ? PARAM_NAME.slice(0, -1) : PARAM_NAME; paramInfo.push({ name: CLEAN_NAME, optional: IS_OPTIONAL, index }); } }); // Try to match - use backtracking for optional parameters function tryMatch(patternIndex, urlIndex, params) { if (patternIndex >= PATTERN_PARTS.length) { return urlIndex === urlParts.length ? params : null; } const part = PATTERN_PARTS[patternIndex]; if (part.startsWith(':')) { const PARAM_NAME = part.slice(1); const IS_OPTIONAL = PARAM_NAME.endsWith('?'); const CLEAN_NAME = IS_OPTIONAL ? PARAM_NAME.slice(0, -1) : PARAM_NAME; if (IS_OPTIONAL) { // Try skipping this optional parameter const skipResult = tryMatch(patternIndex + 1, urlIndex, { ...params, [CLEAN_NAME]: null }); if (skipResult) return skipResult; } // Try using this parameter if (urlIndex < urlParts.length) { return tryMatch(patternIndex + 1, urlIndex + 1, { ...params, [CLEAN_NAME]: urlParts[urlIndex] }); } return null; } else { // Static part if (urlIndex >= urlParts.length || urlParts[urlIndex] !== part) { return null; } return tryMatch(patternIndex + 1, urlIndex + 1, params); } } return tryMatch(0, 0, {}); } }