bolt.diy/app/routes/api.system.diagnostics.ts
Stijnus 0487ed1438
feat: new improvement for the GitHub API Authentication Fix (#1537)
* Add environment variables section to ConnectionsTab and fallback token to git-info

* Add remaining code from original branch

* Import Repo Fix

* refactor the UI

* add a rate limit counter

* Update GithubConnection.tsx

* Update NetlifyConnection.tsx

* fix: ui style

* Sync with upstream and preserve GitHub connection and DataTab fixes

* fix disconnect buttons

* revert commits

* Update api.git-proxy.$.ts

* Update api.git-proxy.$.ts
2025-03-29 21:12:47 +01:00

143 lines
3.8 KiB
TypeScript

import { json, type LoaderFunction, type LoaderFunctionArgs } from '@remix-run/cloudflare';
/**
* Diagnostic API for troubleshooting connection issues
*/
interface AppContext {
env?: {
GITHUB_ACCESS_TOKEN?: string;
NETLIFY_TOKEN?: string;
};
}
export const loader: LoaderFunction = async ({ request, context }: LoaderFunctionArgs & { context: AppContext }) => {
// Get environment variables
const envVars = {
hasGithubToken: Boolean(process.env.GITHUB_ACCESS_TOKEN || context.env?.GITHUB_ACCESS_TOKEN),
hasNetlifyToken: Boolean(process.env.NETLIFY_TOKEN || context.env?.NETLIFY_TOKEN),
nodeEnv: process.env.NODE_ENV,
};
// Check cookies
const cookieHeader = request.headers.get('Cookie') || '';
const cookies = cookieHeader.split(';').reduce(
(acc, cookie) => {
const [key, value] = cookie.trim().split('=');
if (key) {
acc[key] = value;
}
return acc;
},
{} as Record<string, string>,
);
const hasGithubTokenCookie = Boolean(cookies.githubToken);
const hasGithubUsernameCookie = Boolean(cookies.githubUsername);
const hasNetlifyCookie = Boolean(cookies.netlifyToken);
// Get local storage status (this can only be checked client-side)
const localStorageStatus = {
explanation: 'Local storage can only be checked on the client side. Use browser devtools to check.',
githubKeysToCheck: ['github_connection'],
netlifyKeysToCheck: ['netlify_connection'],
};
// Check if CORS might be an issue
const corsStatus = {
headers: {
'Access-Control-Allow-Origin': '*',
'Access-Control-Allow-Methods': 'GET, POST, OPTIONS',
'Access-Control-Allow-Headers': 'Content-Type, Authorization',
},
};
// Check if API endpoints are reachable
const apiEndpoints = {
githubUser: '/api/system/git-info?action=getUser',
githubRepos: '/api/system/git-info?action=getRepos',
githubOrgs: '/api/system/git-info?action=getOrgs',
githubActivity: '/api/system/git-info?action=getActivity',
gitInfo: '/api/system/git-info',
};
// Test GitHub API connectivity
let githubApiStatus;
try {
const githubResponse = await fetch('https://api.github.com/zen', {
method: 'GET',
headers: {
Accept: 'application/vnd.github.v3+json',
},
});
githubApiStatus = {
isReachable: githubResponse.ok,
status: githubResponse.status,
statusText: githubResponse.statusText,
};
} catch (error) {
githubApiStatus = {
isReachable: false,
error: error instanceof Error ? error.message : String(error),
};
}
// Test Netlify API connectivity
let netlifyApiStatus;
try {
const netlifyResponse = await fetch('https://api.netlify.com/api/v1/', {
method: 'GET',
});
netlifyApiStatus = {
isReachable: netlifyResponse.ok,
status: netlifyResponse.status,
statusText: netlifyResponse.statusText,
};
} catch (error) {
netlifyApiStatus = {
isReachable: false,
error: error instanceof Error ? error.message : String(error),
};
}
// Provide technical details about the environment
const technicalDetails = {
serverTimestamp: new Date().toISOString(),
userAgent: request.headers.get('User-Agent'),
referrer: request.headers.get('Referer'),
host: request.headers.get('Host'),
method: request.method,
url: request.url,
};
// Return diagnostics
return json(
{
status: 'success',
environment: envVars,
cookies: {
hasGithubTokenCookie,
hasGithubUsernameCookie,
hasNetlifyCookie,
},
localStorage: localStorageStatus,
apiEndpoints,
externalApis: {
github: githubApiStatus,
netlify: netlifyApiStatus,
},
corsStatus,
technicalDetails,
},
{
headers: corsStatus.headers,
},
);
};