diff --git a/server/src/lib/modules/routes/devMode.ts b/server/src/lib/modules/routes/devMode.ts index 44092d3c8..21d82f485 100644 --- a/server/src/lib/modules/routes/devMode.ts +++ b/server/src/lib/modules/routes/devMode.ts @@ -25,5 +25,5 @@ export const toggle = forge devModeFile.write(JSON.stringify(modules)) - return { success: true, isDevMode: index === -1 } + return true }) diff --git a/server/src/lib/modules/routes/modules.ts b/server/src/lib/modules/routes/modules.ts index 67aeb2634..83b1e4f07 100644 --- a/server/src/lib/modules/routes/modules.ts +++ b/server/src/lib/modules/routes/modules.ts @@ -4,25 +4,13 @@ import fs from 'fs' import path from 'path' import z from 'zod' -import { checkModulesAvailability as cma } from '@functions/utils/checkModulesAvailability' - import forge from '../forge' import scanFederatedModules, { - ModuleManifestEntry + type ModuleManifestEntry } from '../utils/scanFederatedModules' const APPS_DIR = path.join(ROOT_DIR, 'apps') -export const checkModuleAvailability = forge - .query() - .description('Check if a module is available') - .input({ - query: z.object({ - moduleId: z.string().min(1) - }) - }) - .callback(async ({ query: { moduleId } }) => cma(moduleId)) - export const manifest = forge .query() .description('Get installed modules manifest for runtime loading') @@ -51,8 +39,9 @@ export interface InstalledModule { icon: string category: string isInternal: boolean - isDevMode?: boolean - hasClientDist: boolean + isDevMode: boolean + hasDist: boolean + hasSource: boolean } export const list = forge @@ -92,7 +81,17 @@ export const list = forge 'remoteEntry.js' ) - const hasClientDist = fs.existsSync(clientDistPath) + const hasDist = fs.existsSync(clientDistPath) + + const hasSource = fs.existsSync( + path.join(APPS_DIR, dir.name, 'client/src') + ) + + if ( + !(hasSource || hasDist) || + (process.env.NODE_ENV === 'production' && !hasDist) + ) + continue modules.push({ name: pkg.name, @@ -103,15 +102,21 @@ export const list = forge icon: pkg.lifeforge?.icon || 'tabler:package', category: pkg.lifeforge?.category || 'Miscellaneous', isInternal: false, - isDevMode: devModeModules.includes(pkg.name), - hasClientDist + isDevMode: (() => { + if (!hasSource) return false + if (!hasDist) return true + + return devModeModules.includes(pkg.name) + })(), + hasDist, + hasSource }) } catch { // Skip invalid packages } } - return { modules } + return modules }) export const uninstall = forge diff --git a/server/src/lib/modules/utils/scanFederatedModules.ts b/server/src/lib/modules/utils/scanFederatedModules.ts index 2ad495da7..ffd9b344b 100644 --- a/server/src/lib/modules/utils/scanFederatedModules.ts +++ b/server/src/lib/modules/utils/scanFederatedModules.ts @@ -36,10 +36,6 @@ export default function scanFederatedModules( .filter(d => d.isDirectory() && !d.name.startsWith('.')) for (const dir of dirs) { - const isDevMode = - process.env.NODE_ENV !== 'production' && - devModeModules?.includes(`@lifeforge/${dir.name}`) - const pkgPath = path.join(baseDir, dir.name, 'package.json') if (!fs.existsSync(pkgPath)) continue @@ -63,7 +59,26 @@ export default function scanFederatedModules( 'remoteEntry.js' ) - if (!fs.existsSync(remoteEntryPath) && !isDevMode) continue + const hasDist = fs.existsSync(remoteEntryPath) + + const hasSource = fs.existsSync( + path.join(baseDir, dir.name, 'client/src') + ) + + if ( + !(hasDist || hasSource) || + (process.env.NODE_ENV === 'production' && !hasDist) + ) + continue + + const isDevMode = (() => { + if (process.env.NODE_ENV === 'production') return false + + if (!hasDist) return true + if (!hasSource) return false + + return devModeModules?.includes(`@lifeforge/${dir.name}`) + })() modules.push({ name: dir.name,