fix: 修复打包后模块无法加载的问题,改用静态模块加载
This commit is contained in:
@@ -1,51 +1,59 @@
|
|||||||
import { readdirSync, statSync } from 'fs'
|
|
||||||
import { join, dirname } from 'path'
|
|
||||||
import { fileURLToPath } from 'url'
|
|
||||||
import type { ApiModule } from '../infra/types.js'
|
import type { ApiModule } from '../infra/types.js'
|
||||||
|
|
||||||
const __filename = fileURLToPath(import.meta.url)
|
|
||||||
const __dirname = dirname(__filename)
|
|
||||||
|
|
||||||
const moduleFactoryPattern = /^create\w+Module$/
|
|
||||||
|
|
||||||
async function discoverModules(): Promise<ApiModule[]> {
|
async function discoverModules(): Promise<ApiModule[]> {
|
||||||
|
return await getStaticModules()
|
||||||
|
}
|
||||||
|
|
||||||
|
async function getStaticModules(): Promise<ApiModule[]> {
|
||||||
const modules: ApiModule[] = []
|
const modules: ApiModule[] = []
|
||||||
const entries = readdirSync(__dirname)
|
|
||||||
|
|
||||||
for (const entry of entries) {
|
try {
|
||||||
const entryPath = join(__dirname, entry)
|
const { createTodoModule } = await import('./todo/index.js')
|
||||||
|
modules.push(createTodoModule())
|
||||||
|
} catch (e) {
|
||||||
|
console.warn('[ModuleLoader] Failed to load todo module:', e)
|
||||||
|
}
|
||||||
|
|
||||||
try {
|
try {
|
||||||
const stats = statSync(entryPath)
|
const { createTimeTrackingModule } = await import('./time-tracking/index.js')
|
||||||
if (!stats.isDirectory()) {
|
modules.push(createTimeTrackingModule())
|
||||||
continue
|
} catch (e) {
|
||||||
}
|
console.warn('[ModuleLoader] Failed to load time-tracking module:', e)
|
||||||
|
}
|
||||||
|
|
||||||
const moduleIndexPath = join(entryPath, 'index.ts')
|
try {
|
||||||
let moduleIndexStats: ReturnType<typeof statSync>
|
const { createRecycleBinModule } = await import('./recycle-bin/index.js')
|
||||||
try {
|
modules.push(createRecycleBinModule())
|
||||||
moduleIndexStats = statSync(moduleIndexPath)
|
} catch (e) {
|
||||||
} catch {
|
console.warn('[ModuleLoader] Failed to load recycle-bin module:', e)
|
||||||
continue
|
}
|
||||||
}
|
|
||||||
if (!moduleIndexStats.isFile()) {
|
|
||||||
continue
|
|
||||||
}
|
|
||||||
|
|
||||||
const moduleExports = await import(`./${entry}/index.js`)
|
try {
|
||||||
|
const { createPyDemosModule } = await import('./pydemos/index.js')
|
||||||
|
modules.push(createPyDemosModule())
|
||||||
|
} catch (e) {
|
||||||
|
console.warn('[ModuleLoader] Failed to load pydemos module:', e)
|
||||||
|
}
|
||||||
|
|
||||||
for (const exportName of Object.keys(moduleExports)) {
|
try {
|
||||||
if (moduleFactoryPattern.test(exportName)) {
|
const { createDocumentParserModule } = await import('./document-parser/index.js')
|
||||||
const factory = moduleExports[exportName]
|
modules.push(createDocumentParserModule())
|
||||||
if (typeof factory === 'function') {
|
} catch (e) {
|
||||||
const module = factory() as ApiModule
|
console.warn('[ModuleLoader] Failed to load document-parser module:', e)
|
||||||
modules.push(module)
|
}
|
||||||
}
|
|
||||||
}
|
try {
|
||||||
}
|
const { createAiModule } = await import('./ai/index.js')
|
||||||
} catch (error) {
|
modules.push(createAiModule())
|
||||||
console.warn(`[ModuleLoader] Failed to load module '${entry}':`, error)
|
} catch (e) {
|
||||||
}
|
console.warn('[ModuleLoader] Failed to load ai module:', e)
|
||||||
|
}
|
||||||
|
|
||||||
|
try {
|
||||||
|
const { createRemoteModule } = await import('./remote/index.js')
|
||||||
|
modules.push(createRemoteModule())
|
||||||
|
} catch (e) {
|
||||||
|
console.warn('[ModuleLoader] Failed to load remote module:', e)
|
||||||
}
|
}
|
||||||
|
|
||||||
modules.sort((a, b) => {
|
modules.sort((a, b) => {
|
||||||
|
|||||||
@@ -1,6 +1,6 @@
|
|||||||
import chokidar, { FSWatcher } from 'chokidar';
|
import chokidar, { FSWatcher } from 'chokidar';
|
||||||
import path from 'path';
|
import path from 'path';
|
||||||
import { NOTEBOOK_ROOT } from '../config/paths.js';
|
import { config } from '../config/index.js';
|
||||||
import { eventBus } from '../events/eventBus.js';
|
import { eventBus } from '../events/eventBus.js';
|
||||||
import { logger } from '../utils/logger.js';
|
import { logger } from '../utils/logger.js';
|
||||||
import { toPosixPath } from '../../shared/utils/path.js';
|
import { toPosixPath } from '../../shared/utils/path.js';
|
||||||
@@ -10,16 +10,17 @@ let watcher: FSWatcher | null = null;
|
|||||||
export const startWatcher = (): void => {
|
export const startWatcher = (): void => {
|
||||||
if (watcher) return;
|
if (watcher) return;
|
||||||
|
|
||||||
logger.info(`Starting file watcher for: ${NOTEBOOK_ROOT}`);
|
const notebookRoot = config.notebookRoot;
|
||||||
|
logger.info(`Starting file watcher for: ${notebookRoot}`);
|
||||||
|
|
||||||
watcher = chokidar.watch(NOTEBOOK_ROOT, {
|
watcher = chokidar.watch(notebookRoot, {
|
||||||
ignored: /(^|[\/\\])\../,
|
ignored: /(^|[\/\\])\../,
|
||||||
persistent: true,
|
persistent: true,
|
||||||
ignoreInitial: true,
|
ignoreInitial: true,
|
||||||
});
|
});
|
||||||
|
|
||||||
const broadcast = (event: string, changedPath: string) => {
|
const broadcast = (event: string, changedPath: string) => {
|
||||||
const rel = path.relative(NOTEBOOK_ROOT, changedPath);
|
const rel = path.relative(notebookRoot, changedPath);
|
||||||
if (!rel || rel.startsWith('..') || path.isAbsolute(rel)) return;
|
if (!rel || rel.startsWith('..') || path.isAbsolute(rel)) return;
|
||||||
logger.info(`File event: ${event} - ${rel}`);
|
logger.info(`File event: ${event} - ${rel}`);
|
||||||
eventBus.broadcast({ event, path: toPosixPath(rel) });
|
eventBus.broadcast({ event, path: toPosixPath(rel) });
|
||||||
|
|||||||
@@ -13,16 +13,6 @@ log.initialize();
|
|||||||
const __filename = fileURLToPath(import.meta.url);
|
const __filename = fileURLToPath(import.meta.url);
|
||||||
const __dirname = path.dirname(__filename);
|
const __dirname = path.dirname(__filename);
|
||||||
|
|
||||||
process.env.NOTEBOOK_ROOT = path.join(app.getPath('documents'), 'XCDesktop');
|
|
||||||
|
|
||||||
if (!fs.existsSync(process.env.NOTEBOOK_ROOT)) {
|
|
||||||
try {
|
|
||||||
fs.mkdirSync(process.env.NOTEBOOK_ROOT, { recursive: true });
|
|
||||||
} catch (err) {
|
|
||||||
log.error('Failed to create notebook directory:', err);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
electronState.setDevelopment(!app.isPackaged);
|
electronState.setDevelopment(!app.isPackaged);
|
||||||
|
|
||||||
let opencodeProcess: ChildProcess | null = null;
|
let opencodeProcess: ChildProcess | null = null;
|
||||||
@@ -443,6 +433,16 @@ async function startServer() {
|
|||||||
}
|
}
|
||||||
|
|
||||||
app.whenReady().then(async () => {
|
app.whenReady().then(async () => {
|
||||||
|
process.env.NOTEBOOK_ROOT = path.join(app.getPath('documents'), 'XCDesktop');
|
||||||
|
|
||||||
|
if (!fs.existsSync(process.env.NOTEBOOK_ROOT)) {
|
||||||
|
try {
|
||||||
|
fs.mkdirSync(process.env.NOTEBOOK_ROOT, { recursive: true });
|
||||||
|
} catch (err) {
|
||||||
|
log.error('Failed to create notebook directory:', err);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
await startServer();
|
await startServer();
|
||||||
await createWindow();
|
await createWindow();
|
||||||
|
|
||||||
|
|||||||
@@ -35,7 +35,7 @@
|
|||||||
"watch:electron": "tsup --config tsup.electron.ts --watch",
|
"watch:electron": "tsup --config tsup.electron.ts --watch",
|
||||||
"electron:dev": "concurrently -k \"npm run server:dev\" \"npm run client:dev\" \"wait-on tcp:3001 tcp:5173 && npm run watch:electron\"",
|
"electron:dev": "concurrently -k \"npm run server:dev\" \"npm run client:dev\" \"wait-on tcp:3001 tcp:5173 && npm run watch:electron\"",
|
||||||
"build:electron": "tsup --config tsup.electron.ts",
|
"build:electron": "tsup --config tsup.electron.ts",
|
||||||
"build:api": "tsup electron/server.ts --format esm --out-dir dist-api --clean --no-splitting --target esnext",
|
"build:api": "tsup electron/server.ts --format esm --out-dir dist-api --clean --target esnext --external electron",
|
||||||
"electron:build": "npm run build && npm run build:electron && npm run build:api && electron-builder"
|
"electron:build": "npm run build && npm run build:electron && npm run build:api && electron-builder"
|
||||||
},
|
},
|
||||||
"dependencies": {
|
"dependencies": {
|
||||||
|
|||||||
Reference in New Issue
Block a user