Canvas: Github repository picker

Change-Id: Icb8f2ffbef2894b2fdea4e4c13c74c0f4970506b
diff --git a/apps/canvas/back/index.ts b/apps/canvas/back/index.ts
index 258bad9..cdcf9a0 100644
--- a/apps/canvas/back/index.ts
+++ b/apps/canvas/back/index.ts
@@ -2,6 +2,7 @@
 import express from "express";
 import { env } from "node:process";
 import axios from "axios";
+import { GithubClient } from "./github";
 
 const db = new PrismaClient();
 
@@ -134,7 +135,7 @@
                 where: {
                     id: projectId,
                 },
-            });    
+            });
         }
         resp.status(200);
     } catch (e) {
@@ -155,6 +156,8 @@
             },
             select: {
                 instanceId: true,
+                githubToken: true,
+                deployKey: true,
             },
         });
         if (p === null) {
@@ -178,6 +181,7 @@
                     config: req.body.config,
                 },
             });
+            console.log(r);
             if (r.status === 200) {
                 await db.project.update({
                     where: {
@@ -190,6 +194,20 @@
                         deployKey: r.data.deployKey,
                     },
                 });
+
+                if (p.githubToken && r.data.deployKey) {
+                    const stateObj = JSON.parse(JSON.parse(state.toString()));
+                    const githubNodes = stateObj.nodes.filter((n: any) => n.type === "github" && n.data?.repository?.id);
+
+                    const github = new GithubClient(p.githubToken);
+                    for (const node of githubNodes) {
+                        try {
+                            await github.addDeployKey(node.data.repository.sshURL, r.data.deployKey);
+                        } catch (error) {
+                            console.error(`Failed to add deploy key to repository ${node.data.repository.sshURL}:`, error);
+                        }
+                    }
+                }
             }
         } else {
             r = await axios.request({
@@ -255,6 +273,94 @@
     }
 };
 
+const handleGithubRepos: express.Handler = async (req, resp) => {
+    try {
+        const projectId = Number(req.params["projectId"]);
+        const project = await db.project.findUnique({
+            where: { id: projectId },
+            select: { githubToken: true }
+        });
+
+        if (!project?.githubToken) {
+            resp.status(400);
+            resp.write(JSON.stringify({ error: "GitHub token not configured" }));
+            return;
+        }
+
+        const github = new GithubClient(project.githubToken);
+        const repositories = await github.getRepositories();
+
+        resp.status(200);
+        resp.header("Content-Type", "application/json");
+        resp.write(JSON.stringify(repositories));
+    } catch (e) {
+        console.log(e);
+        resp.status(500);
+        resp.write(JSON.stringify({ error: "Failed to fetch repositories" }));
+    } finally {
+        resp.end();
+    }
+};
+
+const handleUpdateGithubToken: express.Handler = async (req, resp) => {
+    try {
+        const projectId = Number(req.params["projectId"]);
+        const { githubToken } = req.body;
+
+        await db.project.update({
+            where: { id: projectId },
+            data: { githubToken },
+        });
+
+        resp.status(200);
+    } catch (e) {
+        console.log(e);
+        resp.status(500);
+    } finally {
+        resp.end();
+    }
+};
+
+const handleEnv: express.Handler = async (req, resp) => {
+    const projectId = Number(req.params["projectId"]);
+    try {
+        const project = await db.project.findUnique({
+            where: { id: projectId },
+            select: {
+                deployKey: true,
+                githubToken: true
+            }
+        });
+
+        if (!project) {
+            resp.status(404);
+            resp.write(JSON.stringify({ error: "Project not found" }));
+            return;
+        }
+
+        resp.status(200);
+        resp.write(JSON.stringify({
+            deployKey: project.deployKey,
+            integrations: {
+                github: !!project.githubToken,
+            },
+            networks: [{
+                name: "Public",
+                domain: "v1.dodo.cloud",
+            }, {
+                name: "Private",
+                domain: "p.v1.dodo.cloud",
+            }]
+        }));
+    } catch (error) {
+        console.error("Error checking integrations:", error);
+        resp.status(500);
+        resp.write(JSON.stringify({ error: "Internal server error" }));
+    } finally {
+        resp.end();
+    }
+};
+
 async function start() {
     await db.$connect();
     const app = express();
@@ -266,6 +372,9 @@
     app.delete("/api/project/:projectId", handleDelete);
     app.get("/api/project", handleProjectAll);
     app.post("/api/project", handleProjectCreate);
+    app.get("/api/project/:projectId/repos/github", handleGithubRepos);
+    app.post("/api/project/:projectId/github-token", handleUpdateGithubToken);
+    app.get("/api/project/:projectId/env", handleEnv);
     app.use("/", express.static("../front/dist"));
     app.listen(env.DODO_PORT_WEB, () => {
         console.log("started");