leshi-ui
Version:
Modern CLI for building and managing React Native UI components with copy-paste simplicity, custom theming, and open source design system support
104 lines (103 loc) • 4.1 kB
JavaScript
import { FileUtils } from '../utils/file-utils.js';
import { Logger } from '../utils/logger.js';
import { GitHubService } from './github-service.js';
export class ComponentRegistryService {
static registryCache = null;
static async getRegistry() {
if (this.registryCache) {
return this.registryCache;
}
try {
try {
const localPath = new URL('../component-registry.json', import.meta.url).pathname;
const localContent = await FileUtils.readFile(localPath);
const registryData = JSON.parse(localContent);
this.registryCache = registryData;
return registryData;
}
catch (localError) {
const registryData = await GitHubService.getRegistry();
this.registryCache = registryData;
return registryData;
}
}
catch (error) {
Logger.error('Failed to load component registry from GitHub');
Logger.error('Please check your internet connection and try again.');
throw error;
}
}
static async getComponent(name) {
const registry = await this.getRegistry();
return registry[name] || null;
}
static async getAllComponents() {
const registry = await this.getRegistry();
return Object.entries(registry).map(([name, info]) => ({
...info,
name,
}));
}
static async componentExists(name) {
const component = await this.getComponent(name);
return component !== null;
}
static async resolveDependencies(componentNames) {
const registry = await this.getRegistry();
const resolved = new Set();
const processing = new Set();
const resolveDependency = async (name) => {
if (resolved.has(name) || processing.has(name)) {
return;
}
const component = registry[name];
if (!component) {
throw new Error(`Component '${name}' not found`);
}
processing.add(name);
for (const dep of component.dependencies) {
await resolveDependency(dep);
}
processing.delete(name);
resolved.add(name);
};
for (const name of componentNames) {
await resolveDependency(name);
}
return Array.from(resolved);
}
static async getComponentsWithDetails() {
const registry = await this.getRegistry();
return Object.entries(registry).map(([name, info]) => ({
name,
description: this.getComponentDescription(name),
dependencies: info.dependencies.join(', ') || 'None',
externalDeps: info.externalDeps.length > 0,
}));
}
static getComponentDescription(name) {
const descriptions = {
'button': 'UI component with variants and sizes',
'text': 'Typography component with semantic variants',
'modal': 'Flexible modal with animations',
'dialog': 'Dialog built on modal',
'alert-dialog': 'Confirmation dialogs',
'surface': 'Surface with elevation and variants',
'text-input': 'Input with validation states',
'text-area': 'Multi-line text input',
'checkbox': 'Custom styled checkbox',
'switch': 'Animated switch component',
'progress': 'Progress bar with animations',
'skeleton': 'Loading skeleton with animations',
'avatar': 'Avatar with fallback support',
'badge': 'Status and label badges',
'divider': 'Visual separator component',
'icon': 'Icon component with theming',
'label': 'Form labels with styling',
'radio': 'Radio group and items',
'slot': 'Component composition utility',
'spinner': 'Loading spinner with animations',
};
return descriptions[name] || 'UI component';
}
}