effect-start 0.26.0 → 0.27.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (58) hide show
  1. package/package.json +4 -2
  2. package/src/Entity.ts +6 -6
  3. package/src/FileRouterCodegen.ts +4 -4
  4. package/src/FileSystem.ts +4 -8
  5. package/src/RouteHook.ts +1 -1
  6. package/src/RouteSse.ts +3 -3
  7. package/src/SqlIntrospect.ts +2 -2
  8. package/src/Start.ts +102 -2
  9. package/src/Values.ts +11 -0
  10. package/src/bun/BunRoute.ts +1 -1
  11. package/src/bun/BunRuntime.ts +5 -5
  12. package/src/hyper/HyperHtml.ts +11 -7
  13. package/src/hyper/jsx.d.ts +1 -1
  14. package/src/lint/plugin.js +174 -4
  15. package/src/sql/SqlClient.ts +355 -0
  16. package/src/sql/bun/index.ts +117 -50
  17. package/src/sql/index.ts +1 -1
  18. package/src/sql/libsql/index.ts +91 -77
  19. package/src/sql/libsql/libsql.d.ts +4 -1
  20. package/src/sql/mssql/index.ts +141 -108
  21. package/src/sql/mssql/mssql.d.ts +1 -0
  22. package/src/testing/TestLogger.ts +4 -4
  23. package/src/x/tailwind/compile.ts +6 -14
  24. package/src/console/Console.ts +0 -42
  25. package/src/console/ConsoleErrors.ts +0 -213
  26. package/src/console/ConsoleLogger.ts +0 -56
  27. package/src/console/ConsoleMetrics.ts +0 -72
  28. package/src/console/ConsoleProcess.ts +0 -59
  29. package/src/console/ConsoleStore.ts +0 -187
  30. package/src/console/ConsoleTracer.ts +0 -107
  31. package/src/console/Simulation.ts +0 -814
  32. package/src/console/console.html +0 -340
  33. package/src/console/index.ts +0 -3
  34. package/src/console/routes/errors/route.tsx +0 -97
  35. package/src/console/routes/fiberDetail.tsx +0 -54
  36. package/src/console/routes/fibers/route.tsx +0 -45
  37. package/src/console/routes/git/route.tsx +0 -64
  38. package/src/console/routes/layout.tsx +0 -4
  39. package/src/console/routes/logs/route.tsx +0 -77
  40. package/src/console/routes/metrics/route.tsx +0 -36
  41. package/src/console/routes/route.tsx +0 -8
  42. package/src/console/routes/routes/route.tsx +0 -30
  43. package/src/console/routes/services/route.tsx +0 -21
  44. package/src/console/routes/system/route.tsx +0 -43
  45. package/src/console/routes/traceDetail.tsx +0 -22
  46. package/src/console/routes/traces/route.tsx +0 -81
  47. package/src/console/routes/tree.ts +0 -30
  48. package/src/console/ui/Errors.tsx +0 -76
  49. package/src/console/ui/Fibers.tsx +0 -321
  50. package/src/console/ui/Git.tsx +0 -182
  51. package/src/console/ui/Logs.tsx +0 -46
  52. package/src/console/ui/Metrics.tsx +0 -78
  53. package/src/console/ui/Routes.tsx +0 -125
  54. package/src/console/ui/Services.tsx +0 -273
  55. package/src/console/ui/Shell.tsx +0 -62
  56. package/src/console/ui/System.tsx +0 -131
  57. package/src/console/ui/Traces.tsx +0 -426
  58. package/src/sql/Sql.ts +0 -51
@@ -1,182 +0,0 @@
1
- export interface GitFileEntry {
2
- readonly status: string
3
- readonly path: string
4
- }
5
-
6
- export interface GitStatus {
7
- readonly oid: string
8
- readonly head: string
9
- readonly upstream: string | undefined
10
- readonly ahead: number
11
- readonly behind: number
12
- readonly tag: string | undefined
13
- readonly tagDistance: number
14
- readonly staged: Array<GitFileEntry>
15
- readonly unstaged: Array<GitFileEntry>
16
- readonly untracked: Array<string>
17
- }
18
-
19
- const xyToLabel: Record<string, string> = {
20
- M: "modified",
21
- A: "new file",
22
- D: "deleted",
23
- R: "renamed",
24
- C: "copied",
25
- T: "typechange",
26
- U: "unmerged",
27
- }
28
-
29
- function statusLabel(code: string): string {
30
- return xyToLabel[code] ?? code
31
- }
32
-
33
- function gitStatusColor(code: string): string {
34
- if (code === "D") return "#ef4444"
35
- if (code === "A") return "#4ade80"
36
- if (code === "R" || code === "C") return "#60a5fa"
37
- if (code === "M") return "#fbbf24"
38
- return "#94a3b8"
39
- }
40
-
41
- export function parseGitStatus(porcelain: string, tagLine: string): GitStatus {
42
- const lines = porcelain.split("\n")
43
- let oid = ""
44
- let head = ""
45
- let upstream: string | undefined
46
- let ahead = 0
47
- let behind = 0
48
- const staged: Array<GitFileEntry> = []
49
- const unstaged: Array<GitFileEntry> = []
50
- const untracked: Array<string> = []
51
-
52
- for (const line of lines) {
53
- if (line.startsWith("# branch.oid ")) {
54
- oid = line.slice("# branch.oid ".length, "# branch.oid ".length + 7)
55
- } else if (line.startsWith("# branch.head ")) {
56
- head = line.slice("# branch.head ".length)
57
- } else if (line.startsWith("# branch.upstream ")) {
58
- upstream = line.slice("# branch.upstream ".length)
59
- } else if (line.startsWith("# branch.ab ")) {
60
- const parts = line.slice("# branch.ab ".length).split(" ")
61
- ahead = parseInt(parts[0]?.slice(1) ?? "0", 10)
62
- behind = parseInt(parts[1]?.slice(1) ?? "0", 10)
63
- } else if (line.startsWith("1 ") || line.startsWith("2 ")) {
64
- const xy = line.slice(2, 4)
65
- const x = xy[0]
66
- const y = xy[1]
67
- const parts = line.split("\t")
68
- const firstParts = parts[0].split(" ")
69
- const path = parts.length > 1 ? parts[1] : firstParts[firstParts.length - 1]
70
- if (x !== "." && x !== "?") staged.push({ status: x, path })
71
- if (y !== "." && y !== "?") unstaged.push({ status: y, path })
72
- } else if (line.startsWith("u ")) {
73
- const parts = line.split("\t")
74
- const path = parts.length > 1 ? parts[1] : line.split(" ").pop()!
75
- staged.push({ status: "U", path })
76
- } else if (line.startsWith("? ")) {
77
- untracked.push(line.slice(2))
78
- }
79
- }
80
-
81
- let tag: string | undefined
82
- let tagDistance = 0
83
- const tagParts = tagLine.trim().split("\n")
84
- if (tagParts[0] && !tagParts[0].startsWith("fatal")) {
85
- tag = tagParts[0]
86
- tagDistance = parseInt(tagParts[1] ?? "0", 10)
87
- }
88
-
89
- return { oid, head, upstream, ahead, behind, tag, tagDistance, staged, unstaged, untracked }
90
- }
91
-
92
- function GitKV({ label, children }: { label: string; children: any }) {
93
- return (
94
- <div style="display:flex;gap:8px;padding:3px 0;font-size:13px;font-family:monospace">
95
- <span style="color:#6b7280;min-width:80px">{label}</span>
96
- <span style="color:#e5e7eb">{children}</span>
97
- </div>
98
- )
99
- }
100
-
101
- function GitFileRow({ entry }: { entry: GitFileEntry }) {
102
- const label = statusLabel(entry.status)
103
- const color = gitStatusColor(entry.status)
104
- return (
105
- <div style="display:flex;gap:12px;padding:2px 0;font-size:13px;font-family:monospace">
106
- <span style={`color:${color};font-style:italic;min-width:80px`}>{label}</span>
107
- <span style="color:#d1d5db">{entry.path}</span>
108
- </div>
109
- )
110
- }
111
-
112
- function SectionHeader({ title, count }: { title: string; count: number }) {
113
- return (
114
- <div style="color:#fbbf24;font-size:14px;font-weight:600;padding:16px 0 6px;font-family:monospace">
115
- {title} ({count})
116
- </div>
117
- )
118
- }
119
-
120
- export function GitStatusView({ status }: { status: GitStatus }) {
121
- return (
122
- <div style="padding:12px 16px">
123
- <GitKV label="Head:">
124
- <span style="color:#94a3b8;font-style:italic">{status.oid}</span>{" "}
125
- <span style="color:#4ade80;font-weight:600">{status.head}</span>
126
- </GitKV>
127
- {status.upstream && (
128
- <GitKV label="Upstream:">
129
- <span style="color:#94a3b8;font-style:italic">{status.oid}</span>{" "}
130
- <span style="color:#60a5fa;font-weight:600">{status.upstream}</span>
131
- {(status.ahead > 0 || status.behind > 0) && (
132
- <span style="color:#94a3b8">
133
- {status.ahead > 0 ? ` +${status.ahead}` : ""}
134
- {status.behind > 0 ? ` -${status.behind}` : ""}
135
- </span>
136
- )}
137
- </GitKV>
138
- )}
139
- {status.tag && (
140
- <GitKV label="Tag:">
141
- <span style="color:#e5e7eb">{status.tag}</span>
142
- {status.tagDistance > 0 && <span style="color:#60a5fa"> ({status.tagDistance})</span>}
143
- </GitKV>
144
- )}
145
-
146
- {status.untracked.length > 0 && (
147
- <>
148
- <SectionHeader title="Untracked files" count={status.untracked.length} />
149
- {status.untracked.map((f) => (
150
- <div style="padding:2px 0;font-size:13px;font-family:monospace;color:#d1d5db">{f}</div>
151
- ))}
152
- </>
153
- )}
154
-
155
- {status.unstaged.length > 0 && (
156
- <>
157
- <SectionHeader title="Unstaged changes" count={status.unstaged.length} />
158
- {status.unstaged.map((e) => (
159
- <GitFileRow entry={e} />
160
- ))}
161
- </>
162
- )}
163
-
164
- {status.staged.length > 0 && (
165
- <>
166
- <SectionHeader title="Staged changes" count={status.staged.length} />
167
- {status.staged.map((e) => (
168
- <GitFileRow entry={e} />
169
- ))}
170
- </>
171
- )}
172
-
173
- {status.untracked.length === 0 &&
174
- status.unstaged.length === 0 &&
175
- status.staged.length === 0 && (
176
- <div style="color:#4ade80;font-size:13px;font-family:monospace;padding:16px 0">
177
- Clean working tree
178
- </div>
179
- )}
180
- </div>
181
- )
182
- }
@@ -1,46 +0,0 @@
1
- import * as ConsoleStore from "../ConsoleStore.ts"
2
-
3
- function levelColor(level: string): string {
4
- if (level === "DEBUG") return "#94a3b8"
5
- if (level === "INFO") return "#60a5fa"
6
- if (level === "WARNING") return "#fbbf24"
7
- if (level === "ERROR") return "#ef4444"
8
- if (level === "FATAL") return "#dc2626"
9
- return "#e5e7eb"
10
- }
11
-
12
- export function LogLine({ log }: { log: ConsoleStore.ConsoleLog }) {
13
- const color = levelColor(log.level)
14
- const time = log.date.toLocaleTimeString("en", {
15
- hour12: false,
16
- hour: "2-digit",
17
- minute: "2-digit",
18
- second: "2-digit",
19
- })
20
-
21
- return (
22
- <div
23
- id={`log-${log.id}`}
24
- style="padding:3px 8px;border-bottom:1px solid #1f2937;font-family:monospace;font-size:12px;display:flex;align-items:baseline"
25
- >
26
- <span style="color:#6b7280;white-space:nowrap">{time}</span>
27
- <span style={`color:${color};font-weight:600;width:56px;text-align:center;flex-shrink:0`}>
28
- {log.level}
29
- </span>
30
- <span style="color:#e5e7eb;flex:1;min-width:0;overflow:hidden;text-overflow:ellipsis">
31
- {log.message}
32
- </span>
33
- <a
34
- href={`${ConsoleStore.store.prefix}/fibers/${log.fiberId.replace("#", "")}`}
35
- style="color:#6b7280;white-space:nowrap;margin-left:8px;text-decoration:none"
36
- >
37
- {log.fiberId}
38
- </a>
39
- {log.cause && (
40
- <div style="color:#ef4444;font-size:11px;padding:2px 0 0 0;white-space:pre-wrap;width:100%">
41
- {log.cause}
42
- </div>
43
- )}
44
- </div>
45
- )
46
- }
@@ -1,78 +0,0 @@
1
- import type * as ConsoleStore from "../ConsoleStore.ts"
2
-
3
- function MetricValue({ metric }: { metric: ConsoleStore.ConsoleMetricSnapshot }) {
4
- if (metric.type === "counter" || metric.type === "gauge") {
5
- return (
6
- <div style="font-size:32px;font-weight:700;color:#e5e7eb;font-family:monospace;line-height:1.1">
7
- {String(metric.value)}
8
- </div>
9
- )
10
- }
11
- if (metric.type === "histogram") {
12
- const h = metric.value as { count: number; sum: number; min: number; max: number }
13
- return (
14
- <div style="display:grid;grid-template-columns:auto auto;gap:2px 12px;font-size:12px;font-family:monospace">
15
- <span style="color:#6b7280">count</span>
16
- <span style="color:#e5e7eb">{h.count}</span>
17
- <span style="color:#6b7280">sum</span>
18
- <span style="color:#e5e7eb">{h.sum.toFixed(2)}</span>
19
- <span style="color:#6b7280">min</span>
20
- <span style="color:#e5e7eb">{h.min.toFixed(2)}</span>
21
- <span style="color:#6b7280">max</span>
22
- <span style="color:#e5e7eb">{h.max.toFixed(2)}</span>
23
- </div>
24
- )
25
- }
26
- if (metric.type === "frequency") {
27
- const occ = metric.value as Record<string, number>
28
- return (
29
- <div style="display:grid;grid-template-columns:auto auto;gap:2px 12px;font-size:12px;font-family:monospace">
30
- {Object.entries(occ)
31
- .slice(0, 10)
32
- .map(([k, v]) => (
33
- <>
34
- <span style="color:#6b7280">{k}</span>
35
- <span style="color:#e5e7eb">{v}</span>
36
- </>
37
- ))}
38
- </div>
39
- )
40
- }
41
- return (
42
- <pre style="font-size:11px;color:#9ca3af;margin:0;white-space:pre-wrap">
43
- {JSON.stringify(metric.value, null, 2)}
44
- </pre>
45
- )
46
- }
47
-
48
- function MetricCard({ metric }: { metric: ConsoleStore.ConsoleMetricSnapshot }) {
49
- return (
50
- <div style="background:#111827;border:1px solid #374151;border-radius:6px;padding:12px;min-width:200px">
51
- <div style="display:flex;align-items:center;gap:8px;margin-bottom:8px">
52
- <span style="color:#d1d5db;font-size:13px;font-weight:600">{metric.name}</span>
53
- <span style="font-size:10px;padding:1px 6px;border-radius:4px;background:#1e3a5f;color:#60a5fa">
54
- {metric.type}
55
- </span>
56
- </div>
57
- <MetricValue metric={metric} />
58
- {metric.tags.length > 0 && (
59
- <div style="font-size:10px;color:#6b7280;margin-top:4px">
60
- {metric.tags.map((t) => `${t.key}=${t.value}`).join(" ")}
61
- </div>
62
- )}
63
- </div>
64
- )
65
- }
66
-
67
- export function MetricsGrid({ metrics }: { metrics: Array<ConsoleStore.ConsoleMetricSnapshot> }) {
68
- if (metrics.length === 0) {
69
- return <div class="empty">Waiting for metrics...</div>
70
- }
71
- return (
72
- <>
73
- {metrics.map((m) => (
74
- <MetricCard metric={m} />
75
- ))}
76
- </>
77
- )
78
- }
@@ -1,125 +0,0 @@
1
- export interface RouteInfo {
2
- readonly method: string
3
- readonly path: string
4
- readonly format: string | undefined
5
- }
6
-
7
- function groupByPath(routes: Array<RouteInfo>): Array<{ path: string; routes: Array<RouteInfo> }> {
8
- const byPath = new Map<string, Array<RouteInfo>>()
9
- for (const r of routes) {
10
- let group = byPath.get(r.path)
11
- if (!group) {
12
- group = []
13
- byPath.set(r.path, group)
14
- }
15
- group.push(r)
16
- }
17
- return Array.from(byPath, ([path, routes]) => ({
18
- path,
19
- routes: routes.sort((a, b) => methodOrder.indexOf(a.method) - methodOrder.indexOf(b.method)),
20
- })).sort((a, b) => a.path.localeCompare(b.path))
21
- }
22
-
23
- function methodColor(method: string): string {
24
- if (method === "GET") return "#22c55e"
25
- if (method === "POST") return "#3b82f6"
26
- if (method === "PUT") return "#f59e0b"
27
- if (method === "DELETE") return "#ef4444"
28
- if (method === "PATCH") return "#a855f7"
29
- if (method === "*") return "#6b7280"
30
- return "#94a3b8"
31
- }
32
-
33
- function methodBg(method: string): string {
34
- if (method === "GET") return "#052e16"
35
- if (method === "POST") return "#172554"
36
- if (method === "PUT") return "#422006"
37
- if (method === "DELETE") return "#450a0a"
38
- if (method === "PATCH") return "#3b0764"
39
- return "#1e293b"
40
- }
41
-
42
- const methodOrder = ["GET", "POST", "PUT", "PATCH", "DELETE", "HEAD", "OPTIONS", "*"]
43
-
44
- function MethodBadge({ method }: { method: string }) {
45
- return (
46
- <span
47
- style={`font-size:10px;font-weight:700;font-family:monospace;padding:2px 6px;border-radius:3px;background:${methodBg(method)};color:${methodColor(method)};min-width:48px;text-align:center;display:inline-block`}
48
- >
49
- {method}
50
- </span>
51
- )
52
- }
53
-
54
- function FormatBadge({ format }: { format: string }) {
55
- return (
56
- <span style="font-size:10px;padding:1px 6px;border-radius:3px;background:#1e3a5f;color:#60a5fa">
57
- {format}
58
- </span>
59
- )
60
- }
61
-
62
- function ColoredPath({ path }: { path: string }) {
63
- const segments = path.split("/").filter(Boolean)
64
- return (
65
- <span style="font-family:monospace;font-size:13px">
66
- {segments.length === 0 ? (
67
- <span style="color:#e2e8f0">/</span>
68
- ) : (
69
- segments.map((seg) => {
70
- const isParam = seg.startsWith(":")
71
- return (
72
- <>
73
- <span style="color:#475569">/</span>
74
- <span style={isParam ? "color:#c084fc" : "color:#e2e8f0"}>{seg}</span>
75
- </>
76
- )
77
- })
78
- )}
79
- </span>
80
- )
81
- }
82
-
83
- function PathGroup({ path, routes }: { path: string; routes: Array<RouteInfo> }) {
84
- return (
85
- <div style="padding:8px 12px;border-bottom:1px solid #1e293b">
86
- <div style="margin-bottom:4px">
87
- <ColoredPath path={path} />
88
- </div>
89
- <div style="display:flex;flex-wrap:wrap;gap:4px">
90
- {routes.map((r) => (
91
- <div style="display:flex;align-items:center;gap:6px">
92
- <MethodBadge method={r.method} />
93
- {r.format && <FormatBadge format={r.format} />}
94
- </div>
95
- ))}
96
- </div>
97
- </div>
98
- )
99
- }
100
-
101
- export function RouteList({ routes }: { routes: Array<RouteInfo> }) {
102
- if (routes.length === 0) {
103
- return <div class="empty">No routes registered</div>
104
- }
105
-
106
- const groups = groupByPath(routes)
107
- const routeCount = routes.length
108
- const pathCount = groups.length
109
-
110
- return (
111
- <>
112
- <div style="padding:8px 12px;border-bottom:1px solid #1e293b;display:flex;gap:16px;font-size:12px;color:#64748b">
113
- <span>
114
- {pathCount} path{pathCount !== 1 ? "s" : ""}
115
- </span>
116
- <span>
117
- {routeCount} route{routeCount !== 1 ? "s" : ""}
118
- </span>
119
- </div>
120
- {groups.map((g) => (
121
- <PathGroup path={g.path} routes={g.routes} />
122
- ))}
123
- </>
124
- )
125
- }