1import * as Schema from "effect/Schema";
2import { ProjectId, ThreadId, TrimmedNonEmptyString } from "./baseSchemas.ts";
3
4export const DevServerTarget = Schema.Union([
5 Schema.Struct({ _tag: Schema.Literal("Thread"), threadId: ThreadId }),
6 Schema.Struct({
7 _tag: Schema.Literal("Project"),
8 projectId: ProjectId,
9 workspacePath: TrimmedNonEmptyString,
10 }),
11]);
12export type DevServerTarget = typeof DevServerTarget.Type;
13
14export const DevServerStatus = Schema.Struct({
15 workspaceRoot: Schema.String,
16 canStart: Schema.Boolean,
17 environment: Schema.NullOr(Schema.String),
18 stopping: Schema.Boolean,
19 services: Schema.Array(
20 Schema.Struct({ id: Schema.String, status: Schema.String, url: Schema.NullOr(Schema.String) }),
21 ),
22 frontendUrl: Schema.NullOr(Schema.String),
23});
24export type DevServerStatus = typeof DevServerStatus.Type;
25
26export class DevServerError extends Schema.TaggedError<DevServerError>()("DevServerError", {
27 reason: Schema.Literals(["workspace", "status", "unsupported", "launch", "not-ready"]),
28 cause: Schema.optional(Schema.Defect()),
29}) {
30 override get message(): string {
31 switch (this.reason) {
32 case "workspace":
33 return "Workspace unavailable. Open another thread and try again.";
34 case "status":
35 return "Server status unavailable. Check the dev server and try again.";
36 case "unsupported":
37 return "Start this workspace's dev server in a terminal, then try again.";
38 case "launch":
39 return "Server did not start. Check .dev-tui/server.log and try again.";
40 case "not-ready":
41 return "Frontend unavailable. Check the dev server and try again.";
42 }
43 }
44}