@lionrockjs/central
Version:
Node.js MVC framework inspire from PHP Kohana Framework
127 lines (126 loc) • 4.81 kB
JavaScript
import Central from '../../Central.mjs';
import { dirname, join } from 'node:path';
import { readdirSync, statSync, existsSync } from 'node:fs';
import { fileURLToPath, pathToFileURL } from 'node:url';
import CascadeFileLoader from '../CascadeFileLoader.mjs';
export default class HelperPath {
constructor() { }
modules = new Map();
loader = new CascadeFileLoader({
ignoreList: [/^\./, /^index/, /^init/, /^readme/],
pathHandler: (path) => {
const classesPath = join(path, 'classes');
try {
if (existsSync(classesPath) && statSync(classesPath).isDirectory()) {
return classesPath;
}
}
catch (e) { }
return path;
}
});
viewLoader = new CascadeFileLoader({
ignoreList: [/^\./, /^readme/],
pathHandler: (path) => path + '/../views'
});
get fileList() { return this.loader.fileList; }
get templateList() { return this.viewLoader.fileList; }
init(EXE_PATH, APP_PATH = null, VIEW_PATH = null, modules = []) {
this.loader.fileList.clear();
this.modules.clear();
this.viewLoader.fileList.clear();
Central.EXE_PATH = EXE_PATH.replace(/\/$/, '');
Central.APP_PATH = (APP_PATH || `${Central.EXE_PATH}/application`).replace(/\/$/, '');
Central.VIEW_PATH = (VIEW_PATH || `${Central.EXE_PATH}/views`).replace(/\/$/, '');
// 1. Modules (Lowest Priority)
this.addModules(modules);
// 2. Scan APP_PATH (High Priority)
if (Central.APP_PATH) {
this.loader.scanDir(Central.APP_PATH + '/classes');
}
// 3. Scan VIEW_PATH (Highest Priority for views)
if (Central.VIEW_PATH) {
this.viewLoader.scanDir(Central.VIEW_PATH);
}
// 4. Scan EXE_PATH/modules
try {
const modulesDir = join(Central.EXE_PATH, 'modules');
const stat = statSync(modulesDir);
if (stat.isDirectory()) {
const dirs = readdirSync(modulesDir);
for (const dir of dirs) {
if (dir.startsWith('.'))
continue;
const modulePath = join(modulesDir, dir);
try {
if (statSync(modulePath).isDirectory()) {
const initFile = join(modulePath, 'init.mjs');
if (statSync(initFile).isFile()) {
this.modules.set(modulePath, {
filename: pathToFileURL(initFile).href
});
const classesPath = join(modulePath, 'classes');
try {
if (statSync(classesPath).isDirectory()) {
this.loader.scanDir(classesPath);
}
else {
this.loader.scanDir(modulePath);
}
}
catch (e) {
this.loader.scanDir(modulePath);
}
}
}
}
catch (e) {
// ignore
}
}
}
}
catch (e) {
// ignore
}
}
async reloadModuleInit() {
const initFiles = [...this.modules.keys()].map(x => `${x}/init.mjs`);
for (let i = 0; i < initFiles.length; i++) {
const file = initFiles[i];
if (!existsSync(file))
continue;
try {
await import(file);
}
catch (e) {
Central.log(e);
}
}
}
resolve(pathToFile) {
if (pathToFile.includes('../'))
throw new Error('invalid require path');
const file = this.loader.resolve(pathToFile);
if (!file) {
throw new Error(`Resolve path error: path ${pathToFile} not found.`);
}
return file;
}
resolveView(viewName) {
return this.viewLoader.resolve(viewName);
}
addModules(modules) {
this.viewLoader.addModules(modules);
this.loader.addModules(modules);
modules.forEach(m => {
if (!m)
return;
const module = m.default || m;
if (!module.filename)
return;
const dir = dirname(fileURLToPath(module.filename));
this.modules.set(dir, module);
});
}
}