| "use strict"; |
| Object.defineProperty(exports, "__esModule", { value: true }); |
| exports.createInstallationOctokit = createInstallationOctokit; |
| exports.handleMount = handleMount; |
| const auth_app_1 = require("@octokit/auth-app"); |
| const rest_1 = require("@octokit/rest"); |
| const supabase_1 = require("./supabase"); |
| |
| |
| |
| |
| async function createInstallationOctokit(installationId) { |
| const appId = process.env.APP_ID; |
| let privateKey = process.env.PRIVATE_KEY; |
| if (!appId || !privateKey) { |
| throw new Error('APP_ID and PRIVATE_KEY must be set in environment variables.'); |
| } |
| |
| privateKey = privateKey.replace(/\\n/g, '\n').replace(/^"(.*)"$/, '$1'); |
| const auth = (0, auth_app_1.createAppAuth)({ |
| appId: Number(appId), |
| privateKey |
| }); |
| |
| const installationAuth = await auth({ |
| type: 'installation', |
| installationId |
| }); |
| const octokit = new rest_1.Octokit({ |
| auth: installationAuth.token |
| }); |
| return { |
| octokit, |
| token: installationAuth.token, |
| expiresAt: installationAuth.expiresAt || |
| new Date(Date.now() + 3600000).toISOString() |
| }; |
| } |
| |
| |
| |
| |
| async function listInstallationRepos(octokit) { |
| const repos = []; |
| let page = 1; |
| const perPage = 100; |
| while (true) { |
| const response = await octokit.request('GET /installation/repositories', { |
| per_page: perPage, |
| page |
| }); |
| const fetchedRepos = response.data.repositories || []; |
| for (const repo of fetchedRepos) { |
| repos.push(repo.full_name); |
| } |
| |
| if (fetchedRepos.length < perPage) { |
| break; |
| } |
| page++; |
| } |
| return repos; |
| } |
| |
| |
| |
| |
| async function syncUserInstallation(githubId, installationId, repos) { |
| |
| |
| const result = await supabase_1.db.query(`UPDATE users
|
| SET github_installation_id = $1,
|
| selected_repos = $2,
|
| updated_at = NOW()
|
| WHERE github_id = $3`, [installationId, repos, githubId]); |
| if (result.rowCount === 0) { |
| throw new Error(`No user found with github_id=${githubId}. User must sign up before mounting repositories.`); |
| } |
| } |
| |
| |
| |
| async function handleMount(body) { |
| const { installationId, githubId } = body; |
| |
| if (!installationId || !githubId) { |
| return { |
| success: false, |
| repos: [], |
| error: 'Missing required fields: installationId and githubId' |
| }; |
| } |
| if (typeof installationId !== 'number' || typeof githubId !== 'number') { |
| return { |
| success: false, |
| repos: [], |
| error: 'installationId and githubId must be numbers' |
| }; |
| } |
| try { |
| |
| console.log(`[MOUNT] Generating installation token for installation=${installationId}, user=${githubId}`); |
| const { octokit, expiresAt } = await createInstallationOctokit(installationId); |
| |
| const repos = await listInstallationRepos(octokit); |
| console.log(`[MOUNT] Found ${repos.length} repos for installation ${installationId}: ${repos.join(', ')}`); |
| |
| await syncUserInstallation(githubId, installationId, repos); |
| console.log(`[MOUNT] Successfully synced ${repos.length} repos for user ${githubId}`); |
| return { |
| success: true, |
| repos, |
| tokenExpiresAt: expiresAt |
| }; |
| } |
| catch (err) { |
| console.error(`[MOUNT] Error: ${err.message}`); |
| return { |
| success: false, |
| repos: [], |
| error: err.message || 'Internal server error' |
| }; |
| } |
| } |
| |