import JSZip from "jszip"; import { saveAs } from "file-saver"; export async function downloadArtifactAsZip(data: string, type: string, language: string = "html") { const zip = new JSZip(); const extension = language === "html" || type === "web" || type === "app" ? "html" : (language === "typescript" || language === "tsx" ? "tsx" : "txt"); const filename = `artifact-${Date.now()}.${extension}`; // Check if data contains common multi-file structures (simple heuristic) // If it looks like a full project (multiple files defined in one block), we could parse it, // but for now we'll just save the main artifact. zip.file(filename, data); // Add a basic README zip.file("README.md", `# AI Generated Artifact\n\nType: ${type}\nGenerated: ${new Date().toLocaleString()}`); const content = await zip.generateAsync({ type: "blob" }); saveAs(content, `promptarch-artifact-${Date.now()}.zip`); } export async function pushToGithub( token: string, repoName: string, files: { path: string; content: string }[], description: string = "Generated by PromptArch" ) { const headers = { 'Authorization': `token ${token}`, 'Accept': 'application/vnd.github.v3+json', 'Content-Type': 'application/json', }; // 1. Check if repo exists, if not create it let repoData; const userResponse = await fetch('https://api.github.com/user', { headers }); if (!userResponse.ok) throw new Error("Failed to authenticate with GitHub"); const userData = await userResponse.json(); const username = userData.login; const repoCheckResponse = await fetch(`https://api.github.com/repos/${username}/${repoName}`, { headers }); if (repoCheckResponse.status === 404) { // Create repo const createResponse = await fetch('https://api.github.com/user/repos', { method: 'POST', headers, body: JSON.stringify({ name: repoName, description, auto_init: true }) }); if (!createResponse.ok) throw new Error("Failed to create repository"); repoData = await createResponse.json(); // Wait a bit for repo to be ready await new Promise(resolve => setTimeout(resolve, 2000)); } else { repoData = await repoCheckResponse.json(); } // 2. Get latest commit SHA of default branch const branchResponse = await fetch(`https://api.github.com/repos/${username}/${repoName}/branches/${repoData.default_branch}`, { headers }); const branchData = await branchResponse.json(); const latestCommitSha = branchData.commit.sha; // 3. Create a new tree const treeItems = files.map(file => ({ path: file.path, mode: '100644', type: 'blob', content: file.content })); const treeResponse = await fetch(`https://api.github.com/repos/${username}/${repoName}/git/trees`, { method: 'POST', headers, body: JSON.stringify({ base_tree: latestCommitSha, tree: treeItems }) }); const treeData = await treeResponse.json(); // 4. Create a new commit const commitResponse = await fetch(`https://api.github.com/repos/${username}/${repoName}/git/commits`, { method: 'POST', headers, body: JSON.stringify({ message: `Update from PromptArch: ${new Date().toISOString()}`, tree: treeData.sha, parents: [latestCommitSha] }) }); const commitData = await commitResponse.json(); // 5. Update the reference const refResponse = await fetch(`https://api.github.com/repos/${username}/${repoName}/git/refs/heads/${repoData.default_branch}`, { method: 'PATCH', headers, body: JSON.stringify({ sha: commitData.sha }) }); if (!refResponse.ok) throw new Error("Failed to update branch reference"); return { url: repoData.html_url }; }