(function(){ 'use strict'; if (window.__mnoteLocalFolderEventBus) { return; } var connections = new Map(); var sidebarRefreshQueues = new Map(); var fileChangeQueues = new Map(); var lastSource = ''; var lastReason = ''; var lastFileChangeDiagnostics = { source: '', changedCount: 0, droppedCount: 0, lastReaction: '', lastBatchSchema: '' }; function root() { return document.documentElement; } function setDiagnostics(source, reason) { lastSource = source || lastSource || ''; lastReason = reason || lastReason || ''; root().setAttribute('data-mnote-local-folder-event-bus', 'ready'); root().setAttribute('data-mnote-local-folder-event-bus-connections', String(connections.size)); root().setAttribute('data-mnote-local-folder-event-bus-last-source', lastSource); root().setAttribute('data-mnote-local-folder-event-bus-last-reason', lastReason); root().setAttribute('data-mnote-file-change-service', 'ready'); root().setAttribute('data-mnote-file-change-service-last-source', lastFileChangeDiagnostics.source || lastSource); root().setAttribute('data-mnote-file-change-service-last-count', String(lastFileChangeDiagnostics.changedCount || 0)); root().setAttribute('data-mnote-file-change-service-dropped-count', String(lastFileChangeDiagnostics.droppedCount || 0)); root().setAttribute('data-mnote-file-change-service-last-reaction', lastFileChangeDiagnostics.lastReaction || ''); } function normalizeRootUri(rootUri) { return String(rootUri || '').trim(); } function normalizeWorkspaceId(workspaceId) { return String(workspaceId || 'default').trim() || 'default'; } function emit(name, detail) { window.dispatchEvent(new CustomEvent(name, { detail: detail || {} })); } function parseEventPayload(event) { try { return JSON.parse((event && event.data) || '{}') || {}; } catch (_) { return {}; } } function revisionOf(payload, event) { return payload.revision || payload.cursor || (event && event.lastEventId) || null; } function arrayOf(value) { if (!value) return []; if (Array.isArray(value)) return value.filter(Boolean).map(String); return [String(value)].filter(Boolean); } function safeNow() { return Date.now ? Date.now() : new Date().getTime(); } function decodeFileUriPath(rootUri) { var value = String(rootUri || '').trim(); if (!value) return ''; try { var url = new URL(value); if (url.protocol !== 'file:') return ''; return decodeURIComponent(url.pathname || '').replace(/\/+$/, ''); } catch (_) { return ''; } } function normalizeSlashes(value) { return String(value || '').trim().replace(/\\/g, '/'); } function rootRelativePath(rawPath, rootUri) { var value = normalizeSlashes(rawPath).replace(/^file:\/\//, ''); if (!value) return ''; if (/^[A-Za-z]:\//.test(value) || value.charAt(0) === '/') { var rootPath = normalizeSlashes(decodeFileUriPath(rootUri)); if (rootPath && (value === rootPath || value.indexOf(rootPath + '/') === 0)) { return value.slice(rootPath.length).replace(/^\/+/, ''); } return ''; } return value.replace(/^\/+/, ''); } function localMarkdownDocumentId(relativePath) { var normalized = normalizeSlashes(relativePath).replace(/^\/+/, ''); if (!/\.md(?:own)?$/i.test(normalized)) return ''; return 'local-md:' + normalized.replace(/\//g, '~2F'); } function normalizeChangeType(item, fallback) { var raw = String( (item && (item.changeType || item.change_type || item.eventKind || item.event_kind || item.kind)) || fallback || 'modified' ).trim(); if (/remove|delete/i.test(raw)) return 'deleted'; if (/create/i.test(raw)) return 'created'; if (/rename|name/i.test(raw)) return 'renamed'; return 'modified'; } function resourceKindForPath(relativePath) { return /\.md(?:own)?$/i.test(String(relativePath || '')) ? 'markdown' : 'resource'; } function normalizeFileChangeItem(item, context) { var source = String((context && context.source) || (item && item.source) || 'watcher').trim() || 'watcher'; var rootUri = normalizeRootUri((context && context.rootUri) || (item && item.rootUri)); var workspaceId = normalizeWorkspaceId((context && context.workspaceId) || (item && item.workspaceId)); var rawPath = typeof item === 'string' ? item : String(item && ( item.relativePath || item.relative_path || item.path || item.sourcePath || item.source_path || item.filePath || item.file_path ) || ''); var relativePath = rootRelativePath(rawPath, rootUri); if (!relativePath) { return { dropped: true, reason: 'outside_root_or_empty_path', rawPath: rawPath }; } var eventKind = String(item && (item.eventKind || item.event_kind || item.kind || item.changeType || item.change_type) || '').trim(); var documentId = String(item && (item.documentId || item.document_id) || '').trim() || localMarkdownDocumentId(relativePath); var observedFileVersion = String(item && (item.observedFileVersion || item.observed_file_version || '') || '').trim(); var bufferFileVersion = String(item && (item.bufferFileVersion || item.buffer_file_version || '') || '').trim(); var fileVersion = String(item && (item.fileVersion || item.file_version || '') || '').trim() || observedFileVersion || bufferFileVersion || String(item && item.revision || (context && context.revision) || '').trim(); return { schema: 'mnote.file_change.v1', rootUri: rootUri, workspaceId: workspaceId, relativePath: relativePath, documentId: documentId, resourceKind: String(item && (item.resourceKind || item.resource_kind) || resourceKindForPath(relativePath)), changeType: normalizeChangeType(item, eventKind), eventKind: eventKind, fileVersion: fileVersion, source: source, selfWriteEcho: Boolean(item && (item.selfWriteEcho || item.self_write_echo)), observedFileVersion: observedFileVersion, bufferFileVersion: bufferFileVersion, lastWriteIntentId: String(item && (item.lastWriteIntentId || item.last_write_intent_id || '') || '').trim(), lastSaveOperationId: String(item && (item.lastSaveOperationId || item.last_save_operation_id || '') || '').trim(), createdAt: Number(item && (item.createdAt || item.created_at) || safeNow()) }; } function standardBatchToCompatPayload(batch) { return { schema: 'mnote.local_folder.watch_batch.v1', kind: 'watch_batch', sourceKind: 'local_folder', source: batch.source, rootUri: batch.rootUri, workspaceId: batch.workspaceId, revision: batch.revision, changedPaths: batch.changes.map(function(change) { return { relativePath: change.relativePath, documentId: change.documentId, kind: change.eventKind || change.changeType, eventKind: change.eventKind || change.changeType, changeType: change.changeType, revision: change.fileVersion || batch.revision, fileVersion: change.fileVersion, observedFileVersion: change.observedFileVersion, bufferFileVersion: change.bufferFileVersion, lastWriteIntentId: change.lastWriteIntentId, lastSaveOperationId: change.lastSaveOperationId, selfWriteEcho: change.selfWriteEcho, source: change.source }; }), affectedParents: batch.affectedParents, eventKinds: Array.from(new Set(batch.changes.map(function(change) { return change.eventKind || change.changeType || ''; }).filter(Boolean))), fallbackResync: batch.resyncRequired === true }; } function normalizeFileChangeBatch(entry, event, payload, meta) { var revision = revisionOf(payload, event); var source = String((meta && meta.source) || payload.source || payload.sourceKind || 'watcher_sse').trim() || 'watcher_sse'; var reason = String((meta && meta.reason) || payload.reason || 'watch_batch').trim() || 'watch_batch'; var rootUri = normalizeRootUri((entry && entry.rootUri) || payload.rootUri); var workspaceId = normalizeWorkspaceId((entry && entry.workspaceId) || payload.workspaceId); var raw = [] .concat(Array.isArray(payload.changedPaths) ? payload.changedPaths : []) .concat(Array.isArray(payload.changed_paths) ? payload.changed_paths : []) .concat(Array.isArray(payload.paths) ? payload.paths : []) .concat(Array.isArray(payload.events) ? payload.events : []); if (!raw.length && payload.relativePath) raw.push(payload); var dropped = []; var changes = []; raw.forEach(function(item) { var normalized = normalizeFileChangeItem(item, { source: source, rootUri: rootUri, workspaceId: workspaceId, revision: revision }); if (normalized && normalized.dropped) { dropped.push(normalized); } else if (normalized) { changes.push(normalized); } }); var affectedParents = collectAffectedParents(payload).map(function(parent) { return { relativePath: parent, reason: reason }; }); changes.forEach(function(change) { var parent = change.relativePath.indexOf('/') >= 0 ? change.relativePath.split('/').slice(0, -1).join('/') : ''; if (!affectedParents.some(function(item) { return item.relativePath === parent; })) { affectedParents.push({ relativePath: parent, reason: reason }); } }); return { schema: 'mnote.file_change_batch.v1', rootUri: rootUri, workspaceId: workspaceId, source: source, reason: reason, changes: changes, affectedParents: affectedParents, revision: revision, dropped: dropped, resyncRequired: payload.fallbackResync === true || payload.requiresResync === true || payload.resyncRequired === true || payload.resync_required === true, rawPayload: payload, bootstrap: entry && entry.bootstrap || null }; } function mergeFileChange(existing, change) { if (!existing) return change; return Object.assign({}, existing, change, { source: change.source || existing.source, selfWriteEcho: change.selfWriteEcho === true ? true : (change.selfWriteEcho === false ? false : existing.selfWriteEcho), observedFileVersion: change.observedFileVersion || existing.observedFileVersion, bufferFileVersion: change.bufferFileVersion || existing.bufferFileVersion, fileVersion: change.fileVersion || existing.fileVersion, createdAt: Math.max(Number(existing.createdAt || 0), Number(change.createdAt || 0)) }); } function fileChangeQueueKey(batch) { return [batch.rootUri || '', batch.workspaceId || 'default'].join('#'); } function enqueueFileChangeBatch(batch) { if (!batch || !batch.rootUri) return; var key = fileChangeQueueKey(batch); var queue = fileChangeQueues.get(key); if (!queue) { queue = { rootUri: batch.rootUri, workspaceId: batch.workspaceId, sources: new Set(), reasons: new Set(), revisions: new Set(), changes: new Map(), affectedParents: new Map(), dropped: [], resyncRequired: false, bootstrap: batch.bootstrap || null, timer: 0 }; fileChangeQueues.set(key, queue); } if (batch.source) queue.sources.add(batch.source); if (batch.reason) queue.reasons.add(batch.reason); if (batch.revision) queue.revisions.add(String(batch.revision)); queue.dropped = queue.dropped.concat(batch.dropped || []); queue.resyncRequired = queue.resyncRequired || batch.resyncRequired === true; (batch.changes || []).forEach(function(change) { var changeKey = [change.rootUri || batch.rootUri, change.relativePath, change.fileVersion || ''].join('#'); queue.changes.set(changeKey, mergeFileChange(queue.changes.get(changeKey), change)); }); (batch.affectedParents || []).forEach(function(parent) { var relativePath = String(parent && parent.relativePath || parent || ''); queue.affectedParents.set(relativePath, { relativePath: relativePath, reason: String(parent && parent.reason || batch.reason || 'file-change') }); }); if (!queue.timer) { queue.timer = window.setTimeout(function() { flushFileChangeQueue(key); }, 80); } } function currentDocumentSessionState(change) { var snapshot = null; try { snapshot = window.__mnoteDebugDocumentSessions && window.__mnoteDebugDocumentSessions.snapshot && window.__mnoteDebugDocumentSessions.snapshot(); } catch (_) { snapshot = null; } root().setAttribute('data-mnote-file-change-service-session-api', snapshot ? 'available' : 'unavailable'); var sessions = Array.isArray(snapshot && snapshot.sessions) ? snapshot.sessions : []; return sessions.find(function(session) { if (!session || session.sourceKind !== 'local_folder') return false; if (change.rootUri && session.rootUri && change.rootUri !== session.rootUri) return false; if (change.documentId && session.documentId === change.documentId) return true; return false; }) || null; } function reactionTypeForChange(change) { if (change.selfWriteEcho) return 'ignore_self_write_echo'; if (change.resourceKind !== 'markdown') return 'refresh_resource_tab'; var session = currentDocumentSessionState(change); if (session && /dirty|external/i.test(String(session.dirtyState || session.status || ''))) { return 'external_conflict_current_document'; } if (session) return 'refresh_current_document'; if (change.changeType === 'created' || change.changeType === 'deleted' || change.changeType === 'renamed') { return 'refresh_page_tree_projection'; } return 'refresh_filetree_parents'; } function emitFileChangeReactions(detail) { var reactionTypes = new Set(); (detail.fileChangeBatch.changes || []).forEach(function(change) { var type = reactionTypeForChange(change); reactionTypes.add(type); emit('mnote:file-change-reaction', { schema: 'mnote.file_change_reaction.v1', type: type, rootUri: detail.rootUri, workspaceId: detail.workspaceId, source: detail.source, change: change, batch: detail.fileChangeBatch }); }); if (detail.affectedParents && detail.affectedParents.length) { reactionTypes.add('refresh_filetree_parents'); } lastFileChangeDiagnostics.lastReaction = Array.from(reactionTypes).join(',') || ''; root().setAttribute('data-mnote-file-change-service-last-reaction', lastFileChangeDiagnostics.lastReaction); return reactionTypes; } function flushFileChangeQueue(key) { var queue = fileChangeQueues.get(key); if (!queue) return; fileChangeQueues.delete(key); var sources = Array.from(queue.sources); var reasons = Array.from(queue.reasons); var revision = Array.from(queue.revisions).pop() || null; var batch = { schema: 'mnote.file_change_batch.v1', rootUri: queue.rootUri, workspaceId: queue.workspaceId, source: sources.join(',') || 'watcher', reason: reasons.join(',') || 'watch_batch', changes: Array.from(queue.changes.values()), affectedParents: Array.from(queue.affectedParents.values()), revision: revision, dropped: queue.dropped, resyncRequired: queue.resyncRequired }; var compatPayload = standardBatchToCompatPayload(batch); var detail = { schema: 'mnote.local_folder.event_bus.watch_batch.v1', source: batch.source, reason: batch.reason, rootUri: batch.rootUri, workspaceId: batch.workspaceId, revision: batch.revision, payload: compatPayload, bootstrap: queue.bootstrap || null, changedPaths: compatPayload.changedPaths, affectedParents: batch.affectedParents, fileChangeBatch: batch, resyncRequired: batch.resyncRequired, viaEventBus: true }; lastFileChangeDiagnostics = { source: batch.source, changedCount: batch.changes.length, droppedCount: batch.dropped.length, lastReaction: '', lastBatchSchema: batch.schema }; setDiagnostics(batch.source, batch.reason); root().setAttribute('data-mnote-tree-live-revision', String(batch.revision || '')); root().setAttribute('data-mnote-file-change-service-last-schema', batch.schema); emit('mnote:file-change-batch', batch); emit('mnote:local-folder:watch-batch', detail); emit('tree:local-folder-watch-batch', detail); var reactionTypes = emitFileChangeReactions(detail); if (batch.affectedParents.length > 0 || reactionTypes.has('refresh_filetree_parents')) { emit('mnote:local-folder:filetree-parent-changed', detail); } if (batch.changes.length > 0) { emit('mnote:local-folder:document-changed', detail); emit('mnote:local-folder:resource-changed', detail); emit('mnote:local-folder:knowledge-rag-source-updated', detail); } queueSidebarRefresh(detail); if (batch.resyncRequired) { emit('mnote:local-folder:resync-required', detail); } } function pathArrayOf(value) { if (!value) return []; var list = Array.isArray(value) ? value : [value]; return list.map(function(item) { if (typeof item === 'string') return item.trim(); if (!item || typeof item !== 'object') return ''; return String(item.relativePath || item.relative_path || item.path || item.sourcePath || item.source_path || '').trim(); }).filter(Boolean); } function collectChangedPaths(payload) { var paths = [] .concat(pathArrayOf(payload.changedPaths)) .concat(pathArrayOf(payload.changed_paths)) .concat(pathArrayOf(payload.paths)); var events = Array.isArray(payload.events) ? payload.events : []; events.forEach(function(item) { if (!item || typeof item !== 'object') return; paths = paths .concat(arrayOf(item.path)) .concat(arrayOf(item.relativePath)) .concat(arrayOf(item.relative_path)) .concat(arrayOf(item.sourcePath)) .concat(arrayOf(item.source_path)); }); return Array.from(new Set(paths)); } function collectChangedPathItems(payload, reason) { var raw = [] .concat(Array.isArray(payload.changedPaths) ? payload.changedPaths : []) .concat(Array.isArray(payload.changed_paths) ? payload.changed_paths : []) .concat(Array.isArray(payload.paths) ? payload.paths : []) .concat(Array.isArray(payload.events) ? payload.events : []); var seen = new Set(); var items = []; raw.forEach(function(item) { var relativePath = typeof item === 'string' ? item.trim() : String(item && (item.relativePath || item.relative_path || item.path || item.sourcePath || item.source_path || '') || '').trim(); if (!relativePath || seen.has(relativePath)) return; seen.add(relativePath); items.push({ relativePath: relativePath, reason: reason || 'event-bus', kind: typeof item === 'object' && item ? String(item.kind || '') : '', eventKind: typeof item === 'object' && item ? String(item.eventKind || item.event_kind || item.changeType || item.change_type || '') : '' }); }); if (items.length) return items; return pathItems(collectChangedPaths(payload), reason); } function collectAffectedParents(payload) { var parents = [] .concat(pathArrayOf(payload.affectedParents)) .concat(pathArrayOf(payload.affected_parents)) .concat(pathArrayOf(payload.parentRelativePaths)) .concat(pathArrayOf(payload.parent_relative_paths)); return Array.from(new Set(parents)); } function pathItems(paths, reason) { return (paths || []).map(function(relativePath) { return { relativePath: String(relativePath || '').trim(), reason: reason || 'event-bus' }; }).filter(function(item) { return item.relativePath || item.relativePath === ''; }); } function queueSidebarRefresh(detail) { var key = String(detail.rootUri || '').trim(); if (!key) return; var queue = sidebarRefreshQueues.get(key); if (!queue) { queue = { rootUri: detail.rootUri, workspaceId: detail.workspaceId, revisions: new Set(), reasons: new Set(), changedPaths: new Map(), affectedParents: new Set(), resyncRequired: false, timer: 0 }; sidebarRefreshQueues.set(key, queue); } if (detail.revision) queue.revisions.add(String(detail.revision)); if (detail.reason) queue.reasons.add(String(detail.reason)); (detail.changedPaths || []).forEach(function(item) { var path = typeof item === 'string' ? item : String(item && (item.relativePath || item.relative_path || '') || ''); if (!path && path !== '') return; var existing = queue.changedPaths.get(path) || { relativePath: path }; queue.changedPaths.set(path, { relativePath: path, reason: String((item && item.reason) || existing.reason || detail.reason || 'event-bus-orchestrated'), kind: String((item && item.kind) || existing.kind || ''), eventKind: String((item && item.eventKind) || (item && item.event_kind) || existing.eventKind || '') }); }); (detail.affectedParents || []).forEach(function(item) { var parent = typeof item === 'string' ? item : String(item && (item.relativePath || item.relative_path || '') || ''); if (parent || parent === '') queue.affectedParents.add(parent); }); queue.resyncRequired = queue.resyncRequired || detail.resyncRequired === true; if (!queue.timer) { queue.timer = window.setTimeout(function() { flushSidebarRefresh(key); }, 0); } root().setAttribute('data-mnote-local-folder-event-bus-sidebar-refresh-pending', String(queue.affectedParents.size)); } function flushSidebarRefresh(key) { var queue = sidebarRefreshQueues.get(key); if (!queue) return; sidebarRefreshQueues.delete(key); var reasons = Array.from(queue.reasons); var detail = { schema: 'mnote.local_folder.event_bus.sidebar_refresh.v1', source: 'event_bus_orchestrator', reason: reasons.join(',') || 'watch_batch', rootUri: queue.rootUri, workspaceId: queue.workspaceId, revision: Array.from(queue.revisions).pop() || null, reasons: reasons, changedPaths: Array.from(queue.changedPaths.values()), affectedParents: pathItems(Array.from(queue.affectedParents), 'event-bus-orchestrated'), resyncRequired: queue.resyncRequired, viaEventBus: true }; root().setAttribute('data-mnote-local-folder-event-bus-sidebar-refresh-applied', detail.reason); root().setAttribute('data-mnote-local-folder-event-bus-sidebar-refresh-parents', String(detail.affectedParents.length)); emit('mnote:local-folder:sidebar-refresh-requested', detail); } function dispatchWatchBatch(entry, event, payload, meta) { enqueueFileChangeBatch(normalizeFileChangeBatch(entry, event, payload, meta)); } function closeEntry(entry) { if (!entry || !entry.source || typeof entry.source.close !== 'function') return; entry.source.close(); } function startLocalFolderWatcher(options) { var rootUri = normalizeRootUri(options && options.rootUri); if (!rootUri || typeof window.EventSource !== 'function') return null; var workspaceId = normalizeWorkspaceId(options && options.workspaceId); var key = rootUri; if (connections.has(key)) { var existing = connections.get(key); if ((!existing.workspaceId || existing.workspaceId === 'default') && workspaceId && workspaceId !== 'default') { existing.workspaceId = workspaceId; if (existing.handle) existing.handle.workspaceId = workspaceId; } setDiagnostics(existing.lastSource || 'watcher_sse', 'reuse_connection'); return existing.handle; } var url = new URL('/api/local-folder/events', window.location.origin); url.searchParams.set('rootUri', rootUri); url.searchParams.set('treeLive', 'true'); var eventSource = new EventSource(url.toString()); var entry = { key: key, rootUri: rootUri, workspaceId: workspaceId, bootstrap: (options && options.bootstrap) || null, source: eventSource, lastSource: 'watcher_sse', close: function() { connections.delete(key); closeEntry(entry); setDiagnostics('watcher_sse', 'closed'); } }; entry.handle = { key: key, rootUri: rootUri, workspaceId: workspaceId, source: eventSource, close: entry.close }; connections.set(key, entry); setDiagnostics('watcher_sse', 'connect'); emit('mnote:local-folder:event-bus-ready', { schema: 'mnote.local_folder.event_bus.ready.v1', source: 'watcher_sse', reason: 'connect', rootUri: rootUri, workspaceId: workspaceId, connections: connections.size }); eventSource.addEventListener('open', function() { setDiagnostics('watcher_sse', 'open'); }); eventSource.addEventListener('watch_batch', function(event) { dispatchWatchBatch(entry, event, parseEventPayload(event), { source: 'watcher_sse', reason: 'watch_batch' }); }); eventSource.addEventListener('tree_error', function(event) { var payload = parseEventPayload(event); setDiagnostics('watcher_sse', 'tree_error'); emit('tree:error', { payload: payload, bootstrap: entry.bootstrap || null, viaEventBus: true }); }); eventSource.onerror = function() { setDiagnostics('watcher_sse', 'error'); }; return entry.handle; } function emitSyntheticWatchBatch(detail) { var payload = detail && detail.payload ? detail.payload : (detail || {}); var rootUri = normalizeRootUri(detail && detail.rootUri); var workspaceId = normalizeWorkspaceId(detail && detail.workspaceId); var entry = { rootUri: rootUri, workspaceId: workspaceId, bootstrap: (detail && detail.bootstrap) || null }; dispatchWatchBatch(entry, { lastEventId: detail && detail.revision }, payload, { source: (detail && detail.source) || 'synthetic', reason: (detail && detail.reason) || payload.source || 'synthetic_watch_batch' }); } function emitChangedFiles(detail) { var payload = detail && detail.payload && typeof detail.payload === 'object' ? detail.payload : {}; var changedFiles = [] .concat(Array.isArray(detail && detail.changedFiles) ? detail.changedFiles : []) .concat(Array.isArray(payload.changedFiles) ? payload.changedFiles : []) .concat(Array.isArray(payload.changed_files) ? payload.changed_files : []); if (!changedFiles.length) return; var rootUri = normalizeRootUri((detail && detail.rootUri) || payload.rootUri); var workspaceId = normalizeWorkspaceId((detail && detail.workspaceId) || payload.workspaceId); emitSyntheticWatchBatch({ source: (detail && detail.source) || payload.source || 'changed_files_adapter', reason: (detail && detail.reason) || payload.reason || 'changed_files_adapter', rootUri: rootUri, workspaceId: workspaceId, payload: { schema: 'mnote.local_folder.watch_batch.v1', source: (detail && detail.source) || payload.source || 'changed_files_adapter', rootUri: rootUri, workspaceId: workspaceId, revision: (detail && detail.revision) || payload.revision || null, changedPaths: changedFiles, affectedParents: Array.isArray(detail && detail.affectedParents) ? detail.affectedParents : [] } }); } function closeAll() { Array.from(connections.values()).forEach(function(entry) { closeEntry(entry); }); connections.clear(); setDiagnostics('watcher_sse', 'closed'); } window.__mnoteLocalFolderEventBus = { startLocalFolderWatcher: startLocalFolderWatcher, emitSyntheticWatchBatch: emitSyntheticWatchBatch, emitChangedFiles: emitChangedFiles, closeAll: closeAll, flushSidebarRefresh: function(rootUri) { flushSidebarRefresh(normalizeRootUri(rootUri)); }, connectionCount: function() { return connections.size; }, diagnostics: function() { return { connections: connections.size, lastSource: lastSource, lastReason: lastReason, fileChange: Object.assign({}, lastFileChangeDiagnostics) }; } }; setDiagnostics('', 'ready'); })();