blob: 4fa8cfd529642cda1c494ddaa1e539472862b143 [file] [log] [blame]
gio3ed59592025-05-14 16:51:09 +00001import axios from "axios";
2import { z } from "zod";
3
giocc5ce582025-06-25 07:45:21 +04004export const accessSchema = z.discriminatedUnion("type", [
giob77cb932025-05-19 09:37:14 +00005 z.object({
6 type: z.literal("https"),
7 name: z.string(),
8 address: z.string(),
giocc5ce582025-06-25 07:45:21 +04009 agentName: z.string().optional(),
giob77cb932025-05-19 09:37:14 +000010 }),
11 z.object({
12 type: z.literal("ssh"),
13 name: z.string(),
14 host: z.string(),
15 port: z.number(),
16 }),
17 z.object({
18 type: z.literal("tcp"),
19 name: z.string(),
20 host: z.string(),
21 port: z.number(),
22 }),
23 z.object({
24 type: z.literal("udp"),
25 name: z.string(),
26 host: z.string(),
27 port: z.number(),
28 }),
29 z.object({
30 type: z.literal("postgresql"),
31 name: z.string(),
32 host: z.string(),
33 port: z.number(),
34 database: z.string(),
35 username: z.string(),
36 password: z.string(),
37 }),
38 z.object({
39 type: z.literal("mongodb"),
40 name: z.string(),
41 host: z.string(),
42 port: z.number(),
43 database: z.string(),
44 username: z.string(),
45 password: z.string(),
46 }),
47]);
48
gio3ed59592025-05-14 16:51:09 +000049export const DeployResponseSchema = z.object({
50 id: z.string(),
51 deployKey: z.string(),
giob77cb932025-05-19 09:37:14 +000052 access: z.array(accessSchema),
gioe085d5b2025-07-08 07:51:36 +000053 envVars: z.array(z.object({ name: z.string(), value: z.string() })),
gio3ed59592025-05-14 16:51:09 +000054});
55
56export type DeployResponse = z.infer<typeof DeployResponseSchema>;
57
58export class AppManager {
59 private baseUrl: string;
60
61 constructor(baseUrl: string = "http://appmanager.hgrz-appmanager.svc.cluster.local") {
62 this.baseUrl = baseUrl;
63 }
64
65 async deploy(config: unknown): Promise<DeployResponse> {
66 const response = await axios.request({
67 url: `${this.baseUrl}/api/dodo-app`,
68 method: "post",
69 data: { config },
70 });
71 if (response.status !== 200) {
72 throw new Error(`Failed to deploy application: ${response.statusText}`);
73 }
74 const result = DeployResponseSchema.safeParse(response.data);
75 if (!result.success) {
76 throw new Error(`Invalid deploy response format: ${result.error.message}`);
77 }
78 return result.data;
79 }
80
giob77cb932025-05-19 09:37:14 +000081 async update(instanceId: string, config: unknown): Promise<DeployResponse> {
gio3ed59592025-05-14 16:51:09 +000082 const response = await axios.request({
83 url: `${this.baseUrl}/api/dodo-app/${instanceId}`,
84 method: "put",
85 data: { config },
86 });
giob77cb932025-05-19 09:37:14 +000087 if (response.status !== 200) {
88 throw new Error(`Failed to update application: ${response.statusText}`);
89 }
90 const result = DeployResponseSchema.safeParse(response.data);
91 if (!result.success) {
92 throw new Error(`Invalid update response format: ${result.error.message}`);
93 }
94 return result.data;
gio3ed59592025-05-14 16:51:09 +000095 }
96
97 async getStatus(instanceId: string): Promise<unknown> {
98 const response = await axios.request({
99 url: `${this.baseUrl}/api/instance/${instanceId}/status`,
100 method: "get",
101 });
102 if (response.status !== 200) {
103 throw new Error(`Failed to get application status: ${response.statusText}`);
104 }
105 return response.data;
106 }
107
108 async removeInstance(instanceId: string): Promise<boolean> {
109 const response = await axios.request({
110 url: `${this.baseUrl}/api/instance/${instanceId}/remove`,
111 method: "post",
112 });
113 return response.status === 200;
114 }
115}