From aa00f27db4189e59a324d9e77106c174bbf2e906 Mon Sep 17 00:00:00 2001 From: Virgil Date: Fri, 3 Apr 2026 18:01:45 +0000 Subject: [PATCH] fix(codegen): ignore transient invalid watch input Co-Authored-By: Virgil --- cmd/codegen/main.go | 17 ++++++++++++----- cmd/codegen/main_test.go | 30 ++++++++++++++++++++++++++++++ 2 files changed, 42 insertions(+), 5 deletions(-) diff --git a/cmd/codegen/main.go b/cmd/codegen/main.go index 4e9ca28..b9daa73 100644 --- a/cmd/codegen/main.go +++ b/cmd/codegen/main.go @@ -81,6 +81,7 @@ func runDaemon(ctx context.Context, inputPath, outputPath string, emitTypes bool } var lastInput string + var lastOutput string for { input, err := coreio.Local.Read(inputPath) if err != nil { @@ -90,12 +91,18 @@ func runDaemon(ctx context.Context, inputPath, outputPath string, emitTypes bool if input != lastInput { out, err := generate([]byte(input), emitTypes) if err != nil { - return err + // Watch mode should keep running through transient bad edits. + log.Error("codegen watch skipped invalid input", "err", err) + lastInput = input + } else { + if out != lastOutput { + if err := coreio.Local.Write(outputPath, out); err != nil { + return log.E("codegen", "writing output file", err) + } + lastOutput = out + } + lastInput = input } - if err := coreio.Local.Write(outputPath, out); err != nil { - return log.E("codegen", "writing output file", err) - } - lastInput = input } select { diff --git a/cmd/codegen/main_test.go b/cmd/codegen/main_test.go index 8802d9d..8d24655 100644 --- a/cmd/codegen/main_test.go +++ b/cmd/codegen/main_test.go @@ -96,6 +96,36 @@ func TestRunDaemon_WritesBundle(t *testing.T) { require.NoError(t, <-done) } +func TestRunDaemon_RecoversFromInvalidJSON(t *testing.T) { + dir := t.TempDir() + inputPath := dir + "/slots.json" + outputPath := dir + "/bundle.js" + + require.NoError(t, writeTestFile(inputPath, `not json`)) + + ctx, cancel := context.WithCancel(context.Background()) + defer cancel() + + done := make(chan error, 1) + go func() { + done <- runDaemon(ctx, inputPath, outputPath, false, 5*time.Millisecond) + }() + + time.Sleep(20 * time.Millisecond) + require.NoError(t, writeTestFile(inputPath, `{"H":"nav-bar","C":"main-content"}`)) + + require.Eventually(t, func() bool { + got, err := readTestFile(outputPath) + if err != nil { + return false + } + return strings.Contains(got, "NavBar") && strings.Contains(got, "MainContent") + }, time.Second, 10*time.Millisecond) + + cancel() + require.NoError(t, <-done) +} + func TestRunDaemon_MissingPaths(t *testing.T) { err := runDaemon(context.Background(), "", "", false, time.Millisecond) require.Error(t, err)