//go:build ignore // NOTE: requires wails dependency in target project — use this file by copying into a Wails project package infra import ( "context" "fmt" "time" "github.com/wailsapp/wails/v2/pkg/runtime" ) // WailsStreamConfig configura un stream de datos hacia el frontend. type WailsStreamConfig struct { StreamName string // Nombre del stream (evento base) ChunkDelay time.Duration // Delay entre chunks (default 0) } // WailsStreamData envía un slice de datos como stream al frontend. // Emite cada elemento como chunk en {streamName}, y {streamName}:complete al terminar. func WailsStreamData[T any](ctx context.Context, cfg WailsStreamConfig, data []T) error { if cfg.StreamName == "" { return fmt.Errorf("stream name is required") } for _, chunk := range data { select { case <-ctx.Done(): runtime.EventsEmit(ctx, cfg.StreamName+":error", map[string]string{ "message": "stream cancelled", }) return ctx.Err() default: runtime.EventsEmit(ctx, cfg.StreamName, chunk) if cfg.ChunkDelay > 0 { time.Sleep(cfg.ChunkDelay) } } } runtime.EventsEmit(ctx, cfg.StreamName+":complete", nil) return nil } // WailsStreamFunc ejecuta una función generadora y envía resultados como stream. // La función generadora envía datos por el canal, y esta función los retransmite al frontend. func WailsStreamFunc[T any](ctx context.Context, streamName string, generator func(ctx context.Context, ch chan<- T) error) error { ch := make(chan T, 100) errCh := make(chan error, 1) go func() { defer close(ch) errCh <- generator(ctx, ch) }() for chunk := range ch { runtime.EventsEmit(ctx, streamName, chunk) } if err := <-errCh; err != nil { runtime.EventsEmit(ctx, streamName+":error", map[string]string{ "message": err.Error(), }) return err } runtime.EventsEmit(ctx, streamName+":complete", nil) return nil }