retrex-extensibles-core 1.3.0 → 1.3.2
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/dist/index.cjs +16 -14
- package/dist/index.cjs.map +1 -1
- package/dist/index.js +16 -14
- package/dist/index.js.map +1 -1
- package/package.json +1 -1
package/dist/index.cjs
CHANGED
|
@@ -93,6 +93,7 @@ var useSettings = {
|
|
|
93
93
|
};
|
|
94
94
|
|
|
95
95
|
// src/core/hooks/useExtensibles.ts
|
|
96
|
+
var import_url = require("url");
|
|
96
97
|
var paths;
|
|
97
98
|
function registerExtensibles(extensiblePaths2) {
|
|
98
99
|
paths = extensiblePaths2;
|
|
@@ -106,9 +107,9 @@ function saveJSON(filePath, data) {
|
|
|
106
107
|
}
|
|
107
108
|
function getModules() {
|
|
108
109
|
if (!useSettings.getPaths().modules) throw new Error("Modules path not registered.");
|
|
109
|
-
const dirs = import_fs_extra.default.readdirSync(
|
|
110
|
+
const dirs = import_fs_extra.default.readdirSync(useSettings.getPaths().modules).filter((d) => import_fs_extra.default.statSync(path2.join(useSettings.getPaths().modules, d)).isDirectory());
|
|
110
111
|
return dirs.map((dir) => {
|
|
111
|
-
const meta = loadJSON(path2.join(
|
|
112
|
+
const meta = loadJSON(path2.join(useSettings.getPaths().modules, dir, "module.json")) || {};
|
|
112
113
|
return {
|
|
113
114
|
name: meta.name || dir,
|
|
114
115
|
lowerName: meta.lowerName || dir.toLowerCase(),
|
|
@@ -259,15 +260,15 @@ async function registerRoutes(routesFolderPath) {
|
|
|
259
260
|
}
|
|
260
261
|
}
|
|
261
262
|
async function loadProviders() {
|
|
262
|
-
|
|
263
|
+
const paths2 = {
|
|
263
264
|
modules: useSettings.getPaths().modules,
|
|
264
265
|
templates: useSettings.getPaths().templates,
|
|
265
266
|
services: useSettings.getPaths().services,
|
|
266
267
|
events: useSettings.getPaths().events
|
|
267
268
|
};
|
|
268
269
|
const all = [
|
|
269
|
-
{ type: "module", list: getModules(), basePath:
|
|
270
|
-
{ type: "service", list: getServices(), basePath:
|
|
270
|
+
{ type: "module", list: getModules(), basePath: paths2.modules },
|
|
271
|
+
{ type: "service", list: getServices(), basePath: paths2.services }
|
|
271
272
|
];
|
|
272
273
|
for (const { type, list, basePath } of all) {
|
|
273
274
|
for (const item of list) {
|
|
@@ -277,16 +278,17 @@ async function loadProviders() {
|
|
|
277
278
|
if (!meta?.providers || !Array.isArray(meta.providers)) continue;
|
|
278
279
|
for (const providerRelPath of meta.providers) {
|
|
279
280
|
try {
|
|
280
|
-
const
|
|
281
|
-
const
|
|
281
|
+
const providerAbsPath = path2.join(basePath, item.lowerName, providerRelPath);
|
|
282
|
+
const providerURL = (0, import_url.pathToFileURL)(providerAbsPath).href;
|
|
283
|
+
const providerModule = await import(providerURL);
|
|
282
284
|
if (typeof providerModule.default === "function") {
|
|
283
285
|
await providerModule.default();
|
|
284
|
-
console.log(`[${type}] Provider loaded: ${providerRelPath}`);
|
|
286
|
+
console.log(`[${type}] \u2705 Provider loaded: ${providerRelPath}`);
|
|
285
287
|
} else {
|
|
286
|
-
console.warn(`[${type}] Provider ${providerRelPath} has no default export.`);
|
|
288
|
+
console.warn(`[${type}] \u26A0\uFE0F Provider ${providerRelPath} has no default export.`);
|
|
287
289
|
}
|
|
288
290
|
} catch (err) {
|
|
289
|
-
console.error(`[${type}] Failed to load provider ${providerRelPath}:`, err);
|
|
291
|
+
console.error(`[${type}] \u274C Failed to load provider ${providerRelPath}:`, err);
|
|
290
292
|
}
|
|
291
293
|
}
|
|
292
294
|
}
|
|
@@ -491,7 +493,7 @@ async function useEvents(io) {
|
|
|
491
493
|
}
|
|
492
494
|
|
|
493
495
|
// src/core/hooks/useRoutes.ts
|
|
494
|
-
var
|
|
496
|
+
var import_url2 = require("url");
|
|
495
497
|
var registeredRoutes = [];
|
|
496
498
|
var routesManager = {
|
|
497
499
|
/**
|
|
@@ -511,7 +513,7 @@ var routesManager = {
|
|
|
511
513
|
*/
|
|
512
514
|
async mountRegisteredRoutes(app) {
|
|
513
515
|
for (const route of registeredRoutes) {
|
|
514
|
-
const mod = await import((0,
|
|
516
|
+
const mod = await import((0, import_url2.pathToFileURL)(route.filePath).toString());
|
|
515
517
|
const hasLoader = typeof mod.loader === "function";
|
|
516
518
|
const hasAction = typeof mod.action === "function";
|
|
517
519
|
const hasDefault = typeof mod.default !== "undefined";
|
|
@@ -543,7 +545,7 @@ var routesManager = {
|
|
|
543
545
|
|
|
544
546
|
// src/core/hooks/useUtils.ts
|
|
545
547
|
var import_path2 = __toESM(require("path"), 1);
|
|
546
|
-
var
|
|
548
|
+
var import_url3 = require("url");
|
|
547
549
|
var import_fs_extra3 = __toESM(require("fs-extra"), 1);
|
|
548
550
|
var useUtils = {
|
|
549
551
|
async loadThemeComponent(componentName, options) {
|
|
@@ -625,7 +627,7 @@ var useUtils = {
|
|
|
625
627
|
for (const filePath of possiblePaths) {
|
|
626
628
|
if (await import_fs_extra3.default.pathExists(filePath)) {
|
|
627
629
|
try {
|
|
628
|
-
const mod = await import((0,
|
|
630
|
+
const mod = await import((0, import_url3.pathToFileURL)(filePath).toString());
|
|
629
631
|
if (mod.default) return mod.default;
|
|
630
632
|
} catch (err) {
|
|
631
633
|
console.error(`Error loading component at ${filePath}:`, err);
|
package/dist/index.cjs.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"sources":["../src/index.ts","../src/core/hooks/useExtensibles.ts","../src/core/hooks/useSettings.ts","../src/core/hooks/useModules.ts","../src/core/hooks/useServices.ts","../src/core/hooks/useTemplates.ts","../src/core/hooks/useEvents.ts","../src/core/hooks/useRoutes.ts","../src/core/hooks/useUtils.ts","../src/core/providers/ThemeProvider.tsx"],"sourcesContent":["// src/index.ts\r\n\r\n// export * from './core/controller/EventController';\r\n// export * from './core/controller/MiddlewareController';\r\nexport * from './core/hooks/useExtensibles';\r\nexport * from './core/hooks/useSettings';\r\nexport * from './core/hooks/useModules';\r\nexport * from './core/hooks/useServices';\r\nexport * from './core/hooks/useTemplates';\r\nexport * from './core/hooks/useEvents';\r\nexport * from './core/hooks/useRoutes';\r\nexport * from './core/hooks/useUtils';\r\n// export * as ThemeProvider from './core/providers/ThemeProvider';\r\nexport * from './core/providers/ThemeProvider';\r\n","// src/hooks/useExtensibles.ts\r\n\r\nimport fs from 'fs-extra';\r\nimport * as path from 'path';\r\nimport { useSettings } from './useSettings';\r\n\r\nexport type TemplateType = 'admin-theme' | 'client-theme' | 'portal' | 'email';\r\n\r\nexport interface ExtensibleMeta {\r\n name: string;\r\n lowerName: string;\r\n version?: string;\r\n description?: string;\r\n author?: string;\r\n icon?: string;\r\n enabled?: boolean;\r\n}\r\n\r\nexport interface ExtensiblePaths {\r\n modules: string;\r\n templates: string;\r\n services: string;\r\n events: string;\r\n}\r\n\r\nlet paths: ExtensiblePaths;\r\n\r\nexport function registerExtensibles(extensiblePaths: ExtensiblePaths) {\r\n paths = extensiblePaths;\r\n}\r\n\r\nexport function loadJSON(filePath: string): any {\r\n if (!fs.existsSync(filePath)) return null;\r\n return JSON.parse(fs.readFileSync(filePath, 'utf-8'));\r\n}\r\n\r\nexport function saveJSON(filePath: string, data: any) {\r\n fs.writeFileSync(filePath, JSON.stringify(data, null, 2), 'utf-8');\r\n}\r\n\r\n// --- MODULES ---\r\n\r\nexport function getModules(): ExtensibleMeta[] {\r\n if (!useSettings.getPaths().modules) throw new Error('Modules path not registered.');\r\n\r\n const dirs = fs\r\n .readdirSync(paths.modules)\r\n .filter((d: any) => fs.statSync(path.join(paths.modules, d)).isDirectory());\r\n\r\n return dirs.map((dir: any) => {\r\n const meta = loadJSON(path.join(paths.modules, dir, 'module.json')) || {};\r\n return {\r\n name: meta.name || dir,\r\n lowerName: meta.lowerName || dir.toLowerCase(),\r\n version: meta.version,\r\n description: meta.description,\r\n author: meta.author,\r\n icon: meta.icon,\r\n enabled: meta.enabled ?? false,\r\n };\r\n });\r\n}\r\n\r\nexport function isModuleEnabled(name: string) {\r\n const modules = getModules();\r\n return modules.find((m) => m.lowerName === name.toLowerCase())?.enabled ?? false;\r\n}\r\n\r\nexport function toggleModule(name: string, enabled: boolean) {\r\n const modules = getModules();\r\n const mod = modules.find((m) => m.lowerName === name.toLowerCase());\r\n if (!mod) throw new Error(`Module ${name} not found`);\r\n\r\n const metaPath = path.join(paths.modules, mod.lowerName, 'module.json');\r\n const meta = loadJSON(metaPath) || {};\r\n meta.enabled = enabled;\r\n saveJSON(metaPath, meta);\r\n\r\n if (enabled) onModuleEnabled(mod.name);\r\n else onModuleDisabled(mod.name);\r\n}\r\n\r\n// --- SERVICES ---\r\n\r\nexport function getServices(): ExtensibleMeta[] {\r\n if (!paths?.services) throw new Error('Services path not registered.');\r\n\r\n const dirs = fs\r\n .readdirSync(paths.services)\r\n .filter((d: any) => fs.statSync(path.join(paths.services, d)).isDirectory());\r\n\r\n return dirs.map((dir: any) => {\r\n const meta = loadJSON(path.join(paths.services, dir, 'service.json')) || {};\r\n return {\r\n name: meta.name || dir,\r\n lowerName: meta.lowerName || dir.toLowerCase(),\r\n version: meta.version,\r\n description: meta.description,\r\n author: meta.author,\r\n icon: meta.icon,\r\n enabled: meta.enabled ?? false,\r\n };\r\n });\r\n}\r\n\r\nexport function isServiceEnabled(name: string) {\r\n const services = getServices();\r\n return services.find((s) => s.lowerName === name.toLowerCase())?.enabled ?? false;\r\n}\r\n\r\nexport function toggleService(name: string, enabled: boolean) {\r\n const services = getServices();\r\n const svc = services.find((s) => s.lowerName === name.toLowerCase());\r\n if (!svc) throw new Error(`Service ${name} not found`);\r\n\r\n const metaPath = path.join(paths.services, svc.lowerName, 'service.json');\r\n const meta = loadJSON(metaPath) || {};\r\n meta.enabled = enabled;\r\n saveJSON(metaPath, meta);\r\n\r\n if (enabled) onServiceEnabled(svc.name);\r\n else onServiceDisabled(svc.name);\r\n}\r\n\r\n// --- TEMPLATES ---\r\n\r\n// Helper to get base path for a template type\r\nfunction getTemplateBasePath(type: TemplateType): string {\r\n if (!paths?.templates) throw new Error('Templates path not registered.');\r\n switch (type) {\r\n case 'admin-theme':\r\n case 'client-theme':\r\n return path.join(paths.templates, 'themes');\r\n case 'portal':\r\n return path.join(paths.templates, 'portals');\r\n case 'email':\r\n return path.join(paths.templates, 'emails');\r\n default:\r\n throw new Error(`Unknown template type: ${type}`);\r\n }\r\n}\r\n\r\nexport function getTemplates(type: TemplateType): ExtensibleMeta[] {\r\n const basePath = getTemplateBasePath(type);\r\n if (!fs.existsSync(basePath)) return [];\r\n\r\n const dirs = fs\r\n .readdirSync(basePath)\r\n .filter((d: any) => fs.statSync(path.join(basePath, d)).isDirectory());\r\n\r\n return dirs.map((dir: any) => {\r\n const meta = loadJSON(path.join(basePath, dir, 'template.json')) || {};\r\n return {\r\n name: meta.name || dir,\r\n lowerName: dir.toLowerCase(),\r\n version: meta.version,\r\n description: meta.description,\r\n author: meta.author,\r\n icon: meta.icon,\r\n enabled: meta.enabled ?? false,\r\n };\r\n });\r\n}\r\n\r\nexport function isTemplateActive(type: TemplateType, name: string) {\r\n const templates = getTemplates(type);\r\n return templates.find((t) => t.lowerName === name.toLowerCase())?.enabled ?? false;\r\n}\r\n\r\n// Toggle templates: only 1 active per type allowed\r\nexport function toggleTemplate(type: TemplateType, name: string) {\r\n const templates = getTemplates(type);\r\n\r\n templates.forEach((tpl) => {\r\n const metaPath = path.join(getTemplateBasePath(type), tpl.lowerName, 'template.json');\r\n const meta = loadJSON(metaPath) || {};\r\n meta.enabled = tpl.lowerName === name.toLowerCase();\r\n saveJSON(metaPath, meta);\r\n });\r\n\r\n onTemplateSelect(type, name);\r\n}\r\n\r\n// --- EVENTS (replace with your event system integration) ---\r\n\r\nexport function onModuleEnabled(name: string) {\r\n console.log(`Module enabled: ${name}`);\r\n // emit event or custom logic here\r\n}\r\n\r\nexport function onModuleDisabled(name: string) {\r\n console.log(`Module disabled: ${name}`);\r\n}\r\n\r\nexport function onServiceEnabled(name: string) {\r\n console.log(`Service enabled: ${name}`);\r\n}\r\n\r\nexport function onServiceDisabled(name: string) {\r\n console.log(`Service disabled: ${name}`);\r\n}\r\n\r\nexport function onTemplateSelect(type: TemplateType, name: string) {\r\n console.log(`Template selected: type=${type}, name=${name}`);\r\n}\r\n\r\n// --- REGISTER HOOKS FOR MODULES ---\r\n\r\nexport async function registerEvents() {\r\n if (!paths?.modules) throw new Error('Modules path not registered.');\r\n const modules = getModules().filter((m) => m.enabled);\r\n for (const mod of modules) {\r\n const eventsFile = path.join(paths.modules, mod.lowerName, 'events.server.js');\r\n if (fs.existsSync(eventsFile)) {\r\n const modEvents = await import(eventsFile);\r\n if (modEvents?.registerEvents) await modEvents.registerEvents();\r\n }\r\n }\r\n}\r\n\r\nexport async function registerMiddleware() {\r\n if (!paths?.modules) throw new Error('Modules path not registered.');\r\n const modules = getModules().filter((m) => m.enabled);\r\n for (const mod of modules) {\r\n const middlewareFile = path.join(paths.modules, mod.lowerName, 'middleware.server.js');\r\n if (fs.existsSync(middlewareFile)) {\r\n const modMiddleware = await import(middlewareFile);\r\n if (modMiddleware?.registerMiddleware) await modMiddleware.registerMiddleware();\r\n }\r\n }\r\n}\r\n\r\n/**\r\n * Registers routes given a path to routes folder (for pages and API routes)\r\n * @param routesFolderPath string - path to module/service routes folder\r\n */\r\nexport async function registerRoutes(routesFolderPath: string) {\r\n if (!fs.existsSync(routesFolderPath)) return;\r\n\r\n const routeFiles = fs.readdirSync(routesFolderPath).filter((f: any) => /\\.(js|ts|jsx|tsx)$/.test(f));\r\n for (const file of routeFiles) {\r\n const routeModule = await import(path.join(routesFolderPath, file));\r\n if (routeModule?.registerRoute) {\r\n await routeModule.registerRoute();\r\n }\r\n }\r\n}\r\n\r\nexport async function loadProviders() {\r\n paths = {\r\n modules: useSettings.getPaths().modules,\r\n templates: useSettings.getPaths().templates,\r\n services: useSettings.getPaths().services,\r\n events: useSettings.getPaths().events,\r\n }\r\n const all = [\r\n { type: 'module', list: getModules(), basePath: paths.modules },\r\n { type: 'service', list: getServices(), basePath: paths.services },\r\n ];\r\n\r\n for (const { type, list, basePath } of all) {\r\n for (const item of list) {\r\n if (!item.enabled) continue;\r\n\r\n const metaPath = path.join(basePath, item.lowerName, `${type}.json`);\r\n const meta = loadJSON(metaPath);\r\n if (!meta?.providers || !Array.isArray(meta.providers)) continue;\r\n\r\n for (const providerRelPath of meta.providers) {\r\n try {\r\n const providerPath = path.join(basePath, item.lowerName, providerRelPath);\r\n const providerModule = await import(providerPath);\r\n if (typeof providerModule.default === 'function') {\r\n await providerModule.default(); // Call provider\r\n console.log(`[${type}] Provider loaded: ${providerRelPath}`);\r\n } else {\r\n console.warn(`[${type}] Provider ${providerRelPath} has no default export.`);\r\n }\r\n } catch (err) {\r\n console.error(`[${type}] Failed to load provider ${providerRelPath}:`, err);\r\n }\r\n }\r\n }\r\n }\r\n}\r\n","// src/hooks/useSettings.ts\r\n\r\nimport * as path from 'path';\r\n\r\nimport { ExtensiblePaths, loadJSON, saveJSON } from './useExtensibles';\r\n\r\n// export interface ExtensiblePaths {\r\n// modulesPath: string;\r\n// templatesPath: string;\r\n// servicesPath: string;\r\n// }\r\n\r\nlet extensiblePaths: ExtensiblePaths = {\r\n modules: path.resolve(process.cwd(), 'modules'),\r\n templates: path.resolve(process.cwd(), 'resources/themes'),\r\n services: path.resolve(process.cwd(), 'app/services'),\r\n events: path.resolve(process.cwd(), 'events'),\r\n};\r\n\r\nexport const useSettings = {\r\n getPaths(): ExtensiblePaths {\r\n extensiblePaths = loadJSON(\"extensiblePaths.json\");\r\n return extensiblePaths;\r\n },\r\n\r\n setPaths(paths: Partial<ExtensiblePaths>) {\r\n saveJSON(\"extensiblePaths.json\", {\r\n ...extensiblePaths,\r\n ...paths,\r\n })\r\n extensiblePaths = {\r\n ...extensiblePaths,\r\n ...paths,\r\n };\r\n },\r\n};\r\n","// src/hooks/useModules.ts\r\n\r\nimport fs from 'fs';\r\nimport * as path from 'path';\r\nimport { useSettings } from './useSettings';\r\n\r\nexport interface ModuleMeta {\r\n name: string;\r\n lowerName: string;\r\n version?: string;\r\n author?: string;\r\n icon?: string;\r\n description?: string;\r\n enabled: boolean;\r\n providers?: string[];\r\n}\r\n\r\nexport const useModules = {\r\n loadModules(): ModuleMeta[] {\r\n const modulesDir = useSettings.getPaths().modules;\r\n if (!fs.existsSync(modulesDir)) return [];\r\n\r\n const moduleFolders = fs.readdirSync(modulesDir);\r\n const modules: ModuleMeta[] = [];\r\n\r\n moduleFolders.forEach((folder) => {\r\n const modulePath = path.join(modulesDir, folder);\r\n const moduleJsonPath = path.join(modulePath, 'module.json');\r\n if (!fs.existsSync(moduleJsonPath)) return;\r\n\r\n try {\r\n const rawData = fs.readFileSync(moduleJsonPath, 'utf-8');\r\n const moduleData = JSON.parse(rawData) as ModuleMeta;\r\n modules.push(moduleData);\r\n } catch {\r\n // invalid json or read error, ignore\r\n }\r\n });\r\n\r\n return modules;\r\n },\r\n\r\n isModuleEnabled(moduleName: string): boolean {\r\n const modules = useModules.loadModules();\r\n const mod = modules.find((m) => m.lowerName === moduleName.toLowerCase());\r\n return mod ? mod.enabled : false;\r\n },\r\n\r\n toggleModule(moduleName: string, enabled: boolean): boolean {\r\n const modulesDir = useSettings.getPaths().modules;\r\n const modules = useModules.loadModules();\r\n const modIndex = modules.findIndex((m) => m.lowerName === moduleName.toLowerCase());\r\n if (modIndex === -1) return false;\r\n\r\n const moduleMeta = modules[modIndex];\r\n moduleMeta.enabled = enabled;\r\n\r\n const moduleJsonPath = path.join(modulesDir, moduleMeta.lowerName, 'module.json');\r\n try {\r\n fs.writeFileSync(moduleJsonPath, JSON.stringify(moduleMeta, null, 2), 'utf-8');\r\n return true;\r\n } catch {\r\n return false;\r\n }\r\n },\r\n\r\n getModules(): ModuleMeta[] {\r\n return useModules.loadModules();\r\n },\r\n};\r\n","// src/hooks/useServices.ts\r\n\r\nimport fs from 'fs';\r\nimport * as path from 'path';\r\nimport { useSettings } from './useSettings';\r\n\r\nexport interface ServiceMeta {\r\n name: string;\r\n lowerName: string;\r\n version?: string;\r\n author?: string;\r\n icon?: string;\r\n description?: string;\r\n enabled: boolean;\r\n providers?: string[];\r\n serviceType?: string;\r\n}\r\n\r\nexport const useServices = {\r\n loadServices(): ServiceMeta[] {\r\n const servicesDir = useSettings.getPaths().services;\r\n if (!fs.existsSync(servicesDir)) return [];\r\n\r\n const serviceFolders = fs.readdirSync(servicesDir);\r\n const services: ServiceMeta[] = [];\r\n\r\n serviceFolders.forEach((folder) => {\r\n const servicePath = path.join(servicesDir, folder);\r\n const serviceJsonPath = path.join(servicePath, 'service.json');\r\n if (!fs.existsSync(serviceJsonPath)) return;\r\n\r\n try {\r\n const rawData = fs.readFileSync(serviceJsonPath, 'utf-8');\r\n const serviceData = JSON.parse(rawData) as ServiceMeta;\r\n services.push(serviceData);\r\n } catch {\r\n // ignore invalid json or errors\r\n }\r\n });\r\n\r\n return services;\r\n },\r\n\r\n isServiceEnabled(serviceName: string): boolean {\r\n const services = useServices.loadServices();\r\n const service = services.find((s) => s.lowerName === serviceName.toLowerCase());\r\n return service ? service.enabled : false;\r\n },\r\n\r\n toggleService(serviceName: string, enabled: boolean): boolean {\r\n const servicesDir = useSettings.getPaths().services;\r\n const services = useServices.loadServices();\r\n const index = services.findIndex((s) => s.lowerName === serviceName.toLowerCase());\r\n if (index === -1) return false;\r\n\r\n const serviceMeta = services[index];\r\n serviceMeta.enabled = enabled;\r\n\r\n const serviceJsonPath = path.join(servicesDir, serviceMeta.lowerName, 'service.json');\r\n try {\r\n fs.writeFileSync(serviceJsonPath, JSON.stringify(serviceMeta, null, 2), 'utf-8');\r\n return true;\r\n } catch {\r\n return false;\r\n }\r\n },\r\n\r\n getServices(): ServiceMeta[] {\r\n return useServices.loadServices();\r\n },\r\n};\r\n","// src/hooks/useTemplates.ts\r\n\r\nimport fs from 'fs';\r\nimport * as path from 'path';\r\nimport { useSettings } from './useSettings';\r\nimport { TemplateType } from './useExtensibles';\r\n\r\nexport interface TemplateMeta {\r\n name: string;\r\n lowerName: string;\r\n version?: string;\r\n author?: string;\r\n icon?: string;\r\n description?: string;\r\n enabled: boolean;\r\n templateType: TemplateType;\r\n}\r\n\r\nexport const useTemplates = {\r\n loadTemplates(templateType?: TemplateType): TemplateMeta[] {\r\n const templatesDir = useSettings.getPaths().templates;\r\n if (!fs.existsSync(templatesDir)) return [];\r\n\r\n const templateFolders = fs.readdirSync(templatesDir);\r\n const templates: TemplateMeta[] = [];\r\n\r\n templateFolders.forEach((folder) => {\r\n const templatePath = path.join(templatesDir, folder);\r\n const templateJsonPath = path.join(templatePath, 'template.json');\r\n if (!fs.existsSync(templateJsonPath)) return;\r\n\r\n try {\r\n const rawData = fs.readFileSync(templateJsonPath, 'utf-8');\r\n const templateData = JSON.parse(rawData) as TemplateMeta;\r\n\r\n if (templateType) {\r\n if (templateData.templateType === templateType) {\r\n templates.push(templateData);\r\n }\r\n } else {\r\n templates.push(templateData);\r\n }\r\n } catch {\r\n // ignore invalid JSON or errors\r\n }\r\n });\r\n\r\n return templates;\r\n },\r\n\r\n isTemplateActive(templateType: TemplateType, templateName: string): boolean {\r\n const templates = useTemplates.loadTemplates(templateType);\r\n const template = templates.find(\r\n (t) => t.lowerName === templateName.toLowerCase() && t.enabled\r\n );\r\n return !!template;\r\n },\r\n\r\n toggleTemplate(templateType: TemplateType, templateName: string): boolean {\r\n // Since only one template of each type can be enabled, disable others and enable this one\r\n const templatesDir = useSettings.getPaths().templates;\r\n const templates = useTemplates.loadTemplates(templateType);\r\n\r\n let toggled = false;\r\n\r\n templates.forEach((template) => {\r\n if (template.name.toLowerCase() === templateName.toLowerCase()) {\r\n if (!template.enabled) {\r\n template.enabled = true;\r\n toggled = true;\r\n }\r\n } else {\r\n if (template.enabled) {\r\n template.enabled = false;\r\n }\r\n }\r\n\r\n const templateJsonPath = path.join(templatesDir, template.lowerName, 'template.json');\r\n try {\r\n fs.writeFileSync(templateJsonPath, JSON.stringify(template, null, 2), 'utf-8');\r\n } catch {\r\n // ignore write errors\r\n }\r\n });\r\n\r\n return toggled;\r\n },\r\n\r\n getTemplates(templateType?: TemplateType): TemplateMeta[] {\r\n return useTemplates.loadTemplates(templateType);\r\n },\r\n};\r\n","import fs from 'fs-extra';\r\nimport path from 'path';\r\nimport { Server as SocketIOServer, Socket } from 'socket.io';\r\nimport { useSettings } from './useSettings';\r\n\r\n// Type signature for an event controller\r\ninterface EventController {\r\n onRegister?: (io: SocketIOServer) => void;\r\n onEvent?: (socket: Socket, event: any) => void;\r\n}\r\n\r\n// Dynamically import and register events\r\nexport async function useEvents(io: SocketIOServer) {\r\n const { modules, services, events: appEventsPath } = useSettings.getPaths();\r\n\r\n const sources = [\r\n { type: 'module', root: modules },\r\n { type: 'service', root: services },\r\n { type: 'app', root: appEventsPath },\r\n ];\r\n\r\n for (const source of sources) {\r\n if (!(await fs.pathExists(source.root))) continue;\r\n\r\n const dirs = await fs.readdir(source.root);\r\n for (const dir of dirs) {\r\n const base = path.join(source.root, dir);\r\n const eventsDir = source.type === 'app' ? base : path.join(base, 'events');\r\n\r\n if (!(await fs.pathExists(eventsDir))) continue;\r\n\r\n const files = (await fs.readdir(eventsDir)).filter((f) => f.endsWith('.ts') || f.endsWith('.js'));\r\n\r\n for (const file of files) {\r\n const eventPath = path.join(eventsDir, file);\r\n try {\r\n const imported = await import(eventPath);\r\n const controller: EventController = imported.default || imported[Object.keys(imported)[0]];\r\n\r\n if (controller?.onRegister) {\r\n controller.onRegister(io);\r\n }\r\n\r\n if (controller?.onEvent) {\r\n io.on('connection', (socket) => {\r\n const eventName = file.replace(/\\.(ts|js)$/, '');\r\n socket.on(eventName, (data) => controller.onEvent!(socket, data));\r\n });\r\n }\r\n } catch (err) {\r\n console.warn(`⚠️ Failed to load event: ${eventPath}`, err);\r\n }\r\n }\r\n }\r\n }\r\n}\r\n","// packages/retrex-extensibles-core/useRoutes.ts\r\nimport { Application, Request, Response, NextFunction } from 'express';\r\nimport { pathToFileURL } from 'url';\r\nimport type { LoaderFunctionArgs, ActionFunctionArgs } from '@remix-run/node';\r\n\r\ninterface RouteDefinition {\r\n path: string;\r\n method: 'get' | 'post' | 'put' | 'patch' | 'delete';\r\n filePath: string; // absolute path to .tsx file\r\n}\r\n\r\n// Registry for dynamically added routes\r\nconst registeredRoutes: RouteDefinition[] = [];\r\nexport const routesManager = {\r\n /**\r\n * Register a dynamic route from a module/service.\r\n */\r\n registerRoute(def: RouteDefinition): void {\r\n registeredRoutes.push(def);\r\n },\r\n\r\n /**\r\n * Return all registered dynamic routes.\r\n */\r\n getRegisteredRoutes(): RouteDefinition[] {\r\n return registeredRoutes;\r\n },\r\n\r\n /**\r\n * Loads and mounts all registered dynamic routes into an Express app.\r\n */\r\n async mountRegisteredRoutes(app: Application): Promise<void> {\r\n for (const route of registeredRoutes) {\r\n const mod = await import(pathToFileURL(route.filePath).toString());\r\n\r\n const hasLoader = typeof mod.loader === 'function';\r\n const hasAction = typeof mod.action === 'function';\r\n const hasDefault = typeof mod.default !== 'undefined';\r\n\r\n // Handle API routes with loader/action\r\n if (!hasDefault && (hasLoader || hasAction)) {\r\n app[route.method](route.path, async (req: Request, res: Response, next: NextFunction) => {\r\n try {\r\n if (route.method === 'get' && hasLoader) {\r\n const result = await mod.loader({ request: req });\r\n res.json(result);\r\n } else if (hasAction) {\r\n const result = await mod.action({ request: req });\r\n res.json(result);\r\n } else {\r\n res.status(405).json({ error: 'Method Not Allowed' });\r\n }\r\n } catch (err) {\r\n next(err);\r\n }\r\n });\r\n }\r\n\r\n // Handle Page Routes (React component as default export)\r\n else if (hasDefault) {\r\n app.use(route.path, (req: Request, res: Response, next: NextFunction) => {\r\n res.locals.__dynamicPageComponent = mod.default;\r\n next(); // forward to Remix handler\r\n });\r\n }\r\n }\r\n }\r\n}\r\n","// packages/retrex-extensibles-core/utils/loadThemeComponent.ts\r\nimport path from 'path';\r\nimport { pathToFileURL } from 'url';\r\nimport fs from 'fs-extra';\r\nimport { useSettings } from './useSettings';\r\n\r\nexport const useUtils = {\r\n async loadThemeComponent(\r\n componentName: string,\r\n options: {\r\n theme: {\r\n name: string;\r\n type: 'admin' | 'client' | 'portal' | 'email';\r\n };\r\n search?: {\r\n themes?: boolean;\r\n modules?: boolean;\r\n services?: boolean;\r\n };\r\n }\r\n ): Promise<React.ComponentType<any> | null> {\r\n const { search = {}, theme } = options;\r\n const searchThemes = search.themes ?? true;\r\n const searchModules = search.modules ?? true;\r\n const searchServices = search.services ?? true;\r\n\r\n const possiblePaths: string[] = [];\r\n\r\n if (searchThemes) {\r\n possiblePaths.push(\r\n path.resolve(\r\n 'resources',\r\n 'themes',\r\n theme.type,\r\n theme.name,\r\n 'routes',\r\n `${componentName}.tsx`\r\n ),\r\n path.resolve(\r\n 'resources',\r\n 'themes',\r\n theme.type,\r\n theme.name,\r\n 'components',\r\n `${componentName}.tsx`\r\n )\r\n );\r\n }\r\n\r\n if (searchModules) {\r\n const moduleDirs = await fs.readdir(useSettings.getPaths().modules);\r\n for (const mod of moduleDirs) {\r\n possiblePaths.push(\r\n path.resolve(\r\n 'modules',\r\n mod,\r\n 'themes',\r\n theme.type,\r\n theme.name,\r\n 'routes',\r\n `${componentName}.tsx`\r\n ),\r\n path.resolve(\r\n 'modules',\r\n mod,\r\n 'themes',\r\n theme.type,\r\n theme.name,\r\n 'components',\r\n `${componentName}.tsx`\r\n )\r\n );\r\n }\r\n }\r\n\r\n if (searchServices) {\r\n const serviceDirs = await fs.readdir(useSettings.getPaths().services);\r\n for (const svc of serviceDirs) {\r\n possiblePaths.push(\r\n path.resolve(\r\n 'services',\r\n svc,\r\n 'themes',\r\n theme.type,\r\n theme.name,\r\n 'routes',\r\n `${componentName}.tsx`\r\n ),\r\n path.resolve(\r\n 'services',\r\n svc,\r\n 'themes',\r\n theme.type,\r\n theme.name,\r\n 'components',\r\n `${componentName}.tsx`\r\n )\r\n );\r\n }\r\n }\r\n\r\n for (const filePath of possiblePaths) {\r\n if (await fs.pathExists(filePath)) {\r\n try {\r\n const mod = await import(pathToFileURL(filePath).toString());\r\n if (mod.default) return mod.default;\r\n } catch (err) {\r\n console.error(`Error loading component at ${filePath}:`, err);\r\n }\r\n }\r\n }\r\n\r\n console.warn(`Component \"${componentName}\" not found in theme \"${theme.name}\" of type \"${theme.type}\".`);\r\n return null;\r\n }\r\n}\r\n","import React, { createContext, useContext, useEffect, useState } from 'react';\r\nimport path from 'path';\r\nimport { useSettings } from '../hooks/useSettings';\r\nimport { getTemplates, TemplateType } from '../hooks/useExtensibles';\r\n\r\ninterface ThemeContextProps {\r\n templateType: TemplateType;\r\n activeTheme: string;\r\n setActiveTheme: (theme: string) => void;\r\n}\r\n\r\nconst ThemeContext = createContext<ThemeContextProps | null>(null);\r\n\r\nexport const ThemeProvider: React.FC<{\r\n type: TemplateType;\r\n children: React.ReactNode;\r\n}> = ({ type, children }) => {\r\n const [activeTheme, setActiveTheme] = useState<string>(() => {\r\n const templates = getTemplates(type);\r\n const enabled = templates.find(t => t.enabled);\r\n return enabled?.lowerName ?? templates[0]?.lowerName ?? 'default';\r\n });\r\n\r\n return (\r\n <ThemeContext.Provider value={{ templateType: type, activeTheme, setActiveTheme }}>\r\n {children}\r\n </ThemeContext.Provider>\r\n );\r\n};\r\n\r\nexport function useTheme() {\r\n const ctx = useContext(ThemeContext);\r\n if (!ctx) throw new Error('useTheme must be used inside a ThemeProvider');\r\n return ctx;\r\n}\r\n"],"mappings":"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","names":["path","paths","extensiblePaths","fs","path","fs","import_fs","path","fs","import_fs","path","fs","import_fs_extra","fs","path","import_path","import_url","import_fs_extra","path","fs"]}
|
|
1
|
+
{"version":3,"sources":["../src/index.ts","../src/core/hooks/useExtensibles.ts","../src/core/hooks/useSettings.ts","../src/core/hooks/useModules.ts","../src/core/hooks/useServices.ts","../src/core/hooks/useTemplates.ts","../src/core/hooks/useEvents.ts","../src/core/hooks/useRoutes.ts","../src/core/hooks/useUtils.ts","../src/core/providers/ThemeProvider.tsx"],"sourcesContent":["// src/index.ts\r\n\r\n// export * from './core/controller/EventController';\r\n// export * from './core/controller/MiddlewareController';\r\nexport * from './core/hooks/useExtensibles';\r\nexport * from './core/hooks/useSettings';\r\nexport * from './core/hooks/useModules';\r\nexport * from './core/hooks/useServices';\r\nexport * from './core/hooks/useTemplates';\r\nexport * from './core/hooks/useEvents';\r\nexport * from './core/hooks/useRoutes';\r\nexport * from './core/hooks/useUtils';\r\n// export * as ThemeProvider from './core/providers/ThemeProvider';\r\nexport * from './core/providers/ThemeProvider';\r\n","// src/hooks/useExtensibles.ts\r\n\r\nimport fs from 'fs-extra';\r\nimport * as path from 'path';\r\nimport { useSettings } from './useSettings';\r\nimport { pathToFileURL } from 'url';\r\n\r\nexport type TemplateType = 'admin-theme' | 'client-theme' | 'portal' | 'email';\r\n\r\nexport interface ExtensibleMeta {\r\n name: string;\r\n lowerName: string;\r\n version?: string;\r\n description?: string;\r\n author?: string;\r\n icon?: string;\r\n enabled?: boolean;\r\n}\r\n\r\nexport interface ExtensiblePaths {\r\n modules: string;\r\n templates: string;\r\n services: string;\r\n events: string;\r\n}\r\n\r\nlet paths: ExtensiblePaths;\r\n\r\nexport function registerExtensibles(extensiblePaths: ExtensiblePaths) {\r\n paths = extensiblePaths;\r\n}\r\n\r\nexport function loadJSON(filePath: string): any {\r\n if (!fs.existsSync(filePath)) return null;\r\n return JSON.parse(fs.readFileSync(filePath, 'utf-8'));\r\n}\r\n\r\nexport function saveJSON(filePath: string, data: any) {\r\n fs.writeFileSync(filePath, JSON.stringify(data, null, 2), 'utf-8');\r\n}\r\n\r\n// --- MODULES ---\r\n\r\nexport function getModules(): ExtensibleMeta[] {\r\n if (!useSettings.getPaths().modules) throw new Error('Modules path not registered.');\r\n\r\n const dirs = fs\r\n .readdirSync(useSettings.getPaths().modules)\r\n .filter((d: any) => fs.statSync(path.join(useSettings.getPaths().modules, d)).isDirectory());\r\n\r\n return dirs.map((dir: any) => {\r\n const meta = loadJSON(path.join(useSettings.getPaths().modules, dir, 'module.json')) || {};\r\n return {\r\n name: meta.name || dir,\r\n lowerName: meta.lowerName || dir.toLowerCase(),\r\n version: meta.version,\r\n description: meta.description,\r\n author: meta.author,\r\n icon: meta.icon,\r\n enabled: meta.enabled ?? false,\r\n };\r\n });\r\n}\r\n\r\nexport function isModuleEnabled(name: string) {\r\n const modules = getModules();\r\n return modules.find((m) => m.lowerName === name.toLowerCase())?.enabled ?? false;\r\n}\r\n\r\nexport function toggleModule(name: string, enabled: boolean) {\r\n const modules = getModules();\r\n const mod = modules.find((m) => m.lowerName === name.toLowerCase());\r\n if (!mod) throw new Error(`Module ${name} not found`);\r\n\r\n const metaPath = path.join(paths.modules, mod.lowerName, 'module.json');\r\n const meta = loadJSON(metaPath) || {};\r\n meta.enabled = enabled;\r\n saveJSON(metaPath, meta);\r\n\r\n if (enabled) onModuleEnabled(mod.name);\r\n else onModuleDisabled(mod.name);\r\n}\r\n\r\n// --- SERVICES ---\r\n\r\nexport function getServices(): ExtensibleMeta[] {\r\n if (!paths?.services) throw new Error('Services path not registered.');\r\n\r\n const dirs = fs\r\n .readdirSync(paths.services)\r\n .filter((d: any) => fs.statSync(path.join(paths.services, d)).isDirectory());\r\n\r\n return dirs.map((dir: any) => {\r\n const meta = loadJSON(path.join(paths.services, dir, 'service.json')) || {};\r\n return {\r\n name: meta.name || dir,\r\n lowerName: meta.lowerName || dir.toLowerCase(),\r\n version: meta.version,\r\n description: meta.description,\r\n author: meta.author,\r\n icon: meta.icon,\r\n enabled: meta.enabled ?? false,\r\n };\r\n });\r\n}\r\n\r\nexport function isServiceEnabled(name: string) {\r\n const services = getServices();\r\n return services.find((s) => s.lowerName === name.toLowerCase())?.enabled ?? false;\r\n}\r\n\r\nexport function toggleService(name: string, enabled: boolean) {\r\n const services = getServices();\r\n const svc = services.find((s) => s.lowerName === name.toLowerCase());\r\n if (!svc) throw new Error(`Service ${name} not found`);\r\n\r\n const metaPath = path.join(paths.services, svc.lowerName, 'service.json');\r\n const meta = loadJSON(metaPath) || {};\r\n meta.enabled = enabled;\r\n saveJSON(metaPath, meta);\r\n\r\n if (enabled) onServiceEnabled(svc.name);\r\n else onServiceDisabled(svc.name);\r\n}\r\n\r\n// --- TEMPLATES ---\r\n\r\n// Helper to get base path for a template type\r\nfunction getTemplateBasePath(type: TemplateType): string {\r\n if (!paths?.templates) throw new Error('Templates path not registered.');\r\n switch (type) {\r\n case 'admin-theme':\r\n case 'client-theme':\r\n return path.join(paths.templates, 'themes');\r\n case 'portal':\r\n return path.join(paths.templates, 'portals');\r\n case 'email':\r\n return path.join(paths.templates, 'emails');\r\n default:\r\n throw new Error(`Unknown template type: ${type}`);\r\n }\r\n}\r\n\r\nexport function getTemplates(type: TemplateType): ExtensibleMeta[] {\r\n const basePath = getTemplateBasePath(type);\r\n if (!fs.existsSync(basePath)) return [];\r\n\r\n const dirs = fs\r\n .readdirSync(basePath)\r\n .filter((d: any) => fs.statSync(path.join(basePath, d)).isDirectory());\r\n\r\n return dirs.map((dir: any) => {\r\n const meta = loadJSON(path.join(basePath, dir, 'template.json')) || {};\r\n return {\r\n name: meta.name || dir,\r\n lowerName: dir.toLowerCase(),\r\n version: meta.version,\r\n description: meta.description,\r\n author: meta.author,\r\n icon: meta.icon,\r\n enabled: meta.enabled ?? false,\r\n };\r\n });\r\n}\r\n\r\nexport function isTemplateActive(type: TemplateType, name: string) {\r\n const templates = getTemplates(type);\r\n return templates.find((t) => t.lowerName === name.toLowerCase())?.enabled ?? false;\r\n}\r\n\r\n// Toggle templates: only 1 active per type allowed\r\nexport function toggleTemplate(type: TemplateType, name: string) {\r\n const templates = getTemplates(type);\r\n\r\n templates.forEach((tpl) => {\r\n const metaPath = path.join(getTemplateBasePath(type), tpl.lowerName, 'template.json');\r\n const meta = loadJSON(metaPath) || {};\r\n meta.enabled = tpl.lowerName === name.toLowerCase();\r\n saveJSON(metaPath, meta);\r\n });\r\n\r\n onTemplateSelect(type, name);\r\n}\r\n\r\n// --- EVENTS (replace with your event system integration) ---\r\n\r\nexport function onModuleEnabled(name: string) {\r\n console.log(`Module enabled: ${name}`);\r\n // emit event or custom logic here\r\n}\r\n\r\nexport function onModuleDisabled(name: string) {\r\n console.log(`Module disabled: ${name}`);\r\n}\r\n\r\nexport function onServiceEnabled(name: string) {\r\n console.log(`Service enabled: ${name}`);\r\n}\r\n\r\nexport function onServiceDisabled(name: string) {\r\n console.log(`Service disabled: ${name}`);\r\n}\r\n\r\nexport function onTemplateSelect(type: TemplateType, name: string) {\r\n console.log(`Template selected: type=${type}, name=${name}`);\r\n}\r\n\r\n// --- REGISTER HOOKS FOR MODULES ---\r\n\r\nexport async function registerEvents() {\r\n if (!paths?.modules) throw new Error('Modules path not registered.');\r\n const modules = getModules().filter((m) => m.enabled);\r\n for (const mod of modules) {\r\n const eventsFile = path.join(paths.modules, mod.lowerName, 'events.server.js');\r\n if (fs.existsSync(eventsFile)) {\r\n const modEvents = await import(eventsFile);\r\n if (modEvents?.registerEvents) await modEvents.registerEvents();\r\n }\r\n }\r\n}\r\n\r\nexport async function registerMiddleware() {\r\n if (!paths?.modules) throw new Error('Modules path not registered.');\r\n const modules = getModules().filter((m) => m.enabled);\r\n for (const mod of modules) {\r\n const middlewareFile = path.join(paths.modules, mod.lowerName, 'middleware.server.js');\r\n if (fs.existsSync(middlewareFile)) {\r\n const modMiddleware = await import(middlewareFile);\r\n if (modMiddleware?.registerMiddleware) await modMiddleware.registerMiddleware();\r\n }\r\n }\r\n}\r\n\r\n/**\r\n * Registers routes given a path to routes folder (for pages and API routes)\r\n * @param routesFolderPath string - path to module/service routes folder\r\n */\r\nexport async function registerRoutes(routesFolderPath: string) {\r\n if (!fs.existsSync(routesFolderPath)) return;\r\n\r\n const routeFiles = fs.readdirSync(routesFolderPath).filter((f: any) => /\\.(js|ts|jsx|tsx)$/.test(f));\r\n for (const file of routeFiles) {\r\n const routeModule = await import(path.join(routesFolderPath, file));\r\n if (routeModule?.registerRoute) {\r\n await routeModule.registerRoute();\r\n }\r\n }\r\n}\r\n\r\nexport async function loadProviders() {\r\n const paths = {\r\n modules: useSettings.getPaths().modules,\r\n templates: useSettings.getPaths().templates,\r\n services: useSettings.getPaths().services,\r\n events: useSettings.getPaths().events,\r\n };\r\n\r\n const all = [\r\n { type: 'module', list: getModules(), basePath: paths.modules },\r\n { type: 'service', list: getServices(), basePath: paths.services },\r\n ];\r\n\r\n for (const { type, list, basePath } of all) {\r\n for (const item of list) {\r\n if (!item.enabled) continue;\r\n\r\n const metaPath = path.join(basePath, item.lowerName, `${type}.json`);\r\n const meta = loadJSON(metaPath);\r\n if (!meta?.providers || !Array.isArray(meta.providers)) continue;\r\n\r\n for (const providerRelPath of meta.providers) {\r\n try {\r\n const providerAbsPath = path.join(basePath, item.lowerName, providerRelPath);\r\n const providerURL = pathToFileURL(providerAbsPath).href; // ✅ Convert to file:// URL\r\n const providerModule = await import(providerURL);\r\n\r\n if (typeof providerModule.default === 'function') {\r\n await providerModule.default();\r\n console.log(`[${type}] ✅ Provider loaded: ${providerRelPath}`);\r\n } else {\r\n console.warn(`[${type}] ⚠️ Provider ${providerRelPath} has no default export.`);\r\n }\r\n } catch (err) {\r\n console.error(`[${type}] ❌ Failed to load provider ${providerRelPath}:`, err);\r\n }\r\n }\r\n }\r\n }\r\n}\r\n\r\n\r\n// export async function loadProviders() {\r\n// paths = {\r\n// modules: useSettings.getPaths().modules,\r\n// templates: useSettings.getPaths().templates,\r\n// services: useSettings.getPaths().services,\r\n// events: useSettings.getPaths().events,\r\n// }\r\n// const all = [\r\n// { type: 'module', list: getModules(), basePath: paths.modules },\r\n// { type: 'service', list: getServices(), basePath: paths.services },\r\n// ];\r\n\r\n// for (const { type, list, basePath } of all) {\r\n// for (const item of list) {\r\n// if (!item.enabled) continue;\r\n\r\n// const metaPath = path.join(basePath, item.lowerName, `${type}.json`);\r\n// const meta = loadJSON(metaPath);\r\n// if (!meta?.providers || !Array.isArray(meta.providers)) continue;\r\n\r\n// for (const providerRelPath of meta.providers) {\r\n// try {\r\n// const providerPath = path.join(basePath, item.lowerName, providerRelPath);\r\n// const providerModule = await import(providerPath);\r\n// if (typeof providerModule.default === 'function') {\r\n// await providerModule.default(); // Call provider\r\n// console.log(`[${type}] Provider loaded: ${providerRelPath}`);\r\n// } else {\r\n// console.warn(`[${type}] Provider ${providerRelPath} has no default export.`);\r\n// }\r\n// } catch (err) {\r\n// console.error(`[${type}] Failed to load provider ${providerRelPath}:`, err);\r\n// }\r\n// }\r\n// }\r\n// }\r\n// }\r\n","// src/hooks/useSettings.ts\r\n\r\nimport * as path from 'path';\r\n\r\nimport { ExtensiblePaths, loadJSON, saveJSON } from './useExtensibles';\r\n\r\n// export interface ExtensiblePaths {\r\n// modulesPath: string;\r\n// templatesPath: string;\r\n// servicesPath: string;\r\n// }\r\n\r\nlet extensiblePaths: ExtensiblePaths = {\r\n modules: path.resolve(process.cwd(), 'modules'),\r\n templates: path.resolve(process.cwd(), 'resources/themes'),\r\n services: path.resolve(process.cwd(), 'app/services'),\r\n events: path.resolve(process.cwd(), 'events'),\r\n};\r\n\r\nexport const useSettings = {\r\n getPaths(): ExtensiblePaths {\r\n extensiblePaths = loadJSON(\"extensiblePaths.json\");\r\n return extensiblePaths;\r\n },\r\n\r\n setPaths(paths: Partial<ExtensiblePaths>) {\r\n saveJSON(\"extensiblePaths.json\", {\r\n ...extensiblePaths,\r\n ...paths,\r\n })\r\n extensiblePaths = {\r\n ...extensiblePaths,\r\n ...paths,\r\n };\r\n },\r\n};\r\n","// src/hooks/useModules.ts\r\n\r\nimport fs from 'fs';\r\nimport * as path from 'path';\r\nimport { useSettings } from './useSettings';\r\n\r\nexport interface ModuleMeta {\r\n name: string;\r\n lowerName: string;\r\n version?: string;\r\n author?: string;\r\n icon?: string;\r\n description?: string;\r\n enabled: boolean;\r\n providers?: string[];\r\n}\r\n\r\nexport const useModules = {\r\n loadModules(): ModuleMeta[] {\r\n const modulesDir = useSettings.getPaths().modules;\r\n if (!fs.existsSync(modulesDir)) return [];\r\n\r\n const moduleFolders = fs.readdirSync(modulesDir);\r\n const modules: ModuleMeta[] = [];\r\n\r\n moduleFolders.forEach((folder) => {\r\n const modulePath = path.join(modulesDir, folder);\r\n const moduleJsonPath = path.join(modulePath, 'module.json');\r\n if (!fs.existsSync(moduleJsonPath)) return;\r\n\r\n try {\r\n const rawData = fs.readFileSync(moduleJsonPath, 'utf-8');\r\n const moduleData = JSON.parse(rawData) as ModuleMeta;\r\n modules.push(moduleData);\r\n } catch {\r\n // invalid json or read error, ignore\r\n }\r\n });\r\n\r\n return modules;\r\n },\r\n\r\n isModuleEnabled(moduleName: string): boolean {\r\n const modules = useModules.loadModules();\r\n const mod = modules.find((m) => m.lowerName === moduleName.toLowerCase());\r\n return mod ? mod.enabled : false;\r\n },\r\n\r\n toggleModule(moduleName: string, enabled: boolean): boolean {\r\n const modulesDir = useSettings.getPaths().modules;\r\n const modules = useModules.loadModules();\r\n const modIndex = modules.findIndex((m) => m.lowerName === moduleName.toLowerCase());\r\n if (modIndex === -1) return false;\r\n\r\n const moduleMeta = modules[modIndex];\r\n moduleMeta.enabled = enabled;\r\n\r\n const moduleJsonPath = path.join(modulesDir, moduleMeta.lowerName, 'module.json');\r\n try {\r\n fs.writeFileSync(moduleJsonPath, JSON.stringify(moduleMeta, null, 2), 'utf-8');\r\n return true;\r\n } catch {\r\n return false;\r\n }\r\n },\r\n\r\n getModules(): ModuleMeta[] {\r\n return useModules.loadModules();\r\n },\r\n};\r\n","// src/hooks/useServices.ts\r\n\r\nimport fs from 'fs';\r\nimport * as path from 'path';\r\nimport { useSettings } from './useSettings';\r\n\r\nexport interface ServiceMeta {\r\n name: string;\r\n lowerName: string;\r\n version?: string;\r\n author?: string;\r\n icon?: string;\r\n description?: string;\r\n enabled: boolean;\r\n providers?: string[];\r\n serviceType?: string;\r\n}\r\n\r\nexport const useServices = {\r\n loadServices(): ServiceMeta[] {\r\n const servicesDir = useSettings.getPaths().services;\r\n if (!fs.existsSync(servicesDir)) return [];\r\n\r\n const serviceFolders = fs.readdirSync(servicesDir);\r\n const services: ServiceMeta[] = [];\r\n\r\n serviceFolders.forEach((folder) => {\r\n const servicePath = path.join(servicesDir, folder);\r\n const serviceJsonPath = path.join(servicePath, 'service.json');\r\n if (!fs.existsSync(serviceJsonPath)) return;\r\n\r\n try {\r\n const rawData = fs.readFileSync(serviceJsonPath, 'utf-8');\r\n const serviceData = JSON.parse(rawData) as ServiceMeta;\r\n services.push(serviceData);\r\n } catch {\r\n // ignore invalid json or errors\r\n }\r\n });\r\n\r\n return services;\r\n },\r\n\r\n isServiceEnabled(serviceName: string): boolean {\r\n const services = useServices.loadServices();\r\n const service = services.find((s) => s.lowerName === serviceName.toLowerCase());\r\n return service ? service.enabled : false;\r\n },\r\n\r\n toggleService(serviceName: string, enabled: boolean): boolean {\r\n const servicesDir = useSettings.getPaths().services;\r\n const services = useServices.loadServices();\r\n const index = services.findIndex((s) => s.lowerName === serviceName.toLowerCase());\r\n if (index === -1) return false;\r\n\r\n const serviceMeta = services[index];\r\n serviceMeta.enabled = enabled;\r\n\r\n const serviceJsonPath = path.join(servicesDir, serviceMeta.lowerName, 'service.json');\r\n try {\r\n fs.writeFileSync(serviceJsonPath, JSON.stringify(serviceMeta, null, 2), 'utf-8');\r\n return true;\r\n } catch {\r\n return false;\r\n }\r\n },\r\n\r\n getServices(): ServiceMeta[] {\r\n return useServices.loadServices();\r\n },\r\n};\r\n","// src/hooks/useTemplates.ts\r\n\r\nimport fs from 'fs';\r\nimport * as path from 'path';\r\nimport { useSettings } from './useSettings';\r\nimport { TemplateType } from './useExtensibles';\r\n\r\nexport interface TemplateMeta {\r\n name: string;\r\n lowerName: string;\r\n version?: string;\r\n author?: string;\r\n icon?: string;\r\n description?: string;\r\n enabled: boolean;\r\n templateType: TemplateType;\r\n}\r\n\r\nexport const useTemplates = {\r\n loadTemplates(templateType?: TemplateType): TemplateMeta[] {\r\n const templatesDir = useSettings.getPaths().templates;\r\n if (!fs.existsSync(templatesDir)) return [];\r\n\r\n const templateFolders = fs.readdirSync(templatesDir);\r\n const templates: TemplateMeta[] = [];\r\n\r\n templateFolders.forEach((folder) => {\r\n const templatePath = path.join(templatesDir, folder);\r\n const templateJsonPath = path.join(templatePath, 'template.json');\r\n if (!fs.existsSync(templateJsonPath)) return;\r\n\r\n try {\r\n const rawData = fs.readFileSync(templateJsonPath, 'utf-8');\r\n const templateData = JSON.parse(rawData) as TemplateMeta;\r\n\r\n if (templateType) {\r\n if (templateData.templateType === templateType) {\r\n templates.push(templateData);\r\n }\r\n } else {\r\n templates.push(templateData);\r\n }\r\n } catch {\r\n // ignore invalid JSON or errors\r\n }\r\n });\r\n\r\n return templates;\r\n },\r\n\r\n isTemplateActive(templateType: TemplateType, templateName: string): boolean {\r\n const templates = useTemplates.loadTemplates(templateType);\r\n const template = templates.find(\r\n (t) => t.lowerName === templateName.toLowerCase() && t.enabled\r\n );\r\n return !!template;\r\n },\r\n\r\n toggleTemplate(templateType: TemplateType, templateName: string): boolean {\r\n // Since only one template of each type can be enabled, disable others and enable this one\r\n const templatesDir = useSettings.getPaths().templates;\r\n const templates = useTemplates.loadTemplates(templateType);\r\n\r\n let toggled = false;\r\n\r\n templates.forEach((template) => {\r\n if (template.name.toLowerCase() === templateName.toLowerCase()) {\r\n if (!template.enabled) {\r\n template.enabled = true;\r\n toggled = true;\r\n }\r\n } else {\r\n if (template.enabled) {\r\n template.enabled = false;\r\n }\r\n }\r\n\r\n const templateJsonPath = path.join(templatesDir, template.lowerName, 'template.json');\r\n try {\r\n fs.writeFileSync(templateJsonPath, JSON.stringify(template, null, 2), 'utf-8');\r\n } catch {\r\n // ignore write errors\r\n }\r\n });\r\n\r\n return toggled;\r\n },\r\n\r\n getTemplates(templateType?: TemplateType): TemplateMeta[] {\r\n return useTemplates.loadTemplates(templateType);\r\n },\r\n};\r\n","import fs from 'fs-extra';\r\nimport path from 'path';\r\nimport { Server as SocketIOServer, Socket } from 'socket.io';\r\nimport { useSettings } from './useSettings';\r\n\r\n// Type signature for an event controller\r\ninterface EventController {\r\n onRegister?: (io: SocketIOServer) => void;\r\n onEvent?: (socket: Socket, event: any) => void;\r\n}\r\n\r\n// Dynamically import and register events\r\nexport async function useEvents(io: SocketIOServer) {\r\n const { modules, services, events: appEventsPath } = useSettings.getPaths();\r\n\r\n const sources = [\r\n { type: 'module', root: modules },\r\n { type: 'service', root: services },\r\n { type: 'app', root: appEventsPath },\r\n ];\r\n\r\n for (const source of sources) {\r\n if (!(await fs.pathExists(source.root))) continue;\r\n\r\n const dirs = await fs.readdir(source.root);\r\n for (const dir of dirs) {\r\n const base = path.join(source.root, dir);\r\n const eventsDir = source.type === 'app' ? base : path.join(base, 'events');\r\n\r\n if (!(await fs.pathExists(eventsDir))) continue;\r\n\r\n const files = (await fs.readdir(eventsDir)).filter((f) => f.endsWith('.ts') || f.endsWith('.js'));\r\n\r\n for (const file of files) {\r\n const eventPath = path.join(eventsDir, file);\r\n try {\r\n const imported = await import(eventPath);\r\n const controller: EventController = imported.default || imported[Object.keys(imported)[0]];\r\n\r\n if (controller?.onRegister) {\r\n controller.onRegister(io);\r\n }\r\n\r\n if (controller?.onEvent) {\r\n io.on('connection', (socket) => {\r\n const eventName = file.replace(/\\.(ts|js)$/, '');\r\n socket.on(eventName, (data) => controller.onEvent!(socket, data));\r\n });\r\n }\r\n } catch (err) {\r\n console.warn(`⚠️ Failed to load event: ${eventPath}`, err);\r\n }\r\n }\r\n }\r\n }\r\n}\r\n","// packages/retrex-extensibles-core/useRoutes.ts\r\nimport { Application, Request, Response, NextFunction } from 'express';\r\nimport { pathToFileURL } from 'url';\r\nimport type { LoaderFunctionArgs, ActionFunctionArgs } from '@remix-run/node';\r\n\r\ninterface RouteDefinition {\r\n path: string;\r\n method: 'get' | 'post' | 'put' | 'patch' | 'delete';\r\n filePath: string; // absolute path to .tsx file\r\n}\r\n\r\n// Registry for dynamically added routes\r\nconst registeredRoutes: RouteDefinition[] = [];\r\nexport const routesManager = {\r\n /**\r\n * Register a dynamic route from a module/service.\r\n */\r\n registerRoute(def: RouteDefinition): void {\r\n registeredRoutes.push(def);\r\n },\r\n\r\n /**\r\n * Return all registered dynamic routes.\r\n */\r\n getRegisteredRoutes(): RouteDefinition[] {\r\n return registeredRoutes;\r\n },\r\n\r\n /**\r\n * Loads and mounts all registered dynamic routes into an Express app.\r\n */\r\n async mountRegisteredRoutes(app: Application): Promise<void> {\r\n for (const route of registeredRoutes) {\r\n const mod = await import(pathToFileURL(route.filePath).toString());\r\n\r\n const hasLoader = typeof mod.loader === 'function';\r\n const hasAction = typeof mod.action === 'function';\r\n const hasDefault = typeof mod.default !== 'undefined';\r\n\r\n // Handle API routes with loader/action\r\n if (!hasDefault && (hasLoader || hasAction)) {\r\n app[route.method](route.path, async (req: Request, res: Response, next: NextFunction) => {\r\n try {\r\n if (route.method === 'get' && hasLoader) {\r\n const result = await mod.loader({ request: req });\r\n res.json(result);\r\n } else if (hasAction) {\r\n const result = await mod.action({ request: req });\r\n res.json(result);\r\n } else {\r\n res.status(405).json({ error: 'Method Not Allowed' });\r\n }\r\n } catch (err) {\r\n next(err);\r\n }\r\n });\r\n }\r\n\r\n // Handle Page Routes (React component as default export)\r\n else if (hasDefault) {\r\n app.use(route.path, (req: Request, res: Response, next: NextFunction) => {\r\n res.locals.__dynamicPageComponent = mod.default;\r\n next(); // forward to Remix handler\r\n });\r\n }\r\n }\r\n }\r\n}\r\n","// packages/retrex-extensibles-core/utils/loadThemeComponent.ts\r\nimport path from 'path';\r\nimport { pathToFileURL } from 'url';\r\nimport fs from 'fs-extra';\r\nimport { useSettings } from './useSettings';\r\n\r\nexport const useUtils = {\r\n async loadThemeComponent(\r\n componentName: string,\r\n options: {\r\n theme: {\r\n name: string;\r\n type: 'admin' | 'client' | 'portal' | 'email';\r\n };\r\n search?: {\r\n themes?: boolean;\r\n modules?: boolean;\r\n services?: boolean;\r\n };\r\n }\r\n ): Promise<React.ComponentType<any> | null> {\r\n const { search = {}, theme } = options;\r\n const searchThemes = search.themes ?? true;\r\n const searchModules = search.modules ?? true;\r\n const searchServices = search.services ?? true;\r\n\r\n const possiblePaths: string[] = [];\r\n\r\n if (searchThemes) {\r\n possiblePaths.push(\r\n path.resolve(\r\n 'resources',\r\n 'themes',\r\n theme.type,\r\n theme.name,\r\n 'routes',\r\n `${componentName}.tsx`\r\n ),\r\n path.resolve(\r\n 'resources',\r\n 'themes',\r\n theme.type,\r\n theme.name,\r\n 'components',\r\n `${componentName}.tsx`\r\n )\r\n );\r\n }\r\n\r\n if (searchModules) {\r\n const moduleDirs = await fs.readdir(useSettings.getPaths().modules);\r\n for (const mod of moduleDirs) {\r\n possiblePaths.push(\r\n path.resolve(\r\n 'modules',\r\n mod,\r\n 'themes',\r\n theme.type,\r\n theme.name,\r\n 'routes',\r\n `${componentName}.tsx`\r\n ),\r\n path.resolve(\r\n 'modules',\r\n mod,\r\n 'themes',\r\n theme.type,\r\n theme.name,\r\n 'components',\r\n `${componentName}.tsx`\r\n )\r\n );\r\n }\r\n }\r\n\r\n if (searchServices) {\r\n const serviceDirs = await fs.readdir(useSettings.getPaths().services);\r\n for (const svc of serviceDirs) {\r\n possiblePaths.push(\r\n path.resolve(\r\n 'services',\r\n svc,\r\n 'themes',\r\n theme.type,\r\n theme.name,\r\n 'routes',\r\n `${componentName}.tsx`\r\n ),\r\n path.resolve(\r\n 'services',\r\n svc,\r\n 'themes',\r\n theme.type,\r\n theme.name,\r\n 'components',\r\n `${componentName}.tsx`\r\n )\r\n );\r\n }\r\n }\r\n\r\n for (const filePath of possiblePaths) {\r\n if (await fs.pathExists(filePath)) {\r\n try {\r\n const mod = await import(pathToFileURL(filePath).toString());\r\n if (mod.default) return mod.default;\r\n } catch (err) {\r\n console.error(`Error loading component at ${filePath}:`, err);\r\n }\r\n }\r\n }\r\n\r\n console.warn(`Component \"${componentName}\" not found in theme \"${theme.name}\" of type \"${theme.type}\".`);\r\n return null;\r\n }\r\n}\r\n","import React, { createContext, useContext, useEffect, useState } from 'react';\r\nimport path from 'path';\r\nimport { useSettings } from '../hooks/useSettings';\r\nimport { getTemplates, TemplateType } from '../hooks/useExtensibles';\r\n\r\ninterface ThemeContextProps {\r\n templateType: TemplateType;\r\n activeTheme: string;\r\n setActiveTheme: (theme: string) => void;\r\n}\r\n\r\nconst ThemeContext = createContext<ThemeContextProps | null>(null);\r\n\r\nexport const ThemeProvider: React.FC<{\r\n type: TemplateType;\r\n children: React.ReactNode;\r\n}> = ({ type, children }) => {\r\n const [activeTheme, setActiveTheme] = useState<string>(() => {\r\n const templates = getTemplates(type);\r\n const enabled = templates.find(t => t.enabled);\r\n return enabled?.lowerName ?? templates[0]?.lowerName ?? 'default';\r\n });\r\n\r\n return (\r\n <ThemeContext.Provider value={{ templateType: type, activeTheme, setActiveTheme }}>\r\n {children}\r\n </ThemeContext.Provider>\r\n );\r\n};\r\n\r\nexport function useTheme() {\r\n const ctx = useContext(ThemeContext);\r\n if (!ctx) throw new Error('useTheme must be used inside a ThemeProvider');\r\n return ctx;\r\n}\r\n"],"mappings":"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","names":["path","paths","extensiblePaths","fs","paths","path","fs","import_fs","path","fs","import_fs","path","fs","import_fs_extra","fs","path","import_url","import_path","import_url","import_fs_extra","path","fs"]}
|
package/dist/index.js
CHANGED
|
@@ -28,6 +28,7 @@ var useSettings = {
|
|
|
28
28
|
};
|
|
29
29
|
|
|
30
30
|
// src/core/hooks/useExtensibles.ts
|
|
31
|
+
import { pathToFileURL } from "url";
|
|
31
32
|
var paths;
|
|
32
33
|
function registerExtensibles(extensiblePaths2) {
|
|
33
34
|
paths = extensiblePaths2;
|
|
@@ -41,9 +42,9 @@ function saveJSON(filePath, data) {
|
|
|
41
42
|
}
|
|
42
43
|
function getModules() {
|
|
43
44
|
if (!useSettings.getPaths().modules) throw new Error("Modules path not registered.");
|
|
44
|
-
const dirs = fs.readdirSync(
|
|
45
|
+
const dirs = fs.readdirSync(useSettings.getPaths().modules).filter((d) => fs.statSync(path2.join(useSettings.getPaths().modules, d)).isDirectory());
|
|
45
46
|
return dirs.map((dir) => {
|
|
46
|
-
const meta = loadJSON(path2.join(
|
|
47
|
+
const meta = loadJSON(path2.join(useSettings.getPaths().modules, dir, "module.json")) || {};
|
|
47
48
|
return {
|
|
48
49
|
name: meta.name || dir,
|
|
49
50
|
lowerName: meta.lowerName || dir.toLowerCase(),
|
|
@@ -194,15 +195,15 @@ async function registerRoutes(routesFolderPath) {
|
|
|
194
195
|
}
|
|
195
196
|
}
|
|
196
197
|
async function loadProviders() {
|
|
197
|
-
|
|
198
|
+
const paths2 = {
|
|
198
199
|
modules: useSettings.getPaths().modules,
|
|
199
200
|
templates: useSettings.getPaths().templates,
|
|
200
201
|
services: useSettings.getPaths().services,
|
|
201
202
|
events: useSettings.getPaths().events
|
|
202
203
|
};
|
|
203
204
|
const all = [
|
|
204
|
-
{ type: "module", list: getModules(), basePath:
|
|
205
|
-
{ type: "service", list: getServices(), basePath:
|
|
205
|
+
{ type: "module", list: getModules(), basePath: paths2.modules },
|
|
206
|
+
{ type: "service", list: getServices(), basePath: paths2.services }
|
|
206
207
|
];
|
|
207
208
|
for (const { type, list, basePath } of all) {
|
|
208
209
|
for (const item of list) {
|
|
@@ -212,16 +213,17 @@ async function loadProviders() {
|
|
|
212
213
|
if (!meta?.providers || !Array.isArray(meta.providers)) continue;
|
|
213
214
|
for (const providerRelPath of meta.providers) {
|
|
214
215
|
try {
|
|
215
|
-
const
|
|
216
|
-
const
|
|
216
|
+
const providerAbsPath = path2.join(basePath, item.lowerName, providerRelPath);
|
|
217
|
+
const providerURL = pathToFileURL(providerAbsPath).href;
|
|
218
|
+
const providerModule = await import(providerURL);
|
|
217
219
|
if (typeof providerModule.default === "function") {
|
|
218
220
|
await providerModule.default();
|
|
219
|
-
console.log(`[${type}] Provider loaded: ${providerRelPath}`);
|
|
221
|
+
console.log(`[${type}] \u2705 Provider loaded: ${providerRelPath}`);
|
|
220
222
|
} else {
|
|
221
|
-
console.warn(`[${type}] Provider ${providerRelPath} has no default export.`);
|
|
223
|
+
console.warn(`[${type}] \u26A0\uFE0F Provider ${providerRelPath} has no default export.`);
|
|
222
224
|
}
|
|
223
225
|
} catch (err) {
|
|
224
|
-
console.error(`[${type}] Failed to load provider ${providerRelPath}:`, err);
|
|
226
|
+
console.error(`[${type}] \u274C Failed to load provider ${providerRelPath}:`, err);
|
|
225
227
|
}
|
|
226
228
|
}
|
|
227
229
|
}
|
|
@@ -426,7 +428,7 @@ async function useEvents(io) {
|
|
|
426
428
|
}
|
|
427
429
|
|
|
428
430
|
// src/core/hooks/useRoutes.ts
|
|
429
|
-
import { pathToFileURL } from "url";
|
|
431
|
+
import { pathToFileURL as pathToFileURL2 } from "url";
|
|
430
432
|
var registeredRoutes = [];
|
|
431
433
|
var routesManager = {
|
|
432
434
|
/**
|
|
@@ -446,7 +448,7 @@ var routesManager = {
|
|
|
446
448
|
*/
|
|
447
449
|
async mountRegisteredRoutes(app) {
|
|
448
450
|
for (const route of registeredRoutes) {
|
|
449
|
-
const mod = await import(
|
|
451
|
+
const mod = await import(pathToFileURL2(route.filePath).toString());
|
|
450
452
|
const hasLoader = typeof mod.loader === "function";
|
|
451
453
|
const hasAction = typeof mod.action === "function";
|
|
452
454
|
const hasDefault = typeof mod.default !== "undefined";
|
|
@@ -478,7 +480,7 @@ var routesManager = {
|
|
|
478
480
|
|
|
479
481
|
// src/core/hooks/useUtils.ts
|
|
480
482
|
import path7 from "path";
|
|
481
|
-
import { pathToFileURL as
|
|
483
|
+
import { pathToFileURL as pathToFileURL3 } from "url";
|
|
482
484
|
import fs6 from "fs-extra";
|
|
483
485
|
var useUtils = {
|
|
484
486
|
async loadThemeComponent(componentName, options) {
|
|
@@ -560,7 +562,7 @@ var useUtils = {
|
|
|
560
562
|
for (const filePath of possiblePaths) {
|
|
561
563
|
if (await fs6.pathExists(filePath)) {
|
|
562
564
|
try {
|
|
563
|
-
const mod = await import(
|
|
565
|
+
const mod = await import(pathToFileURL3(filePath).toString());
|
|
564
566
|
if (mod.default) return mod.default;
|
|
565
567
|
} catch (err) {
|
|
566
568
|
console.error(`Error loading component at ${filePath}:`, err);
|
package/dist/index.js.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"sources":["../src/core/hooks/useExtensibles.ts","../src/core/hooks/useSettings.ts","../src/core/hooks/useModules.ts","../src/core/hooks/useServices.ts","../src/core/hooks/useTemplates.ts","../src/core/hooks/useEvents.ts","../src/core/hooks/useRoutes.ts","../src/core/hooks/useUtils.ts","../src/core/providers/ThemeProvider.tsx"],"sourcesContent":["// src/hooks/useExtensibles.ts\r\n\r\nimport fs from 'fs-extra';\r\nimport * as path from 'path';\r\nimport { useSettings } from './useSettings';\r\n\r\nexport type TemplateType = 'admin-theme' | 'client-theme' | 'portal' | 'email';\r\n\r\nexport interface ExtensibleMeta {\r\n name: string;\r\n lowerName: string;\r\n version?: string;\r\n description?: string;\r\n author?: string;\r\n icon?: string;\r\n enabled?: boolean;\r\n}\r\n\r\nexport interface ExtensiblePaths {\r\n modules: string;\r\n templates: string;\r\n services: string;\r\n events: string;\r\n}\r\n\r\nlet paths: ExtensiblePaths;\r\n\r\nexport function registerExtensibles(extensiblePaths: ExtensiblePaths) {\r\n paths = extensiblePaths;\r\n}\r\n\r\nexport function loadJSON(filePath: string): any {\r\n if (!fs.existsSync(filePath)) return null;\r\n return JSON.parse(fs.readFileSync(filePath, 'utf-8'));\r\n}\r\n\r\nexport function saveJSON(filePath: string, data: any) {\r\n fs.writeFileSync(filePath, JSON.stringify(data, null, 2), 'utf-8');\r\n}\r\n\r\n// --- MODULES ---\r\n\r\nexport function getModules(): ExtensibleMeta[] {\r\n if (!useSettings.getPaths().modules) throw new Error('Modules path not registered.');\r\n\r\n const dirs = fs\r\n .readdirSync(paths.modules)\r\n .filter((d: any) => fs.statSync(path.join(paths.modules, d)).isDirectory());\r\n\r\n return dirs.map((dir: any) => {\r\n const meta = loadJSON(path.join(paths.modules, dir, 'module.json')) || {};\r\n return {\r\n name: meta.name || dir,\r\n lowerName: meta.lowerName || dir.toLowerCase(),\r\n version: meta.version,\r\n description: meta.description,\r\n author: meta.author,\r\n icon: meta.icon,\r\n enabled: meta.enabled ?? false,\r\n };\r\n });\r\n}\r\n\r\nexport function isModuleEnabled(name: string) {\r\n const modules = getModules();\r\n return modules.find((m) => m.lowerName === name.toLowerCase())?.enabled ?? false;\r\n}\r\n\r\nexport function toggleModule(name: string, enabled: boolean) {\r\n const modules = getModules();\r\n const mod = modules.find((m) => m.lowerName === name.toLowerCase());\r\n if (!mod) throw new Error(`Module ${name} not found`);\r\n\r\n const metaPath = path.join(paths.modules, mod.lowerName, 'module.json');\r\n const meta = loadJSON(metaPath) || {};\r\n meta.enabled = enabled;\r\n saveJSON(metaPath, meta);\r\n\r\n if (enabled) onModuleEnabled(mod.name);\r\n else onModuleDisabled(mod.name);\r\n}\r\n\r\n// --- SERVICES ---\r\n\r\nexport function getServices(): ExtensibleMeta[] {\r\n if (!paths?.services) throw new Error('Services path not registered.');\r\n\r\n const dirs = fs\r\n .readdirSync(paths.services)\r\n .filter((d: any) => fs.statSync(path.join(paths.services, d)).isDirectory());\r\n\r\n return dirs.map((dir: any) => {\r\n const meta = loadJSON(path.join(paths.services, dir, 'service.json')) || {};\r\n return {\r\n name: meta.name || dir,\r\n lowerName: meta.lowerName || dir.toLowerCase(),\r\n version: meta.version,\r\n description: meta.description,\r\n author: meta.author,\r\n icon: meta.icon,\r\n enabled: meta.enabled ?? false,\r\n };\r\n });\r\n}\r\n\r\nexport function isServiceEnabled(name: string) {\r\n const services = getServices();\r\n return services.find((s) => s.lowerName === name.toLowerCase())?.enabled ?? false;\r\n}\r\n\r\nexport function toggleService(name: string, enabled: boolean) {\r\n const services = getServices();\r\n const svc = services.find((s) => s.lowerName === name.toLowerCase());\r\n if (!svc) throw new Error(`Service ${name} not found`);\r\n\r\n const metaPath = path.join(paths.services, svc.lowerName, 'service.json');\r\n const meta = loadJSON(metaPath) || {};\r\n meta.enabled = enabled;\r\n saveJSON(metaPath, meta);\r\n\r\n if (enabled) onServiceEnabled(svc.name);\r\n else onServiceDisabled(svc.name);\r\n}\r\n\r\n// --- TEMPLATES ---\r\n\r\n// Helper to get base path for a template type\r\nfunction getTemplateBasePath(type: TemplateType): string {\r\n if (!paths?.templates) throw new Error('Templates path not registered.');\r\n switch (type) {\r\n case 'admin-theme':\r\n case 'client-theme':\r\n return path.join(paths.templates, 'themes');\r\n case 'portal':\r\n return path.join(paths.templates, 'portals');\r\n case 'email':\r\n return path.join(paths.templates, 'emails');\r\n default:\r\n throw new Error(`Unknown template type: ${type}`);\r\n }\r\n}\r\n\r\nexport function getTemplates(type: TemplateType): ExtensibleMeta[] {\r\n const basePath = getTemplateBasePath(type);\r\n if (!fs.existsSync(basePath)) return [];\r\n\r\n const dirs = fs\r\n .readdirSync(basePath)\r\n .filter((d: any) => fs.statSync(path.join(basePath, d)).isDirectory());\r\n\r\n return dirs.map((dir: any) => {\r\n const meta = loadJSON(path.join(basePath, dir, 'template.json')) || {};\r\n return {\r\n name: meta.name || dir,\r\n lowerName: dir.toLowerCase(),\r\n version: meta.version,\r\n description: meta.description,\r\n author: meta.author,\r\n icon: meta.icon,\r\n enabled: meta.enabled ?? false,\r\n };\r\n });\r\n}\r\n\r\nexport function isTemplateActive(type: TemplateType, name: string) {\r\n const templates = getTemplates(type);\r\n return templates.find((t) => t.lowerName === name.toLowerCase())?.enabled ?? false;\r\n}\r\n\r\n// Toggle templates: only 1 active per type allowed\r\nexport function toggleTemplate(type: TemplateType, name: string) {\r\n const templates = getTemplates(type);\r\n\r\n templates.forEach((tpl) => {\r\n const metaPath = path.join(getTemplateBasePath(type), tpl.lowerName, 'template.json');\r\n const meta = loadJSON(metaPath) || {};\r\n meta.enabled = tpl.lowerName === name.toLowerCase();\r\n saveJSON(metaPath, meta);\r\n });\r\n\r\n onTemplateSelect(type, name);\r\n}\r\n\r\n// --- EVENTS (replace with your event system integration) ---\r\n\r\nexport function onModuleEnabled(name: string) {\r\n console.log(`Module enabled: ${name}`);\r\n // emit event or custom logic here\r\n}\r\n\r\nexport function onModuleDisabled(name: string) {\r\n console.log(`Module disabled: ${name}`);\r\n}\r\n\r\nexport function onServiceEnabled(name: string) {\r\n console.log(`Service enabled: ${name}`);\r\n}\r\n\r\nexport function onServiceDisabled(name: string) {\r\n console.log(`Service disabled: ${name}`);\r\n}\r\n\r\nexport function onTemplateSelect(type: TemplateType, name: string) {\r\n console.log(`Template selected: type=${type}, name=${name}`);\r\n}\r\n\r\n// --- REGISTER HOOKS FOR MODULES ---\r\n\r\nexport async function registerEvents() {\r\n if (!paths?.modules) throw new Error('Modules path not registered.');\r\n const modules = getModules().filter((m) => m.enabled);\r\n for (const mod of modules) {\r\n const eventsFile = path.join(paths.modules, mod.lowerName, 'events.server.js');\r\n if (fs.existsSync(eventsFile)) {\r\n const modEvents = await import(eventsFile);\r\n if (modEvents?.registerEvents) await modEvents.registerEvents();\r\n }\r\n }\r\n}\r\n\r\nexport async function registerMiddleware() {\r\n if (!paths?.modules) throw new Error('Modules path not registered.');\r\n const modules = getModules().filter((m) => m.enabled);\r\n for (const mod of modules) {\r\n const middlewareFile = path.join(paths.modules, mod.lowerName, 'middleware.server.js');\r\n if (fs.existsSync(middlewareFile)) {\r\n const modMiddleware = await import(middlewareFile);\r\n if (modMiddleware?.registerMiddleware) await modMiddleware.registerMiddleware();\r\n }\r\n }\r\n}\r\n\r\n/**\r\n * Registers routes given a path to routes folder (for pages and API routes)\r\n * @param routesFolderPath string - path to module/service routes folder\r\n */\r\nexport async function registerRoutes(routesFolderPath: string) {\r\n if (!fs.existsSync(routesFolderPath)) return;\r\n\r\n const routeFiles = fs.readdirSync(routesFolderPath).filter((f: any) => /\\.(js|ts|jsx|tsx)$/.test(f));\r\n for (const file of routeFiles) {\r\n const routeModule = await import(path.join(routesFolderPath, file));\r\n if (routeModule?.registerRoute) {\r\n await routeModule.registerRoute();\r\n }\r\n }\r\n}\r\n\r\nexport async function loadProviders() {\r\n paths = {\r\n modules: useSettings.getPaths().modules,\r\n templates: useSettings.getPaths().templates,\r\n services: useSettings.getPaths().services,\r\n events: useSettings.getPaths().events,\r\n }\r\n const all = [\r\n { type: 'module', list: getModules(), basePath: paths.modules },\r\n { type: 'service', list: getServices(), basePath: paths.services },\r\n ];\r\n\r\n for (const { type, list, basePath } of all) {\r\n for (const item of list) {\r\n if (!item.enabled) continue;\r\n\r\n const metaPath = path.join(basePath, item.lowerName, `${type}.json`);\r\n const meta = loadJSON(metaPath);\r\n if (!meta?.providers || !Array.isArray(meta.providers)) continue;\r\n\r\n for (const providerRelPath of meta.providers) {\r\n try {\r\n const providerPath = path.join(basePath, item.lowerName, providerRelPath);\r\n const providerModule = await import(providerPath);\r\n if (typeof providerModule.default === 'function') {\r\n await providerModule.default(); // Call provider\r\n console.log(`[${type}] Provider loaded: ${providerRelPath}`);\r\n } else {\r\n console.warn(`[${type}] Provider ${providerRelPath} has no default export.`);\r\n }\r\n } catch (err) {\r\n console.error(`[${type}] Failed to load provider ${providerRelPath}:`, err);\r\n }\r\n }\r\n }\r\n }\r\n}\r\n","// src/hooks/useSettings.ts\r\n\r\nimport * as path from 'path';\r\n\r\nimport { ExtensiblePaths, loadJSON, saveJSON } from './useExtensibles';\r\n\r\n// export interface ExtensiblePaths {\r\n// modulesPath: string;\r\n// templatesPath: string;\r\n// servicesPath: string;\r\n// }\r\n\r\nlet extensiblePaths: ExtensiblePaths = {\r\n modules: path.resolve(process.cwd(), 'modules'),\r\n templates: path.resolve(process.cwd(), 'resources/themes'),\r\n services: path.resolve(process.cwd(), 'app/services'),\r\n events: path.resolve(process.cwd(), 'events'),\r\n};\r\n\r\nexport const useSettings = {\r\n getPaths(): ExtensiblePaths {\r\n extensiblePaths = loadJSON(\"extensiblePaths.json\");\r\n return extensiblePaths;\r\n },\r\n\r\n setPaths(paths: Partial<ExtensiblePaths>) {\r\n saveJSON(\"extensiblePaths.json\", {\r\n ...extensiblePaths,\r\n ...paths,\r\n })\r\n extensiblePaths = {\r\n ...extensiblePaths,\r\n ...paths,\r\n };\r\n },\r\n};\r\n","// src/hooks/useModules.ts\r\n\r\nimport fs from 'fs';\r\nimport * as path from 'path';\r\nimport { useSettings } from './useSettings';\r\n\r\nexport interface ModuleMeta {\r\n name: string;\r\n lowerName: string;\r\n version?: string;\r\n author?: string;\r\n icon?: string;\r\n description?: string;\r\n enabled: boolean;\r\n providers?: string[];\r\n}\r\n\r\nexport const useModules = {\r\n loadModules(): ModuleMeta[] {\r\n const modulesDir = useSettings.getPaths().modules;\r\n if (!fs.existsSync(modulesDir)) return [];\r\n\r\n const moduleFolders = fs.readdirSync(modulesDir);\r\n const modules: ModuleMeta[] = [];\r\n\r\n moduleFolders.forEach((folder) => {\r\n const modulePath = path.join(modulesDir, folder);\r\n const moduleJsonPath = path.join(modulePath, 'module.json');\r\n if (!fs.existsSync(moduleJsonPath)) return;\r\n\r\n try {\r\n const rawData = fs.readFileSync(moduleJsonPath, 'utf-8');\r\n const moduleData = JSON.parse(rawData) as ModuleMeta;\r\n modules.push(moduleData);\r\n } catch {\r\n // invalid json or read error, ignore\r\n }\r\n });\r\n\r\n return modules;\r\n },\r\n\r\n isModuleEnabled(moduleName: string): boolean {\r\n const modules = useModules.loadModules();\r\n const mod = modules.find((m) => m.lowerName === moduleName.toLowerCase());\r\n return mod ? mod.enabled : false;\r\n },\r\n\r\n toggleModule(moduleName: string, enabled: boolean): boolean {\r\n const modulesDir = useSettings.getPaths().modules;\r\n const modules = useModules.loadModules();\r\n const modIndex = modules.findIndex((m) => m.lowerName === moduleName.toLowerCase());\r\n if (modIndex === -1) return false;\r\n\r\n const moduleMeta = modules[modIndex];\r\n moduleMeta.enabled = enabled;\r\n\r\n const moduleJsonPath = path.join(modulesDir, moduleMeta.lowerName, 'module.json');\r\n try {\r\n fs.writeFileSync(moduleJsonPath, JSON.stringify(moduleMeta, null, 2), 'utf-8');\r\n return true;\r\n } catch {\r\n return false;\r\n }\r\n },\r\n\r\n getModules(): ModuleMeta[] {\r\n return useModules.loadModules();\r\n },\r\n};\r\n","// src/hooks/useServices.ts\r\n\r\nimport fs from 'fs';\r\nimport * as path from 'path';\r\nimport { useSettings } from './useSettings';\r\n\r\nexport interface ServiceMeta {\r\n name: string;\r\n lowerName: string;\r\n version?: string;\r\n author?: string;\r\n icon?: string;\r\n description?: string;\r\n enabled: boolean;\r\n providers?: string[];\r\n serviceType?: string;\r\n}\r\n\r\nexport const useServices = {\r\n loadServices(): ServiceMeta[] {\r\n const servicesDir = useSettings.getPaths().services;\r\n if (!fs.existsSync(servicesDir)) return [];\r\n\r\n const serviceFolders = fs.readdirSync(servicesDir);\r\n const services: ServiceMeta[] = [];\r\n\r\n serviceFolders.forEach((folder) => {\r\n const servicePath = path.join(servicesDir, folder);\r\n const serviceJsonPath = path.join(servicePath, 'service.json');\r\n if (!fs.existsSync(serviceJsonPath)) return;\r\n\r\n try {\r\n const rawData = fs.readFileSync(serviceJsonPath, 'utf-8');\r\n const serviceData = JSON.parse(rawData) as ServiceMeta;\r\n services.push(serviceData);\r\n } catch {\r\n // ignore invalid json or errors\r\n }\r\n });\r\n\r\n return services;\r\n },\r\n\r\n isServiceEnabled(serviceName: string): boolean {\r\n const services = useServices.loadServices();\r\n const service = services.find((s) => s.lowerName === serviceName.toLowerCase());\r\n return service ? service.enabled : false;\r\n },\r\n\r\n toggleService(serviceName: string, enabled: boolean): boolean {\r\n const servicesDir = useSettings.getPaths().services;\r\n const services = useServices.loadServices();\r\n const index = services.findIndex((s) => s.lowerName === serviceName.toLowerCase());\r\n if (index === -1) return false;\r\n\r\n const serviceMeta = services[index];\r\n serviceMeta.enabled = enabled;\r\n\r\n const serviceJsonPath = path.join(servicesDir, serviceMeta.lowerName, 'service.json');\r\n try {\r\n fs.writeFileSync(serviceJsonPath, JSON.stringify(serviceMeta, null, 2), 'utf-8');\r\n return true;\r\n } catch {\r\n return false;\r\n }\r\n },\r\n\r\n getServices(): ServiceMeta[] {\r\n return useServices.loadServices();\r\n },\r\n};\r\n","// src/hooks/useTemplates.ts\r\n\r\nimport fs from 'fs';\r\nimport * as path from 'path';\r\nimport { useSettings } from './useSettings';\r\nimport { TemplateType } from './useExtensibles';\r\n\r\nexport interface TemplateMeta {\r\n name: string;\r\n lowerName: string;\r\n version?: string;\r\n author?: string;\r\n icon?: string;\r\n description?: string;\r\n enabled: boolean;\r\n templateType: TemplateType;\r\n}\r\n\r\nexport const useTemplates = {\r\n loadTemplates(templateType?: TemplateType): TemplateMeta[] {\r\n const templatesDir = useSettings.getPaths().templates;\r\n if (!fs.existsSync(templatesDir)) return [];\r\n\r\n const templateFolders = fs.readdirSync(templatesDir);\r\n const templates: TemplateMeta[] = [];\r\n\r\n templateFolders.forEach((folder) => {\r\n const templatePath = path.join(templatesDir, folder);\r\n const templateJsonPath = path.join(templatePath, 'template.json');\r\n if (!fs.existsSync(templateJsonPath)) return;\r\n\r\n try {\r\n const rawData = fs.readFileSync(templateJsonPath, 'utf-8');\r\n const templateData = JSON.parse(rawData) as TemplateMeta;\r\n\r\n if (templateType) {\r\n if (templateData.templateType === templateType) {\r\n templates.push(templateData);\r\n }\r\n } else {\r\n templates.push(templateData);\r\n }\r\n } catch {\r\n // ignore invalid JSON or errors\r\n }\r\n });\r\n\r\n return templates;\r\n },\r\n\r\n isTemplateActive(templateType: TemplateType, templateName: string): boolean {\r\n const templates = useTemplates.loadTemplates(templateType);\r\n const template = templates.find(\r\n (t) => t.lowerName === templateName.toLowerCase() && t.enabled\r\n );\r\n return !!template;\r\n },\r\n\r\n toggleTemplate(templateType: TemplateType, templateName: string): boolean {\r\n // Since only one template of each type can be enabled, disable others and enable this one\r\n const templatesDir = useSettings.getPaths().templates;\r\n const templates = useTemplates.loadTemplates(templateType);\r\n\r\n let toggled = false;\r\n\r\n templates.forEach((template) => {\r\n if (template.name.toLowerCase() === templateName.toLowerCase()) {\r\n if (!template.enabled) {\r\n template.enabled = true;\r\n toggled = true;\r\n }\r\n } else {\r\n if (template.enabled) {\r\n template.enabled = false;\r\n }\r\n }\r\n\r\n const templateJsonPath = path.join(templatesDir, template.lowerName, 'template.json');\r\n try {\r\n fs.writeFileSync(templateJsonPath, JSON.stringify(template, null, 2), 'utf-8');\r\n } catch {\r\n // ignore write errors\r\n }\r\n });\r\n\r\n return toggled;\r\n },\r\n\r\n getTemplates(templateType?: TemplateType): TemplateMeta[] {\r\n return useTemplates.loadTemplates(templateType);\r\n },\r\n};\r\n","import fs from 'fs-extra';\r\nimport path from 'path';\r\nimport { Server as SocketIOServer, Socket } from 'socket.io';\r\nimport { useSettings } from './useSettings';\r\n\r\n// Type signature for an event controller\r\ninterface EventController {\r\n onRegister?: (io: SocketIOServer) => void;\r\n onEvent?: (socket: Socket, event: any) => void;\r\n}\r\n\r\n// Dynamically import and register events\r\nexport async function useEvents(io: SocketIOServer) {\r\n const { modules, services, events: appEventsPath } = useSettings.getPaths();\r\n\r\n const sources = [\r\n { type: 'module', root: modules },\r\n { type: 'service', root: services },\r\n { type: 'app', root: appEventsPath },\r\n ];\r\n\r\n for (const source of sources) {\r\n if (!(await fs.pathExists(source.root))) continue;\r\n\r\n const dirs = await fs.readdir(source.root);\r\n for (const dir of dirs) {\r\n const base = path.join(source.root, dir);\r\n const eventsDir = source.type === 'app' ? base : path.join(base, 'events');\r\n\r\n if (!(await fs.pathExists(eventsDir))) continue;\r\n\r\n const files = (await fs.readdir(eventsDir)).filter((f) => f.endsWith('.ts') || f.endsWith('.js'));\r\n\r\n for (const file of files) {\r\n const eventPath = path.join(eventsDir, file);\r\n try {\r\n const imported = await import(eventPath);\r\n const controller: EventController = imported.default || imported[Object.keys(imported)[0]];\r\n\r\n if (controller?.onRegister) {\r\n controller.onRegister(io);\r\n }\r\n\r\n if (controller?.onEvent) {\r\n io.on('connection', (socket) => {\r\n const eventName = file.replace(/\\.(ts|js)$/, '');\r\n socket.on(eventName, (data) => controller.onEvent!(socket, data));\r\n });\r\n }\r\n } catch (err) {\r\n console.warn(`⚠️ Failed to load event: ${eventPath}`, err);\r\n }\r\n }\r\n }\r\n }\r\n}\r\n","// packages/retrex-extensibles-core/useRoutes.ts\r\nimport { Application, Request, Response, NextFunction } from 'express';\r\nimport { pathToFileURL } from 'url';\r\nimport type { LoaderFunctionArgs, ActionFunctionArgs } from '@remix-run/node';\r\n\r\ninterface RouteDefinition {\r\n path: string;\r\n method: 'get' | 'post' | 'put' | 'patch' | 'delete';\r\n filePath: string; // absolute path to .tsx file\r\n}\r\n\r\n// Registry for dynamically added routes\r\nconst registeredRoutes: RouteDefinition[] = [];\r\nexport const routesManager = {\r\n /**\r\n * Register a dynamic route from a module/service.\r\n */\r\n registerRoute(def: RouteDefinition): void {\r\n registeredRoutes.push(def);\r\n },\r\n\r\n /**\r\n * Return all registered dynamic routes.\r\n */\r\n getRegisteredRoutes(): RouteDefinition[] {\r\n return registeredRoutes;\r\n },\r\n\r\n /**\r\n * Loads and mounts all registered dynamic routes into an Express app.\r\n */\r\n async mountRegisteredRoutes(app: Application): Promise<void> {\r\n for (const route of registeredRoutes) {\r\n const mod = await import(pathToFileURL(route.filePath).toString());\r\n\r\n const hasLoader = typeof mod.loader === 'function';\r\n const hasAction = typeof mod.action === 'function';\r\n const hasDefault = typeof mod.default !== 'undefined';\r\n\r\n // Handle API routes with loader/action\r\n if (!hasDefault && (hasLoader || hasAction)) {\r\n app[route.method](route.path, async (req: Request, res: Response, next: NextFunction) => {\r\n try {\r\n if (route.method === 'get' && hasLoader) {\r\n const result = await mod.loader({ request: req });\r\n res.json(result);\r\n } else if (hasAction) {\r\n const result = await mod.action({ request: req });\r\n res.json(result);\r\n } else {\r\n res.status(405).json({ error: 'Method Not Allowed' });\r\n }\r\n } catch (err) {\r\n next(err);\r\n }\r\n });\r\n }\r\n\r\n // Handle Page Routes (React component as default export)\r\n else if (hasDefault) {\r\n app.use(route.path, (req: Request, res: Response, next: NextFunction) => {\r\n res.locals.__dynamicPageComponent = mod.default;\r\n next(); // forward to Remix handler\r\n });\r\n }\r\n }\r\n }\r\n}\r\n","// packages/retrex-extensibles-core/utils/loadThemeComponent.ts\r\nimport path from 'path';\r\nimport { pathToFileURL } from 'url';\r\nimport fs from 'fs-extra';\r\nimport { useSettings } from './useSettings';\r\n\r\nexport const useUtils = {\r\n async loadThemeComponent(\r\n componentName: string,\r\n options: {\r\n theme: {\r\n name: string;\r\n type: 'admin' | 'client' | 'portal' | 'email';\r\n };\r\n search?: {\r\n themes?: boolean;\r\n modules?: boolean;\r\n services?: boolean;\r\n };\r\n }\r\n ): Promise<React.ComponentType<any> | null> {\r\n const { search = {}, theme } = options;\r\n const searchThemes = search.themes ?? true;\r\n const searchModules = search.modules ?? true;\r\n const searchServices = search.services ?? true;\r\n\r\n const possiblePaths: string[] = [];\r\n\r\n if (searchThemes) {\r\n possiblePaths.push(\r\n path.resolve(\r\n 'resources',\r\n 'themes',\r\n theme.type,\r\n theme.name,\r\n 'routes',\r\n `${componentName}.tsx`\r\n ),\r\n path.resolve(\r\n 'resources',\r\n 'themes',\r\n theme.type,\r\n theme.name,\r\n 'components',\r\n `${componentName}.tsx`\r\n )\r\n );\r\n }\r\n\r\n if (searchModules) {\r\n const moduleDirs = await fs.readdir(useSettings.getPaths().modules);\r\n for (const mod of moduleDirs) {\r\n possiblePaths.push(\r\n path.resolve(\r\n 'modules',\r\n mod,\r\n 'themes',\r\n theme.type,\r\n theme.name,\r\n 'routes',\r\n `${componentName}.tsx`\r\n ),\r\n path.resolve(\r\n 'modules',\r\n mod,\r\n 'themes',\r\n theme.type,\r\n theme.name,\r\n 'components',\r\n `${componentName}.tsx`\r\n )\r\n );\r\n }\r\n }\r\n\r\n if (searchServices) {\r\n const serviceDirs = await fs.readdir(useSettings.getPaths().services);\r\n for (const svc of serviceDirs) {\r\n possiblePaths.push(\r\n path.resolve(\r\n 'services',\r\n svc,\r\n 'themes',\r\n theme.type,\r\n theme.name,\r\n 'routes',\r\n `${componentName}.tsx`\r\n ),\r\n path.resolve(\r\n 'services',\r\n svc,\r\n 'themes',\r\n theme.type,\r\n theme.name,\r\n 'components',\r\n `${componentName}.tsx`\r\n )\r\n );\r\n }\r\n }\r\n\r\n for (const filePath of possiblePaths) {\r\n if (await fs.pathExists(filePath)) {\r\n try {\r\n const mod = await import(pathToFileURL(filePath).toString());\r\n if (mod.default) return mod.default;\r\n } catch (err) {\r\n console.error(`Error loading component at ${filePath}:`, err);\r\n }\r\n }\r\n }\r\n\r\n console.warn(`Component \"${componentName}\" not found in theme \"${theme.name}\" of type \"${theme.type}\".`);\r\n return null;\r\n }\r\n}\r\n","import React, { createContext, useContext, useEffect, useState } from 'react';\r\nimport path from 'path';\r\nimport { useSettings } from '../hooks/useSettings';\r\nimport { getTemplates, TemplateType } from '../hooks/useExtensibles';\r\n\r\ninterface ThemeContextProps {\r\n templateType: TemplateType;\r\n activeTheme: string;\r\n setActiveTheme: (theme: string) => void;\r\n}\r\n\r\nconst ThemeContext = createContext<ThemeContextProps | null>(null);\r\n\r\nexport const ThemeProvider: React.FC<{\r\n type: TemplateType;\r\n children: React.ReactNode;\r\n}> = ({ type, children }) => {\r\n const [activeTheme, setActiveTheme] = useState<string>(() => {\r\n const templates = getTemplates(type);\r\n const enabled = templates.find(t => t.enabled);\r\n return enabled?.lowerName ?? templates[0]?.lowerName ?? 'default';\r\n });\r\n\r\n return (\r\n <ThemeContext.Provider value={{ templateType: type, activeTheme, setActiveTheme }}>\r\n {children}\r\n </ThemeContext.Provider>\r\n );\r\n};\r\n\r\nexport function useTheme() {\r\n const ctx = useContext(ThemeContext);\r\n if (!ctx) throw new Error('useTheme must be used inside a ThemeProvider');\r\n return ctx;\r\n}\r\n"],"mappings":"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","names":["path","paths","extensiblePaths","fs","path","fs","fs","path","fs","fs","path","fs","fs","path","fs","path","path","pathToFileURL","fs","path","fs","pathToFileURL"]}
|
|
1
|
+
{"version":3,"sources":["../src/core/hooks/useExtensibles.ts","../src/core/hooks/useSettings.ts","../src/core/hooks/useModules.ts","../src/core/hooks/useServices.ts","../src/core/hooks/useTemplates.ts","../src/core/hooks/useEvents.ts","../src/core/hooks/useRoutes.ts","../src/core/hooks/useUtils.ts","../src/core/providers/ThemeProvider.tsx"],"sourcesContent":["// src/hooks/useExtensibles.ts\r\n\r\nimport fs from 'fs-extra';\r\nimport * as path from 'path';\r\nimport { useSettings } from './useSettings';\r\nimport { pathToFileURL } from 'url';\r\n\r\nexport type TemplateType = 'admin-theme' | 'client-theme' | 'portal' | 'email';\r\n\r\nexport interface ExtensibleMeta {\r\n name: string;\r\n lowerName: string;\r\n version?: string;\r\n description?: string;\r\n author?: string;\r\n icon?: string;\r\n enabled?: boolean;\r\n}\r\n\r\nexport interface ExtensiblePaths {\r\n modules: string;\r\n templates: string;\r\n services: string;\r\n events: string;\r\n}\r\n\r\nlet paths: ExtensiblePaths;\r\n\r\nexport function registerExtensibles(extensiblePaths: ExtensiblePaths) {\r\n paths = extensiblePaths;\r\n}\r\n\r\nexport function loadJSON(filePath: string): any {\r\n if (!fs.existsSync(filePath)) return null;\r\n return JSON.parse(fs.readFileSync(filePath, 'utf-8'));\r\n}\r\n\r\nexport function saveJSON(filePath: string, data: any) {\r\n fs.writeFileSync(filePath, JSON.stringify(data, null, 2), 'utf-8');\r\n}\r\n\r\n// --- MODULES ---\r\n\r\nexport function getModules(): ExtensibleMeta[] {\r\n if (!useSettings.getPaths().modules) throw new Error('Modules path not registered.');\r\n\r\n const dirs = fs\r\n .readdirSync(useSettings.getPaths().modules)\r\n .filter((d: any) => fs.statSync(path.join(useSettings.getPaths().modules, d)).isDirectory());\r\n\r\n return dirs.map((dir: any) => {\r\n const meta = loadJSON(path.join(useSettings.getPaths().modules, dir, 'module.json')) || {};\r\n return {\r\n name: meta.name || dir,\r\n lowerName: meta.lowerName || dir.toLowerCase(),\r\n version: meta.version,\r\n description: meta.description,\r\n author: meta.author,\r\n icon: meta.icon,\r\n enabled: meta.enabled ?? false,\r\n };\r\n });\r\n}\r\n\r\nexport function isModuleEnabled(name: string) {\r\n const modules = getModules();\r\n return modules.find((m) => m.lowerName === name.toLowerCase())?.enabled ?? false;\r\n}\r\n\r\nexport function toggleModule(name: string, enabled: boolean) {\r\n const modules = getModules();\r\n const mod = modules.find((m) => m.lowerName === name.toLowerCase());\r\n if (!mod) throw new Error(`Module ${name} not found`);\r\n\r\n const metaPath = path.join(paths.modules, mod.lowerName, 'module.json');\r\n const meta = loadJSON(metaPath) || {};\r\n meta.enabled = enabled;\r\n saveJSON(metaPath, meta);\r\n\r\n if (enabled) onModuleEnabled(mod.name);\r\n else onModuleDisabled(mod.name);\r\n}\r\n\r\n// --- SERVICES ---\r\n\r\nexport function getServices(): ExtensibleMeta[] {\r\n if (!paths?.services) throw new Error('Services path not registered.');\r\n\r\n const dirs = fs\r\n .readdirSync(paths.services)\r\n .filter((d: any) => fs.statSync(path.join(paths.services, d)).isDirectory());\r\n\r\n return dirs.map((dir: any) => {\r\n const meta = loadJSON(path.join(paths.services, dir, 'service.json')) || {};\r\n return {\r\n name: meta.name || dir,\r\n lowerName: meta.lowerName || dir.toLowerCase(),\r\n version: meta.version,\r\n description: meta.description,\r\n author: meta.author,\r\n icon: meta.icon,\r\n enabled: meta.enabled ?? false,\r\n };\r\n });\r\n}\r\n\r\nexport function isServiceEnabled(name: string) {\r\n const services = getServices();\r\n return services.find((s) => s.lowerName === name.toLowerCase())?.enabled ?? false;\r\n}\r\n\r\nexport function toggleService(name: string, enabled: boolean) {\r\n const services = getServices();\r\n const svc = services.find((s) => s.lowerName === name.toLowerCase());\r\n if (!svc) throw new Error(`Service ${name} not found`);\r\n\r\n const metaPath = path.join(paths.services, svc.lowerName, 'service.json');\r\n const meta = loadJSON(metaPath) || {};\r\n meta.enabled = enabled;\r\n saveJSON(metaPath, meta);\r\n\r\n if (enabled) onServiceEnabled(svc.name);\r\n else onServiceDisabled(svc.name);\r\n}\r\n\r\n// --- TEMPLATES ---\r\n\r\n// Helper to get base path for a template type\r\nfunction getTemplateBasePath(type: TemplateType): string {\r\n if (!paths?.templates) throw new Error('Templates path not registered.');\r\n switch (type) {\r\n case 'admin-theme':\r\n case 'client-theme':\r\n return path.join(paths.templates, 'themes');\r\n case 'portal':\r\n return path.join(paths.templates, 'portals');\r\n case 'email':\r\n return path.join(paths.templates, 'emails');\r\n default:\r\n throw new Error(`Unknown template type: ${type}`);\r\n }\r\n}\r\n\r\nexport function getTemplates(type: TemplateType): ExtensibleMeta[] {\r\n const basePath = getTemplateBasePath(type);\r\n if (!fs.existsSync(basePath)) return [];\r\n\r\n const dirs = fs\r\n .readdirSync(basePath)\r\n .filter((d: any) => fs.statSync(path.join(basePath, d)).isDirectory());\r\n\r\n return dirs.map((dir: any) => {\r\n const meta = loadJSON(path.join(basePath, dir, 'template.json')) || {};\r\n return {\r\n name: meta.name || dir,\r\n lowerName: dir.toLowerCase(),\r\n version: meta.version,\r\n description: meta.description,\r\n author: meta.author,\r\n icon: meta.icon,\r\n enabled: meta.enabled ?? false,\r\n };\r\n });\r\n}\r\n\r\nexport function isTemplateActive(type: TemplateType, name: string) {\r\n const templates = getTemplates(type);\r\n return templates.find((t) => t.lowerName === name.toLowerCase())?.enabled ?? false;\r\n}\r\n\r\n// Toggle templates: only 1 active per type allowed\r\nexport function toggleTemplate(type: TemplateType, name: string) {\r\n const templates = getTemplates(type);\r\n\r\n templates.forEach((tpl) => {\r\n const metaPath = path.join(getTemplateBasePath(type), tpl.lowerName, 'template.json');\r\n const meta = loadJSON(metaPath) || {};\r\n meta.enabled = tpl.lowerName === name.toLowerCase();\r\n saveJSON(metaPath, meta);\r\n });\r\n\r\n onTemplateSelect(type, name);\r\n}\r\n\r\n// --- EVENTS (replace with your event system integration) ---\r\n\r\nexport function onModuleEnabled(name: string) {\r\n console.log(`Module enabled: ${name}`);\r\n // emit event or custom logic here\r\n}\r\n\r\nexport function onModuleDisabled(name: string) {\r\n console.log(`Module disabled: ${name}`);\r\n}\r\n\r\nexport function onServiceEnabled(name: string) {\r\n console.log(`Service enabled: ${name}`);\r\n}\r\n\r\nexport function onServiceDisabled(name: string) {\r\n console.log(`Service disabled: ${name}`);\r\n}\r\n\r\nexport function onTemplateSelect(type: TemplateType, name: string) {\r\n console.log(`Template selected: type=${type}, name=${name}`);\r\n}\r\n\r\n// --- REGISTER HOOKS FOR MODULES ---\r\n\r\nexport async function registerEvents() {\r\n if (!paths?.modules) throw new Error('Modules path not registered.');\r\n const modules = getModules().filter((m) => m.enabled);\r\n for (const mod of modules) {\r\n const eventsFile = path.join(paths.modules, mod.lowerName, 'events.server.js');\r\n if (fs.existsSync(eventsFile)) {\r\n const modEvents = await import(eventsFile);\r\n if (modEvents?.registerEvents) await modEvents.registerEvents();\r\n }\r\n }\r\n}\r\n\r\nexport async function registerMiddleware() {\r\n if (!paths?.modules) throw new Error('Modules path not registered.');\r\n const modules = getModules().filter((m) => m.enabled);\r\n for (const mod of modules) {\r\n const middlewareFile = path.join(paths.modules, mod.lowerName, 'middleware.server.js');\r\n if (fs.existsSync(middlewareFile)) {\r\n const modMiddleware = await import(middlewareFile);\r\n if (modMiddleware?.registerMiddleware) await modMiddleware.registerMiddleware();\r\n }\r\n }\r\n}\r\n\r\n/**\r\n * Registers routes given a path to routes folder (for pages and API routes)\r\n * @param routesFolderPath string - path to module/service routes folder\r\n */\r\nexport async function registerRoutes(routesFolderPath: string) {\r\n if (!fs.existsSync(routesFolderPath)) return;\r\n\r\n const routeFiles = fs.readdirSync(routesFolderPath).filter((f: any) => /\\.(js|ts|jsx|tsx)$/.test(f));\r\n for (const file of routeFiles) {\r\n const routeModule = await import(path.join(routesFolderPath, file));\r\n if (routeModule?.registerRoute) {\r\n await routeModule.registerRoute();\r\n }\r\n }\r\n}\r\n\r\nexport async function loadProviders() {\r\n const paths = {\r\n modules: useSettings.getPaths().modules,\r\n templates: useSettings.getPaths().templates,\r\n services: useSettings.getPaths().services,\r\n events: useSettings.getPaths().events,\r\n };\r\n\r\n const all = [\r\n { type: 'module', list: getModules(), basePath: paths.modules },\r\n { type: 'service', list: getServices(), basePath: paths.services },\r\n ];\r\n\r\n for (const { type, list, basePath } of all) {\r\n for (const item of list) {\r\n if (!item.enabled) continue;\r\n\r\n const metaPath = path.join(basePath, item.lowerName, `${type}.json`);\r\n const meta = loadJSON(metaPath);\r\n if (!meta?.providers || !Array.isArray(meta.providers)) continue;\r\n\r\n for (const providerRelPath of meta.providers) {\r\n try {\r\n const providerAbsPath = path.join(basePath, item.lowerName, providerRelPath);\r\n const providerURL = pathToFileURL(providerAbsPath).href; // ✅ Convert to file:// URL\r\n const providerModule = await import(providerURL);\r\n\r\n if (typeof providerModule.default === 'function') {\r\n await providerModule.default();\r\n console.log(`[${type}] ✅ Provider loaded: ${providerRelPath}`);\r\n } else {\r\n console.warn(`[${type}] ⚠️ Provider ${providerRelPath} has no default export.`);\r\n }\r\n } catch (err) {\r\n console.error(`[${type}] ❌ Failed to load provider ${providerRelPath}:`, err);\r\n }\r\n }\r\n }\r\n }\r\n}\r\n\r\n\r\n// export async function loadProviders() {\r\n// paths = {\r\n// modules: useSettings.getPaths().modules,\r\n// templates: useSettings.getPaths().templates,\r\n// services: useSettings.getPaths().services,\r\n// events: useSettings.getPaths().events,\r\n// }\r\n// const all = [\r\n// { type: 'module', list: getModules(), basePath: paths.modules },\r\n// { type: 'service', list: getServices(), basePath: paths.services },\r\n// ];\r\n\r\n// for (const { type, list, basePath } of all) {\r\n// for (const item of list) {\r\n// if (!item.enabled) continue;\r\n\r\n// const metaPath = path.join(basePath, item.lowerName, `${type}.json`);\r\n// const meta = loadJSON(metaPath);\r\n// if (!meta?.providers || !Array.isArray(meta.providers)) continue;\r\n\r\n// for (const providerRelPath of meta.providers) {\r\n// try {\r\n// const providerPath = path.join(basePath, item.lowerName, providerRelPath);\r\n// const providerModule = await import(providerPath);\r\n// if (typeof providerModule.default === 'function') {\r\n// await providerModule.default(); // Call provider\r\n// console.log(`[${type}] Provider loaded: ${providerRelPath}`);\r\n// } else {\r\n// console.warn(`[${type}] Provider ${providerRelPath} has no default export.`);\r\n// }\r\n// } catch (err) {\r\n// console.error(`[${type}] Failed to load provider ${providerRelPath}:`, err);\r\n// }\r\n// }\r\n// }\r\n// }\r\n// }\r\n","// src/hooks/useSettings.ts\r\n\r\nimport * as path from 'path';\r\n\r\nimport { ExtensiblePaths, loadJSON, saveJSON } from './useExtensibles';\r\n\r\n// export interface ExtensiblePaths {\r\n// modulesPath: string;\r\n// templatesPath: string;\r\n// servicesPath: string;\r\n// }\r\n\r\nlet extensiblePaths: ExtensiblePaths = {\r\n modules: path.resolve(process.cwd(), 'modules'),\r\n templates: path.resolve(process.cwd(), 'resources/themes'),\r\n services: path.resolve(process.cwd(), 'app/services'),\r\n events: path.resolve(process.cwd(), 'events'),\r\n};\r\n\r\nexport const useSettings = {\r\n getPaths(): ExtensiblePaths {\r\n extensiblePaths = loadJSON(\"extensiblePaths.json\");\r\n return extensiblePaths;\r\n },\r\n\r\n setPaths(paths: Partial<ExtensiblePaths>) {\r\n saveJSON(\"extensiblePaths.json\", {\r\n ...extensiblePaths,\r\n ...paths,\r\n })\r\n extensiblePaths = {\r\n ...extensiblePaths,\r\n ...paths,\r\n };\r\n },\r\n};\r\n","// src/hooks/useModules.ts\r\n\r\nimport fs from 'fs';\r\nimport * as path from 'path';\r\nimport { useSettings } from './useSettings';\r\n\r\nexport interface ModuleMeta {\r\n name: string;\r\n lowerName: string;\r\n version?: string;\r\n author?: string;\r\n icon?: string;\r\n description?: string;\r\n enabled: boolean;\r\n providers?: string[];\r\n}\r\n\r\nexport const useModules = {\r\n loadModules(): ModuleMeta[] {\r\n const modulesDir = useSettings.getPaths().modules;\r\n if (!fs.existsSync(modulesDir)) return [];\r\n\r\n const moduleFolders = fs.readdirSync(modulesDir);\r\n const modules: ModuleMeta[] = [];\r\n\r\n moduleFolders.forEach((folder) => {\r\n const modulePath = path.join(modulesDir, folder);\r\n const moduleJsonPath = path.join(modulePath, 'module.json');\r\n if (!fs.existsSync(moduleJsonPath)) return;\r\n\r\n try {\r\n const rawData = fs.readFileSync(moduleJsonPath, 'utf-8');\r\n const moduleData = JSON.parse(rawData) as ModuleMeta;\r\n modules.push(moduleData);\r\n } catch {\r\n // invalid json or read error, ignore\r\n }\r\n });\r\n\r\n return modules;\r\n },\r\n\r\n isModuleEnabled(moduleName: string): boolean {\r\n const modules = useModules.loadModules();\r\n const mod = modules.find((m) => m.lowerName === moduleName.toLowerCase());\r\n return mod ? mod.enabled : false;\r\n },\r\n\r\n toggleModule(moduleName: string, enabled: boolean): boolean {\r\n const modulesDir = useSettings.getPaths().modules;\r\n const modules = useModules.loadModules();\r\n const modIndex = modules.findIndex((m) => m.lowerName === moduleName.toLowerCase());\r\n if (modIndex === -1) return false;\r\n\r\n const moduleMeta = modules[modIndex];\r\n moduleMeta.enabled = enabled;\r\n\r\n const moduleJsonPath = path.join(modulesDir, moduleMeta.lowerName, 'module.json');\r\n try {\r\n fs.writeFileSync(moduleJsonPath, JSON.stringify(moduleMeta, null, 2), 'utf-8');\r\n return true;\r\n } catch {\r\n return false;\r\n }\r\n },\r\n\r\n getModules(): ModuleMeta[] {\r\n return useModules.loadModules();\r\n },\r\n};\r\n","// src/hooks/useServices.ts\r\n\r\nimport fs from 'fs';\r\nimport * as path from 'path';\r\nimport { useSettings } from './useSettings';\r\n\r\nexport interface ServiceMeta {\r\n name: string;\r\n lowerName: string;\r\n version?: string;\r\n author?: string;\r\n icon?: string;\r\n description?: string;\r\n enabled: boolean;\r\n providers?: string[];\r\n serviceType?: string;\r\n}\r\n\r\nexport const useServices = {\r\n loadServices(): ServiceMeta[] {\r\n const servicesDir = useSettings.getPaths().services;\r\n if (!fs.existsSync(servicesDir)) return [];\r\n\r\n const serviceFolders = fs.readdirSync(servicesDir);\r\n const services: ServiceMeta[] = [];\r\n\r\n serviceFolders.forEach((folder) => {\r\n const servicePath = path.join(servicesDir, folder);\r\n const serviceJsonPath = path.join(servicePath, 'service.json');\r\n if (!fs.existsSync(serviceJsonPath)) return;\r\n\r\n try {\r\n const rawData = fs.readFileSync(serviceJsonPath, 'utf-8');\r\n const serviceData = JSON.parse(rawData) as ServiceMeta;\r\n services.push(serviceData);\r\n } catch {\r\n // ignore invalid json or errors\r\n }\r\n });\r\n\r\n return services;\r\n },\r\n\r\n isServiceEnabled(serviceName: string): boolean {\r\n const services = useServices.loadServices();\r\n const service = services.find((s) => s.lowerName === serviceName.toLowerCase());\r\n return service ? service.enabled : false;\r\n },\r\n\r\n toggleService(serviceName: string, enabled: boolean): boolean {\r\n const servicesDir = useSettings.getPaths().services;\r\n const services = useServices.loadServices();\r\n const index = services.findIndex((s) => s.lowerName === serviceName.toLowerCase());\r\n if (index === -1) return false;\r\n\r\n const serviceMeta = services[index];\r\n serviceMeta.enabled = enabled;\r\n\r\n const serviceJsonPath = path.join(servicesDir, serviceMeta.lowerName, 'service.json');\r\n try {\r\n fs.writeFileSync(serviceJsonPath, JSON.stringify(serviceMeta, null, 2), 'utf-8');\r\n return true;\r\n } catch {\r\n return false;\r\n }\r\n },\r\n\r\n getServices(): ServiceMeta[] {\r\n return useServices.loadServices();\r\n },\r\n};\r\n","// src/hooks/useTemplates.ts\r\n\r\nimport fs from 'fs';\r\nimport * as path from 'path';\r\nimport { useSettings } from './useSettings';\r\nimport { TemplateType } from './useExtensibles';\r\n\r\nexport interface TemplateMeta {\r\n name: string;\r\n lowerName: string;\r\n version?: string;\r\n author?: string;\r\n icon?: string;\r\n description?: string;\r\n enabled: boolean;\r\n templateType: TemplateType;\r\n}\r\n\r\nexport const useTemplates = {\r\n loadTemplates(templateType?: TemplateType): TemplateMeta[] {\r\n const templatesDir = useSettings.getPaths().templates;\r\n if (!fs.existsSync(templatesDir)) return [];\r\n\r\n const templateFolders = fs.readdirSync(templatesDir);\r\n const templates: TemplateMeta[] = [];\r\n\r\n templateFolders.forEach((folder) => {\r\n const templatePath = path.join(templatesDir, folder);\r\n const templateJsonPath = path.join(templatePath, 'template.json');\r\n if (!fs.existsSync(templateJsonPath)) return;\r\n\r\n try {\r\n const rawData = fs.readFileSync(templateJsonPath, 'utf-8');\r\n const templateData = JSON.parse(rawData) as TemplateMeta;\r\n\r\n if (templateType) {\r\n if (templateData.templateType === templateType) {\r\n templates.push(templateData);\r\n }\r\n } else {\r\n templates.push(templateData);\r\n }\r\n } catch {\r\n // ignore invalid JSON or errors\r\n }\r\n });\r\n\r\n return templates;\r\n },\r\n\r\n isTemplateActive(templateType: TemplateType, templateName: string): boolean {\r\n const templates = useTemplates.loadTemplates(templateType);\r\n const template = templates.find(\r\n (t) => t.lowerName === templateName.toLowerCase() && t.enabled\r\n );\r\n return !!template;\r\n },\r\n\r\n toggleTemplate(templateType: TemplateType, templateName: string): boolean {\r\n // Since only one template of each type can be enabled, disable others and enable this one\r\n const templatesDir = useSettings.getPaths().templates;\r\n const templates = useTemplates.loadTemplates(templateType);\r\n\r\n let toggled = false;\r\n\r\n templates.forEach((template) => {\r\n if (template.name.toLowerCase() === templateName.toLowerCase()) {\r\n if (!template.enabled) {\r\n template.enabled = true;\r\n toggled = true;\r\n }\r\n } else {\r\n if (template.enabled) {\r\n template.enabled = false;\r\n }\r\n }\r\n\r\n const templateJsonPath = path.join(templatesDir, template.lowerName, 'template.json');\r\n try {\r\n fs.writeFileSync(templateJsonPath, JSON.stringify(template, null, 2), 'utf-8');\r\n } catch {\r\n // ignore write errors\r\n }\r\n });\r\n\r\n return toggled;\r\n },\r\n\r\n getTemplates(templateType?: TemplateType): TemplateMeta[] {\r\n return useTemplates.loadTemplates(templateType);\r\n },\r\n};\r\n","import fs from 'fs-extra';\r\nimport path from 'path';\r\nimport { Server as SocketIOServer, Socket } from 'socket.io';\r\nimport { useSettings } from './useSettings';\r\n\r\n// Type signature for an event controller\r\ninterface EventController {\r\n onRegister?: (io: SocketIOServer) => void;\r\n onEvent?: (socket: Socket, event: any) => void;\r\n}\r\n\r\n// Dynamically import and register events\r\nexport async function useEvents(io: SocketIOServer) {\r\n const { modules, services, events: appEventsPath } = useSettings.getPaths();\r\n\r\n const sources = [\r\n { type: 'module', root: modules },\r\n { type: 'service', root: services },\r\n { type: 'app', root: appEventsPath },\r\n ];\r\n\r\n for (const source of sources) {\r\n if (!(await fs.pathExists(source.root))) continue;\r\n\r\n const dirs = await fs.readdir(source.root);\r\n for (const dir of dirs) {\r\n const base = path.join(source.root, dir);\r\n const eventsDir = source.type === 'app' ? base : path.join(base, 'events');\r\n\r\n if (!(await fs.pathExists(eventsDir))) continue;\r\n\r\n const files = (await fs.readdir(eventsDir)).filter((f) => f.endsWith('.ts') || f.endsWith('.js'));\r\n\r\n for (const file of files) {\r\n const eventPath = path.join(eventsDir, file);\r\n try {\r\n const imported = await import(eventPath);\r\n const controller: EventController = imported.default || imported[Object.keys(imported)[0]];\r\n\r\n if (controller?.onRegister) {\r\n controller.onRegister(io);\r\n }\r\n\r\n if (controller?.onEvent) {\r\n io.on('connection', (socket) => {\r\n const eventName = file.replace(/\\.(ts|js)$/, '');\r\n socket.on(eventName, (data) => controller.onEvent!(socket, data));\r\n });\r\n }\r\n } catch (err) {\r\n console.warn(`⚠️ Failed to load event: ${eventPath}`, err);\r\n }\r\n }\r\n }\r\n }\r\n}\r\n","// packages/retrex-extensibles-core/useRoutes.ts\r\nimport { Application, Request, Response, NextFunction } from 'express';\r\nimport { pathToFileURL } from 'url';\r\nimport type { LoaderFunctionArgs, ActionFunctionArgs } from '@remix-run/node';\r\n\r\ninterface RouteDefinition {\r\n path: string;\r\n method: 'get' | 'post' | 'put' | 'patch' | 'delete';\r\n filePath: string; // absolute path to .tsx file\r\n}\r\n\r\n// Registry for dynamically added routes\r\nconst registeredRoutes: RouteDefinition[] = [];\r\nexport const routesManager = {\r\n /**\r\n * Register a dynamic route from a module/service.\r\n */\r\n registerRoute(def: RouteDefinition): void {\r\n registeredRoutes.push(def);\r\n },\r\n\r\n /**\r\n * Return all registered dynamic routes.\r\n */\r\n getRegisteredRoutes(): RouteDefinition[] {\r\n return registeredRoutes;\r\n },\r\n\r\n /**\r\n * Loads and mounts all registered dynamic routes into an Express app.\r\n */\r\n async mountRegisteredRoutes(app: Application): Promise<void> {\r\n for (const route of registeredRoutes) {\r\n const mod = await import(pathToFileURL(route.filePath).toString());\r\n\r\n const hasLoader = typeof mod.loader === 'function';\r\n const hasAction = typeof mod.action === 'function';\r\n const hasDefault = typeof mod.default !== 'undefined';\r\n\r\n // Handle API routes with loader/action\r\n if (!hasDefault && (hasLoader || hasAction)) {\r\n app[route.method](route.path, async (req: Request, res: Response, next: NextFunction) => {\r\n try {\r\n if (route.method === 'get' && hasLoader) {\r\n const result = await mod.loader({ request: req });\r\n res.json(result);\r\n } else if (hasAction) {\r\n const result = await mod.action({ request: req });\r\n res.json(result);\r\n } else {\r\n res.status(405).json({ error: 'Method Not Allowed' });\r\n }\r\n } catch (err) {\r\n next(err);\r\n }\r\n });\r\n }\r\n\r\n // Handle Page Routes (React component as default export)\r\n else if (hasDefault) {\r\n app.use(route.path, (req: Request, res: Response, next: NextFunction) => {\r\n res.locals.__dynamicPageComponent = mod.default;\r\n next(); // forward to Remix handler\r\n });\r\n }\r\n }\r\n }\r\n}\r\n","// packages/retrex-extensibles-core/utils/loadThemeComponent.ts\r\nimport path from 'path';\r\nimport { pathToFileURL } from 'url';\r\nimport fs from 'fs-extra';\r\nimport { useSettings } from './useSettings';\r\n\r\nexport const useUtils = {\r\n async loadThemeComponent(\r\n componentName: string,\r\n options: {\r\n theme: {\r\n name: string;\r\n type: 'admin' | 'client' | 'portal' | 'email';\r\n };\r\n search?: {\r\n themes?: boolean;\r\n modules?: boolean;\r\n services?: boolean;\r\n };\r\n }\r\n ): Promise<React.ComponentType<any> | null> {\r\n const { search = {}, theme } = options;\r\n const searchThemes = search.themes ?? true;\r\n const searchModules = search.modules ?? true;\r\n const searchServices = search.services ?? true;\r\n\r\n const possiblePaths: string[] = [];\r\n\r\n if (searchThemes) {\r\n possiblePaths.push(\r\n path.resolve(\r\n 'resources',\r\n 'themes',\r\n theme.type,\r\n theme.name,\r\n 'routes',\r\n `${componentName}.tsx`\r\n ),\r\n path.resolve(\r\n 'resources',\r\n 'themes',\r\n theme.type,\r\n theme.name,\r\n 'components',\r\n `${componentName}.tsx`\r\n )\r\n );\r\n }\r\n\r\n if (searchModules) {\r\n const moduleDirs = await fs.readdir(useSettings.getPaths().modules);\r\n for (const mod of moduleDirs) {\r\n possiblePaths.push(\r\n path.resolve(\r\n 'modules',\r\n mod,\r\n 'themes',\r\n theme.type,\r\n theme.name,\r\n 'routes',\r\n `${componentName}.tsx`\r\n ),\r\n path.resolve(\r\n 'modules',\r\n mod,\r\n 'themes',\r\n theme.type,\r\n theme.name,\r\n 'components',\r\n `${componentName}.tsx`\r\n )\r\n );\r\n }\r\n }\r\n\r\n if (searchServices) {\r\n const serviceDirs = await fs.readdir(useSettings.getPaths().services);\r\n for (const svc of serviceDirs) {\r\n possiblePaths.push(\r\n path.resolve(\r\n 'services',\r\n svc,\r\n 'themes',\r\n theme.type,\r\n theme.name,\r\n 'routes',\r\n `${componentName}.tsx`\r\n ),\r\n path.resolve(\r\n 'services',\r\n svc,\r\n 'themes',\r\n theme.type,\r\n theme.name,\r\n 'components',\r\n `${componentName}.tsx`\r\n )\r\n );\r\n }\r\n }\r\n\r\n for (const filePath of possiblePaths) {\r\n if (await fs.pathExists(filePath)) {\r\n try {\r\n const mod = await import(pathToFileURL(filePath).toString());\r\n if (mod.default) return mod.default;\r\n } catch (err) {\r\n console.error(`Error loading component at ${filePath}:`, err);\r\n }\r\n }\r\n }\r\n\r\n console.warn(`Component \"${componentName}\" not found in theme \"${theme.name}\" of type \"${theme.type}\".`);\r\n return null;\r\n }\r\n}\r\n","import React, { createContext, useContext, useEffect, useState } from 'react';\r\nimport path from 'path';\r\nimport { useSettings } from '../hooks/useSettings';\r\nimport { getTemplates, TemplateType } from '../hooks/useExtensibles';\r\n\r\ninterface ThemeContextProps {\r\n templateType: TemplateType;\r\n activeTheme: string;\r\n setActiveTheme: (theme: string) => void;\r\n}\r\n\r\nconst ThemeContext = createContext<ThemeContextProps | null>(null);\r\n\r\nexport const ThemeProvider: React.FC<{\r\n type: TemplateType;\r\n children: React.ReactNode;\r\n}> = ({ type, children }) => {\r\n const [activeTheme, setActiveTheme] = useState<string>(() => {\r\n const templates = getTemplates(type);\r\n const enabled = templates.find(t => t.enabled);\r\n return enabled?.lowerName ?? templates[0]?.lowerName ?? 'default';\r\n });\r\n\r\n return (\r\n <ThemeContext.Provider value={{ templateType: type, activeTheme, setActiveTheme }}>\r\n {children}\r\n </ThemeContext.Provider>\r\n );\r\n};\r\n\r\nexport function useTheme() {\r\n const ctx = useContext(ThemeContext);\r\n if (!ctx) throw new Error('useTheme must be used inside a ThemeProvider');\r\n return ctx;\r\n}\r\n"],"mappings":"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","names":["path","paths","extensiblePaths","paths","fs","path","fs","fs","path","fs","fs","path","fs","fs","path","fs","path","pathToFileURL","path","pathToFileURL","fs","path","fs","pathToFileURL"]}
|