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
146 lines (145 loc) • 5.66 kB
JavaScript
import { Logger } from '../utils/logger.js';
import { VersionUtils } from '../utils/version.js';
export class GitHubService {
static REPO_OWNER = 'AgustinOberg';
static REPO_NAME = 'leshi-ui';
static BASE_URL = `https://api.github.com/repos/${this.REPO_OWNER}/${this.REPO_NAME}`;
static registryCache = null;
static gitHubRef = null;
static async getGitHubRef() {
if (this.gitHubRef) {
return this.gitHubRef;
}
this.gitHubRef = await VersionUtils.getGitHubRef();
return this.gitHubRef;
}
static async getRawBaseUrl() {
const ref = await this.getGitHubRef();
return `https://raw.githubusercontent.com/${this.REPO_OWNER}/${this.REPO_NAME}/${ref}`;
}
static async getRegistry() {
if (this.registryCache) {
return this.registryCache;
}
try {
const rawBaseUrl = await this.getRawBaseUrl();
const registryUrl = `${rawBaseUrl}/cli/component-registry.json`;
const response = await fetch(registryUrl);
if (!response.ok) {
throw new Error(`Failed to fetch registry: ${response.status} ${response.statusText}`);
}
const registryData = await response.json();
this.registryCache = registryData;
return registryData;
}
catch (error) {
Logger.error('Failed to load component registry from GitHub');
throw error;
}
}
static async downloadComponent(framework, componentName) {
try {
const rawBaseUrl = await this.getRawBaseUrl();
const componentPath = `packages/${framework}/components/ui/${componentName}.tsx`;
const fileUrl = `${rawBaseUrl}/${componentPath}`;
const response = await fetch(fileUrl);
if (!response.ok) {
throw new Error(`Failed to download component '${componentName}': ${response.status} ${response.statusText}`);
}
return await response.text();
}
catch (error) {
Logger.error(`Failed to download component '${componentName}' from GitHub`);
throw error;
}
}
static async downloadUtility(framework, utilityPath) {
try {
const rawBaseUrl = await this.getRawBaseUrl();
const filename = utilityPath.split('/').pop();
const fileUrl = `${rawBaseUrl}/packages/${framework}/lib/${filename}`;
const response = await fetch(fileUrl);
if (!response.ok) {
throw new Error(`Failed to download utility '${filename}': ${response.status} ${response.statusText}`);
}
return await response.text();
}
catch (error) {
Logger.error(`Failed to download utility '${utilityPath}' from GitHub`);
throw error;
}
}
static async downloadTheme(framework, themeName) {
try {
const rawBaseUrl = await this.getRawBaseUrl();
const themeUrl = `${rawBaseUrl}/packages/${framework}/styles/themes/${themeName}.ts`;
const response = await fetch(themeUrl);
if (!response.ok) {
throw new Error(`Failed to download theme '${themeName}': ${response.status} ${response.statusText}`);
}
return await response.text();
}
catch (error) {
Logger.error(`Failed to download theme '${themeName}' from GitHub`);
throw error;
}
}
static async downloadStyleFiles(framework) {
const files = {};
try {
const rawBaseUrl = await this.getRawBaseUrl();
const styleFiles = [
'theme.ts',
'context.tsx',
...(framework === 'rn' ? ['theme.d.ts'] : ['breakpoints.ts'])
];
for (const filename of styleFiles) {
const fileUrl = `${rawBaseUrl}/packages/${framework}/styles/${filename}`;
const response = await fetch(fileUrl);
if (response.ok) {
files[filename] = await response.text();
}
}
return files;
}
catch (error) {
Logger.error(`Failed to download style files from GitHub`);
throw error;
}
}
static async getAvailableThemes(framework) {
try {
const ref = await this.getGitHubRef();
const apiUrl = `${this.BASE_URL}/contents/packages/${framework}/styles/themes?ref=${ref}`;
const response = await fetch(apiUrl);
if (!response.ok) {
throw new Error(`Failed to fetch themes: ${response.status} ${response.statusText}`);
}
const files = await response.json();
return files
.filter(file => file.type === 'file' && file.name.endsWith('.ts') &&
file.name !== 'index.ts' && file.name !== 'common.ts')
.map(file => file.name.replace('.ts', ''));
}
catch (error) {
Logger.error('Failed to fetch available themes from GitHub');
throw error;
}
}
static async isRepositoryAccessible() {
try {
const response = await fetch(`${this.BASE_URL}`, { method: 'HEAD' });
return response.ok;
}
catch {
return false;
}
}
static clearCache() {
this.registryCache = null;
this.gitHubRef = null;
}
static async getCurrentRef() {
return await this.getGitHubRef();
}
}