UNPKG

templui-mcp-server

Version:

A Model Context Protocol (MCP) server for TemplUI components, providing AI assistants with access to component source code, documentation, demos, and metadata.

148 lines 6.3 kB
import { cache } from './cache.js'; import { logInfo, logError } from './logger.js'; export class Updater { githubClient; CACHE_KEY = 'repository-info'; UPDATE_CHECK_TTL = 3600; // 1 hour constructor(githubClient) { this.githubClient = githubClient; } async checkForUpdates() { try { logInfo('Checking for TemplUI repository updates...'); // Get cached repository info const cachedInfo = await cache.get(this.CACHE_KEY); // Get latest repository info from GitHub const latestInfo = await this.getRepositoryInfo(); if (!cachedInfo) { // First time check - cache the current state await cache.set(this.CACHE_KEY, latestInfo, this.UPDATE_CHECK_TTL); return { hasUpdates: false, latestCommit: latestInfo.latestCommit, message: 'Repository info cached for future update checks' }; } const hasUpdates = cachedInfo.latestCommit !== latestInfo.latestCommit; if (hasUpdates) { logInfo(`Updates detected: ${cachedInfo.latestCommit.slice(0, 7)} -> ${latestInfo.latestCommit.slice(0, 7)}`); return { hasUpdates: true, currentCommit: cachedInfo.latestCommit, latestCommit: latestInfo.latestCommit, message: `New updates available in TemplUI repository. Components may have changed since last cache.` }; } return { hasUpdates: false, currentCommit: cachedInfo.latestCommit, latestCommit: latestInfo.latestCommit, message: 'Repository is up to date' }; } catch (error) { logError('Failed to check for updates', error); return { hasUpdates: false, message: `Update check failed: ${error instanceof Error ? error.message : String(error)}` }; } } async updateRepositoryInfo() { try { logInfo('Updating repository information...'); const latestInfo = await this.getRepositoryInfo(); await cache.set(this.CACHE_KEY, latestInfo, this.UPDATE_CHECK_TTL); logInfo(`Repository info updated - Commit: ${latestInfo.latestCommit.slice(0, 7)}, Components: ${latestInfo.componentsCount}`); } catch (error) { logError('Failed to update repository info', error); throw error; } } async clearCache() { try { logInfo('Clearing all cached data...'); await cache.clear(); logInfo('Cache cleared successfully'); } catch (error) { logError('Failed to clear cache', error); throw error; } } async invalidateComponentCache() { try { logInfo('Invalidating component cache...'); // Get all cache keys and remove component-related ones const keysToDelete = [ 'list-components:all', 'list-components:form', 'list-components:layout', 'list-components:navigation', 'list-components:overlay', 'list-components:feedback', 'list-components:display' ]; // Also remove individual component caches const componentNames = [ 'button', 'input', 'textarea', 'checkbox', 'radio', 'selectbox', 'datepicker', 'timepicker', 'inputotp', 'tagsinput', 'form', 'label', 'toggle', 'rating', 'slider', 'card', 'separator', 'aspectratio', 'accordion', 'table', 'breadcrumb', 'pagination', 'tabs', 'modal', 'drawer', 'dropdown', 'popover', 'tooltip', 'alert', 'toast', 'progress', 'skeleton', 'avatar', 'badge', 'icon', 'code', 'chart', 'carousel' ]; for (const name of componentNames) { keysToDelete.push(`component-source:${name}`, `component-demo:${name}`, `component-docs:${name}`, `component-javascript:${name}`, `component-metadata:${name}`); } // Delete all component-related cache entries for (const key of keysToDelete) { await cache.delete(key); } logInfo(`Invalidated cache for ${keysToDelete.length} entries`); } catch (error) { logError('Failed to invalidate component cache', error); throw error; } } async getRepositoryInfo() { try { // Get latest commit from main branch const latestCommit = await this.githubClient.getLatestCommit(); // Get components list to count them const components = await this.githubClient.getComponentsFromRepository(); return { latestCommit: latestCommit.sha, lastModified: latestCommit.date, componentsCount: components.length }; } catch (error) { logError('Failed to get repository info', error); throw error; } } async getUpdateStatus() { try { const result = await this.checkForUpdates(); const cachedInfo = await cache.get(this.CACHE_KEY); let status = `TemplUI Repository Status:\n`; status += `- ${result.message}\n`; if (cachedInfo) { status += `- Last checked: ${new Date(cachedInfo.lastModified).toLocaleString()}\n`; status += `- Components available: ${cachedInfo.componentsCount}\n`; status += `- Current commit: ${cachedInfo.latestCommit.slice(0, 7)}\n`; } if (result.hasUpdates) { status += `\nRecommendation: Run with --clear-cache to refresh component data`; } return status; } catch (error) { return `Failed to get update status: ${error instanceof Error ? error.message : String(error)}`; } } } //# sourceMappingURL=updater.js.map