Skip to content

Commit 4fba48f

Browse files
committed
lots of small updates to clean up code
1 parent 4259018 commit 4fba48f

7 files changed

Lines changed: 47 additions & 28 deletions

File tree

‎tsunami/demo/cpuchart/app.go‎

Lines changed: 5 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -34,9 +34,9 @@ var (
3434
)
3535

3636
type CPUDataPoint struct {
37-
Time int64 `json:"time"` // Unix timestamp in seconds
38-
CPUUsage *float64 `json:"cpuUsage"` // CPU usage percentage (nil for empty slots)
39-
Timestamp string `json:"timestamp"` // Human readable timestamp
37+
Time int64 `json:"time" desc:"Unix timestamp (seconds since epoch)" units:"s"`
38+
CPUUsage *float64 `json:"cpuUsage" desc:"CPU usage percentage" units:"%" min:"0" max:"100"`
39+
Timestamp string `json:"timestamp" desc:"Human-readable HH:MM:SS"`
4040
}
4141

4242
type StatsPanelProps struct {
@@ -213,7 +213,7 @@ var App = app.DefineComponent("App", func(_ struct{}) any {
213213
}, "Real-Time CPU Usage Monitor"),
214214
vdom.H("p", map[string]any{
215215
"className": "text-gray-400",
216-
}, "Live CPU usage data collected using gopsutil, displaying 60 seconds of history"),
216+
}, "Live CPU usage data collected using gopsutil, displaying ", dataPointCount, " seconds of history"),
217217
),
218218

219219
// Controls
@@ -340,7 +340,7 @@ var App = app.DefineComponent("App", func(_ struct{}) any {
340340
vdom.H("span", map[string]any{
341341
"className": "text-blue-400 mt-1",
342342
}, "•"),
343-
"Rolling window of 60 seconds of historical data",
343+
"Rolling window of ", dataPointCount, " seconds of historical data",
344344
),
345345
vdom.H("li", map[string]any{
346346
"className": "flex items-start gap-2",

‎tsunami/demo/githubaction/app.go‎

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -411,7 +411,7 @@ var App = app.DefineComponent("App",
411411
vdom.H("span", map[string]any{
412412
"className": "text-blue-400 mt-1",
413413
}, "•"),
414-
"Polls GitHub API every 5 seconds for real-time updates",
414+
"Polls GitHub API every ", pollInterval, " seconds for real-time updates",
415415
),
416416
vdom.H("li", map[string]any{
417417
"className": "flex items-start gap-2",

‎tsunami/engine/atomimpl.go‎

Lines changed: 6 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -6,6 +6,7 @@ package engine
66
import (
77
"encoding/json"
88
"fmt"
9+
"reflect"
910
"sync"
1011
)
1112

@@ -102,3 +103,8 @@ func (a *AtomImpl[T]) GetMeta() *AtomMeta {
102103
defer a.lock.Unlock()
103104
return a.meta
104105
}
106+
107+
func (a *AtomImpl[T]) GetAtomType() reflect.Type {
108+
var zero T
109+
return reflect.TypeOf(zero)
110+
}

‎tsunami/engine/rootelem.go‎

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -30,6 +30,7 @@ type genAtom interface {
3030
SetUsedBy(string, bool)
3131
GetUsedBy() []string
3232
GetMeta() *AtomMeta
33+
GetAtomType() reflect.Type
3334
}
3435

3536
type RootElem struct {

‎tsunami/engine/schema.go‎

Lines changed: 15 additions & 18 deletions
Original file line numberDiff line numberDiff line change
@@ -78,6 +78,13 @@ func createStructDefinition(t reflect.Type) map[string]any {
7878
}
7979
}
8080

81+
// Add pattern constraint for string types
82+
if fieldSchema["type"] == "string" {
83+
if pattern := field.Tag.Get("pattern"); pattern != "" {
84+
fieldSchema["pattern"] = pattern
85+
}
86+
}
87+
8188
properties[fieldInfo.FieldName] = fieldSchema
8289

8390
// Add to required if not a pointer and not marked as omitempty
@@ -195,7 +202,8 @@ func generateShallowJSONSchema(t reflect.Type, meta *AtomMeta) map[string]any {
195202
// Special case for []byte - treat as string with base64 encoding
196203
if t.Kind() == reflect.Slice && t.Elem().Kind() == reflect.Uint8 {
197204
schema["type"] = "string"
198-
schema["format"] = "base64"
205+
schema["contentEncoding"] = "base64"
206+
schema["contentMediaType"] = "application/octet-stream"
199207
return schema
200208
}
201209

@@ -233,17 +241,6 @@ func generateShallowJSONSchema(t reflect.Type, meta *AtomMeta) map[string]any {
233241
return schema
234242
}
235243

236-
237-
238-
// getAtomValueType returns the reflect.Type of the atom's value
239-
func getAtomValueType(atom genAtom) reflect.Type {
240-
val := atom.GetVal()
241-
if val == nil {
242-
return nil
243-
}
244-
return reflect.TypeOf(val)
245-
}
246-
247244
// getAtomMeta extracts AtomMeta from the atom
248245
func getAtomMeta(atom genAtom) *AtomMeta {
249246
return atom.GetMeta()
@@ -254,22 +251,22 @@ func generateSchemaFromAtoms(atoms map[string]genAtom, title, description string
254251
// Collect all struct definitions
255252
defs := make(map[reflect.Type]any)
256253
for _, atom := range atoms {
257-
atomType := getAtomValueType(atom)
254+
atomType := atom.GetAtomType()
258255
if atomType != nil {
259256
collectStructDefs(atomType, defs)
260257
}
261258
}
262-
259+
263260
// Generate properties for each atom
264261
properties := make(map[string]any)
265262
for atomName, atom := range atoms {
266-
atomType := getAtomValueType(atom)
263+
atomType := atom.GetAtomType()
267264
if atomType != nil {
268265
atomMeta := getAtomMeta(atom)
269266
properties[atomName] = generateShallowJSONSchema(atomType, atomMeta)
270267
}
271268
}
272-
269+
273270
// Build the final schema
274271
schema := map[string]any{
275272
"$schema": "https://json-schema.org/draft/2020-12/schema",
@@ -278,7 +275,7 @@ func generateSchemaFromAtoms(atoms map[string]genAtom, title, description string
278275
"description": description,
279276
"properties": properties,
280277
}
281-
278+
282279
// Add definitions if any
283280
if len(defs) > 0 {
284281
definitions := make(map[string]any)
@@ -287,7 +284,7 @@ func generateSchemaFromAtoms(atoms map[string]genAtom, title, description string
287284
}
288285
schema["definitions"] = definitions
289286
}
290-
287+
291288
return schema
292289
}
293290

‎tsunami/engine/serverhandlers.go‎

Lines changed: 17 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -43,6 +43,12 @@ func newHTTPHandlers(client *ClientImpl) *httpHandlers {
4343
}
4444
}
4545

46+
func setNoCacheHeaders(w http.ResponseWriter) {
47+
w.Header().Set("Cache-Control", "no-cache, no-store, must-revalidate")
48+
w.Header().Set("Pragma", "no-cache")
49+
w.Header().Set("Expires", "0")
50+
}
51+
4652
func (h *httpHandlers) registerHandlers(mux *http.ServeMux, opts handlerOpts) {
4753
mux.HandleFunc("/api/render", h.handleRender)
4854
mux.HandleFunc("/api/updates", h.handleSSE)
@@ -71,6 +77,8 @@ func (h *httpHandlers) handleRender(w http.ResponseWriter, r *http.Request) {
7177
}
7278
}()
7379

80+
setNoCacheHeaders(w)
81+
7482
if r.Method != http.MethodPost {
7583
http.Error(w, "method not allowed", http.StatusMethodNotAllowed)
7684
return
@@ -181,6 +189,8 @@ func (h *httpHandlers) handleData(w http.ResponseWriter, r *http.Request) {
181189
}
182190
}()
183191

192+
setNoCacheHeaders(w)
193+
184194
if r.Method != http.MethodGet {
185195
http.Error(w, "method not allowed", http.StatusMethodNotAllowed)
186196
return
@@ -203,6 +213,8 @@ func (h *httpHandlers) handleConfig(w http.ResponseWriter, r *http.Request) {
203213
}
204214
}()
205215

216+
setNoCacheHeaders(w)
217+
206218
switch r.Method {
207219
case http.MethodGet:
208220
h.handleConfigGet(w, r)
@@ -270,6 +282,8 @@ func (h *httpHandlers) handleSchemas(w http.ResponseWriter, r *http.Request) {
270282
}
271283
}()
272284

285+
setNoCacheHeaders(w)
286+
273287
if r.Method != http.MethodGet {
274288
http.Error(w, "method not allowed", http.StatusMethodNotAllowed)
275289
return
@@ -327,12 +341,11 @@ func (h *httpHandlers) handleSSE(w http.ResponseWriter, r *http.Request) {
327341
}
328342

329343
// Set SSE headers
344+
setNoCacheHeaders(w)
330345
w.Header().Set("Content-Type", "text/event-stream")
331-
w.Header().Set("Cache-Control", "no-cache, no-transform")
332346
w.Header().Set("Connection", "keep-alive")
333347
w.Header().Set("X-Accel-Buffering", "no")
334348
w.Header().Set("X-Content-Type-Options", "nosniff")
335-
w.Header().Set("X-Accel-Buffering", "no") // nginx hint
336349

337350
// Use ResponseController for better flushing control
338351
rc := http.NewResponseController(w)
@@ -441,6 +454,8 @@ func (h *httpHandlers) handleManifest(manifestFileBytes []byte) http.HandlerFunc
441454
}
442455
}()
443456

457+
setNoCacheHeaders(w)
458+
444459
if r.Method != http.MethodGet {
445460
http.Error(w, "method not allowed", http.StatusMethodNotAllowed)
446461
return

‎tsunami/prompts/system.md‎

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -456,7 +456,7 @@ For state shared across components or accessible to external systems, declare gl
456456

457457
#### AtomMeta for External Integration
458458

459-
ConfigAtom and DataAtom require an AtomMeta parameter to provide schema information for external tools and AI agents. SharedAtom does not use AtomMeta since it's only for internal state sharing.
459+
ConfigAtom and DataAtom require an AtomMeta parameter (can pass nil if not not needed) to provide schema information for external tools and AI agents. SharedAtom does not use AtomMeta since it's only for internal state sharing.
460460

461461
```go
462462
type AtomMeta struct {
@@ -692,7 +692,7 @@ The style map in props mirrors React's style object pattern, making it familiar
692692
Quick styles can be added using a vdom.H("style", nil, "...") tag. You may also place CSS files in the `static` directory, and serve them directly with:
693693

694694
```go
695-
vdom.H("link", map[string]any{"rel": "stylesheet", "src": "/static/mystyles.css"})
695+
vdom.H("link", map[string]any{"rel": "stylesheet", "href": "/static/mystyles.css"})
696696
```
697697

698698
## Component Definition Pattern

0 commit comments

Comments
 (0)