blob: 325216c1e8fce1da5b8cd8f3f20a13cfbc902390 [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 }),
gio8323a052025-08-04 06:12:26 +000047 z.object({
48 type: z.literal("env_var"),
49 name: z.string(),
50 var: z.string(),
51 }),
giob77cb932025-05-19 09:37:14 +000052]);
53
gio3ed59592025-05-14 16:51:09 +000054export const DeployResponseSchema = z.object({
55 id: z.string(),
56 deployKey: z.string(),
giob77cb932025-05-19 09:37:14 +000057 access: z.array(accessSchema),
gioe085d5b2025-07-08 07:51:36 +000058 envVars: z.array(z.object({ name: z.string(), value: z.string() })),
gio3ed59592025-05-14 16:51:09 +000059});
60
61export type DeployResponse = z.infer<typeof DeployResponseSchema>;
62
63export class AppManager {
64 private baseUrl: string;
65
66 constructor(baseUrl: string = "http://appmanager.hgrz-appmanager.svc.cluster.local") {
67 this.baseUrl = baseUrl;
68 }
69
70 async deploy(config: unknown): Promise<DeployResponse> {
71 const response = await axios.request({
72 url: `${this.baseUrl}/api/dodo-app`,
73 method: "post",
74 data: { config },
75 });
76 if (response.status !== 200) {
77 throw new Error(`Failed to deploy application: ${response.statusText}`);
78 }
79 const result = DeployResponseSchema.safeParse(response.data);
80 if (!result.success) {
81 throw new Error(`Invalid deploy response format: ${result.error.message}`);
82 }
83 return result.data;
84 }
85
giob77cb932025-05-19 09:37:14 +000086 async update(instanceId: string, config: unknown): Promise<DeployResponse> {
gio3ed59592025-05-14 16:51:09 +000087 const response = await axios.request({
88 url: `${this.baseUrl}/api/dodo-app/${instanceId}`,
89 method: "put",
90 data: { config },
91 });
giob77cb932025-05-19 09:37:14 +000092 if (response.status !== 200) {
93 throw new Error(`Failed to update application: ${response.statusText}`);
94 }
95 const result = DeployResponseSchema.safeParse(response.data);
96 if (!result.success) {
97 throw new Error(`Invalid update response format: ${result.error.message}`);
98 }
99 return result.data;
gio3ed59592025-05-14 16:51:09 +0000100 }
101
102 async getStatus(instanceId: string): Promise<unknown> {
103 const response = await axios.request({
104 url: `${this.baseUrl}/api/instance/${instanceId}/status`,
105 method: "get",
106 });
107 if (response.status !== 200) {
108 throw new Error(`Failed to get application status: ${response.statusText}`);
109 }
110 return response.data;
111 }
112
113 async removeInstance(instanceId: string): Promise<boolean> {
114 const response = await axios.request({
115 url: `${this.baseUrl}/api/instance/${instanceId}/remove`,
116 method: "post",
117 });
118 return response.status === 200;
119 }
120}