blob: 65eab15de982eb3974d7f64af6aa827077f6ba69 [file] [log] [blame]
giod0026612025-05-08 13:00:36 +00001import { PrismaClient } from "@prisma/client";
2import express from "express";
3import { env } from "node:process";
4import axios from "axios";
5import { GithubClient } from "./github";
6
7const db = new PrismaClient();
8
9const handleProjectCreate: express.Handler = async (req, resp) => {
10 try {
11 const { id } = await db.project.create({
12 data: {
13 userId: "gio", // req.get("x-forwarded-userid")!,
14 name: req.body.name,
15 },
16 });
17 resp.status(200);
18 resp.header("Content-Type", "application/json");
19 resp.write(
20 JSON.stringify({
21 id,
22 }),
23 );
24 } catch (e) {
25 console.log(e);
26 resp.status(500);
27 } finally {
28 resp.end();
29 }
30};
31
32const handleProjectAll: express.Handler = async (req, resp) => {
33 try {
34 const r = await db.project.findMany({
35 where: {
36 userId: "gio", // req.get("x-forwarded-userid")!,
37 },
38 });
39 resp.status(200);
40 resp.header("Content-Type", "application/json");
41 resp.write(
42 JSON.stringify(
43 r.map((p) => ({
44 id: p.id.toString(),
45 name: p.name,
46 })),
47 ),
48 );
49 } catch (e) {
50 console.log(e);
51 resp.status(500);
52 } finally {
53 resp.end();
54 }
55};
56
57const handleSave: express.Handler = async (req, resp) => {
58 try {
59 await db.project.update({
60 where: {
61 id: Number(req.params["projectId"]),
62 },
63 data: {
64 draft: Buffer.from(JSON.stringify(req.body)),
65 },
66 });
67 resp.status(200);
68 } catch (e) {
69 console.log(e);
70 resp.status(500);
71 } finally {
72 resp.end();
73 }
74};
75
76const handleSavedGet: express.Handler = async (req, resp) => {
77 try {
78 const r = await db.project.findUnique({
79 where: {
80 id: Number(req.params["projectId"]),
81 },
82 select: {
83 state: true,
84 draft: true,
85 },
86 });
87 if (r == null) {
88 resp.status(404);
89 } else {
90 resp.status(200);
91 resp.header("content-type", "application/json");
92 if (r.draft == null) {
93 if (r.state == null) {
94 resp.send({
95 nodes: [],
96 edges: [],
97 viewport: { x: 0, y: 0, zoom: 1 },
98 });
99 } else {
100 resp.send(JSON.parse(Buffer.from(r.state).toString("utf8")));
101 }
102 } else {
103 resp.send(JSON.parse(Buffer.from(r.draft).toString("utf8")));
104 }
105 }
106 } catch (e) {
107 console.log(e);
108 resp.status(500);
109 } finally {
110 resp.end();
111 }
112};
113
114const handleDelete: express.Handler = async (req, resp) => {
115 try {
116 const projectId = Number(req.params["projectId"]);
117 const p = await db.project.findUnique({
118 where: {
119 id: projectId,
120 },
121 select: {
122 instanceId: true,
123 },
124 });
125 if (p === null) {
126 resp.status(404);
127 return;
128 }
129 const r = await axios.request({
130 url: `http://appmanager.hgrz-appmanager.svc.cluster.local/api/instance/${p.instanceId}/remove`,
131 method: "post",
132 });
133 if (r.status === 200) {
134 await db.project.delete({
135 where: {
136 id: projectId,
137 },
138 });
139 }
140 resp.status(200);
141 } catch (e) {
142 console.log(e);
143 resp.status(500);
144 } finally {
145 resp.end();
146 }
147};
148
149const handleDeploy: express.Handler = async (req, resp) => {
150 try {
151 const projectId = Number(req.params["projectId"]);
152 const state = Buffer.from(JSON.stringify(req.body.state));
153 const p = await db.project.findUnique({
154 where: {
155 id: projectId,
156 },
157 select: {
158 instanceId: true,
159 githubToken: true,
160 deployKey: true,
161 },
162 });
163 if (p === null) {
164 resp.status(404);
165 return;
166 }
167 await db.project.update({
168 where: {
169 id: projectId,
170 },
171 data: {
172 draft: state,
173 },
174 });
175 let r: { status: number; data: { id: string; deployKey: string } };
176 if (p.instanceId == null) {
177 r = await axios.request({
178 url: "http://appmanager.hgrz-appmanager.svc.cluster.local/api/dodo-app",
179 method: "post",
180 data: {
181 config: req.body.config,
182 },
183 });
184 console.log(r);
185 if (r.status === 200) {
186 await db.project.update({
187 where: {
188 id: projectId,
189 },
190 data: {
191 state,
192 draft: null,
193 instanceId: r.data.id,
194 deployKey: r.data.deployKey,
195 },
196 });
197
198 if (p.githubToken && r.data.deployKey) {
199 const stateObj = JSON.parse(JSON.parse(state.toString()));
200 const githubNodes = stateObj.nodes.filter(
201 (n: any) => n.type === "github" && n.data?.repository?.id,
202 );
203
204 const github = new GithubClient(p.githubToken);
205 for (const node of githubNodes) {
206 try {
207 await github.addDeployKey(node.data.repository.sshURL, r.data.deployKey);
208 } catch (error) {
209 console.error(
210 `Failed to add deploy key to repository ${node.data.repository.sshURL}:`,
211 error,
212 );
213 }
214 }
215 }
216 }
217 } else {
218 r = await axios.request({
219 url: `http://appmanager.hgrz-appmanager.svc.cluster.local/api/dodo-app/${p.instanceId}`,
220 method: "put",
221 data: {
222 config: req.body.config,
223 },
224 });
225 if (r.status === 200) {
226 await db.project.update({
227 where: {
228 id: projectId,
229 },
230 data: {
231 state,
232 draft: null,
233 },
234 });
235 }
236 }
237 } catch (e) {
238 console.log(e);
239 resp.status(500);
240 } finally {
241 resp.end();
242 }
243};
244
245const handleStatus: express.Handler = async (req, resp) => {
246 try {
247 const projectId = Number(req.params["projectId"]);
248 const p = await db.project.findUnique({
249 where: {
250 id: projectId,
251 },
252 select: {
253 instanceId: true,
254 },
255 });
256 console.log(projectId, p);
257 if (p === null) {
258 resp.status(404);
259 return;
260 }
261 if (p.instanceId == null) {
262 resp.status(404);
263 return;
264 }
265 const r = await axios.request({
266 url: `http://appmanager.hgrz-appmanager.svc.cluster.local/api/instance/${p.instanceId}/status`,
267 method: "get",
268 });
269 resp.status(r.status);
270 if (r.status === 200) {
271 resp.write(JSON.stringify(r.data));
272 }
273 } catch (e) {
274 console.log(e);
275 resp.status(500);
276 } finally {
277 resp.end();
278 }
279};
280
281const handleGithubRepos: express.Handler = async (req, resp) => {
282 try {
283 const projectId = Number(req.params["projectId"]);
284 const project = await db.project.findUnique({
285 where: { id: projectId },
286 select: { githubToken: true },
287 });
288
289 if (!project?.githubToken) {
290 resp.status(400);
291 resp.write(JSON.stringify({ error: "GitHub token not configured" }));
292 return;
293 }
294
295 const github = new GithubClient(project.githubToken);
296 const repositories = await github.getRepositories();
297
298 resp.status(200);
299 resp.header("Content-Type", "application/json");
300 resp.write(JSON.stringify(repositories));
301 } catch (e) {
302 console.log(e);
303 resp.status(500);
304 resp.write(JSON.stringify({ error: "Failed to fetch repositories" }));
305 } finally {
306 resp.end();
307 }
308};
309
310const handleUpdateGithubToken: express.Handler = async (req, resp) => {
311 try {
312 const projectId = Number(req.params["projectId"]);
313 const { githubToken } = req.body;
314
315 await db.project.update({
316 where: { id: projectId },
317 data: { githubToken },
318 });
319
320 resp.status(200);
321 } catch (e) {
322 console.log(e);
323 resp.status(500);
324 } finally {
325 resp.end();
326 }
327};
328
329const handleEnv: express.Handler = async (req, resp) => {
330 const projectId = Number(req.params["projectId"]);
331 try {
332 const project = await db.project.findUnique({
333 where: { id: projectId },
334 select: {
335 deployKey: true,
336 githubToken: true,
337 },
338 });
339
340 if (!project) {
341 resp.status(404);
342 resp.write(JSON.stringify({ error: "Project not found" }));
343 return;
344 }
345
346 resp.status(200);
347 resp.write(
348 JSON.stringify({
349 deployKey: project.deployKey,
350 integrations: {
351 github: !!project.githubToken,
352 },
353 networks: [
354 {
355 name: "Public",
356 domain: "v1.dodo.cloud",
357 },
358 {
359 name: "Private",
360 domain: "p.v1.dodo.cloud",
361 },
362 ],
363 }),
364 );
365 } catch (error) {
366 console.error("Error checking integrations:", error);
367 resp.status(500);
368 resp.write(JSON.stringify({ error: "Internal server error" }));
369 } finally {
370 resp.end();
371 }
372};
373
374async function start() {
375 await db.$connect();
376 const app = express();
377 app.use(express.json());
378 app.post("/api/project/:projectId/saved", handleSave);
379 app.get("/api/project/:projectId/saved", handleSavedGet);
380 app.post("/api/project/:projectId/deploy", handleDeploy);
381 app.get("/api/project/:projectId/status", handleStatus);
382 app.delete("/api/project/:projectId", handleDelete);
383 app.get("/api/project", handleProjectAll);
384 app.post("/api/project", handleProjectCreate);
385 app.get("/api/project/:projectId/repos/github", handleGithubRepos);
386 app.post("/api/project/:projectId/github-token", handleUpdateGithubToken);
387 app.get("/api/project/:projectId/env", handleEnv);
388 app.use("/", express.static("../front/dist"));
389 app.listen(env.DODO_PORT_WEB, () => {
390 console.log("started");
391 });
392}
393
394start();