refactor(server): improve dev mode handling and module listing logic

This commit is contained in:
melvinchia3636
2026-01-28 10:06:59 +08:00
parent eb0b6de118
commit 5f8aa2d5ff
3 changed files with 45 additions and 25 deletions

View File

@@ -25,5 +25,5 @@ export const toggle = forge
devModeFile.write(JSON.stringify(modules))
return { success: true, isDevMode: index === -1 }
return true
})

View File

@@ -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

View File

@@ -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,