Canvas: App wide env vars

Change-Id: Ia4101ba7c646e33591a1ddd642622e2712865b71
diff --git a/apps/canvas/back/src/index.ts b/apps/canvas/back/src/index.ts
index 1fd9b37..97df61f 100644
--- a/apps/canvas/back/src/index.ts
+++ b/apps/canvas/back/src/index.ts
@@ -4,7 +4,7 @@
 import { env } from "node:process";
 import axios from "axios";
 import { GithubClient } from "./github.js";
-import { AppManager } from "./app_manager.js";
+import { AppManager, DeployResponse } from "./app_manager.js";
 import { z } from "zod";
 import { ProjectMonitor, WorkerSchema, LogItem } from "./project_monitor.js";
 import tmp from "tmp";
@@ -386,34 +386,31 @@
 			},
 		};
 		try {
+			let deployResponse: DeployResponse | null = null;
 			if (p.instanceId == null) {
-				const deployResponse = await appManager.deploy(cfg);
-				await db.project.update({
-					where: {
-						id: projectId,
-					},
-					data: {
-						state: JSON.stringify(graph),
-						draft: null,
-						instanceId: deployResponse.id,
-						access: JSON.stringify(deployResponse.access),
-					},
-				});
+				deployResponse = await appManager.deploy(cfg);
 				diff = { toAdd: extractGithubRepos(JSON.stringify(graph)) };
 			} else {
-				const deployResponse = await appManager.update(p.instanceId, cfg);
+				deployResponse = await appManager.update(p.instanceId, cfg);
 				diff = calculateRepoDiff(extractGithubRepos(p.state), extractGithubRepos(JSON.stringify(graph)));
-				await db.project.update({
-					where: {
-						id: projectId,
-					},
-					data: {
-						state: JSON.stringify(graph),
-						draft: null,
-						access: JSON.stringify(deployResponse.access),
-					},
-				});
 			}
+			if (deployResponse == null) {
+				resp.status(500);
+				resp.write(JSON.stringify({ error: "Failed to deploy" }));
+				return;
+			}
+			await db.project.update({
+				where: {
+					id: projectId,
+				},
+				data: {
+					state: JSON.stringify(graph),
+					draft: null,
+					instanceId: deployResponse.id,
+					access: JSON.stringify(deployResponse.access),
+					envVars: JSON.stringify(deployResponse.envVars),
+				},
+			});
 			if (diff && p.githubToken && deployKey) {
 				const github = new GithubClient(p.githubToken);
 				await manageGithubRepos(github, diff, deployKeyPublic!, env.PUBLIC_ADDR);
@@ -819,6 +816,7 @@
 			hasAuth: z.boolean(),
 		}),
 	),
+	envVars: z.array(z.object({ name: z.string(), value: z.string() })),
 });
 
 type InternalEnv = z.infer<typeof internalEnvSchema>;
@@ -833,12 +831,14 @@
 			},
 			select: {
 				githubToken: true,
+				envVars: true,
 			},
 		});
 		const networks = getNetworks(resp.locals.username);
 		const env: InternalEnv = {
 			networks,
 			githubToken: project?.githubToken ?? undefined,
+			envVars: JSON.parse(project?.envVars ?? "[]"),
 		};
 		resp.status(200);
 		resp.write(JSON.stringify(env));