blob: e8741f9e2db3cbff943c7f4393679bce4307d2d7 [file] [log] [blame]
gioc31bf142025-06-16 07:48:20 +00001import { z } from "zod";
2import { Node } from "@xyflow/react";
3import { Domain, ServiceType, VolumeType } from "./types.js";
4
5export const serviceAnalyzisSchema = z.object({
6 name: z.string(),
7 location: z.string(),
8 configVars: z.array(
9 z.object({
10 name: z.string(),
11 category: z.enum(["CommandLineFlag", "EnvironmentVariable"]),
12 type: z.optional(z.enum(["String", "Number", "Boolean"])),
13 semanticType: z.optional(
14 z.enum([
15 "EXPANDED_ENV_VAR",
16 "PORT",
17 "FILESYSTEM_PATH",
18 "DATABASE_URL",
19 "SQLITE_PATH",
20 "POSTGRES_URL",
21 "POSTGRES_PASSWORD",
22 "POSTGRES_USER",
23 "POSTGRES_DB",
24 "POSTGRES_PORT",
25 "POSTGRES_HOST",
26 "POSTGRES_SSL",
27 "MONGO_URL",
28 "MONGO_PASSWORD",
29 "MONGO_USER",
30 "MONGO_DB",
31 "MONGO_PORT",
32 "MONGO_HOST",
33 "MONGO_SSL",
34 ]),
35 ),
36 }),
37 ),
38});
39
40export type BoundEnvVar =
41 | {
42 id: string;
43 source: string | null;
44 }
45 | {
46 id: string;
47 source: string | null;
48 name: string;
49 isEditting: boolean;
50 }
51 | {
52 id: string;
53 source: string | null;
54 name: string;
55 alias: string;
56 isEditting: boolean;
57 }
58 | {
59 id: string;
60 source: string | null;
61 portId: string;
62 name: string;
63 alias: string;
64 isEditting: boolean;
65 };
66
67export type EnvVar = {
68 name: string;
69 value: string;
70};
71
72export type InitData = {
73 label: string;
74 envVars: BoundEnvVar[];
75 ports: Port[];
76};
77
78export type NodeData = InitData & {
79 activeField?: string | undefined;
80 state?: string | null;
81};
82
83export type PortConnectedTo = {
84 serviceId: string;
85 portId: string;
86};
87
88export type NetworkData = NodeData & {
89 domain: string;
90};
91
92export type NetworkNode = Node<NetworkData> & {
93 type: "network";
94};
95
96export type GatewayHttpsData = NodeData & {
97 readonly?: boolean;
98 network?: string;
99 subdomain?: string;
100 https?: PortConnectedTo;
101 auth?: {
102 enabled: boolean;
103 groups: string[];
104 noAuthPathPatterns: string[];
105 };
106};
107
108export type GatewayHttpsNode = Node<GatewayHttpsData> & {
109 type: "gateway-https";
110};
111
112export type GatewayTCPData = NodeData & {
113 readonly?: boolean;
114 network?: string;
115 subdomain?: string;
116 exposed: PortConnectedTo[];
117 selected?: {
118 serviceId?: string;
119 portId?: string;
120 };
121};
122
123export type GatewayTCPNode = Node<GatewayTCPData> & {
124 type: "gateway-tcp";
125};
126
127export type Port = {
128 id: string;
129 name: string;
130 value: number;
131};
132
133export type ServiceData = NodeData & {
134 type: ServiceType;
135 repository?:
136 | {
137 id: number;
138 repoNodeId: string;
139 }
140 | {
141 id: number;
142 repoNodeId: string;
143 branch: string;
144 }
145 | {
146 id: number;
147 repoNodeId: string;
148 branch: string;
149 rootDir: string;
150 };
151 env: string[];
152 volume: string[];
153 preBuildCommands: string;
154 isChoosingPortToConnect: boolean;
155 dev?:
156 | {
157 enabled: false;
158 expose?: Domain;
159 }
160 | {
161 enabled: true;
162 expose?: Domain;
163 codeServerNodeId: string;
164 sshNodeId: string;
165 };
166 info?: z.infer<typeof serviceAnalyzisSchema>;
167};
168
169export type ServiceNode = Node<ServiceData> & {
170 type: "app";
171};
172
173export type VolumeData = NodeData & {
174 type: VolumeType;
175 size: string;
176 attachedTo: string[];
177};
178
179export type VolumeNode = Node<VolumeData> & {
180 type: "volume";
181};
182
183export type PostgreSQLData = NodeData & {
184 volumeId: string;
185};
186
187export type PostgreSQLNode = Node<PostgreSQLData> & {
188 type: "postgresql";
189};
190
191export type MongoDBData = NodeData & {
192 volumeId: string;
193};
194
195export type MongoDBNode = Node<MongoDBData> & {
196 type: "mongodb";
197};
198
199export type GithubData = NodeData & {
200 repository?: {
201 id: number;
202 sshURL: string;
203 fullName: string;
204 };
205};
206
207export type GithubNode = Node<GithubData> & {
208 type: "github";
209};
210
211export type NANode = Node<NodeData> & {
212 type: undefined;
213};
214
215export type AppNode =
216 | NetworkNode
217 | GatewayHttpsNode
218 | GatewayTCPNode
219 | ServiceNode
220 | VolumeNode
221 | PostgreSQLNode
222 | MongoDBNode
223 | GithubNode
224 | NANode;
225
226export type NodeType = Exclude<Pick<AppNode, "type">["type"], undefined>;
227
228export const networkSchema = z.object({
229 name: z.string().min(1),
230 domain: z.string().min(1),
231 hasAuth: z.boolean(),
232});
233
234export type Network = z.infer<typeof networkSchema>;
235
236export const accessSchema = z.discriminatedUnion("type", [
237 z.object({
238 type: z.literal("https"),
239 name: z.string(),
240 address: z.string(),
241 }),
242 z.object({
243 type: z.literal("ssh"),
244 name: z.string(),
245 host: z.string(),
246 port: z.number(),
247 }),
248 z.object({
249 type: z.literal("tcp"),
250 name: z.string(),
251 host: z.string(),
252 port: z.number(),
253 }),
254 z.object({
255 type: z.literal("udp"),
256 name: z.string(),
257 host: z.string(),
258 port: z.number(),
259 }),
260 z.object({
261 type: z.literal("postgresql"),
262 name: z.string(),
263 host: z.string(),
264 port: z.number(),
265 database: z.string(),
266 username: z.string(),
267 password: z.string(),
268 }),
269 z.object({
270 type: z.literal("mongodb"),
271 name: z.string(),
272 host: z.string(),
273 port: z.number(),
274 database: z.string(),
275 username: z.string(),
276 password: z.string(),
277 }),
278]);
279
280export const serviceInfoSchema = z.object({
281 name: z.string(),
282 workers: z.array(
283 z.object({
284 id: z.string(),
285 commit: z.optional(
286 z.object({
287 hash: z.string(),
288 message: z.string(),
289 }),
290 ),
291 commands: z.optional(
292 z.array(
293 z.object({
294 command: z.string(),
295 state: z.string(),
296 }),
297 ),
298 ),
299 }),
300 ),
301});
302
303export const envSchema = z.object({
304 managerAddr: z.optional(z.string().min(1)),
305 instanceId: z.optional(z.string().min(1)),
306 deployKeyPublic: z.optional(z.nullable(z.string().min(1))),
307 networks: z.array(networkSchema).default([]),
308 integrations: z.object({
309 github: z.boolean(),
310 }),
311 services: z.array(serviceInfoSchema),
312 user: z.object({
313 id: z.string(),
314 username: z.string(),
315 }),
316 access: z.array(accessSchema),
317});
318
319export type ServiceInfo = z.infer<typeof serviceInfoSchema>;
320export type Env = z.infer<typeof envSchema>;