From 49f485c70d8ddab9a6f945fdf75a34662fa884c5 Mon Sep 17 00:00:00 2001 From: Mamerto Fabian Jr Date: Sun, 29 Dec 2024 07:58:40 +0800 Subject: [PATCH] chore: update version to 1.1.4 and enhance GitHub error handling and repository initialization - Bumped the version number from 1.1.3 to 1.1.4 in manifest.json to reflect the latest release. - Improved error handling in GitHubService to provide more informative error messages for GitHub API errors. - Added methods to check if a repository is empty and to initialize it with an auto-generated README if necessary. - Updated ZipHandler to check for empty repositories and initialize them during the upload process, enhancing user experience and reliability. --- manifest.json | 2 +- src/background/BackgroundService.ts | 7 ++- src/services/GitHubService.ts | 96 ++++++++++++++++++++++++----- src/services/zipHandler.ts | 7 +++ 4 files changed, 93 insertions(+), 19 deletions(-) diff --git a/manifest.json b/manifest.json index 0a86ba4..83af99f 100644 --- a/manifest.json +++ b/manifest.json @@ -1,7 +1,7 @@ { "manifest_version": 3, "name": "Bolt to GitHub", - "version": "1.1.3", + "version": "1.1.4", "description": "Automatically process your Bolt project zip files and upload them to your GitHub repository.", "icons": { "16": "assets/icons/icon16.png", diff --git a/src/background/BackgroundService.ts b/src/background/BackgroundService.ts index 84b0524..4c17671 100644 --- a/src/background/BackgroundService.ts +++ b/src/background/BackgroundService.ts @@ -223,9 +223,12 @@ export class BackgroundService { const isGitHubError = errorMessage.includes('GitHub API Error'); if (isGitHubError) { + // Extract the original GitHub error message if available + const originalMessage = (decodeError as any).originalMessage || + 'GitHub authentication or API error occurred'; + throw new Error( - `GitHub authentication failed. Please check your GitHub token in the extension settings and try again. \n\n` + - `If the issue persists, please open a GitHub issue.` + `GitHub Error: ${originalMessage}` ); } else { throw new Error( diff --git a/src/services/GitHubService.ts b/src/services/GitHubService.ts index 1a57a9a..6760ad9 100644 --- a/src/services/GitHubService.ts +++ b/src/services/GitHubService.ts @@ -73,24 +73,49 @@ export class GitHubService { async request(method: string, endpoint: string, body?: any, options: RequestInit = {}) { const url = `${this.baseUrl}${endpoint}`; - const response = await fetch(url, { - method, - ...options, - headers: { - 'Accept': 'application/vnd.github.v3+json', - 'Authorization': `Bearer ${this.token}`, - 'Content-Type': 'application/json', - ...options.headers, - }, - body: body ? JSON.stringify(body) : undefined, - }); + try { + const response = await fetch(url, { + method, + ...options, + headers: { + 'Accept': 'application/vnd.github.v3+json', + 'Authorization': `Bearer ${this.token}`, + 'Content-Type': 'application/json', + ...options.headers, + }, + body: body ? JSON.stringify(body) : undefined, + }); - if (!response.ok) { - const error = await response.json(); - throw new Error(`GitHub API Error: ${response.status} ${error.message || JSON.stringify(error)}`); - } + if (!response.ok) { + let errorDetails; + try { + errorDetails = await response.json(); + } catch { + // If parsing JSON fails, use the status text + errorDetails = { message: response.statusText }; + } - return response.json(); + // Construct a more informative error message + const errorMessage = errorDetails.message || + errorDetails.error || + 'Unknown GitHub API error'; + + const fullErrorMessage = `GitHub API Error (${response.status}): ${errorMessage}`; + + // Create a custom error with additional properties + const apiError = new Error(fullErrorMessage) as any; + apiError.status = response.status; + apiError.originalMessage = errorMessage; + apiError.githubErrorResponse = errorDetails; + + throw apiError; + } + + return await response.json(); + } catch (error) { + // Re-throw the error to maintain the original error details + throw error; + } } async repoExists(owner: string, repo: string): Promise { @@ -144,6 +169,45 @@ export class GitHubService { } } + async isRepoEmpty(owner: string, repo: string): Promise { + try { + const commits = await this.request('GET', `/repos/${owner}/${repo}/commits`); + return commits.length === 0; + } catch (error) { + console.log('error', error); + if (error instanceof Error && error.message.includes('409')) { + // 409 is returned for empty repositories + return true; + } + throw error; + } + } + + async initializeEmptyRepo(owner: string, repo: string, branch: string): Promise { + // Create a more informative README.md to initialize the repository + const readmeContent = `# ${repo} + +## Repository Initialization Notice + +This repository was automatically initialized by the Bolt to GitHub extension. + +**Auto-Generated Repository** +- Created to ensure a valid Git repository structure +- Serves as an initial commit point for your project + +If you did not intend to create this repository or have any questions, +please check your Bolt to GitHub extension settings.`; + + await this.pushFile({ + owner, + repo, + path: 'README.md', + content: btoa(readmeContent), + branch, + message: 'Initialize repository with auto-generated README' + }); + } + async pushFile(params: { owner: string; repo: string; diff --git a/src/services/zipHandler.ts b/src/services/zipHandler.ts index 93519b8..a6d683f 100644 --- a/src/services/zipHandler.ts +++ b/src/services/zipHandler.ts @@ -82,6 +82,13 @@ export class ZipHandler { await this.updateStatus('uploading', 15, 'Checking repository...'); await this.githubService.ensureRepoExists(repoOwner, repoName); + // Check if repo is empty and needs initialization + const isEmpty = await this.githubService.isRepoEmpty(repoOwner, repoName); + if (isEmpty) { + await this.updateStatus('uploading', 18, 'Initializing empty repository...'); + await this.githubService.initializeEmptyRepo(repoOwner, repoName, targetBranch); + } + await this.ensureBranchExists(repoOwner, repoName, targetBranch); const processedFiles = await this.processFilesWithGitignore(files);