retrex-extensibles-core 2.1.2 → 2.1.4
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/core/hooks/useUtils.cjs +49 -11
- package/dist/core/hooks/useUtils.cjs.map +1 -1
- package/dist/core/hooks/useUtils.d.cts +12 -1
- package/dist/core/hooks/useUtils.d.ts +12 -1
- package/dist/core/hooks/useUtils.js +44 -7
- package/dist/core/hooks/useUtils.js.map +1 -1
- package/dist/index.cjs +106 -68
- package/dist/index.cjs.map +1 -1
- package/dist/index.d.cts +1 -1
- package/dist/index.d.ts +1 -1
- package/dist/index.js +121 -84
- package/dist/index.js.map +1 -1
- package/package.json +1 -1
|
@@ -17,19 +17,20 @@ var __copyProps = (to, from, except, desc) => {
|
|
|
17
17
|
}
|
|
18
18
|
return to;
|
|
19
19
|
};
|
|
20
|
-
var __toESM = (
|
|
20
|
+
var __toESM = (mod2, isNodeMode, target) => (target = mod2 != null ? __create(__getProtoOf(mod2)) : {}, __copyProps(
|
|
21
21
|
// If the importer is in node compatibility mode or this is not an ESM
|
|
22
22
|
// file that has been converted to a CommonJS file using a Babel-
|
|
23
23
|
// compatible transform (i.e. "__esModule" has not been set), then set
|
|
24
24
|
// "default" to the CommonJS "module.exports" for node compatibility.
|
|
25
|
-
isNodeMode || !
|
|
26
|
-
|
|
25
|
+
isNodeMode || !mod2 || !mod2.__esModule ? __defProp(target, "default", { value: mod2, enumerable: true }) : target,
|
|
26
|
+
mod2
|
|
27
27
|
));
|
|
28
|
-
var __toCommonJS = (
|
|
28
|
+
var __toCommonJS = (mod2) => __copyProps(__defProp({}, "__esModule", { value: true }), mod2);
|
|
29
29
|
|
|
30
30
|
// src/core/hooks/useUtils.ts
|
|
31
31
|
var useUtils_exports = {};
|
|
32
32
|
__export(useUtils_exports, {
|
|
33
|
+
logPrefix: () => logPrefix,
|
|
33
34
|
useUtils: () => useUtils
|
|
34
35
|
});
|
|
35
36
|
module.exports = __toCommonJS(useUtils_exports);
|
|
@@ -109,6 +110,7 @@ function toFileUrl(filePath) {
|
|
|
109
110
|
return `${prefix}${encodeURI(normalized)}`;
|
|
110
111
|
}
|
|
111
112
|
var useUtils = {
|
|
113
|
+
logPrefix,
|
|
112
114
|
async loadThemeComponent(componentName, options) {
|
|
113
115
|
const { search = {}, theme } = options;
|
|
114
116
|
const searchThemes = search.themes ?? true;
|
|
@@ -154,11 +156,11 @@ var useUtils = {
|
|
|
154
156
|
const modulesRoot = import_node_path2.default.resolve(useSettings.getPaths().modules);
|
|
155
157
|
if (import_node_fs3.default.existsSync(modulesRoot)) {
|
|
156
158
|
const moduleDirs = await import_node_fs3.default.readdirSync(modulesRoot);
|
|
157
|
-
for (const
|
|
159
|
+
for (const mod2 of moduleDirs) {
|
|
158
160
|
possiblePaths.push(
|
|
159
161
|
import_node_path2.default.resolve(
|
|
160
162
|
modulesRoot,
|
|
161
|
-
|
|
163
|
+
mod2,
|
|
162
164
|
"resources",
|
|
163
165
|
"themes",
|
|
164
166
|
theme.type,
|
|
@@ -168,7 +170,7 @@ var useUtils = {
|
|
|
168
170
|
),
|
|
169
171
|
import_node_path2.default.resolve(
|
|
170
172
|
modulesRoot,
|
|
171
|
-
|
|
173
|
+
mod2,
|
|
172
174
|
"resources",
|
|
173
175
|
"themes",
|
|
174
176
|
theme.type,
|
|
@@ -178,7 +180,7 @@ var useUtils = {
|
|
|
178
180
|
),
|
|
179
181
|
import_node_path2.default.resolve(
|
|
180
182
|
modulesRoot,
|
|
181
|
-
|
|
183
|
+
mod2,
|
|
182
184
|
"resources",
|
|
183
185
|
"themes",
|
|
184
186
|
theme.type,
|
|
@@ -188,7 +190,7 @@ var useUtils = {
|
|
|
188
190
|
),
|
|
189
191
|
import_node_path2.default.resolve(
|
|
190
192
|
modulesRoot,
|
|
191
|
-
|
|
193
|
+
mod2,
|
|
192
194
|
"resources",
|
|
193
195
|
"themes",
|
|
194
196
|
theme.type,
|
|
@@ -253,8 +255,8 @@ var useUtils = {
|
|
|
253
255
|
for (const filePath of possiblePaths) {
|
|
254
256
|
if (await import_node_fs3.default.existsSync(filePath)) {
|
|
255
257
|
try {
|
|
256
|
-
const
|
|
257
|
-
if (
|
|
258
|
+
const mod2 = await import(toFileUrl(filePath));
|
|
259
|
+
if (mod2.default) return mod2.default;
|
|
258
260
|
} catch (err) {
|
|
259
261
|
console.error(`Error loading component at ${filePath}:`, err);
|
|
260
262
|
}
|
|
@@ -273,8 +275,44 @@ var useUtils = {
|
|
|
273
275
|
}
|
|
274
276
|
}
|
|
275
277
|
};
|
|
278
|
+
function logPrefix(et, type, color) {
|
|
279
|
+
const label = `${et || "Extensibles"} Manager${type ? " | " + type?.charAt(0).toUpperCase() + type?.slice(1) : ""}`;
|
|
280
|
+
const getChalk = () => {
|
|
281
|
+
if (typeof window !== "undefined") return null;
|
|
282
|
+
try {
|
|
283
|
+
const req = eval("require");
|
|
284
|
+
const mod = req("chalk");
|
|
285
|
+
return mod?.default ?? mod;
|
|
286
|
+
} catch {
|
|
287
|
+
return null;
|
|
288
|
+
}
|
|
289
|
+
};
|
|
290
|
+
const chalk = getChalk();
|
|
291
|
+
const wrap = (fn, value) => fn ? fn(value) : value;
|
|
292
|
+
let colored = label;
|
|
293
|
+
if (chalk) {
|
|
294
|
+
if (type === "error") colored = wrap(chalk.redBright, label);
|
|
295
|
+
else if (type === "warning") colored = wrap(chalk.yellow, label);
|
|
296
|
+
else if (type === "success") colored = wrap(chalk.green, label);
|
|
297
|
+
else if (type === "info") colored = wrap(chalk.blue, label);
|
|
298
|
+
else if (color === "green") colored = wrap(chalk.green, label);
|
|
299
|
+
else if (color === "cyan") colored = wrap(chalk.cyan, label);
|
|
300
|
+
else if (color === "magenta") colored = wrap(chalk.magenta, label);
|
|
301
|
+
else if (color === "blue") colored = wrap(chalk.blue, label);
|
|
302
|
+
else if (color === "yellow") colored = wrap(chalk.yellow, label);
|
|
303
|
+
else if (color === "red") colored = wrap(chalk.red, label);
|
|
304
|
+
else if (color === "gray") colored = wrap(chalk.gray, label);
|
|
305
|
+
else if (color === "black") colored = wrap(chalk.black, label);
|
|
306
|
+
else if (color === "white") colored = wrap(chalk.white, label);
|
|
307
|
+
}
|
|
308
|
+
if (chalk?.white) {
|
|
309
|
+
return chalk.white("[") + colored + chalk.white("] ");
|
|
310
|
+
}
|
|
311
|
+
return `[${colored}] `;
|
|
312
|
+
}
|
|
276
313
|
// Annotate the CommonJS export names for ESM import in node:
|
|
277
314
|
0 && (module.exports = {
|
|
315
|
+
logPrefix,
|
|
278
316
|
useUtils
|
|
279
317
|
});
|
|
280
318
|
//# sourceMappingURL=useUtils.cjs.map
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"sources":["../../../src/core/hooks/useUtils.ts","../../../src/core/hooks/useSettings.ts","../../../src/core/hooks/useExtensibles.ts"],"sourcesContent":["/* @vite-ignore */\n// packages/retrex-extensibles-core/hooks/useUtils.ts\nimport path from 'node:path';\nimport fs from 'node:fs';\nimport { useSettings } from './useSettings';\n\nfunction toFileUrl(filePath: string): string {\n const normalized = filePath.replace(/\\\\/g, '/');\n if (normalized.startsWith('file://')) return normalized;\n const prefix = normalized.startsWith('/') ? 'file://' : 'file:///';\n return `${prefix}${encodeURI(normalized)}`;\n}\n\nexport const useUtils = {\n async loadThemeComponent(\n componentName: string,\n options: {\n theme: {\n name: string;\n type: 'admin' | 'client' | 'portal' | 'email';\n };\n search?: {\n themes?: boolean;\n modules?: boolean;\n services?: boolean;\n };\n }\n ): Promise<React.ComponentType<any> | null> {\n const { search = {}, theme } = options;\n const searchThemes = search.themes ?? true;\n const searchModules = search.modules ?? true;\n const searchServices = search.services ?? true;\n\n const possiblePaths: string[] = [];\n\n console.log(`Searching for component \"${componentName}\" in theme \"${theme.name}\" of type \"${theme.type}\"...`);\n\n try {\n if (searchThemes) {\n const templatesRoot = path.resolve(useSettings.getPaths().templates);\n possiblePaths.push(\n path.resolve(\n templatesRoot,\n theme.type,\n theme.name,\n 'routes',\n `${componentName}.tsx`\n ),\n path.resolve(\n templatesRoot,\n theme.type,\n theme.name,\n 'components',\n `${componentName}.tsx`\n ),\n path.resolve(\n templatesRoot,\n theme.type,\n 'default',\n 'routes',\n `${componentName}.tsx`\n ),\n path.resolve(\n templatesRoot,\n theme.type,\n 'default',\n 'components',\n `${componentName}.tsx`\n )\n );\n }\n \n if (searchModules) {\n const modulesRoot = path.resolve(useSettings.getPaths().modules);\n if (fs.existsSync(modulesRoot)) {\n const moduleDirs = await fs.readdirSync(modulesRoot);\n for (const mod of moduleDirs) {\n possiblePaths.push(\n path.resolve(\n modulesRoot,\n mod,\n 'resources',\n 'themes',\n theme.type,\n theme.name,\n 'routes',\n `${componentName}.tsx`\n ),\n path.resolve(\n modulesRoot,\n mod,\n 'resources',\n 'themes',\n theme.type,\n theme.name,\n 'components',\n `${componentName}.tsx`\n ),\n path.resolve(\n modulesRoot,\n mod,\n 'resources',\n 'themes',\n theme.type,\n 'default',\n 'routes',\n `${componentName}.tsx`\n ),\n path.resolve(\n modulesRoot,\n mod,\n 'resources',\n 'themes',\n theme.type,\n 'default',\n 'components',\n `${componentName}.tsx`\n )\n );\n }\n }\n }\n \n if (searchServices) {\n const servicesRoot = path.resolve(useSettings.getPaths().services);\n if (fs.existsSync(servicesRoot)) {\n const serviceDirs = await fs.readdirSync(servicesRoot);\n for (const svc of serviceDirs) {\n possiblePaths.push(\n path.resolve(\n servicesRoot,\n svc,\n 'resources',\n 'themes',\n theme.type,\n theme.name,\n 'routes',\n `${componentName}.tsx`\n ),\n path.resolve(\n servicesRoot,\n svc,\n 'resources',\n 'themes',\n theme.type,\n theme.name,\n 'components',\n `${componentName}.tsx`\n ),\n path.resolve(\n servicesRoot,\n svc,\n 'resources',\n 'themes',\n theme.type,\n 'default',\n 'routes',\n `${componentName}.tsx`\n ),\n path.resolve(\n servicesRoot,\n svc,\n 'resources',\n 'themes',\n theme.type,\n 'default',\n 'components',\n `${componentName}.tsx`\n )\n );\n }\n }\n }\n \n for (const filePath of possiblePaths) {\n if (await fs.existsSync(filePath)) {\n try {\n const mod = await import(toFileUrl(filePath));\n if (mod.default) return mod.default;\n } catch (err) {\n console.error(`Error loading component at ${filePath}:`, err);\n }\n }\n }\n \n console.warn(`Component \"${componentName}\" not found in theme \"${theme.name}\" of type \"${theme.type}\".`);\n return null;\n } catch (err) {\n console.error(`Error searching for component \"${componentName}\":`, err);\n console.warn(`Component \"${componentName}\" not found in theme \"${theme.name}\" of type \"${theme.type}\".`);\n console.warn(`Searched paths:`, possiblePaths);\n console.warn(`Ensure the component exists in the specified theme and type.`);\n console.warn(`If the component is in a module or service, ensure the theme structure is correct.`);\n console.warn(`If you are using a custom theme, module, or service, ensure it is properly configured and registered in the settings.`);\n return null;\n }\n }\n}\n","// src/hooks/useSettings.ts\n\nimport path from 'node:path';\nimport fs from 'node:fs';\n\nimport { loadJSON, saveJSON } from './useExtensibles';\nimport type { ExtensiblePaths } from '../types'; // Adjust the import path as necessary\n\nconst defaultPaths: ExtensiblePaths = {\n modules: './app/modules',\n templates: './app/resources/themes',\n services: './app/services',\n events: './app/events',\n langs: './public/langs',\n providers: './app/providers',\n};\n\nlet extensiblePaths: ExtensiblePaths = { ...defaultPaths };\nconst isServer = typeof window === 'undefined';\n\n\nexport const useSettings = {\n getPaths(): ExtensiblePaths {\n if (isServer) {\n const json = loadJSON('./app/extensiblePaths.json');\n if (json) extensiblePaths = json;\n }\n\n if (isServer) {\n for (const key of Object.keys(defaultPaths) as Array<keyof ExtensiblePaths>) {\n const candidate = extensiblePaths[key];\n if (!candidate || !fs.existsSync(candidate)) {\n extensiblePaths[key] = defaultPaths[key];\n }\n }\n }\n\n extensiblePaths = {\n ...extensiblePaths,\n langs: './langs',\n };\n // extensiblePaths = loadJSON(\"./app/extensiblePaths.json\");\n return extensiblePaths;\n },\n\n setPaths(paths: Partial<ExtensiblePaths>): void {\n if (isServer) {\n saveJSON('./app/extensiblePaths.json', {\n ...extensiblePaths,\n ...paths,\n });\n }\n\n extensiblePaths = {\n ...extensiblePaths,\n ...paths,\n };\n },\n \n getKeyValue(key: string): string {\n return 'Coming Soon'\n },\n setKeyValue(key: string, value: string): void {\n return;\n },\n};\n","// src/hooks/useExtensibles.ts\n\nimport fs from 'node:fs';\nimport path from 'node:path';\nimport { useSettings } from './useSettings';\nimport type { TemplateType, ExtensibleMeta, ExtensiblePaths } from '../types';\n\nlet paths: ExtensiblePaths;\n\nfunction toFileUrl(filePath: string): string {\n const normalized = filePath.replace(/\\\\/g, '/');\n if (normalized.startsWith('file://')) return normalized;\n const prefix = normalized.startsWith('/') ? 'file://' : 'file:///';\n return `${prefix}${encodeURI(normalized)}`;\n}\n\nexport function registerExtensibles(extensiblePaths: ExtensiblePaths) {\n paths = extensiblePaths;\n}\n\nexport function loadJSON(filePath: string): any {\n if (!fs.existsSync(filePath)) return null;\n return JSON.parse(fs.readFileSync(filePath, 'utf-8'));\n}\n\nexport function saveJSON(filePath: string, data: any) {\n fs.writeFileSync(filePath, JSON.stringify(data, null, 2), 'utf-8');\n}\n\n// --- MODULES ---\n\nexport function getModules(): ExtensibleMeta[] {\n if (!useSettings.getPaths().modules) throw new Error('Modules path not registered.');\n\n const dirs = fs\n .readdirSync(useSettings.getPaths().modules)\n .filter((d: any) => fs.statSync(path.join(useSettings.getPaths().modules, d)).isDirectory());\n\n return dirs.map((dir: any) => {\n const meta = loadJSON(path.join(useSettings.getPaths().modules, dir, 'module.json')) || {};\n return {\n name: meta.name || dir,\n lowerName: meta.lowerName || dir.toLowerCase(),\n version: meta.version,\n description: meta.description,\n author: meta.author,\n icon: meta.icon,\n enabled: meta.enabled ?? false,\n };\n });\n}\n\nexport function isModuleEnabled(name: string) {\n const modules = getModules();\n return modules.find((m) => m.lowerName === name.toLowerCase())?.enabled ?? false;\n}\n\nexport function toggleModule(name: string, enabled: boolean) {\n const modules = getModules();\n const mod = modules.find((m) => m.lowerName === name.toLowerCase());\n if (!mod) throw new Error(`Module ${name} not found`);\n\n const metaPath = path.join(useSettings.getPaths().modules, mod.lowerName, 'module.json');\n const meta = loadJSON(metaPath) || {};\n meta.enabled = enabled;\n saveJSON(metaPath, meta);\n\n if (enabled) onModuleEnabled(mod.name);\n else onModuleDisabled(mod.name);\n}\n\n// --- SERVICES ---\n\nexport function getServices(): ExtensibleMeta[] {\n if (!useSettings.getPaths().services) throw new Error('Services path not registered.');\n\n const dirs = fs\n .readdirSync(useSettings.getPaths().services)\n .filter((d: any) => fs.statSync(path.join(useSettings.getPaths().services, d)).isDirectory());\n\n return dirs.map((dir: any) => {\n const meta = loadJSON(path.join(useSettings.getPaths().services, dir, 'service.json')) || {};\n return {\n name: meta.name || dir,\n lowerName: meta.lowerName || dir.toLowerCase(),\n version: meta.version,\n description: meta.description,\n author: meta.author,\n icon: meta.icon,\n enabled: meta.enabled ?? false,\n };\n });\n}\n\nexport function isServiceEnabled(name: string) {\n const services = getServices();\n return services.find((s) => s.lowerName === name.toLowerCase())?.enabled ?? false;\n}\n\nexport function toggleService(name: string, enabled: boolean) {\n const services = getServices();\n const svc = services.find((s) => s.lowerName === name.toLowerCase());\n if (!svc) throw new Error(`Service ${name} not found`);\n\n const metaPath = path.join(useSettings.getPaths().services, svc.lowerName, 'service.json');\n const meta = loadJSON(metaPath) || {};\n meta.enabled = enabled;\n saveJSON(metaPath, meta);\n\n if (enabled) onServiceEnabled(svc.name);\n else onServiceDisabled(svc.name);\n}\n\n// --- TEMPLATES ---\n\n// Helper to get base path for a template type\nfunction getTemplateBasePath(type: TemplateType): string {\n if (!useSettings.getPaths().templates) throw new Error('Templates path not registered.');\n switch (type) {\n case 'admin-theme':\n case 'client-theme':\n return path.join(useSettings.getPaths().templates, 'themes');\n case 'portal':\n return path.join(useSettings.getPaths().templates, 'portals');\n case 'email':\n return path.join(useSettings.getPaths().templates, 'emails');\n default:\n throw new Error(`Unknown template type: ${type}`);\n }\n}\n\nexport function getTemplates(type: TemplateType): ExtensibleMeta[] {\n const basePath = getTemplateBasePath(type);\n if (!fs.existsSync(basePath)) return [];\n\n const dirs = fs\n .readdirSync(basePath)\n .filter((d: any) => fs.statSync(path.join(basePath, d)).isDirectory());\n\n return dirs.map((dir: any) => {\n const meta = loadJSON(path.join(basePath, dir, 'template.json')) || {};\n return {\n name: meta.name || dir,\n lowerName: dir.toLowerCase(),\n version: meta.version,\n description: meta.description,\n author: meta.author,\n icon: meta.icon,\n enabled: meta.enabled ?? false,\n };\n });\n}\n\nexport function isTemplateActive(type: TemplateType, name: string) {\n const templates = getTemplates(type);\n return templates.find((t) => t.lowerName === name.toLowerCase())?.enabled ?? false;\n}\n\n// Toggle templates: only 1 active per type allowed\nexport function toggleTemplate(type: TemplateType, name: string) {\n const templates = getTemplates(type);\n\n templates.forEach((tpl) => {\n const metaPath = path.join(getTemplateBasePath(type), tpl.lowerName, 'template.json');\n const meta = loadJSON(metaPath) || {};\n meta.enabled = tpl.lowerName === name.toLowerCase();\n saveJSON(metaPath, meta);\n });\n\n onTemplateSelect(type, name);\n}\n\n// --- EVENTS (replace with your event system integration) ---\n\nexport function onModuleEnabled(name: string) {\n console.log(`Module enabled: ${name}`);\n // emit event or custom logic here\n}\n\nexport function onModuleDisabled(name: string) {\n console.log(`Module disabled: ${name}`);\n}\n\nexport function onServiceEnabled(name: string) {\n console.log(`Service enabled: ${name}`);\n}\n\nexport function onServiceDisabled(name: string) {\n console.log(`Service disabled: ${name}`);\n}\n\nexport function onTemplateSelect(type: TemplateType, name: string) {\n console.log(`Template selected: type=${type}, name=${name}`);\n}\n\n// --- REGISTER HOOKS FOR MODULES ---\n\nexport async function registerEvents() {\n if (!useSettings.getPaths().modules) throw new Error('Modules path not registered.');\n const modules = getModules().filter((m) => m.enabled);\n for (const mod of modules) {\n const eventsFile = path.join(useSettings.getPaths().modules, mod.lowerName, 'events.server.js');\n if (fs.existsSync(eventsFile)) {\n const modEvents = await import(eventsFile);\n if (modEvents?.registerEvents) await modEvents.registerEvents();\n }\n }\n}\n\nexport async function registerMiddleware() {\n if (!useSettings.getPaths().modules) throw new Error('Modules path not registered.');\n const modules = getModules().filter((m) => m.enabled);\n for (const mod of modules) {\n const middlewareFile = path.join(useSettings.getPaths().modules, mod.lowerName, 'middleware.server.js');\n if (fs.existsSync(middlewareFile)) {\n const modMiddleware = await import(middlewareFile);\n if (modMiddleware?.registerMiddleware) await modMiddleware.registerMiddleware();\n }\n }\n}\n\n/**\n * Registers routes given a path to routes folder (for pages and API routes)\n * @param routesFolderPath string - path to module/service routes folder\n */\nexport async function registerRoutes(routesFolderPath: string) {\n if (!fs.existsSync(routesFolderPath)) return;\n\n const routeFiles = fs.readdirSync(routesFolderPath).filter((f: any) => /\\.(js|ts|jsx|tsx)$/.test(f));\n for (const file of routeFiles) {\n const routeModule = await import(path.join(routesFolderPath, file));\n if (routeModule?.registerRoute) {\n await routeModule.registerRoute();\n }\n }\n}\n\nexport async function loadProviders() {\n const paths = useSettings.getPaths();\n\n const all = [\n { type: 'module', list: getModules(), basePath: paths.modules },\n { type: 'service', list: getServices(), basePath: paths.services },\n ];\n\n for (const { type, list, basePath } of all) {\n for (const item of list) {\n if (!item.enabled) continue;\n\n const metaPath = path.join(path.resolve(basePath), item.lowerName, `${type}.json`);\n const meta = loadJSON(metaPath);\n if (!meta?.providers || !Array.isArray(meta.providers)) continue;\n\n for (const providerRelPath of meta.providers) {\n try {\n let providerAbsPath = path.join(path.resolve(basePath), item.lowerName, providerRelPath);\n\n // Try .js fallback if file is .ts or .tsx\n const ext = path.extname(providerAbsPath);\n if (ext === '.ts' || ext === '.tsx') {\n const jsPath = providerAbsPath.replace(/\\.(ts|tsx)$/, '.js');\n try {\n await fs.accessSync(jsPath); // Check if compiled JS file exists\n providerAbsPath = jsPath;\n } catch {\n throw new Error(`Compiled JS version not found for provider: ${providerRelPath}`);\n }\n }\n\n const providerUrl = toFileUrl(providerAbsPath);\n const providerModule = await import(providerUrl);\n\n if (typeof providerModule.default === 'function') {\n // Expose context so nav registration can auto-tag module/service\n (globalThis as any).__retrex_provider_context__ = {\n type,\n name: item.lowerName,\n };\n await providerModule.default();\n (globalThis as any).__retrex_provider_context__ = undefined;\n console.log(`[${type}] ✅ Provider loaded: ${providerRelPath}`);\n } else {\n console.warn(`[${type}] ⚠️ Provider ${providerRelPath} has no default export.`);\n }\n } catch (err) {\n console.error(`[${type}] ❌ Failed to load provider ${providerRelPath}:`, err);\n }\n }\n }\n }\n}\n\n\n// export async function loadProviders() {\n// paths = {\n// modules: useSettings.getPaths().modules,\n// templates: useSettings.getPaths().templates,\n// services: useSettings.getPaths().services,\n// events: useSettings.getPaths().events,\n// }\n// const all = [\n// { type: 'module', list: getModules(), basePath: useSettings.getPaths().modules },\n// { type: 'service', list: getServices(), basePath: useSettings.getPaths().services },\n// ];\n\n// for (const { type, list, basePath } of all) {\n// for (const item of list) {\n// if (!item.enabled) continue;\n\n// const metaPath = path.join(basePath, item.lowerName, `${type}.json`);\n// const meta = loadJSON(metaPath);\n// if (!meta?.providers || !Array.isArray(meta.providers)) continue;\n\n// for (const providerRelPath of meta.providers) {\n// try {\n// const providerPath = path.join(basePath, item.lowerName, providerRelPath);\n// const providerModule = await import(providerPath);\n// if (typeof providerModule.default === 'function') {\n// await providerModule.default(); // Call provider\n// console.log(`[${type}] Provider loaded: ${providerRelPath}`);\n// } else {\n// console.warn(`[${type}] Provider ${providerRelPath} has no default export.`);\n// }\n// } catch (err) {\n// console.error(`[${type}] Failed to load provider ${providerRelPath}:`, err);\n// }\n// }\n// }\n// }\n// }\n"],"mappings":"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","names":["import_node_path","import_node_fs","import_node_fs","fs","fs","path","fs"]}
|
|
1
|
+
{"version":3,"sources":["../../../src/core/hooks/useUtils.ts","../../../src/core/hooks/useSettings.ts","../../../src/core/hooks/useExtensibles.ts"],"sourcesContent":["/* @vite-ignore */\n// packages/retrex-extensibles-core/hooks/useUtils.ts\nimport path from 'node:path';\nimport fs from 'node:fs';\nimport { useSettings } from './useSettings';\n\nfunction toFileUrl(filePath: string): string {\n const normalized = filePath.replace(/\\\\/g, '/');\n if (normalized.startsWith('file://')) return normalized;\n const prefix = normalized.startsWith('/') ? 'file://' : 'file:///';\n return `${prefix}${encodeURI(normalized)}`;\n}\n\nexport const useUtils = {\n logPrefix,\n async loadThemeComponent(\n componentName: string,\n options: {\n theme: {\n name: string;\n type: 'admin' | 'client' | 'portal' | 'email';\n };\n search?: {\n themes?: boolean;\n modules?: boolean;\n services?: boolean;\n };\n }\n ): Promise<React.ComponentType<any> | null> {\n const { search = {}, theme } = options;\n const searchThemes = search.themes ?? true;\n const searchModules = search.modules ?? true;\n const searchServices = search.services ?? true;\n\n const possiblePaths: string[] = [];\n\n console.log(`Searching for component \"${componentName}\" in theme \"${theme.name}\" of type \"${theme.type}\"...`);\n\n try {\n if (searchThemes) {\n const templatesRoot = path.resolve(useSettings.getPaths().templates);\n possiblePaths.push(\n path.resolve(\n templatesRoot,\n theme.type,\n theme.name,\n 'routes',\n `${componentName}.tsx`\n ),\n path.resolve(\n templatesRoot,\n theme.type,\n theme.name,\n 'components',\n `${componentName}.tsx`\n ),\n path.resolve(\n templatesRoot,\n theme.type,\n 'default',\n 'routes',\n `${componentName}.tsx`\n ),\n path.resolve(\n templatesRoot,\n theme.type,\n 'default',\n 'components',\n `${componentName}.tsx`\n )\n );\n }\n \n if (searchModules) {\n const modulesRoot = path.resolve(useSettings.getPaths().modules);\n if (fs.existsSync(modulesRoot)) {\n const moduleDirs = await fs.readdirSync(modulesRoot);\n for (const mod of moduleDirs) {\n possiblePaths.push(\n path.resolve(\n modulesRoot,\n mod,\n 'resources',\n 'themes',\n theme.type,\n theme.name,\n 'routes',\n `${componentName}.tsx`\n ),\n path.resolve(\n modulesRoot,\n mod,\n 'resources',\n 'themes',\n theme.type,\n theme.name,\n 'components',\n `${componentName}.tsx`\n ),\n path.resolve(\n modulesRoot,\n mod,\n 'resources',\n 'themes',\n theme.type,\n 'default',\n 'routes',\n `${componentName}.tsx`\n ),\n path.resolve(\n modulesRoot,\n mod,\n 'resources',\n 'themes',\n theme.type,\n 'default',\n 'components',\n `${componentName}.tsx`\n )\n );\n }\n }\n }\n \n if (searchServices) {\n const servicesRoot = path.resolve(useSettings.getPaths().services);\n if (fs.existsSync(servicesRoot)) {\n const serviceDirs = await fs.readdirSync(servicesRoot);\n for (const svc of serviceDirs) {\n possiblePaths.push(\n path.resolve(\n servicesRoot,\n svc,\n 'resources',\n 'themes',\n theme.type,\n theme.name,\n 'routes',\n `${componentName}.tsx`\n ),\n path.resolve(\n servicesRoot,\n svc,\n 'resources',\n 'themes',\n theme.type,\n theme.name,\n 'components',\n `${componentName}.tsx`\n ),\n path.resolve(\n servicesRoot,\n svc,\n 'resources',\n 'themes',\n theme.type,\n 'default',\n 'routes',\n `${componentName}.tsx`\n ),\n path.resolve(\n servicesRoot,\n svc,\n 'resources',\n 'themes',\n theme.type,\n 'default',\n 'components',\n `${componentName}.tsx`\n )\n );\n }\n }\n }\n \n for (const filePath of possiblePaths) {\n if (await fs.existsSync(filePath)) {\n try {\n const mod = await import(toFileUrl(filePath));\n if (mod.default) return mod.default;\n } catch (err) {\n console.error(`Error loading component at ${filePath}:`, err);\n }\n }\n }\n \n console.warn(`Component \"${componentName}\" not found in theme \"${theme.name}\" of type \"${theme.type}\".`);\n return null;\n } catch (err) {\n console.error(`Error searching for component \"${componentName}\":`, err);\n console.warn(`Component \"${componentName}\" not found in theme \"${theme.name}\" of type \"${theme.type}\".`);\n console.warn(`Searched paths:`, possiblePaths);\n console.warn(`Ensure the component exists in the specified theme and type.`);\n console.warn(`If the component is in a module or service, ensure the theme structure is correct.`);\n console.warn(`If you are using a custom theme, module, or service, ensure it is properly configured and registered in the settings.`);\n return null;\n }\n }\n}\n\n/**\n * \n * @param { 'Providers' | 'Routes' | 'Templates' | 'Modules' | 'Services' | 'Events' | 'Server' | undefined } [et=undefined]\n * @param { 'error' | 'success' | 'info' | 'warning' | undefined } [type=undefined]\n * @param { 'green' | 'cyan' | 'magenta' | 'blue' | 'yellow' | 'red' | 'gray' | 'black' | 'white' | undefined } [color=undefined]\n * @returns\n * Log prefix helper (safe in Node and browser).\n * Mirrors server.js behavior with optional chalk styling when available.\n */\nexport function logPrefix(\n et?: 'Providers' | 'Routes' | 'Templates' | 'Modules' | 'Services' | 'Events' | 'Server' | string,\n type?: 'error' | 'success' | 'info' | 'warning' | string,\n color?: 'green' | 'cyan' | 'magenta' | 'blue' | 'yellow' | 'red' | 'gray' | 'black' | 'white' | string\n): string {\n const label = `${et || 'Extensibles'} Manager${type ? ' | ' + type?.charAt(0).toUpperCase() + type?.slice(1) : ''}`;\n\n const getChalk = (): any => {\n if (typeof window !== 'undefined') return null;\n try {\n // eslint-disable-next-line no-eval\n const req = eval('require');\n const mod = req('chalk');\n return mod?.default ?? mod;\n } catch {\n return null;\n }\n };\n\n const chalk = getChalk();\n const wrap = (fn: ((v: string) => string) | null, value: string) => (fn ? fn(value) : value);\n\n let colored = label;\n if (chalk) {\n if (type === 'error') colored = wrap(chalk.redBright, label);\n else if (type === 'warning') colored = wrap(chalk.yellow, label);\n else if (type === 'success') colored = wrap(chalk.green, label);\n else if (type === 'info') colored = wrap(chalk.blue, label);\n else if (color === 'green') colored = wrap(chalk.green, label);\n else if (color === 'cyan') colored = wrap(chalk.cyan, label);\n else if (color === 'magenta') colored = wrap(chalk.magenta, label);\n else if (color === 'blue') colored = wrap(chalk.blue, label);\n else if (color === 'yellow') colored = wrap(chalk.yellow, label);\n else if (color === 'red') colored = wrap(chalk.red, label);\n else if (color === 'gray') colored = wrap(chalk.gray, label);\n else if (color === 'black') colored = wrap(chalk.black, label);\n else if (color === 'white') colored = wrap(chalk.white, label);\n }\n\n if (chalk?.white) {\n return chalk.white('[') + colored + chalk.white('] ');\n }\n return `[${colored}] `;\n}\n","// src/hooks/useSettings.ts\n\nimport path from 'node:path';\nimport fs from 'node:fs';\n\nimport { loadJSON, saveJSON } from './useExtensibles';\nimport type { ExtensiblePaths } from '../types'; // Adjust the import path as necessary\n\nconst defaultPaths: ExtensiblePaths = {\n modules: './app/modules',\n templates: './app/resources/themes',\n services: './app/services',\n events: './app/events',\n langs: './public/langs',\n providers: './app/providers',\n};\n\nlet extensiblePaths: ExtensiblePaths = { ...defaultPaths };\nconst isServer = typeof window === 'undefined';\n\n\nexport const useSettings = {\n getPaths(): ExtensiblePaths {\n if (isServer) {\n const json = loadJSON('./app/extensiblePaths.json');\n if (json) extensiblePaths = json;\n }\n\n if (isServer) {\n for (const key of Object.keys(defaultPaths) as Array<keyof ExtensiblePaths>) {\n const candidate = extensiblePaths[key];\n if (!candidate || !fs.existsSync(candidate)) {\n extensiblePaths[key] = defaultPaths[key];\n }\n }\n }\n\n extensiblePaths = {\n ...extensiblePaths,\n langs: './langs',\n };\n // extensiblePaths = loadJSON(\"./app/extensiblePaths.json\");\n return extensiblePaths;\n },\n\n setPaths(paths: Partial<ExtensiblePaths>): void {\n if (isServer) {\n saveJSON('./app/extensiblePaths.json', {\n ...extensiblePaths,\n ...paths,\n });\n }\n\n extensiblePaths = {\n ...extensiblePaths,\n ...paths,\n };\n },\n \n getKeyValue(key: string): string {\n return 'Coming Soon'\n },\n setKeyValue(key: string, value: string): void {\n return;\n },\n};\n","// src/hooks/useExtensibles.ts\n\nimport fs from 'node:fs';\nimport path from 'node:path';\nimport { useSettings } from './useSettings';\nimport type { TemplateType, ExtensibleMeta, ExtensiblePaths } from '../types';\n\nlet paths: ExtensiblePaths;\n\nfunction toFileUrl(filePath: string): string {\n const normalized = filePath.replace(/\\\\/g, '/');\n if (normalized.startsWith('file://')) return normalized;\n const prefix = normalized.startsWith('/') ? 'file://' : 'file:///';\n return `${prefix}${encodeURI(normalized)}`;\n}\n\nexport function registerExtensibles(extensiblePaths: ExtensiblePaths) {\n paths = extensiblePaths;\n}\n\nexport function loadJSON(filePath: string): any {\n if (!fs.existsSync(filePath)) return null;\n return JSON.parse(fs.readFileSync(filePath, 'utf-8'));\n}\n\nexport function saveJSON(filePath: string, data: any) {\n fs.writeFileSync(filePath, JSON.stringify(data, null, 2), 'utf-8');\n}\n\n// --- MODULES ---\n\nexport function getModules(): ExtensibleMeta[] {\n if (!useSettings.getPaths().modules) throw new Error('Modules path not registered.');\n\n const dirs = fs\n .readdirSync(useSettings.getPaths().modules)\n .filter((d: any) => fs.statSync(path.join(useSettings.getPaths().modules, d)).isDirectory());\n\n return dirs.map((dir: any) => {\n const meta = loadJSON(path.join(useSettings.getPaths().modules, dir, 'module.json')) || {};\n return {\n name: meta.name || dir,\n lowerName: meta.lowerName || dir.toLowerCase(),\n version: meta.version,\n description: meta.description,\n author: meta.author,\n icon: meta.icon,\n enabled: meta.enabled ?? false,\n };\n });\n}\n\nexport function isModuleEnabled(name: string) {\n const modules = getModules();\n return modules.find((m) => m.lowerName === name.toLowerCase())?.enabled ?? false;\n}\n\nexport function toggleModule(name: string, enabled: boolean) {\n const modules = getModules();\n const mod = modules.find((m) => m.lowerName === name.toLowerCase());\n if (!mod) throw new Error(`Module ${name} not found`);\n\n const metaPath = path.join(useSettings.getPaths().modules, mod.lowerName, 'module.json');\n const meta = loadJSON(metaPath) || {};\n meta.enabled = enabled;\n saveJSON(metaPath, meta);\n\n if (enabled) onModuleEnabled(mod.name);\n else onModuleDisabled(mod.name);\n}\n\n// --- SERVICES ---\n\nexport function getServices(): ExtensibleMeta[] {\n if (!useSettings.getPaths().services) throw new Error('Services path not registered.');\n\n const dirs = fs\n .readdirSync(useSettings.getPaths().services)\n .filter((d: any) => fs.statSync(path.join(useSettings.getPaths().services, d)).isDirectory());\n\n return dirs.map((dir: any) => {\n const meta = loadJSON(path.join(useSettings.getPaths().services, dir, 'service.json')) || {};\n return {\n name: meta.name || dir,\n lowerName: meta.lowerName || dir.toLowerCase(),\n version: meta.version,\n description: meta.description,\n author: meta.author,\n icon: meta.icon,\n enabled: meta.enabled ?? false,\n };\n });\n}\n\nexport function isServiceEnabled(name: string) {\n const services = getServices();\n return services.find((s) => s.lowerName === name.toLowerCase())?.enabled ?? false;\n}\n\nexport function toggleService(name: string, enabled: boolean) {\n const services = getServices();\n const svc = services.find((s) => s.lowerName === name.toLowerCase());\n if (!svc) throw new Error(`Service ${name} not found`);\n\n const metaPath = path.join(useSettings.getPaths().services, svc.lowerName, 'service.json');\n const meta = loadJSON(metaPath) || {};\n meta.enabled = enabled;\n saveJSON(metaPath, meta);\n\n if (enabled) onServiceEnabled(svc.name);\n else onServiceDisabled(svc.name);\n}\n\n// --- TEMPLATES ---\n\n// Helper to get base path for a template type\nfunction getTemplateBasePath(type: TemplateType): string {\n if (!useSettings.getPaths().templates) throw new Error('Templates path not registered.');\n switch (type) {\n case 'admin-theme':\n case 'client-theme':\n return path.join(useSettings.getPaths().templates, 'themes');\n case 'portal':\n return path.join(useSettings.getPaths().templates, 'portals');\n case 'email':\n return path.join(useSettings.getPaths().templates, 'emails');\n default:\n throw new Error(`Unknown template type: ${type}`);\n }\n}\n\nexport function getTemplates(type: TemplateType): ExtensibleMeta[] {\n const basePath = getTemplateBasePath(type);\n if (!fs.existsSync(basePath)) return [];\n\n const dirs = fs\n .readdirSync(basePath)\n .filter((d: any) => fs.statSync(path.join(basePath, d)).isDirectory());\n\n return dirs.map((dir: any) => {\n const meta = loadJSON(path.join(basePath, dir, 'template.json')) || {};\n return {\n name: meta.name || dir,\n lowerName: dir.toLowerCase(),\n version: meta.version,\n description: meta.description,\n author: meta.author,\n icon: meta.icon,\n enabled: meta.enabled ?? false,\n };\n });\n}\n\nexport function isTemplateActive(type: TemplateType, name: string) {\n const templates = getTemplates(type);\n return templates.find((t) => t.lowerName === name.toLowerCase())?.enabled ?? false;\n}\n\n// Toggle templates: only 1 active per type allowed\nexport function toggleTemplate(type: TemplateType, name: string) {\n const templates = getTemplates(type);\n\n templates.forEach((tpl) => {\n const metaPath = path.join(getTemplateBasePath(type), tpl.lowerName, 'template.json');\n const meta = loadJSON(metaPath) || {};\n meta.enabled = tpl.lowerName === name.toLowerCase();\n saveJSON(metaPath, meta);\n });\n\n onTemplateSelect(type, name);\n}\n\n// --- EVENTS (replace with your event system integration) ---\n\nexport function onModuleEnabled(name: string) {\n console.log(`Module enabled: ${name}`);\n // emit event or custom logic here\n}\n\nexport function onModuleDisabled(name: string) {\n console.log(`Module disabled: ${name}`);\n}\n\nexport function onServiceEnabled(name: string) {\n console.log(`Service enabled: ${name}`);\n}\n\nexport function onServiceDisabled(name: string) {\n console.log(`Service disabled: ${name}`);\n}\n\nexport function onTemplateSelect(type: TemplateType, name: string) {\n console.log(`Template selected: type=${type}, name=${name}`);\n}\n\n// --- REGISTER HOOKS FOR MODULES ---\n\nexport async function registerEvents() {\n if (!useSettings.getPaths().modules) throw new Error('Modules path not registered.');\n const modules = getModules().filter((m) => m.enabled);\n for (const mod of modules) {\n const eventsFile = path.join(useSettings.getPaths().modules, mod.lowerName, 'events.server.js');\n if (fs.existsSync(eventsFile)) {\n const modEvents = await import(eventsFile);\n if (modEvents?.registerEvents) await modEvents.registerEvents();\n }\n }\n}\n\nexport async function registerMiddleware() {\n if (!useSettings.getPaths().modules) throw new Error('Modules path not registered.');\n const modules = getModules().filter((m) => m.enabled);\n for (const mod of modules) {\n const middlewareFile = path.join(useSettings.getPaths().modules, mod.lowerName, 'middleware.server.js');\n if (fs.existsSync(middlewareFile)) {\n const modMiddleware = await import(middlewareFile);\n if (modMiddleware?.registerMiddleware) await modMiddleware.registerMiddleware();\n }\n }\n}\n\n/**\n * Registers routes given a path to routes folder (for pages and API routes)\n * @param routesFolderPath string - path to module/service routes folder\n */\nexport async function registerRoutes(routesFolderPath: string) {\n if (!fs.existsSync(routesFolderPath)) return;\n\n const routeFiles = fs.readdirSync(routesFolderPath).filter((f: any) => /\\.(js|ts|jsx|tsx)$/.test(f));\n for (const file of routeFiles) {\n const routeModule = await import(path.join(routesFolderPath, file));\n if (routeModule?.registerRoute) {\n await routeModule.registerRoute();\n }\n }\n}\n\nexport async function loadProviders() {\n const paths = useSettings.getPaths();\n\n const all = [\n { type: 'module', list: getModules(), basePath: paths.modules },\n { type: 'service', list: getServices(), basePath: paths.services },\n ];\n\n for (const { type, list, basePath } of all) {\n for (const item of list) {\n if (!item.enabled) continue;\n\n const metaPath = path.join(path.resolve(basePath), item.lowerName, `${type}.json`);\n const meta = loadJSON(metaPath);\n if (!meta?.providers || !Array.isArray(meta.providers)) continue;\n\n for (const providerRelPath of meta.providers) {\n try {\n let providerAbsPath = path.join(path.resolve(basePath), item.lowerName, providerRelPath);\n\n // Try .js fallback if file is .ts or .tsx\n const ext = path.extname(providerAbsPath);\n if (ext === '.ts' || ext === '.tsx') {\n const jsPath = providerAbsPath.replace(/\\.(ts|tsx)$/, '.js');\n try {\n await fs.accessSync(jsPath); // Check if compiled JS file exists\n providerAbsPath = jsPath;\n } catch {\n throw new Error(`Compiled JS version not found for provider: ${providerRelPath}`);\n }\n }\n\n const providerUrl = toFileUrl(providerAbsPath);\n const providerModule = await import(providerUrl);\n\n if (typeof providerModule.default === 'function') {\n // Expose context so nav registration can auto-tag module/service\n (globalThis as any).__retrex_provider_context__ = {\n type,\n name: item.lowerName,\n };\n await providerModule.default();\n (globalThis as any).__retrex_provider_context__ = undefined;\n console.log(`[${type}] ✅ Provider loaded: ${providerRelPath}`);\n } else {\n console.warn(`[${type}] ⚠️ Provider ${providerRelPath} has no default export.`);\n }\n } catch (err) {\n console.error(`[${type}] ❌ Failed to load provider ${providerRelPath}:`, err);\n }\n }\n }\n }\n}\n\n\n// export async function loadProviders() {\n// paths = {\n// modules: useSettings.getPaths().modules,\n// templates: useSettings.getPaths().templates,\n// services: useSettings.getPaths().services,\n// events: useSettings.getPaths().events,\n// }\n// const all = [\n// { type: 'module', list: getModules(), basePath: useSettings.getPaths().modules },\n// { type: 'service', list: getServices(), basePath: useSettings.getPaths().services },\n// ];\n\n// for (const { type, list, basePath } of all) {\n// for (const item of list) {\n// if (!item.enabled) continue;\n\n// const metaPath = path.join(basePath, item.lowerName, `${type}.json`);\n// const meta = loadJSON(metaPath);\n// if (!meta?.providers || !Array.isArray(meta.providers)) continue;\n\n// for (const providerRelPath of meta.providers) {\n// try {\n// const providerPath = path.join(basePath, item.lowerName, providerRelPath);\n// const providerModule = await import(providerPath);\n// if (typeof providerModule.default === 'function') {\n// await providerModule.default(); // Call provider\n// console.log(`[${type}] Provider loaded: ${providerRelPath}`);\n// } else {\n// console.warn(`[${type}] Provider ${providerRelPath} has no default export.`);\n// }\n// } catch (err) {\n// console.error(`[${type}] Failed to load provider ${providerRelPath}:`, err);\n// }\n// }\n// }\n// }\n// }\n"],"mappings":"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","names":["import_node_path","import_node_fs","import_node_fs","fs","fs","path","fs","mod"]}
|
|
@@ -1,4 +1,5 @@
|
|
|
1
1
|
declare const useUtils: {
|
|
2
|
+
logPrefix: typeof logPrefix;
|
|
2
3
|
loadThemeComponent(componentName: string, options: {
|
|
3
4
|
theme: {
|
|
4
5
|
name: string;
|
|
@@ -11,5 +12,15 @@ declare const useUtils: {
|
|
|
11
12
|
};
|
|
12
13
|
}): Promise<React.ComponentType<any> | null>;
|
|
13
14
|
};
|
|
15
|
+
/**
|
|
16
|
+
*
|
|
17
|
+
* @param { 'Providers' | 'Routes' | 'Templates' | 'Modules' | 'Services' | 'Events' | 'Server' | undefined } [et=undefined]
|
|
18
|
+
* @param { 'error' | 'success' | 'info' | 'warning' | undefined } [type=undefined]
|
|
19
|
+
* @param { 'green' | 'cyan' | 'magenta' | 'blue' | 'yellow' | 'red' | 'gray' | 'black' | 'white' | undefined } [color=undefined]
|
|
20
|
+
* @returns
|
|
21
|
+
* Log prefix helper (safe in Node and browser).
|
|
22
|
+
* Mirrors server.js behavior with optional chalk styling when available.
|
|
23
|
+
*/
|
|
24
|
+
declare function logPrefix(et?: 'Providers' | 'Routes' | 'Templates' | 'Modules' | 'Services' | 'Events' | 'Server' | string, type?: 'error' | 'success' | 'info' | 'warning' | string, color?: 'green' | 'cyan' | 'magenta' | 'blue' | 'yellow' | 'red' | 'gray' | 'black' | 'white' | string): string;
|
|
14
25
|
|
|
15
|
-
export { useUtils };
|
|
26
|
+
export { logPrefix, useUtils };
|
|
@@ -1,4 +1,5 @@
|
|
|
1
1
|
declare const useUtils: {
|
|
2
|
+
logPrefix: typeof logPrefix;
|
|
2
3
|
loadThemeComponent(componentName: string, options: {
|
|
3
4
|
theme: {
|
|
4
5
|
name: string;
|
|
@@ -11,5 +12,15 @@ declare const useUtils: {
|
|
|
11
12
|
};
|
|
12
13
|
}): Promise<React.ComponentType<any> | null>;
|
|
13
14
|
};
|
|
15
|
+
/**
|
|
16
|
+
*
|
|
17
|
+
* @param { 'Providers' | 'Routes' | 'Templates' | 'Modules' | 'Services' | 'Events' | 'Server' | undefined } [et=undefined]
|
|
18
|
+
* @param { 'error' | 'success' | 'info' | 'warning' | undefined } [type=undefined]
|
|
19
|
+
* @param { 'green' | 'cyan' | 'magenta' | 'blue' | 'yellow' | 'red' | 'gray' | 'black' | 'white' | undefined } [color=undefined]
|
|
20
|
+
* @returns
|
|
21
|
+
* Log prefix helper (safe in Node and browser).
|
|
22
|
+
* Mirrors server.js behavior with optional chalk styling when available.
|
|
23
|
+
*/
|
|
24
|
+
declare function logPrefix(et?: 'Providers' | 'Routes' | 'Templates' | 'Modules' | 'Services' | 'Events' | 'Server' | string, type?: 'error' | 'success' | 'info' | 'warning' | string, color?: 'green' | 'cyan' | 'magenta' | 'blue' | 'yellow' | 'red' | 'gray' | 'black' | 'white' | string): string;
|
|
14
25
|
|
|
15
|
-
export { useUtils };
|
|
26
|
+
export { logPrefix, useUtils };
|
|
@@ -75,6 +75,7 @@ function toFileUrl(filePath) {
|
|
|
75
75
|
return `${prefix}${encodeURI(normalized)}`;
|
|
76
76
|
}
|
|
77
77
|
var useUtils = {
|
|
78
|
+
logPrefix,
|
|
78
79
|
async loadThemeComponent(componentName, options) {
|
|
79
80
|
const { search = {}, theme } = options;
|
|
80
81
|
const searchThemes = search.themes ?? true;
|
|
@@ -120,11 +121,11 @@ var useUtils = {
|
|
|
120
121
|
const modulesRoot = path2.resolve(useSettings.getPaths().modules);
|
|
121
122
|
if (fs3.existsSync(modulesRoot)) {
|
|
122
123
|
const moduleDirs = await fs3.readdirSync(modulesRoot);
|
|
123
|
-
for (const
|
|
124
|
+
for (const mod2 of moduleDirs) {
|
|
124
125
|
possiblePaths.push(
|
|
125
126
|
path2.resolve(
|
|
126
127
|
modulesRoot,
|
|
127
|
-
|
|
128
|
+
mod2,
|
|
128
129
|
"resources",
|
|
129
130
|
"themes",
|
|
130
131
|
theme.type,
|
|
@@ -134,7 +135,7 @@ var useUtils = {
|
|
|
134
135
|
),
|
|
135
136
|
path2.resolve(
|
|
136
137
|
modulesRoot,
|
|
137
|
-
|
|
138
|
+
mod2,
|
|
138
139
|
"resources",
|
|
139
140
|
"themes",
|
|
140
141
|
theme.type,
|
|
@@ -144,7 +145,7 @@ var useUtils = {
|
|
|
144
145
|
),
|
|
145
146
|
path2.resolve(
|
|
146
147
|
modulesRoot,
|
|
147
|
-
|
|
148
|
+
mod2,
|
|
148
149
|
"resources",
|
|
149
150
|
"themes",
|
|
150
151
|
theme.type,
|
|
@@ -154,7 +155,7 @@ var useUtils = {
|
|
|
154
155
|
),
|
|
155
156
|
path2.resolve(
|
|
156
157
|
modulesRoot,
|
|
157
|
-
|
|
158
|
+
mod2,
|
|
158
159
|
"resources",
|
|
159
160
|
"themes",
|
|
160
161
|
theme.type,
|
|
@@ -219,8 +220,8 @@ var useUtils = {
|
|
|
219
220
|
for (const filePath of possiblePaths) {
|
|
220
221
|
if (await fs3.existsSync(filePath)) {
|
|
221
222
|
try {
|
|
222
|
-
const
|
|
223
|
-
if (
|
|
223
|
+
const mod2 = await import(toFileUrl(filePath));
|
|
224
|
+
if (mod2.default) return mod2.default;
|
|
224
225
|
} catch (err) {
|
|
225
226
|
console.error(`Error loading component at ${filePath}:`, err);
|
|
226
227
|
}
|
|
@@ -239,7 +240,43 @@ var useUtils = {
|
|
|
239
240
|
}
|
|
240
241
|
}
|
|
241
242
|
};
|
|
243
|
+
function logPrefix(et, type, color) {
|
|
244
|
+
const label = `${et || "Extensibles"} Manager${type ? " | " + type?.charAt(0).toUpperCase() + type?.slice(1) : ""}`;
|
|
245
|
+
const getChalk = () => {
|
|
246
|
+
if (typeof window !== "undefined") return null;
|
|
247
|
+
try {
|
|
248
|
+
const req = eval("require");
|
|
249
|
+
const mod = req("chalk");
|
|
250
|
+
return mod?.default ?? mod;
|
|
251
|
+
} catch {
|
|
252
|
+
return null;
|
|
253
|
+
}
|
|
254
|
+
};
|
|
255
|
+
const chalk = getChalk();
|
|
256
|
+
const wrap = (fn, value) => fn ? fn(value) : value;
|
|
257
|
+
let colored = label;
|
|
258
|
+
if (chalk) {
|
|
259
|
+
if (type === "error") colored = wrap(chalk.redBright, label);
|
|
260
|
+
else if (type === "warning") colored = wrap(chalk.yellow, label);
|
|
261
|
+
else if (type === "success") colored = wrap(chalk.green, label);
|
|
262
|
+
else if (type === "info") colored = wrap(chalk.blue, label);
|
|
263
|
+
else if (color === "green") colored = wrap(chalk.green, label);
|
|
264
|
+
else if (color === "cyan") colored = wrap(chalk.cyan, label);
|
|
265
|
+
else if (color === "magenta") colored = wrap(chalk.magenta, label);
|
|
266
|
+
else if (color === "blue") colored = wrap(chalk.blue, label);
|
|
267
|
+
else if (color === "yellow") colored = wrap(chalk.yellow, label);
|
|
268
|
+
else if (color === "red") colored = wrap(chalk.red, label);
|
|
269
|
+
else if (color === "gray") colored = wrap(chalk.gray, label);
|
|
270
|
+
else if (color === "black") colored = wrap(chalk.black, label);
|
|
271
|
+
else if (color === "white") colored = wrap(chalk.white, label);
|
|
272
|
+
}
|
|
273
|
+
if (chalk?.white) {
|
|
274
|
+
return chalk.white("[") + colored + chalk.white("] ");
|
|
275
|
+
}
|
|
276
|
+
return `[${colored}] `;
|
|
277
|
+
}
|
|
242
278
|
export {
|
|
279
|
+
logPrefix,
|
|
243
280
|
useUtils
|
|
244
281
|
};
|
|
245
282
|
//# sourceMappingURL=useUtils.js.map
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"sources":["../../../src/core/hooks/useUtils.ts","../../../src/core/hooks/useSettings.ts","../../../src/core/hooks/useExtensibles.ts"],"sourcesContent":["/* @vite-ignore */\n// packages/retrex-extensibles-core/hooks/useUtils.ts\nimport path from 'node:path';\nimport fs from 'node:fs';\nimport { useSettings } from './useSettings';\n\nfunction toFileUrl(filePath: string): string {\n const normalized = filePath.replace(/\\\\/g, '/');\n if (normalized.startsWith('file://')) return normalized;\n const prefix = normalized.startsWith('/') ? 'file://' : 'file:///';\n return `${prefix}${encodeURI(normalized)}`;\n}\n\nexport const useUtils = {\n async loadThemeComponent(\n componentName: string,\n options: {\n theme: {\n name: string;\n type: 'admin' | 'client' | 'portal' | 'email';\n };\n search?: {\n themes?: boolean;\n modules?: boolean;\n services?: boolean;\n };\n }\n ): Promise<React.ComponentType<any> | null> {\n const { search = {}, theme } = options;\n const searchThemes = search.themes ?? true;\n const searchModules = search.modules ?? true;\n const searchServices = search.services ?? true;\n\n const possiblePaths: string[] = [];\n\n console.log(`Searching for component \"${componentName}\" in theme \"${theme.name}\" of type \"${theme.type}\"...`);\n\n try {\n if (searchThemes) {\n const templatesRoot = path.resolve(useSettings.getPaths().templates);\n possiblePaths.push(\n path.resolve(\n templatesRoot,\n theme.type,\n theme.name,\n 'routes',\n `${componentName}.tsx`\n ),\n path.resolve(\n templatesRoot,\n theme.type,\n theme.name,\n 'components',\n `${componentName}.tsx`\n ),\n path.resolve(\n templatesRoot,\n theme.type,\n 'default',\n 'routes',\n `${componentName}.tsx`\n ),\n path.resolve(\n templatesRoot,\n theme.type,\n 'default',\n 'components',\n `${componentName}.tsx`\n )\n );\n }\n \n if (searchModules) {\n const modulesRoot = path.resolve(useSettings.getPaths().modules);\n if (fs.existsSync(modulesRoot)) {\n const moduleDirs = await fs.readdirSync(modulesRoot);\n for (const mod of moduleDirs) {\n possiblePaths.push(\n path.resolve(\n modulesRoot,\n mod,\n 'resources',\n 'themes',\n theme.type,\n theme.name,\n 'routes',\n `${componentName}.tsx`\n ),\n path.resolve(\n modulesRoot,\n mod,\n 'resources',\n 'themes',\n theme.type,\n theme.name,\n 'components',\n `${componentName}.tsx`\n ),\n path.resolve(\n modulesRoot,\n mod,\n 'resources',\n 'themes',\n theme.type,\n 'default',\n 'routes',\n `${componentName}.tsx`\n ),\n path.resolve(\n modulesRoot,\n mod,\n 'resources',\n 'themes',\n theme.type,\n 'default',\n 'components',\n `${componentName}.tsx`\n )\n );\n }\n }\n }\n \n if (searchServices) {\n const servicesRoot = path.resolve(useSettings.getPaths().services);\n if (fs.existsSync(servicesRoot)) {\n const serviceDirs = await fs.readdirSync(servicesRoot);\n for (const svc of serviceDirs) {\n possiblePaths.push(\n path.resolve(\n servicesRoot,\n svc,\n 'resources',\n 'themes',\n theme.type,\n theme.name,\n 'routes',\n `${componentName}.tsx`\n ),\n path.resolve(\n servicesRoot,\n svc,\n 'resources',\n 'themes',\n theme.type,\n theme.name,\n 'components',\n `${componentName}.tsx`\n ),\n path.resolve(\n servicesRoot,\n svc,\n 'resources',\n 'themes',\n theme.type,\n 'default',\n 'routes',\n `${componentName}.tsx`\n ),\n path.resolve(\n servicesRoot,\n svc,\n 'resources',\n 'themes',\n theme.type,\n 'default',\n 'components',\n `${componentName}.tsx`\n )\n );\n }\n }\n }\n \n for (const filePath of possiblePaths) {\n if (await fs.existsSync(filePath)) {\n try {\n const mod = await import(toFileUrl(filePath));\n if (mod.default) return mod.default;\n } catch (err) {\n console.error(`Error loading component at ${filePath}:`, err);\n }\n }\n }\n \n console.warn(`Component \"${componentName}\" not found in theme \"${theme.name}\" of type \"${theme.type}\".`);\n return null;\n } catch (err) {\n console.error(`Error searching for component \"${componentName}\":`, err);\n console.warn(`Component \"${componentName}\" not found in theme \"${theme.name}\" of type \"${theme.type}\".`);\n console.warn(`Searched paths:`, possiblePaths);\n console.warn(`Ensure the component exists in the specified theme and type.`);\n console.warn(`If the component is in a module or service, ensure the theme structure is correct.`);\n console.warn(`If you are using a custom theme, module, or service, ensure it is properly configured and registered in the settings.`);\n return null;\n }\n }\n}\n","// src/hooks/useSettings.ts\n\nimport path from 'node:path';\nimport fs from 'node:fs';\n\nimport { loadJSON, saveJSON } from './useExtensibles';\nimport type { ExtensiblePaths } from '../types'; // Adjust the import path as necessary\n\nconst defaultPaths: ExtensiblePaths = {\n modules: './app/modules',\n templates: './app/resources/themes',\n services: './app/services',\n events: './app/events',\n langs: './public/langs',\n providers: './app/providers',\n};\n\nlet extensiblePaths: ExtensiblePaths = { ...defaultPaths };\nconst isServer = typeof window === 'undefined';\n\n\nexport const useSettings = {\n getPaths(): ExtensiblePaths {\n if (isServer) {\n const json = loadJSON('./app/extensiblePaths.json');\n if (json) extensiblePaths = json;\n }\n\n if (isServer) {\n for (const key of Object.keys(defaultPaths) as Array<keyof ExtensiblePaths>) {\n const candidate = extensiblePaths[key];\n if (!candidate || !fs.existsSync(candidate)) {\n extensiblePaths[key] = defaultPaths[key];\n }\n }\n }\n\n extensiblePaths = {\n ...extensiblePaths,\n langs: './langs',\n };\n // extensiblePaths = loadJSON(\"./app/extensiblePaths.json\");\n return extensiblePaths;\n },\n\n setPaths(paths: Partial<ExtensiblePaths>): void {\n if (isServer) {\n saveJSON('./app/extensiblePaths.json', {\n ...extensiblePaths,\n ...paths,\n });\n }\n\n extensiblePaths = {\n ...extensiblePaths,\n ...paths,\n };\n },\n \n getKeyValue(key: string): string {\n return 'Coming Soon'\n },\n setKeyValue(key: string, value: string): void {\n return;\n },\n};\n","// src/hooks/useExtensibles.ts\n\nimport fs from 'node:fs';\nimport path from 'node:path';\nimport { useSettings } from './useSettings';\nimport type { TemplateType, ExtensibleMeta, ExtensiblePaths } from '../types';\n\nlet paths: ExtensiblePaths;\n\nfunction toFileUrl(filePath: string): string {\n const normalized = filePath.replace(/\\\\/g, '/');\n if (normalized.startsWith('file://')) return normalized;\n const prefix = normalized.startsWith('/') ? 'file://' : 'file:///';\n return `${prefix}${encodeURI(normalized)}`;\n}\n\nexport function registerExtensibles(extensiblePaths: ExtensiblePaths) {\n paths = extensiblePaths;\n}\n\nexport function loadJSON(filePath: string): any {\n if (!fs.existsSync(filePath)) return null;\n return JSON.parse(fs.readFileSync(filePath, 'utf-8'));\n}\n\nexport function saveJSON(filePath: string, data: any) {\n fs.writeFileSync(filePath, JSON.stringify(data, null, 2), 'utf-8');\n}\n\n// --- MODULES ---\n\nexport function getModules(): ExtensibleMeta[] {\n if (!useSettings.getPaths().modules) throw new Error('Modules path not registered.');\n\n const dirs = fs\n .readdirSync(useSettings.getPaths().modules)\n .filter((d: any) => fs.statSync(path.join(useSettings.getPaths().modules, d)).isDirectory());\n\n return dirs.map((dir: any) => {\n const meta = loadJSON(path.join(useSettings.getPaths().modules, dir, 'module.json')) || {};\n return {\n name: meta.name || dir,\n lowerName: meta.lowerName || dir.toLowerCase(),\n version: meta.version,\n description: meta.description,\n author: meta.author,\n icon: meta.icon,\n enabled: meta.enabled ?? false,\n };\n });\n}\n\nexport function isModuleEnabled(name: string) {\n const modules = getModules();\n return modules.find((m) => m.lowerName === name.toLowerCase())?.enabled ?? false;\n}\n\nexport function toggleModule(name: string, enabled: boolean) {\n const modules = getModules();\n const mod = modules.find((m) => m.lowerName === name.toLowerCase());\n if (!mod) throw new Error(`Module ${name} not found`);\n\n const metaPath = path.join(useSettings.getPaths().modules, mod.lowerName, 'module.json');\n const meta = loadJSON(metaPath) || {};\n meta.enabled = enabled;\n saveJSON(metaPath, meta);\n\n if (enabled) onModuleEnabled(mod.name);\n else onModuleDisabled(mod.name);\n}\n\n// --- SERVICES ---\n\nexport function getServices(): ExtensibleMeta[] {\n if (!useSettings.getPaths().services) throw new Error('Services path not registered.');\n\n const dirs = fs\n .readdirSync(useSettings.getPaths().services)\n .filter((d: any) => fs.statSync(path.join(useSettings.getPaths().services, d)).isDirectory());\n\n return dirs.map((dir: any) => {\n const meta = loadJSON(path.join(useSettings.getPaths().services, dir, 'service.json')) || {};\n return {\n name: meta.name || dir,\n lowerName: meta.lowerName || dir.toLowerCase(),\n version: meta.version,\n description: meta.description,\n author: meta.author,\n icon: meta.icon,\n enabled: meta.enabled ?? false,\n };\n });\n}\n\nexport function isServiceEnabled(name: string) {\n const services = getServices();\n return services.find((s) => s.lowerName === name.toLowerCase())?.enabled ?? false;\n}\n\nexport function toggleService(name: string, enabled: boolean) {\n const services = getServices();\n const svc = services.find((s) => s.lowerName === name.toLowerCase());\n if (!svc) throw new Error(`Service ${name} not found`);\n\n const metaPath = path.join(useSettings.getPaths().services, svc.lowerName, 'service.json');\n const meta = loadJSON(metaPath) || {};\n meta.enabled = enabled;\n saveJSON(metaPath, meta);\n\n if (enabled) onServiceEnabled(svc.name);\n else onServiceDisabled(svc.name);\n}\n\n// --- TEMPLATES ---\n\n// Helper to get base path for a template type\nfunction getTemplateBasePath(type: TemplateType): string {\n if (!useSettings.getPaths().templates) throw new Error('Templates path not registered.');\n switch (type) {\n case 'admin-theme':\n case 'client-theme':\n return path.join(useSettings.getPaths().templates, 'themes');\n case 'portal':\n return path.join(useSettings.getPaths().templates, 'portals');\n case 'email':\n return path.join(useSettings.getPaths().templates, 'emails');\n default:\n throw new Error(`Unknown template type: ${type}`);\n }\n}\n\nexport function getTemplates(type: TemplateType): ExtensibleMeta[] {\n const basePath = getTemplateBasePath(type);\n if (!fs.existsSync(basePath)) return [];\n\n const dirs = fs\n .readdirSync(basePath)\n .filter((d: any) => fs.statSync(path.join(basePath, d)).isDirectory());\n\n return dirs.map((dir: any) => {\n const meta = loadJSON(path.join(basePath, dir, 'template.json')) || {};\n return {\n name: meta.name || dir,\n lowerName: dir.toLowerCase(),\n version: meta.version,\n description: meta.description,\n author: meta.author,\n icon: meta.icon,\n enabled: meta.enabled ?? false,\n };\n });\n}\n\nexport function isTemplateActive(type: TemplateType, name: string) {\n const templates = getTemplates(type);\n return templates.find((t) => t.lowerName === name.toLowerCase())?.enabled ?? false;\n}\n\n// Toggle templates: only 1 active per type allowed\nexport function toggleTemplate(type: TemplateType, name: string) {\n const templates = getTemplates(type);\n\n templates.forEach((tpl) => {\n const metaPath = path.join(getTemplateBasePath(type), tpl.lowerName, 'template.json');\n const meta = loadJSON(metaPath) || {};\n meta.enabled = tpl.lowerName === name.toLowerCase();\n saveJSON(metaPath, meta);\n });\n\n onTemplateSelect(type, name);\n}\n\n// --- EVENTS (replace with your event system integration) ---\n\nexport function onModuleEnabled(name: string) {\n console.log(`Module enabled: ${name}`);\n // emit event or custom logic here\n}\n\nexport function onModuleDisabled(name: string) {\n console.log(`Module disabled: ${name}`);\n}\n\nexport function onServiceEnabled(name: string) {\n console.log(`Service enabled: ${name}`);\n}\n\nexport function onServiceDisabled(name: string) {\n console.log(`Service disabled: ${name}`);\n}\n\nexport function onTemplateSelect(type: TemplateType, name: string) {\n console.log(`Template selected: type=${type}, name=${name}`);\n}\n\n// --- REGISTER HOOKS FOR MODULES ---\n\nexport async function registerEvents() {\n if (!useSettings.getPaths().modules) throw new Error('Modules path not registered.');\n const modules = getModules().filter((m) => m.enabled);\n for (const mod of modules) {\n const eventsFile = path.join(useSettings.getPaths().modules, mod.lowerName, 'events.server.js');\n if (fs.existsSync(eventsFile)) {\n const modEvents = await import(eventsFile);\n if (modEvents?.registerEvents) await modEvents.registerEvents();\n }\n }\n}\n\nexport async function registerMiddleware() {\n if (!useSettings.getPaths().modules) throw new Error('Modules path not registered.');\n const modules = getModules().filter((m) => m.enabled);\n for (const mod of modules) {\n const middlewareFile = path.join(useSettings.getPaths().modules, mod.lowerName, 'middleware.server.js');\n if (fs.existsSync(middlewareFile)) {\n const modMiddleware = await import(middlewareFile);\n if (modMiddleware?.registerMiddleware) await modMiddleware.registerMiddleware();\n }\n }\n}\n\n/**\n * Registers routes given a path to routes folder (for pages and API routes)\n * @param routesFolderPath string - path to module/service routes folder\n */\nexport async function registerRoutes(routesFolderPath: string) {\n if (!fs.existsSync(routesFolderPath)) return;\n\n const routeFiles = fs.readdirSync(routesFolderPath).filter((f: any) => /\\.(js|ts|jsx|tsx)$/.test(f));\n for (const file of routeFiles) {\n const routeModule = await import(path.join(routesFolderPath, file));\n if (routeModule?.registerRoute) {\n await routeModule.registerRoute();\n }\n }\n}\n\nexport async function loadProviders() {\n const paths = useSettings.getPaths();\n\n const all = [\n { type: 'module', list: getModules(), basePath: paths.modules },\n { type: 'service', list: getServices(), basePath: paths.services },\n ];\n\n for (const { type, list, basePath } of all) {\n for (const item of list) {\n if (!item.enabled) continue;\n\n const metaPath = path.join(path.resolve(basePath), item.lowerName, `${type}.json`);\n const meta = loadJSON(metaPath);\n if (!meta?.providers || !Array.isArray(meta.providers)) continue;\n\n for (const providerRelPath of meta.providers) {\n try {\n let providerAbsPath = path.join(path.resolve(basePath), item.lowerName, providerRelPath);\n\n // Try .js fallback if file is .ts or .tsx\n const ext = path.extname(providerAbsPath);\n if (ext === '.ts' || ext === '.tsx') {\n const jsPath = providerAbsPath.replace(/\\.(ts|tsx)$/, '.js');\n try {\n await fs.accessSync(jsPath); // Check if compiled JS file exists\n providerAbsPath = jsPath;\n } catch {\n throw new Error(`Compiled JS version not found for provider: ${providerRelPath}`);\n }\n }\n\n const providerUrl = toFileUrl(providerAbsPath);\n const providerModule = await import(providerUrl);\n\n if (typeof providerModule.default === 'function') {\n // Expose context so nav registration can auto-tag module/service\n (globalThis as any).__retrex_provider_context__ = {\n type,\n name: item.lowerName,\n };\n await providerModule.default();\n (globalThis as any).__retrex_provider_context__ = undefined;\n console.log(`[${type}] ✅ Provider loaded: ${providerRelPath}`);\n } else {\n console.warn(`[${type}] ⚠️ Provider ${providerRelPath} has no default export.`);\n }\n } catch (err) {\n console.error(`[${type}] ❌ Failed to load provider ${providerRelPath}:`, err);\n }\n }\n }\n }\n}\n\n\n// export async function loadProviders() {\n// paths = {\n// modules: useSettings.getPaths().modules,\n// templates: useSettings.getPaths().templates,\n// services: useSettings.getPaths().services,\n// events: useSettings.getPaths().events,\n// }\n// const all = [\n// { type: 'module', list: getModules(), basePath: useSettings.getPaths().modules },\n// { type: 'service', list: getServices(), basePath: useSettings.getPaths().services },\n// ];\n\n// for (const { type, list, basePath } of all) {\n// for (const item of list) {\n// if (!item.enabled) continue;\n\n// const metaPath = path.join(basePath, item.lowerName, `${type}.json`);\n// const meta = loadJSON(metaPath);\n// if (!meta?.providers || !Array.isArray(meta.providers)) continue;\n\n// for (const providerRelPath of meta.providers) {\n// try {\n// const providerPath = path.join(basePath, item.lowerName, providerRelPath);\n// const providerModule = await import(providerPath);\n// if (typeof providerModule.default === 'function') {\n// await providerModule.default(); // Call provider\n// console.log(`[${type}] Provider loaded: ${providerRelPath}`);\n// } else {\n// console.warn(`[${type}] Provider ${providerRelPath} has no default export.`);\n// }\n// } catch (err) {\n// console.error(`[${type}] Failed to load provider ${providerRelPath}:`, err);\n// }\n// }\n// }\n// }\n// }\n"],"mappings":"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","names":["path","fs","fs","fs","path","fs"]}
|
|
1
|
+
{"version":3,"sources":["../../../src/core/hooks/useUtils.ts","../../../src/core/hooks/useSettings.ts","../../../src/core/hooks/useExtensibles.ts"],"sourcesContent":["/* @vite-ignore */\n// packages/retrex-extensibles-core/hooks/useUtils.ts\nimport path from 'node:path';\nimport fs from 'node:fs';\nimport { useSettings } from './useSettings';\n\nfunction toFileUrl(filePath: string): string {\n const normalized = filePath.replace(/\\\\/g, '/');\n if (normalized.startsWith('file://')) return normalized;\n const prefix = normalized.startsWith('/') ? 'file://' : 'file:///';\n return `${prefix}${encodeURI(normalized)}`;\n}\n\nexport const useUtils = {\n logPrefix,\n async loadThemeComponent(\n componentName: string,\n options: {\n theme: {\n name: string;\n type: 'admin' | 'client' | 'portal' | 'email';\n };\n search?: {\n themes?: boolean;\n modules?: boolean;\n services?: boolean;\n };\n }\n ): Promise<React.ComponentType<any> | null> {\n const { search = {}, theme } = options;\n const searchThemes = search.themes ?? true;\n const searchModules = search.modules ?? true;\n const searchServices = search.services ?? true;\n\n const possiblePaths: string[] = [];\n\n console.log(`Searching for component \"${componentName}\" in theme \"${theme.name}\" of type \"${theme.type}\"...`);\n\n try {\n if (searchThemes) {\n const templatesRoot = path.resolve(useSettings.getPaths().templates);\n possiblePaths.push(\n path.resolve(\n templatesRoot,\n theme.type,\n theme.name,\n 'routes',\n `${componentName}.tsx`\n ),\n path.resolve(\n templatesRoot,\n theme.type,\n theme.name,\n 'components',\n `${componentName}.tsx`\n ),\n path.resolve(\n templatesRoot,\n theme.type,\n 'default',\n 'routes',\n `${componentName}.tsx`\n ),\n path.resolve(\n templatesRoot,\n theme.type,\n 'default',\n 'components',\n `${componentName}.tsx`\n )\n );\n }\n \n if (searchModules) {\n const modulesRoot = path.resolve(useSettings.getPaths().modules);\n if (fs.existsSync(modulesRoot)) {\n const moduleDirs = await fs.readdirSync(modulesRoot);\n for (const mod of moduleDirs) {\n possiblePaths.push(\n path.resolve(\n modulesRoot,\n mod,\n 'resources',\n 'themes',\n theme.type,\n theme.name,\n 'routes',\n `${componentName}.tsx`\n ),\n path.resolve(\n modulesRoot,\n mod,\n 'resources',\n 'themes',\n theme.type,\n theme.name,\n 'components',\n `${componentName}.tsx`\n ),\n path.resolve(\n modulesRoot,\n mod,\n 'resources',\n 'themes',\n theme.type,\n 'default',\n 'routes',\n `${componentName}.tsx`\n ),\n path.resolve(\n modulesRoot,\n mod,\n 'resources',\n 'themes',\n theme.type,\n 'default',\n 'components',\n `${componentName}.tsx`\n )\n );\n }\n }\n }\n \n if (searchServices) {\n const servicesRoot = path.resolve(useSettings.getPaths().services);\n if (fs.existsSync(servicesRoot)) {\n const serviceDirs = await fs.readdirSync(servicesRoot);\n for (const svc of serviceDirs) {\n possiblePaths.push(\n path.resolve(\n servicesRoot,\n svc,\n 'resources',\n 'themes',\n theme.type,\n theme.name,\n 'routes',\n `${componentName}.tsx`\n ),\n path.resolve(\n servicesRoot,\n svc,\n 'resources',\n 'themes',\n theme.type,\n theme.name,\n 'components',\n `${componentName}.tsx`\n ),\n path.resolve(\n servicesRoot,\n svc,\n 'resources',\n 'themes',\n theme.type,\n 'default',\n 'routes',\n `${componentName}.tsx`\n ),\n path.resolve(\n servicesRoot,\n svc,\n 'resources',\n 'themes',\n theme.type,\n 'default',\n 'components',\n `${componentName}.tsx`\n )\n );\n }\n }\n }\n \n for (const filePath of possiblePaths) {\n if (await fs.existsSync(filePath)) {\n try {\n const mod = await import(toFileUrl(filePath));\n if (mod.default) return mod.default;\n } catch (err) {\n console.error(`Error loading component at ${filePath}:`, err);\n }\n }\n }\n \n console.warn(`Component \"${componentName}\" not found in theme \"${theme.name}\" of type \"${theme.type}\".`);\n return null;\n } catch (err) {\n console.error(`Error searching for component \"${componentName}\":`, err);\n console.warn(`Component \"${componentName}\" not found in theme \"${theme.name}\" of type \"${theme.type}\".`);\n console.warn(`Searched paths:`, possiblePaths);\n console.warn(`Ensure the component exists in the specified theme and type.`);\n console.warn(`If the component is in a module or service, ensure the theme structure is correct.`);\n console.warn(`If you are using a custom theme, module, or service, ensure it is properly configured and registered in the settings.`);\n return null;\n }\n }\n}\n\n/**\n * \n * @param { 'Providers' | 'Routes' | 'Templates' | 'Modules' | 'Services' | 'Events' | 'Server' | undefined } [et=undefined]\n * @param { 'error' | 'success' | 'info' | 'warning' | undefined } [type=undefined]\n * @param { 'green' | 'cyan' | 'magenta' | 'blue' | 'yellow' | 'red' | 'gray' | 'black' | 'white' | undefined } [color=undefined]\n * @returns\n * Log prefix helper (safe in Node and browser).\n * Mirrors server.js behavior with optional chalk styling when available.\n */\nexport function logPrefix(\n et?: 'Providers' | 'Routes' | 'Templates' | 'Modules' | 'Services' | 'Events' | 'Server' | string,\n type?: 'error' | 'success' | 'info' | 'warning' | string,\n color?: 'green' | 'cyan' | 'magenta' | 'blue' | 'yellow' | 'red' | 'gray' | 'black' | 'white' | string\n): string {\n const label = `${et || 'Extensibles'} Manager${type ? ' | ' + type?.charAt(0).toUpperCase() + type?.slice(1) : ''}`;\n\n const getChalk = (): any => {\n if (typeof window !== 'undefined') return null;\n try {\n // eslint-disable-next-line no-eval\n const req = eval('require');\n const mod = req('chalk');\n return mod?.default ?? mod;\n } catch {\n return null;\n }\n };\n\n const chalk = getChalk();\n const wrap = (fn: ((v: string) => string) | null, value: string) => (fn ? fn(value) : value);\n\n let colored = label;\n if (chalk) {\n if (type === 'error') colored = wrap(chalk.redBright, label);\n else if (type === 'warning') colored = wrap(chalk.yellow, label);\n else if (type === 'success') colored = wrap(chalk.green, label);\n else if (type === 'info') colored = wrap(chalk.blue, label);\n else if (color === 'green') colored = wrap(chalk.green, label);\n else if (color === 'cyan') colored = wrap(chalk.cyan, label);\n else if (color === 'magenta') colored = wrap(chalk.magenta, label);\n else if (color === 'blue') colored = wrap(chalk.blue, label);\n else if (color === 'yellow') colored = wrap(chalk.yellow, label);\n else if (color === 'red') colored = wrap(chalk.red, label);\n else if (color === 'gray') colored = wrap(chalk.gray, label);\n else if (color === 'black') colored = wrap(chalk.black, label);\n else if (color === 'white') colored = wrap(chalk.white, label);\n }\n\n if (chalk?.white) {\n return chalk.white('[') + colored + chalk.white('] ');\n }\n return `[${colored}] `;\n}\n","// src/hooks/useSettings.ts\n\nimport path from 'node:path';\nimport fs from 'node:fs';\n\nimport { loadJSON, saveJSON } from './useExtensibles';\nimport type { ExtensiblePaths } from '../types'; // Adjust the import path as necessary\n\nconst defaultPaths: ExtensiblePaths = {\n modules: './app/modules',\n templates: './app/resources/themes',\n services: './app/services',\n events: './app/events',\n langs: './public/langs',\n providers: './app/providers',\n};\n\nlet extensiblePaths: ExtensiblePaths = { ...defaultPaths };\nconst isServer = typeof window === 'undefined';\n\n\nexport const useSettings = {\n getPaths(): ExtensiblePaths {\n if (isServer) {\n const json = loadJSON('./app/extensiblePaths.json');\n if (json) extensiblePaths = json;\n }\n\n if (isServer) {\n for (const key of Object.keys(defaultPaths) as Array<keyof ExtensiblePaths>) {\n const candidate = extensiblePaths[key];\n if (!candidate || !fs.existsSync(candidate)) {\n extensiblePaths[key] = defaultPaths[key];\n }\n }\n }\n\n extensiblePaths = {\n ...extensiblePaths,\n langs: './langs',\n };\n // extensiblePaths = loadJSON(\"./app/extensiblePaths.json\");\n return extensiblePaths;\n },\n\n setPaths(paths: Partial<ExtensiblePaths>): void {\n if (isServer) {\n saveJSON('./app/extensiblePaths.json', {\n ...extensiblePaths,\n ...paths,\n });\n }\n\n extensiblePaths = {\n ...extensiblePaths,\n ...paths,\n };\n },\n \n getKeyValue(key: string): string {\n return 'Coming Soon'\n },\n setKeyValue(key: string, value: string): void {\n return;\n },\n};\n","// src/hooks/useExtensibles.ts\n\nimport fs from 'node:fs';\nimport path from 'node:path';\nimport { useSettings } from './useSettings';\nimport type { TemplateType, ExtensibleMeta, ExtensiblePaths } from '../types';\n\nlet paths: ExtensiblePaths;\n\nfunction toFileUrl(filePath: string): string {\n const normalized = filePath.replace(/\\\\/g, '/');\n if (normalized.startsWith('file://')) return normalized;\n const prefix = normalized.startsWith('/') ? 'file://' : 'file:///';\n return `${prefix}${encodeURI(normalized)}`;\n}\n\nexport function registerExtensibles(extensiblePaths: ExtensiblePaths) {\n paths = extensiblePaths;\n}\n\nexport function loadJSON(filePath: string): any {\n if (!fs.existsSync(filePath)) return null;\n return JSON.parse(fs.readFileSync(filePath, 'utf-8'));\n}\n\nexport function saveJSON(filePath: string, data: any) {\n fs.writeFileSync(filePath, JSON.stringify(data, null, 2), 'utf-8');\n}\n\n// --- MODULES ---\n\nexport function getModules(): ExtensibleMeta[] {\n if (!useSettings.getPaths().modules) throw new Error('Modules path not registered.');\n\n const dirs = fs\n .readdirSync(useSettings.getPaths().modules)\n .filter((d: any) => fs.statSync(path.join(useSettings.getPaths().modules, d)).isDirectory());\n\n return dirs.map((dir: any) => {\n const meta = loadJSON(path.join(useSettings.getPaths().modules, dir, 'module.json')) || {};\n return {\n name: meta.name || dir,\n lowerName: meta.lowerName || dir.toLowerCase(),\n version: meta.version,\n description: meta.description,\n author: meta.author,\n icon: meta.icon,\n enabled: meta.enabled ?? false,\n };\n });\n}\n\nexport function isModuleEnabled(name: string) {\n const modules = getModules();\n return modules.find((m) => m.lowerName === name.toLowerCase())?.enabled ?? false;\n}\n\nexport function toggleModule(name: string, enabled: boolean) {\n const modules = getModules();\n const mod = modules.find((m) => m.lowerName === name.toLowerCase());\n if (!mod) throw new Error(`Module ${name} not found`);\n\n const metaPath = path.join(useSettings.getPaths().modules, mod.lowerName, 'module.json');\n const meta = loadJSON(metaPath) || {};\n meta.enabled = enabled;\n saveJSON(metaPath, meta);\n\n if (enabled) onModuleEnabled(mod.name);\n else onModuleDisabled(mod.name);\n}\n\n// --- SERVICES ---\n\nexport function getServices(): ExtensibleMeta[] {\n if (!useSettings.getPaths().services) throw new Error('Services path not registered.');\n\n const dirs = fs\n .readdirSync(useSettings.getPaths().services)\n .filter((d: any) => fs.statSync(path.join(useSettings.getPaths().services, d)).isDirectory());\n\n return dirs.map((dir: any) => {\n const meta = loadJSON(path.join(useSettings.getPaths().services, dir, 'service.json')) || {};\n return {\n name: meta.name || dir,\n lowerName: meta.lowerName || dir.toLowerCase(),\n version: meta.version,\n description: meta.description,\n author: meta.author,\n icon: meta.icon,\n enabled: meta.enabled ?? false,\n };\n });\n}\n\nexport function isServiceEnabled(name: string) {\n const services = getServices();\n return services.find((s) => s.lowerName === name.toLowerCase())?.enabled ?? false;\n}\n\nexport function toggleService(name: string, enabled: boolean) {\n const services = getServices();\n const svc = services.find((s) => s.lowerName === name.toLowerCase());\n if (!svc) throw new Error(`Service ${name} not found`);\n\n const metaPath = path.join(useSettings.getPaths().services, svc.lowerName, 'service.json');\n const meta = loadJSON(metaPath) || {};\n meta.enabled = enabled;\n saveJSON(metaPath, meta);\n\n if (enabled) onServiceEnabled(svc.name);\n else onServiceDisabled(svc.name);\n}\n\n// --- TEMPLATES ---\n\n// Helper to get base path for a template type\nfunction getTemplateBasePath(type: TemplateType): string {\n if (!useSettings.getPaths().templates) throw new Error('Templates path not registered.');\n switch (type) {\n case 'admin-theme':\n case 'client-theme':\n return path.join(useSettings.getPaths().templates, 'themes');\n case 'portal':\n return path.join(useSettings.getPaths().templates, 'portals');\n case 'email':\n return path.join(useSettings.getPaths().templates, 'emails');\n default:\n throw new Error(`Unknown template type: ${type}`);\n }\n}\n\nexport function getTemplates(type: TemplateType): ExtensibleMeta[] {\n const basePath = getTemplateBasePath(type);\n if (!fs.existsSync(basePath)) return [];\n\n const dirs = fs\n .readdirSync(basePath)\n .filter((d: any) => fs.statSync(path.join(basePath, d)).isDirectory());\n\n return dirs.map((dir: any) => {\n const meta = loadJSON(path.join(basePath, dir, 'template.json')) || {};\n return {\n name: meta.name || dir,\n lowerName: dir.toLowerCase(),\n version: meta.version,\n description: meta.description,\n author: meta.author,\n icon: meta.icon,\n enabled: meta.enabled ?? false,\n };\n });\n}\n\nexport function isTemplateActive(type: TemplateType, name: string) {\n const templates = getTemplates(type);\n return templates.find((t) => t.lowerName === name.toLowerCase())?.enabled ?? false;\n}\n\n// Toggle templates: only 1 active per type allowed\nexport function toggleTemplate(type: TemplateType, name: string) {\n const templates = getTemplates(type);\n\n templates.forEach((tpl) => {\n const metaPath = path.join(getTemplateBasePath(type), tpl.lowerName, 'template.json');\n const meta = loadJSON(metaPath) || {};\n meta.enabled = tpl.lowerName === name.toLowerCase();\n saveJSON(metaPath, meta);\n });\n\n onTemplateSelect(type, name);\n}\n\n// --- EVENTS (replace with your event system integration) ---\n\nexport function onModuleEnabled(name: string) {\n console.log(`Module enabled: ${name}`);\n // emit event or custom logic here\n}\n\nexport function onModuleDisabled(name: string) {\n console.log(`Module disabled: ${name}`);\n}\n\nexport function onServiceEnabled(name: string) {\n console.log(`Service enabled: ${name}`);\n}\n\nexport function onServiceDisabled(name: string) {\n console.log(`Service disabled: ${name}`);\n}\n\nexport function onTemplateSelect(type: TemplateType, name: string) {\n console.log(`Template selected: type=${type}, name=${name}`);\n}\n\n// --- REGISTER HOOKS FOR MODULES ---\n\nexport async function registerEvents() {\n if (!useSettings.getPaths().modules) throw new Error('Modules path not registered.');\n const modules = getModules().filter((m) => m.enabled);\n for (const mod of modules) {\n const eventsFile = path.join(useSettings.getPaths().modules, mod.lowerName, 'events.server.js');\n if (fs.existsSync(eventsFile)) {\n const modEvents = await import(eventsFile);\n if (modEvents?.registerEvents) await modEvents.registerEvents();\n }\n }\n}\n\nexport async function registerMiddleware() {\n if (!useSettings.getPaths().modules) throw new Error('Modules path not registered.');\n const modules = getModules().filter((m) => m.enabled);\n for (const mod of modules) {\n const middlewareFile = path.join(useSettings.getPaths().modules, mod.lowerName, 'middleware.server.js');\n if (fs.existsSync(middlewareFile)) {\n const modMiddleware = await import(middlewareFile);\n if (modMiddleware?.registerMiddleware) await modMiddleware.registerMiddleware();\n }\n }\n}\n\n/**\n * Registers routes given a path to routes folder (for pages and API routes)\n * @param routesFolderPath string - path to module/service routes folder\n */\nexport async function registerRoutes(routesFolderPath: string) {\n if (!fs.existsSync(routesFolderPath)) return;\n\n const routeFiles = fs.readdirSync(routesFolderPath).filter((f: any) => /\\.(js|ts|jsx|tsx)$/.test(f));\n for (const file of routeFiles) {\n const routeModule = await import(path.join(routesFolderPath, file));\n if (routeModule?.registerRoute) {\n await routeModule.registerRoute();\n }\n }\n}\n\nexport async function loadProviders() {\n const paths = useSettings.getPaths();\n\n const all = [\n { type: 'module', list: getModules(), basePath: paths.modules },\n { type: 'service', list: getServices(), basePath: paths.services },\n ];\n\n for (const { type, list, basePath } of all) {\n for (const item of list) {\n if (!item.enabled) continue;\n\n const metaPath = path.join(path.resolve(basePath), item.lowerName, `${type}.json`);\n const meta = loadJSON(metaPath);\n if (!meta?.providers || !Array.isArray(meta.providers)) continue;\n\n for (const providerRelPath of meta.providers) {\n try {\n let providerAbsPath = path.join(path.resolve(basePath), item.lowerName, providerRelPath);\n\n // Try .js fallback if file is .ts or .tsx\n const ext = path.extname(providerAbsPath);\n if (ext === '.ts' || ext === '.tsx') {\n const jsPath = providerAbsPath.replace(/\\.(ts|tsx)$/, '.js');\n try {\n await fs.accessSync(jsPath); // Check if compiled JS file exists\n providerAbsPath = jsPath;\n } catch {\n throw new Error(`Compiled JS version not found for provider: ${providerRelPath}`);\n }\n }\n\n const providerUrl = toFileUrl(providerAbsPath);\n const providerModule = await import(providerUrl);\n\n if (typeof providerModule.default === 'function') {\n // Expose context so nav registration can auto-tag module/service\n (globalThis as any).__retrex_provider_context__ = {\n type,\n name: item.lowerName,\n };\n await providerModule.default();\n (globalThis as any).__retrex_provider_context__ = undefined;\n console.log(`[${type}] ✅ Provider loaded: ${providerRelPath}`);\n } else {\n console.warn(`[${type}] ⚠️ Provider ${providerRelPath} has no default export.`);\n }\n } catch (err) {\n console.error(`[${type}] ❌ Failed to load provider ${providerRelPath}:`, err);\n }\n }\n }\n }\n}\n\n\n// export async function loadProviders() {\n// paths = {\n// modules: useSettings.getPaths().modules,\n// templates: useSettings.getPaths().templates,\n// services: useSettings.getPaths().services,\n// events: useSettings.getPaths().events,\n// }\n// const all = [\n// { type: 'module', list: getModules(), basePath: useSettings.getPaths().modules },\n// { type: 'service', list: getServices(), basePath: useSettings.getPaths().services },\n// ];\n\n// for (const { type, list, basePath } of all) {\n// for (const item of list) {\n// if (!item.enabled) continue;\n\n// const metaPath = path.join(basePath, item.lowerName, `${type}.json`);\n// const meta = loadJSON(metaPath);\n// if (!meta?.providers || !Array.isArray(meta.providers)) continue;\n\n// for (const providerRelPath of meta.providers) {\n// try {\n// const providerPath = path.join(basePath, item.lowerName, providerRelPath);\n// const providerModule = await import(providerPath);\n// if (typeof providerModule.default === 'function') {\n// await providerModule.default(); // Call provider\n// console.log(`[${type}] Provider loaded: ${providerRelPath}`);\n// } else {\n// console.warn(`[${type}] Provider ${providerRelPath} has no default export.`);\n// }\n// } catch (err) {\n// console.error(`[${type}] Failed to load provider ${providerRelPath}:`, err);\n// }\n// }\n// }\n// }\n// }\n"],"mappings":"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","names":["path","fs","fs","fs","path","fs","mod"]}
|