-
Notifications
You must be signed in to change notification settings - Fork 2
Fix flash of diff sidebar and toggle button during page load #630
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
Conversation
Move repository-to-project mapping logic into a dedicated ProjectMapper class. The mapper handles filtering, sorting, and all mapping transformations with generic type support for provider-specific repository types. This prepares the codebase for supporting multiple project source providers by decoupling the mapping logic from the data source implementation.
- Add Microsoft Entra ID authentication via next-auth - Implement AzureDevOpsClient for REST API interactions - Add AzureDevOpsProjectDataSource and AzureDevOpsRepositoryDataSource - Create unified IBlobProvider interface for file content fetching - Support binary image files in blob API - Configure via PROJECT_SOURCE_PROVIDER env var (github or azure-devops)
Add comprehensive tests for ProjectMapper, Azure DevOps client, blob providers, and repository data sources. Fix AzureDevOpsError prototype chain to ensure instanceof checks work correctly.
Add provider configuration section explaining how to use either GitHub or Azure DevOps as the project source provider.
Remove duplicated mapping code by having AzureDevOpsProjectDataSource use the shared ProjectMapper class with Azure DevOps-specific URL builders. - Update AzureDevOpsRepositoryWithRefs to extend RepositoryWithRefs - Create azureDevOpsURLBuilders for Azure DevOps URL generation - Reduce AzureDevOpsProjectDataSource from 270 to 57 lines
Microsoft Entra ID access tokens are JWTs that can exceed 2000 characters, which doesn't fit in VARCHAR(255).
|
|
b412054 to
3c06370
Compare
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Pull request overview
This pull request addresses two main objectives: fixing UI flashing during SSR/hydration and adding Azure DevOps support as an alternative to GitHub. The changes introduce a provider-based architecture that allows switching between GitHub and Azure DevOps through environment configuration while sharing common logic through a new ProjectMapper abstraction.
- Prevents flash of right drawer and toggle button during SSR by deferring rendering until client mount
- Refactors project mapping logic into a provider-agnostic
ProjectMapperclass with URL builder abstraction - Adds full Azure DevOps support including authentication (Microsoft Entra ID), repository access, and blob retrieval
Reviewed changes
Copilot reviewed 37 out of 37 changed files in this pull request and generated 4 comments.
Show a summary per file
| File | Description |
|---|---|
| src/features/sidebar/view/internal/tertiary/RightContainer.tsx | Adds mounted state check to prevent SSR flash |
| src/features/sidebar/view/SecondarySplitHeader.tsx | Adds mounted state check to prevent button flash |
| src/features/projects/domain/ProjectMapper.ts | New abstraction for mapping repositories to projects with provider-specific URL builders |
| src/features/projects/domain/IAzureDevOpsRepositoryDataSource.ts | Type definitions for Azure DevOps repository structure |
| src/features/projects/data/GitHubProjectDataSource.ts | Refactored to use ProjectMapper with GitHub-specific URL builders |
| src/features/projects/data/AzureDevOpsRepositoryDataSource.ts | Fetches and maps Azure DevOps repositories |
| src/features/projects/data/AzureDevOpsProjectDataSource.ts | Azure DevOps project data source using ProjectMapper |
| src/common/azure-devops/AzureDevOpsClient.ts | HTTP client for Azure DevOps REST API with auth error handling |
| src/common/azure-devops/OAuthTokenRefreshingAzureDevOpsClient.ts | Wrapper client that auto-refreshes OAuth tokens on auth errors |
| src/common/azure-devops/AzureDevOpsError.ts | Custom error type for Azure DevOps API failures |
| src/common/blob/GitHubBlobProvider.ts | Blob provider implementation for GitHub |
| src/common/blob/AzureDevOpsBlobProvider.ts | Blob provider implementation for Azure DevOps |
| src/features/auth/data/AzureDevOpsOAuthTokenRefresher.ts | OAuth token refresher using Microsoft Entra ID endpoints |
| src/features/auth/domain/log-in/LogInHandler.ts | Updated to handle both GitHub and Microsoft Entra ID providers |
| src/composition.ts | Provider-based composition with conditional initialization |
| src/app/auth/signin/page.tsx | Refactored sign-in page to support multiple providers |
| src/app/auth/signin/SignInButton.tsx | New client component for provider-specific sign-in buttons |
| src/app/api/hooks/github/route.ts | Added null check for GitHub webhook handler |
| src/app/api/diff/[owner]/[repository]/[...path]/route.ts | Added null check for diff calculator |
| src/app/api/blob/[owner]/[repository]/[...path]/route.ts | Refactored to use provider-agnostic blob provider |
| create-tables.sql | Expanded token columns from VARCHAR(255) to TEXT for longer tokens |
| test/projects/ProjectMapper.test.ts | Comprehensive tests for ProjectMapper logic |
| test/projects/testUtils.ts | Shared test utilities for encryption and encoding |
| test/projects/GitHubProjectDataSource.test.ts | Simplified tests now that ProjectMapper handles mapping logic |
| test/projects/AzureDevOpsRepositoryDataSource.test.ts | Tests for Azure DevOps repository data source |
| test/projects/AzureDevOpsProjectDataSource.test.ts | Tests for Azure DevOps project data source |
| test/common/blob/GitHubBlobProvider.test.ts | Tests for GitHub blob provider |
| test/common/blob/AzureDevOpsBlobProvider.test.ts | Tests for Azure DevOps blob provider |
| test/common/azure-devops/*.test.ts | Comprehensive tests for Azure DevOps client components |
| README.md | Updated documentation to mention Azure DevOps support |
| .env.example | Added Azure DevOps configuration variables |
💡 Add Copilot custom instructions for smarter, more guided reviews. Learn how to get started.
| return `https://github.com/${repository.owner}/${repository.name}/tree/${ref.name}` | ||
| }, | ||
| getSpecEditUrl(repository: RepositoryWithRefs, ref: RepositoryRef, fileName: string): string { | ||
| return `https://github.com/${repository.owner}/${repository.name}/edit/${ref.name}/${encodeURIComponent(fileName)}` |
Copilot
AI
Dec 8, 2025
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
The editURL uses simple encodeURIComponent on the entire filename, which is incorrect for paths with slashes. It should use per-segment encoding like getDiffUrl does. For example, a file like "apis/users.yml" would be incorrectly encoded as "apis%2Fusers.yml" instead of "apis/users.yml".
Consider changing line 27 to:
const encodedPath = fileName.split('/').map(segment => encodeURIComponent(segment)).join('/')
return `https://github.com/${repository.owner}/${repository.name}/edit/${ref.name}/${encodedPath}`| getSpecEditUrl(repository: AzureDevOpsRepositoryWithRefs, ref: RepositoryRef, fileName: string): string { | ||
| return `${repository.webUrl}?path=/${fileName}&version=GB${ref.name}&_a=contents` |
Copilot
AI
Dec 8, 2025
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
The getSpecEditUrl doesn't encode the filename path, which could cause issues for files with special characters or spaces. Consider applying URL encoding per path segment similar to the GitHub implementation:
const encodedPath = fileName.split('/').map(segment => encodeURIComponent(segment)).join('/')
return `${repository.webUrl}?path=/${encodedPath}&version=GB${ref.name}&_a=contents`| async getFileContent(repositoryId: string, path: string, version: string): Promise<string | ArrayBuffer | null> { | ||
| try { | ||
| const oauthToken = await this.oauthTokenDataSource.getOAuthToken() | ||
| const url = `https://dev.azure.com/${this.organization}/_apis/git/repositories/${repositoryId}/items?path=${encodeURIComponent(path)}&versionDescriptor.version=${encodeURIComponent(version)}&api-version=${this.apiVersion}` |
Copilot
AI
Dec 8, 2025
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
The path parameter in the URL is not properly encoded. This could cause issues for file paths containing special characters or spaces. Use encodeURIComponent for the path value:
const url = `https://dev.azure.com/${this.organization}/_apis/git/repositories/${repositoryId}/items?path=${encodeURIComponent(path)}&versionDescriptor.version=${encodeURIComponent(version)}&api-version=${this.apiVersion}`| export function getBlobURL(owner: string, repository: string, path: string, ref: string): string { | ||
| return `/api/blob/${owner}/${repository}/${path}?ref=${ref}` | ||
| } |
Copilot
AI
Dec 8, 2025
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
The getBlobURL function doesn't apply per-segment encoding to the path parameter, which is inconsistent with how paths are encoded elsewhere (e.g., in getDiffUrl). Files with slashes in subdirectories won't be correctly encoded. Consider updating to:
export function getBlobURL(owner: string, repository: string, path: string, ref: string): string {
const encodedPath = path.split('/').map(segment => encodeURIComponent(segment)).join('/')
return `/api/blob/${owner}/${repository}/${encodedPath}?ref=${ref}`
}This matches the pattern established in the codebase memory.
Summary