@mdfriday/foundry
Version:
The core engine of MDFriday. Convert Markdown and shortcodes into fully themed static sites – Hugo-style, powered by TypeScript.
189 lines • 6.85 kB
JavaScript
"use strict";
Object.defineProperty(exports, "__esModule", { value: true });
exports.IncrementalBuildCoordinator = void 0;
const ssg_1 = require("./ssg");
const log_1 = require("../../pkg/log");
const content_file_watcher_1 = require("../../pkg/web/watcher/content-file-watcher");
const server_1 = require("../../pkg/web/server");
const log = (0, log_1.getDomainLogger)('build', { component: 'incremental-coordinator' });
class IncrementalBuildCoordinator {
constructor(config) {
this.config = config;
this.buildInProgress = false;
this.initialized = false;
// 初始化文件监控器
if (config.enableWatching) {
const watcherConfig = {
contentDir: config.contentDir,
projContentDir: config.projContentDir || config.contentDir, // 默认与 contentDir 相同
batchDelay: config.batchDelay || 500
};
this.fileWatcher = new content_file_watcher_1.ContentFileWatcher(watcherConfig);
this.fileWatcher.onFileChange((events) => this.handleFileChanges(events));
}
// 初始化 Live Reload 服务器
if (config.liveReload?.enabled !== false) {
const liveReloadConfig = {
port: config.liveReload?.port || 8091,
host: config.liveReload?.host || 'localhost',
livereloadPort: config.liveReload?.livereloadPort || 35729,
publicDir: config.publicDir,
enableLiveReload: true
};
this.liveReloadServer = (0, server_1.createLiveReloadServer)(liveReloadConfig);
}
}
/**
* 初始化:执行首次完整构建并保存 domain 实例
*/
async initialize() {
if (this.initialized) {
log.warn('IncrementalBuildCoordinator already initialized');
return;
}
await this.performFullBuildAndCacheDomains();
this.initialized = true;
}
/**
* 执行完整构建并缓存 domain 实例
*/
async performFullBuildAndCacheDomains() {
try {
this.domainInstances = await (0, ssg_1.serveSSG)(this.config.projDir, this.config.modulesDir, this.config.markdown, this.config.progressCallback);
}
catch (error) {
log.error('Failed to perform full build and cache domains:', error);
throw error;
}
}
async startWatching() {
if (!this.initialized) {
throw new Error('Must call initialize() before startWatching()');
}
// 启动文件监控
if (this.config.enableWatching && this.fileWatcher) {
await this.fileWatcher.startWatching();
}
// 启动 Live Reload 服务器
if (this.liveReloadServer) {
await this.liveReloadServer.start();
}
}
async stopWatching() {
// 停止文件监控
if (this.fileWatcher) {
await this.fileWatcher.stopWatching();
}
// 停止 Live Reload 服务器
if (this.liveReloadServer) {
await this.liveReloadServer.stop();
}
}
/**
* 处理文件变更事件,触发增量构建
* 阶段3-5:完整的增量构建流程
*/
async handleFileChanges(events) {
if (this.buildInProgress) {
setTimeout(() => this.handleFileChanges(events), 1000);
return;
}
try {
this.buildInProgress = true;
if (this.needFullRebuild(events)) {
await this.performFullRebuild(events);
return;
}
// 执行完整的增量构建流程
await this.performIncrementalBuild(events);
}
finally {
this.buildInProgress = false;
}
}
needFullRebuild(events) {
return events.some(event => event.eventType === 'deleted' || event.eventType === 'created');
}
/**
* 执行增量构建(阶段3-5的核心实现)
*/
async performIncrementalBuild(events) {
if (!this.domainInstances) {
log.error('Domain instances not available, falling back to full rebuild');
await this.performFullRebuild(events);
return;
}
try {
// 阶段3: 从 FS Domain 获取修改文件的 FileMetaInfo
const fileMetaInfos = await this.domainInstances.fs.getFileMetaInfos(this.getEventsFilePaths(events));
// 阶段4: 更新 Content Domain 的 PageMap 并标记 stale 页面
await this.domainInstances.content.handleChangeFiles(fileMetaInfos);
// 阶段5: 在 Site Domain 中执行增量渲染
await this.domainInstances.site.render();
// 通知 Live Reload 客户端刷新
if (this.liveReloadServer) {
const changedPaths = events.map(e => e.filePath);
this.liveReloadServer.notifyReload(changedPaths);
}
}
catch (error) {
log.error('Incremental build failed, falling back to full rebuild:', error);
await this.performFullRebuild(events);
}
}
getEventsFilePaths(events) {
return events.map(event => event.filePath);
}
/**
* 第2阶段的临时实现:执行完整重建并通知 Live Reload
*/
async performFullRebuild(events) {
await (0, ssg_1.processSSGWithProgress)(this.config.projDir, this.config.modulesDir, this.config.markdown, (progress) => {
log.info(`Rebuild progress: ${progress.stage} - ${progress.percentage}%`);
});
// 通知 Live Reload 客户端刷新
if (this.liveReloadServer) {
const changedPaths = events.map(e => e.filePath);
this.liveReloadServer.notifyReload(changedPaths);
}
}
/**
* 获取当前是否已初始化
*/
isInitialized() {
return this.initialized;
}
/**
* 获取是否正在构建
*/
isBuildInProgress() {
return this.buildInProgress;
}
/**
* 获取配置信息
*/
getConfig() {
return { ...this.config };
}
getServerUrl() {
if (this.liveReloadServer) {
return this.liveReloadServer.getUrl();
}
return '';
}
/**
* 获取 Live Reload 服务器状态
*/
getLiveReloadStatus() {
if (!this.liveReloadServer) {
return { running: false };
}
const isRunning = this.liveReloadServer.isServerRunning();
return {
running: isRunning,
...(isRunning && { url: this.liveReloadServer.getUrl() })
};
}
}
exports.IncrementalBuildCoordinator = IncrementalBuildCoordinator;
//# sourceMappingURL=incremental-build-coordinator.js.map