// Command bundle-check is a developer tool that bundles a spec file and loads // it into the evaluator to confirm it compiles and registers properties. package main import ( "errors" "fmt" "io" "os" "path/filepath" "strings" "github.com/priyanshujain/sanderling/internal/bundler" "github.com/priyanshujain/sanderling/internal/testrun" "github.com/priyanshujain/sanderling/internal/verifier" ) // checkSeed keeps the load deterministic. The bundle it seeds is only loaded, // never hashed or reported, so the value is arbitrary. const checkSeed = 1 func bundleSpec(specSrc, entryFile string) (bundler.Result, error) { return bundler.Bundle(bundler.Options{ EntryFile: entryFile, Aliases: map[string]string{ "@sanderling/spec": filepath.Join(specSrc, "index.ts"), "@sanderling/spec/defaults": filepath.Join(specSrc, "defaults/index.ts"), "@sanderling/spec/defaults/properties": filepath.Join(specSrc, "defaults/properties.ts"), }, }) } // registeredProperties bundles the spec the way a run bundles it, with the // runtime entry that assigns globalThis.properties, and loads it into the real // evaluator. Bundling alone proves nothing about registration: a spec that // registers no property compiles perfectly and then judges nothing. func registeredProperties(entryFile string) ([]string, error) { bundle, err := testrun.BundleSpec(entryFile, checkSeed) if err != nil { return nil, fmt.Errorf("bundle with runtime entry: %w", err) } evaluator, err := verifier.New() if err != nil { return nil, fmt.Errorf("evaluator: %w", err) } if err := evaluator.Load(string(bundle.JavaScript)); err != nil { return nil, fmt.Errorf("load spec: %w", err) } return evaluator.PropertyNames(), nil } func check(specSrc, entryFile string, stdout io.Writer) error { result, err := bundleSpec(specSrc, entryFile) if err != nil { return fmt.Errorf("bundle: %w", err) } fmt.Fprintf(stdout, "bundled: %d bytes, sha256=%s\n", len(result.JavaScript), result.SHA256) names, err := registeredProperties(entryFile) if err != nil { return err } if len(names) == 0 { return errors.New("the spec bundles and loads cleanly but registers no properties: " + "nothing is wrong with the source, and a run against it would check nothing " + "and report no violations") } fmt.Fprintf(stdout, "properties registered: %d (%s)\n", len(names), strings.Join(names, ", ")) return nil } func main() { if len(os.Args) < 2 { fmt.Fprintln(os.Stderr, "usage: bundle-check ") os.Exit(1) } entryFile, err := filepath.Abs(os.Args[1]) if err != nil { fmt.Fprintf(os.Stderr, "resolve spec path: %v\n", err) os.Exit(1) } repoRoot, err := os.Getwd() if err != nil { fmt.Fprintf(os.Stderr, "getwd: %v\n", err) os.Exit(1) } if err := check(filepath.Join(repoRoot, "pkg/spec/src"), entryFile, os.Stdout); err != nil { fmt.Fprintf(os.Stderr, "%v\n", err) os.Exit(1) } }