Skip to main content
Glama
githubOperations.ts5.24 kB
/** * GitHub operations for creating and updating prompts */ import { Octokit } from '@octokit/rest'; import { GitHubConfig } from './config.js'; import { PromptMetadata } from './types.js'; export class GitHubPromptOperations { private octokit: Octokit; private config: GitHubConfig; constructor(config: GitHubConfig) { this.config = config; this.octokit = new Octokit({ auth: config.token, }); } /** * Create or update a prompt in GitHub */ async savePromptToGitHub( path: string, content: string, message: string ): Promise<{ path: string; sha: string }> { try { // First, try to get the file to see if it exists let sha: string | undefined; try { const params: any = { owner: this.config.owner, repo: this.config.repo, path, }; if (this.config.branch) { params.ref = this.config.branch; } const { data: existingFile } = await this.octokit.repos.getContent(params); if ('sha' in existingFile) { sha = existingFile.sha; } } catch (error: any) { // File doesn't exist, which is fine for creation if (error.status !== 404) { throw error; } } // Create or update the file const createParams: any = { owner: this.config.owner, repo: this.config.repo, path, message, content: Buffer.from(content).toString('base64'), }; if (this.config.branch) { createParams.branch = this.config.branch; } if (sha) { createParams.sha = sha; } const { data } = await this.octokit.repos.createOrUpdateFileContents(createParams); return { path, sha: data.content?.sha || '', }; } catch (error) { console.error('Error saving prompt to GitHub:', error); throw new Error(`Failed to save prompt to GitHub: ${error instanceof Error ? error.message : 'Unknown error'}`); } } /** * Delete a prompt from GitHub */ async deletePromptFromGitHub(path: string, message: string): Promise<void> { try { // Get the file SHA first const getParams: any = { owner: this.config.owner, repo: this.config.repo, path, }; if (this.config.branch) { getParams.ref = this.config.branch; } const { data: file } = await this.octokit.repos.getContent(getParams); if (!('sha' in file)) { throw new Error('Could not get file SHA'); } // Delete the file const deleteParams: any = { owner: this.config.owner, repo: this.config.repo, path, message, sha: file.sha, }; if (this.config.branch) { deleteParams.branch = this.config.branch; } await this.octokit.repos.deleteFile(deleteParams); } catch (error) { console.error('Error deleting prompt from GitHub:', error); throw new Error(`Failed to delete prompt from GitHub: ${error instanceof Error ? error.message : 'Unknown error'}`); } } /** * Build a properly formatted prompt file path */ buildPromptPath(category: string, filename: string): string { // Ensure filename ends with .md const mdFilename = filename.endsWith('.md') ? filename : `${filename}.md`; // Build path with category directory return category ? `${category}/${mdFilename}` : mdFilename; } /** * Format prompt content with YAML frontmatter */ formatPromptContent(metadata: PromptMetadata, content: string, name: string): string { const frontmatter = `--- name: ${name} title: ${metadata.title} description: ${metadata.description} category: ${metadata.category || 'uncategorized'} tags: ${JSON.stringify(metadata.tags || [])} difficulty: ${metadata.difficulty || 'intermediate'} author: ${metadata.author || 'User'} version: ${metadata.version || '1.0'} created: ${metadata.created || new Date().toISOString()} updated: ${new Date().toISOString()}${metadata.arguments ? ` arguments:${metadata.arguments.map((arg: any) => ` - name: ${arg.name} description: ${arg.description} required: ${arg.required || false}`).join('')}` : ''} --- ${content}`; return frontmatter; } /** * Validate GitHub configuration */ async validateConfig(): Promise<boolean> { try { await this.octokit.repos.get({ owner: this.config.owner, repo: this.config.repo, }); return true; } catch (error) { console.error('GitHub configuration validation failed:', error); return false; } } /** * Check if user has write access to the repository */ async hasWriteAccess(): Promise<boolean> { try { if (!this.config.token) { return false; } const { data: repo } = await this.octokit.repos.get({ owner: this.config.owner, repo: this.config.repo, }); // Check if the authenticated user has push access return repo.permissions?.push || false; } catch (error) { console.error('Error checking write access:', error); return false; } } }

Implementation Reference

Latest Blog Posts

MCP directory API

We provide all the information about MCP servers via our MCP API.

curl -X GET 'https://glama.ai/api/mcp/v1/servers/jezweb/smart-prompts-mcp'

If you have feedback or need assistance with the MCP directory API, please join our Discord server