effect-start 0.25.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 (174) hide show
  1. package/package.json +20 -86
  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/dist/ChildProcess.js +0 -42
  25. package/dist/Commander.js +0 -410
  26. package/dist/ContentNegotiation.js +0 -465
  27. package/dist/Cookies.js +0 -371
  28. package/dist/Development.js +0 -94
  29. package/dist/Effectify.js +0 -27
  30. package/dist/Entity.js +0 -289
  31. package/dist/Fetch.js +0 -192
  32. package/dist/FilePathPattern.js +0 -97
  33. package/dist/FileRouter.js +0 -204
  34. package/dist/FileRouterCodegen.js +0 -298
  35. package/dist/FileSystem.js +0 -132
  36. package/dist/Http.js +0 -107
  37. package/dist/PathPattern.js +0 -451
  38. package/dist/PlatformError.js +0 -40
  39. package/dist/PlatformRuntime.js +0 -71
  40. package/dist/Route.js +0 -143
  41. package/dist/RouteBody.js +0 -92
  42. package/dist/RouteError.js +0 -76
  43. package/dist/RouteHook.js +0 -64
  44. package/dist/RouteHttp.js +0 -367
  45. package/dist/RouteHttpTracer.js +0 -90
  46. package/dist/RouteMount.js +0 -86
  47. package/dist/RouteSchema.js +0 -271
  48. package/dist/RouteSse.js +0 -94
  49. package/dist/RouteTree.js +0 -119
  50. package/dist/RouteTrie.js +0 -179
  51. package/dist/SchemaExtra.js +0 -99
  52. package/dist/Socket.js +0 -40
  53. package/dist/SqlIntrospect.js +0 -515
  54. package/dist/Start.js +0 -79
  55. package/dist/StartApp.js +0 -3
  56. package/dist/StreamExtra.js +0 -135
  57. package/dist/System.js +0 -38
  58. package/dist/TuplePathPattern.js +0 -74
  59. package/dist/Unique.js +0 -226
  60. package/dist/Values.js +0 -52
  61. package/dist/bun/BunBundle.js +0 -186
  62. package/dist/bun/BunChildProcessSpawner.js +0 -142
  63. package/dist/bun/BunImportTrackerPlugin.js +0 -91
  64. package/dist/bun/BunRoute.js +0 -157
  65. package/dist/bun/BunRuntime.js +0 -41
  66. package/dist/bun/BunServer.js +0 -285
  67. package/dist/bun/BunVirtualFilesPlugin.js +0 -54
  68. package/dist/bun/_BunEnhancedResolve.js +0 -127
  69. package/dist/bun/index.js +0 -5
  70. package/dist/bundler/Bundle.js +0 -92
  71. package/dist/bundler/BundleFiles.js +0 -154
  72. package/dist/bundler/BundleRoute.js +0 -62
  73. package/dist/client/Overlay.js +0 -33
  74. package/dist/client/ScrollState.js +0 -106
  75. package/dist/client/index.js +0 -97
  76. package/dist/console/Console.js +0 -42
  77. package/dist/console/ConsoleErrors.js +0 -211
  78. package/dist/console/ConsoleLogger.js +0 -56
  79. package/dist/console/ConsoleMetrics.js +0 -72
  80. package/dist/console/ConsoleProcess.js +0 -59
  81. package/dist/console/ConsoleStore.js +0 -72
  82. package/dist/console/ConsoleTracer.js +0 -107
  83. package/dist/console/Simulation.js +0 -784
  84. package/dist/console/index.js +0 -3
  85. package/dist/console/routes/tree.js +0 -30
  86. package/dist/datastar/actions/fetch.js +0 -536
  87. package/dist/datastar/actions/peek.js +0 -13
  88. package/dist/datastar/actions/setAll.js +0 -19
  89. package/dist/datastar/actions/toggleAll.js +0 -19
  90. package/dist/datastar/attributes/attr.js +0 -49
  91. package/dist/datastar/attributes/bind.js +0 -194
  92. package/dist/datastar/attributes/class.js +0 -54
  93. package/dist/datastar/attributes/computed.js +0 -25
  94. package/dist/datastar/attributes/effect.js +0 -10
  95. package/dist/datastar/attributes/indicator.js +0 -33
  96. package/dist/datastar/attributes/init.js +0 -27
  97. package/dist/datastar/attributes/jsonSignals.js +0 -33
  98. package/dist/datastar/attributes/on.js +0 -81
  99. package/dist/datastar/attributes/onIntersect.js +0 -53
  100. package/dist/datastar/attributes/onInterval.js +0 -31
  101. package/dist/datastar/attributes/onSignalPatch.js +0 -51
  102. package/dist/datastar/attributes/ref.js +0 -11
  103. package/dist/datastar/attributes/show.js +0 -32
  104. package/dist/datastar/attributes/signals.js +0 -18
  105. package/dist/datastar/attributes/style.js +0 -57
  106. package/dist/datastar/attributes/text.js +0 -29
  107. package/dist/datastar/engine.js +0 -1145
  108. package/dist/datastar/index.js +0 -25
  109. package/dist/datastar/utils.js +0 -250
  110. package/dist/datastar/watchers/patchElements.js +0 -486
  111. package/dist/datastar/watchers/patchSignals.js +0 -14
  112. package/dist/experimental/EncryptedCookies.js +0 -328
  113. package/dist/experimental/index.js +0 -1
  114. package/dist/hyper/Hyper.js +0 -28
  115. package/dist/hyper/HyperHtml.js +0 -165
  116. package/dist/hyper/HyperNode.js +0 -13
  117. package/dist/hyper/HyperRoute.js +0 -45
  118. package/dist/hyper/html.js +0 -30
  119. package/dist/hyper/index.js +0 -5
  120. package/dist/hyper/jsx-runtime.js +0 -14
  121. package/dist/index.js +0 -8
  122. package/dist/node/NodeFileSystem.js +0 -675
  123. package/dist/node/NodeUtils.js +0 -23
  124. package/dist/sql/Sql.js +0 -8
  125. package/dist/sql/bun/index.js +0 -142
  126. package/dist/sql/index.js +0 -1
  127. package/dist/sql/libsql/index.js +0 -156
  128. package/dist/sql/mssql/docker.js +0 -110
  129. package/dist/sql/mssql/index.js +0 -194
  130. package/dist/testing/TestLogger.js +0 -42
  131. package/dist/testing/index.js +0 -2
  132. package/dist/testing/utils.js +0 -61
  133. package/dist/x/cloudflare/CloudflareTunnel.js +0 -63
  134. package/dist/x/cloudflare/index.js +0 -1
  135. package/dist/x/tailscale/TailscaleTunnel.js +0 -94
  136. package/dist/x/tailscale/index.js +0 -1
  137. package/dist/x/tailwind/TailwindPlugin.js +0 -294
  138. package/dist/x/tailwind/compile.js +0 -210
  139. package/dist/x/tailwind/plugin.js +0 -17
  140. package/src/console/Console.ts +0 -42
  141. package/src/console/ConsoleErrors.ts +0 -213
  142. package/src/console/ConsoleLogger.ts +0 -56
  143. package/src/console/ConsoleMetrics.ts +0 -72
  144. package/src/console/ConsoleProcess.ts +0 -59
  145. package/src/console/ConsoleStore.ts +0 -187
  146. package/src/console/ConsoleTracer.ts +0 -107
  147. package/src/console/Simulation.ts +0 -814
  148. package/src/console/console.html +0 -340
  149. package/src/console/index.ts +0 -3
  150. package/src/console/routes/errors/route.tsx +0 -97
  151. package/src/console/routes/fiberDetail.tsx +0 -54
  152. package/src/console/routes/fibers/route.tsx +0 -45
  153. package/src/console/routes/git/route.tsx +0 -64
  154. package/src/console/routes/layout.tsx +0 -4
  155. package/src/console/routes/logs/route.tsx +0 -77
  156. package/src/console/routes/metrics/route.tsx +0 -36
  157. package/src/console/routes/route.tsx +0 -8
  158. package/src/console/routes/routes/route.tsx +0 -30
  159. package/src/console/routes/services/route.tsx +0 -21
  160. package/src/console/routes/system/route.tsx +0 -43
  161. package/src/console/routes/traceDetail.tsx +0 -22
  162. package/src/console/routes/traces/route.tsx +0 -81
  163. package/src/console/routes/tree.ts +0 -30
  164. package/src/console/ui/Errors.tsx +0 -76
  165. package/src/console/ui/Fibers.tsx +0 -321
  166. package/src/console/ui/Git.tsx +0 -182
  167. package/src/console/ui/Logs.tsx +0 -46
  168. package/src/console/ui/Metrics.tsx +0 -78
  169. package/src/console/ui/Routes.tsx +0 -125
  170. package/src/console/ui/Services.tsx +0 -273
  171. package/src/console/ui/Shell.tsx +0 -62
  172. package/src/console/ui/System.tsx +0 -131
  173. package/src/console/ui/Traces.tsx +0 -426
  174. package/src/sql/Sql.ts +0 -51
@@ -1,273 +0,0 @@
1
- import * as Option from "effect/Option"
2
-
3
- const EffectTypeIds: Record<symbol, string> = {
4
- [Symbol.for("effect/Ref")]: "Ref",
5
- [Symbol.for("effect/SynchronizedRef")]: "SynchronizedRef",
6
- [Symbol.for("effect/QueueDequeue")]: "Dequeue",
7
- [Symbol.for("effect/QueueEnqueue")]: "Enqueue",
8
- [Symbol.for("effect/Pool")]: "Pool",
9
- [Symbol.for("effect/Deferred")]: "Deferred",
10
- [Symbol.for("effect/FiberRef")]: "FiberRef",
11
- [Symbol.for("effect/Scope")]: "Scope",
12
- [Symbol.for("effect/Tracer")]: "Tracer",
13
- [Symbol.for("effect/Request/Cache")]: "RequestCache",
14
- [Symbol.for("effect/Logger")]: "Logger",
15
- [Symbol.for("effect/Supervisor")]: "Supervisor",
16
- [Symbol.for("effect/Clock")]: "Clock",
17
- [Symbol.for("effect/Random")]: "Random",
18
- [Symbol.for("effect/KeyValueStore")]: "KeyValueStore",
19
- [Symbol.for("effect/RateLimiter")]: "RateLimiter",
20
- }
21
-
22
- function detectEffectType(value: unknown): string | undefined {
23
- if (value === null || value === undefined || typeof value !== "object") return undefined
24
- if ("publish" in value && "subscribe" in value && "offer" in value) return "PubSub"
25
- for (const sym of Object.getOwnPropertySymbols(value)) {
26
- const name = EffectTypeIds[sym]
27
- if (name) return name
28
- }
29
- return undefined
30
- }
31
-
32
- function inspectEffectValue(type: string, value: any): Record<string, unknown> {
33
- const info: Record<string, unknown> = { _type: type }
34
- try {
35
- switch (type) {
36
- case "PubSub": {
37
- if (typeof value.capacity === "function") info.capacity = value.capacity()
38
- if (typeof value.isActive === "function") info.active = value.isActive()
39
- if (typeof value.unsafeSize === "function") {
40
- const size = value.unsafeSize()
41
- info.size = Option.isSome(size) ? size.value : "shutdown"
42
- }
43
- if (value.pubsub && typeof value.pubsub.subscriberCount === "number") {
44
- info.subscribers = value.pubsub.subscriberCount
45
- }
46
- break
47
- }
48
- case "Enqueue":
49
- case "Dequeue": {
50
- if (typeof value.capacity === "function") info.capacity = value.capacity()
51
- if (typeof value.isActive === "function") info.active = value.isActive()
52
- if (typeof value.unsafeSize === "function") {
53
- const size = value.unsafeSize()
54
- info.size = Option.isSome(size) ? size.value : "shutdown"
55
- }
56
- break
57
- }
58
- case "Ref":
59
- case "SynchronizedRef": {
60
- if (value.ref && "current" in value.ref) {
61
- const current = value.ref.current
62
- info.value = safeSerialize(current)
63
- }
64
- break
65
- }
66
- case "Pool": {
67
- if (typeof value.minSize === "number") info.minSize = value.minSize
68
- if (typeof value.maxSize === "number") info.maxSize = value.maxSize
69
- if (typeof value.concurrency === "number") info.concurrency = value.concurrency
70
- if (value.items instanceof Set) info.items = value.items.size
71
- if (value.available instanceof Set) info.available = value.available.size
72
- if (value.invalidated instanceof Set) info.invalidated = value.invalidated.size
73
- if (typeof value.waiters === "number") info.waiters = value.waiters
74
- break
75
- }
76
- case "FiberRef": {
77
- if ("initial" in value) info.initial = safeSerialize(value.initial)
78
- break
79
- }
80
- case "Deferred": {
81
- if ("state" in value && value.state) {
82
- const state = value.state
83
- if (typeof state === "object" && "_tag" in state) {
84
- info.status = state._tag
85
- }
86
- }
87
- break
88
- }
89
- }
90
- } catch {
91
- // ignore introspection errors
92
- }
93
- return info
94
- }
95
-
96
- function safeSerialize(value: unknown): unknown {
97
- if (value === null || value === undefined) return value
98
- if (typeof value === "bigint") return `${value}n`
99
- if (typeof value === "function") return "<function>"
100
- if (typeof value === "symbol") return value.toString()
101
- if (typeof value !== "object") return value
102
- if (detectEffectType(value)) return `<${detectEffectType(value)}>`
103
- if (Array.isArray(value)) return value.map(safeSerialize)
104
- const proto = Object.getPrototypeOf(value)
105
- if (proto !== null && proto !== Object.prototype)
106
- return `<${proto.constructor?.name ?? "object"}>`
107
- const out: Record<string, unknown> = {}
108
- for (const [k, v] of Object.entries(value)) {
109
- if (typeof v === "function") continue
110
- out[k] = safeSerialize(v)
111
- }
112
- return out
113
- }
114
-
115
- export interface ServiceEntry {
116
- readonly key: string
117
- readonly kind: string
118
- readonly display: string
119
- readonly type: "config" | "value" | "effect"
120
- }
121
-
122
- function isJsonPrimitive(value: unknown): boolean {
123
- if (value === null) return true
124
- const t = typeof value
125
- return t === "string" || t === "number" || t === "boolean" || t === "bigint"
126
- }
127
-
128
- function isPlainJson(value: unknown): boolean {
129
- if (isJsonPrimitive(value)) return true
130
- if (Array.isArray(value)) return value.every(isPlainJson)
131
- if (typeof value === "object" && value !== null) {
132
- const proto = Object.getPrototypeOf(value)
133
- if (proto !== null && proto !== Object.prototype) return false
134
- return Object.values(value).every(isPlainJson)
135
- }
136
- return false
137
- }
138
-
139
- function jsonReplacer(_key: string, v: unknown): unknown {
140
- if (typeof v === "bigint") return `${v}n`
141
- return v
142
- }
143
-
144
- function collectDisplayValues(obj: unknown, prefix: string, out: Record<string, unknown>): void {
145
- if (typeof obj === "function") return
146
- if (isJsonPrimitive(obj) || Array.isArray(obj)) {
147
- out[prefix] = safeSerialize(obj)
148
- return
149
- }
150
- if (typeof obj === "object" && obj !== null) {
151
- const et = detectEffectType(obj)
152
- if (et) {
153
- out[prefix || et] = inspectEffectValue(et, obj)
154
- return
155
- }
156
- for (const [k, v] of Object.entries(obj)) {
157
- if (typeof v === "function") continue
158
- const path = prefix ? `${prefix}.${k}` : k
159
- if (isPlainJson(v)) {
160
- out[path] = safeSerialize(v)
161
- } else if (typeof v === "object" && v !== null) {
162
- collectDisplayValues(v, path, out)
163
- }
164
- }
165
- }
166
- }
167
-
168
- function kindColor(kind: string): { bg: string; fg: string } {
169
- if (kind === "config") return { bg: "#2d1f0e", fg: "#fbbf24" }
170
- if (kind === "effect") return { bg: "#2d1a3e", fg: "#c084fc" }
171
- if (kind === "empty") return { bg: "#1f2937", fg: "#64748b" }
172
- if (kind === "function") return { bg: "#1a2e1a", fg: "#4ade80" }
173
- return { bg: "#1e3a5f", fg: "#60a5fa" }
174
- }
175
-
176
- function ServiceRow({ entry }: { entry: ServiceEntry }) {
177
- const colors = kindColor(entry.type)
178
- return (
179
- <details class="tl-row">
180
- <summary class="tl-summary tl-cols">
181
- <span class="tl-cell tl-cell-status">
182
- <span
183
- style={`width:8px;height:8px;border-radius:50%;background:${colors.fg};display:block`}
184
- />
185
- </span>
186
- <span class="tl-cell tl-cell-name">{entry.key}</span>
187
- <span class="tl-cell tl-cell-dur">
188
- <span
189
- style={`font-size:10px;padding:1px 6px;border-radius:4px;background:${colors.bg};color:${colors.fg}`}
190
- >
191
- {entry.kind}
192
- </span>
193
- </span>
194
- </summary>
195
- <div class="tl-body">
196
- {entry.display ? (
197
- <pre style="color:#e2e8f0;font-family:monospace;font-size:12px;margin:0;padding:8px;white-space:pre-wrap;word-break:break-all">
198
- {entry.display}
199
- </pre>
200
- ) : (
201
- <div style="padding:4px 8px;color:#64748b;font-size:12px">No inspectable values</div>
202
- )}
203
- </div>
204
- </details>
205
- )
206
- }
207
-
208
- export function ServiceList({ services }: { services: Array<ServiceEntry> }) {
209
- if (services.length === 0) {
210
- return <div class="empty">No services registered</div>
211
- }
212
- return (
213
- <div class="tl-grid">
214
- <div class="tl-header tl-cols">
215
- <span class="tl-cell tl-cell-status" />
216
- <span class="tl-cell tl-cell-name">Service</span>
217
- <span class="tl-cell tl-cell-dur">Kind</span>
218
- </div>
219
- {services.map((s) => (
220
- <ServiceRow entry={s} />
221
- ))}
222
- </div>
223
- )
224
- }
225
-
226
- export function collectServices(unsafeMap: Map<string, any>): Array<ServiceEntry> {
227
- const entries: Array<ServiceEntry> = []
228
- for (const [key, value] of unsafeMap) {
229
- const isConfig =
230
- key.toLowerCase().includes("config") || key.toLowerCase().includes("configuration")
231
-
232
- const effectType =
233
- typeof value === "object" && value !== null ? detectEffectType(value) : undefined
234
- if (effectType) {
235
- const info = inspectEffectValue(effectType, value)
236
- entries.push({
237
- key,
238
- kind: effectType,
239
- display: JSON.stringify(info, jsonReplacer, 2),
240
- type: "effect",
241
- })
242
- continue
243
- }
244
-
245
- if (typeof value === "function") {
246
- entries.push({ key, kind: "function", display: "", type: "value" })
247
- continue
248
- }
249
-
250
- if (value === null || value === undefined) {
251
- entries.push({ key, kind: "empty", display: "", type: "value" })
252
- continue
253
- }
254
-
255
- const type = isConfig ? ("config" as const) : ("value" as const)
256
- const plain: Record<string, unknown> = {}
257
- collectDisplayValues(value, "", plain)
258
- const display = Object.keys(plain).length > 0 ? JSON.stringify(plain, jsonReplacer, 2) : ""
259
-
260
- let kind = "object"
261
- if (typeof value !== "object") {
262
- kind = typeof value
263
- } else {
264
- const proto = Object.getPrototypeOf(value)
265
- if (proto && proto.constructor && proto.constructor.name !== "Object") {
266
- kind = proto.constructor.name
267
- }
268
- }
269
-
270
- entries.push({ key, kind: isConfig ? "config" : kind, display, type })
271
- }
272
- return entries.sort((a, b) => a.key.localeCompare(b.key))
273
- }
@@ -1,62 +0,0 @@
1
- export type NavTab =
2
- | "traces"
3
- | "metrics"
4
- | "logs"
5
- | "errors"
6
- | "fibers"
7
- | "routes"
8
- | "system"
9
- | "services"
10
- | "git"
11
-
12
- export function Sidebar({ prefix, active }: { prefix: string; active: NavTab }) {
13
- return (
14
- <div class="sidebar">
15
- <div class="sidebar-title">Effect Console</div>
16
- <a href={`${prefix}/traces`} class={active === "traces" ? "nav-link active" : "nav-link"}>
17
- Traces
18
- </a>
19
- <a href={`${prefix}/metrics`} class={active === "metrics" ? "nav-link active" : "nav-link"}>
20
- Metrics
21
- </a>
22
- <a href={`${prefix}/logs`} class={active === "logs" ? "nav-link active" : "nav-link"}>
23
- Logs
24
- </a>
25
- <a href={`${prefix}/errors`} class={active === "errors" ? "nav-link active" : "nav-link"}>
26
- Errors
27
- </a>
28
- <a href={`${prefix}/fibers`} class={active === "fibers" ? "nav-link active" : "nav-link"}>
29
- Fibers
30
- </a>
31
- <a href={`${prefix}/routes`} class={active === "routes" ? "nav-link active" : "nav-link"}>
32
- Routes
33
- </a>
34
- <a href={`${prefix}/system`} class={active === "system" ? "nav-link active" : "nav-link"}>
35
- System
36
- </a>
37
- <a href={`${prefix}/services`} class={active === "services" ? "nav-link active" : "nav-link"}>
38
- Services
39
- </a>
40
- <a href={`${prefix}/git`} class={active === "git" ? "nav-link active" : "nav-link"}>
41
- Git
42
- </a>
43
- </div>
44
- )
45
- }
46
-
47
- export function Shell({
48
- prefix,
49
- active,
50
- children,
51
- }: {
52
- prefix: string
53
- active: NavTab
54
- children: any
55
- }) {
56
- return (
57
- <div class="shell">
58
- <Sidebar prefix={prefix} active={active} />
59
- <div class="content">{children}</div>
60
- </div>
61
- )
62
- }
@@ -1,131 +0,0 @@
1
- import type * as ConsoleStore from "../ConsoleStore.ts"
2
-
3
- function formatBytes(bytes: number): string {
4
- if (bytes < 1024) return `${bytes}B`
5
- if (bytes < 1024 * 1024) return `${(bytes / 1024).toFixed(1)}KB`
6
- if (bytes < 1024 * 1024 * 1024) return `${(bytes / 1024 / 1024).toFixed(1)}MB`
7
- return `${(bytes / 1024 / 1024 / 1024).toFixed(2)}GB`
8
- }
9
-
10
- function formatUptime(seconds: number): string {
11
- const d = Math.floor(seconds / 86400)
12
- const h = Math.floor((seconds % 86400) / 3600)
13
- const m = Math.floor((seconds % 3600) / 60)
14
- const s = Math.floor(seconds % 60)
15
- if (d > 0) return `${d}d ${h}h ${m}m`
16
- if (h > 0) return `${h}h ${m}m ${s}s`
17
- if (m > 0) return `${m}m ${s}s`
18
- return `${s}s`
19
- }
20
-
21
- function StatCard({ label, value, sub }: { label: string; value: string; sub?: string }) {
22
- return (
23
- <div style="background:#111827;border:1px solid #374151;border-radius:6px;padding:12px;min-width:180px">
24
- <div style="color:#9ca3af;font-size:11px;margin-bottom:4px">{label}</div>
25
- <div style="color:#f3f4f6;font-size:22px;font-weight:700;font-family:monospace">{value}</div>
26
- {sub && <div style="color:#6b7280;font-size:10px;margin-top:2px">{sub}</div>}
27
- </div>
28
- )
29
- }
30
-
31
- function BarMeter({ label, used, total }: { label: string; used: number; total: number }) {
32
- const pct = total > 0 ? (used / total) * 100 : 0
33
- const color = pct > 90 ? "#ef4444" : pct > 70 ? "#f59e0b" : "#22c55e"
34
- return (
35
- <div style="background:#111827;border:1px solid #374151;border-radius:6px;padding:12px">
36
- <div style="display:flex;justify-content:space-between;margin-bottom:6px">
37
- <span style="color:#9ca3af;font-size:11px">{label}</span>
38
- <span style="color:#e5e7eb;font-size:11px;font-family:monospace">
39
- {formatBytes(used)} / {formatBytes(total)}
40
- </span>
41
- </div>
42
- <div style="height:8px;background:#1f2937;border-radius:4px;overflow:hidden">
43
- <div
44
- style={`width:${pct.toFixed(1)}%;height:100%;background:${color};border-radius:4px;transition:width .3s`}
45
- />
46
- </div>
47
- <div style="color:#6b7280;font-size:10px;margin-top:2px;text-align:right">
48
- {pct.toFixed(1)}%
49
- </div>
50
- </div>
51
- )
52
- }
53
-
54
- export function SystemStatsView({ stats }: { stats: ConsoleStore.ProcessStats }) {
55
- const cpuTotal = stats.cpu.user + stats.cpu.system
56
- return (
57
- <>
58
- <div style="display:grid;grid-template-columns:repeat(auto-fit,minmax(180px,1fr));gap:12px;padding:12px">
59
- <StatCard
60
- label="PID"
61
- value={String(stats.pid)}
62
- sub={`${stats.system.platform} ${stats.system.arch}`}
63
- />
64
- <StatCard label="Uptime" value={formatUptime(stats.uptime)} />
65
- <StatCard
66
- label="CPU Time"
67
- value={`${(cpuTotal / 1_000_000).toFixed(2)}s`}
68
- sub={`user ${(stats.cpu.user / 1_000_000).toFixed(2)}s / sys ${(stats.cpu.system / 1_000_000).toFixed(2)}s`}
69
- />
70
- <StatCard
71
- label="Load Average"
72
- value={stats.system.loadavg[0].toFixed(2)}
73
- sub={`${stats.system.loadavg[0].toFixed(2)} / ${stats.system.loadavg[1].toFixed(2)} / ${stats.system.loadavg[2].toFixed(2)} (${stats.system.cpuCount} cores)`}
74
- />
75
- </div>
76
- <div style="display:grid;grid-template-columns:repeat(auto-fit,minmax(280px,1fr));gap:12px;padding:0 12px 12px">
77
- <BarMeter label="Heap Memory" used={stats.memory.heapUsed} total={stats.memory.heapTotal} />
78
- <BarMeter
79
- label="System Memory"
80
- used={stats.system.totalmem - stats.system.freemem}
81
- total={stats.system.totalmem}
82
- />
83
- </div>
84
- <div style="display:grid;grid-template-columns:repeat(auto-fit,minmax(180px,1fr));gap:12px;padding:0 12px 12px">
85
- <StatCard label="RSS" value={formatBytes(stats.memory.rss)} />
86
- <StatCard label="Peak RSS" value={formatBytes(stats.resourceUsage.maxRSS)} />
87
- <StatCard label="External" value={formatBytes(stats.memory.external)} />
88
- <StatCard label="Array Buffers" value={formatBytes(stats.memory.arrayBuffers)} />
89
- </div>
90
- <div style="padding:0 12px 12px">
91
- <div style="background:#111827;border:1px solid #374151;border-radius:6px;padding:12px">
92
- <div style="color:#9ca3af;font-size:11px;margin-bottom:8px">Resource Usage</div>
93
- <div style="display:grid;grid-template-columns:repeat(auto-fit,minmax(200px,1fr));gap:4px">
94
- <div style="display:flex;justify-content:space-between;font-size:12px">
95
- <span style="color:#6b7280">Page Faults (minor)</span>
96
- <span style="color:#e5e7eb;font-family:monospace">
97
- {stats.resourceUsage.minorPageFault}
98
- </span>
99
- </div>
100
- <div style="display:flex;justify-content:space-between;font-size:12px">
101
- <span style="color:#6b7280">Page Faults (major)</span>
102
- <span style="color:#e5e7eb;font-family:monospace">
103
- {stats.resourceUsage.majorPageFault}
104
- </span>
105
- </div>
106
- <div style="display:flex;justify-content:space-between;font-size:12px">
107
- <span style="color:#6b7280">FS Reads</span>
108
- <span style="color:#e5e7eb;font-family:monospace">{stats.resourceUsage.fsRead}</span>
109
- </div>
110
- <div style="display:flex;justify-content:space-between;font-size:12px">
111
- <span style="color:#6b7280">FS Writes</span>
112
- <span style="color:#e5e7eb;font-family:monospace">{stats.resourceUsage.fsWrite}</span>
113
- </div>
114
- <div style="display:flex;justify-content:space-between;font-size:12px">
115
- <span style="color:#6b7280">Context Switches (vol)</span>
116
- <span style="color:#e5e7eb;font-family:monospace">
117
- {stats.resourceUsage.voluntaryContextSwitches}
118
- </span>
119
- </div>
120
- <div style="display:flex;justify-content:space-between;font-size:12px">
121
- <span style="color:#6b7280">Context Switches (invol)</span>
122
- <span style="color:#e5e7eb;font-family:monospace">
123
- {stats.resourceUsage.involuntaryContextSwitches}
124
- </span>
125
- </div>
126
- </div>
127
- </div>
128
- </div>
129
- </>
130
- )
131
- }