eval

package
v0.8.0 Latest Latest
Warning

This package is not in the latest version of its module.

Go to latest
Published: Aug 17, 2026 License: Apache-2.0 Imports: 11 Imported by: 0

Documentation

Index

Constants

This section is empty.

Variables

View Source
var EvalCmd = &cobra.Command{
	Use:   "eval",
	Short: "Evaluate a Datalog query against policy and data",
	Long: `Evaluate a Datalog query against policy and data.

Output modes (--output):
  json   Print the query results as a JSON array on stdout. All progress
         messages go to stderr, so the output can be piped to jq.
  table  Print the results as an aligned table (default).

Exit codes: 0 success, 1 policy-deny, 2 usage error, 3 runtime error.`,
	RunE: func(cmd *cobra.Command, args []string) error {
		if outputMode != outputJSON && outputMode != outputTable {
			return exitcode.UsageErrorf("invalid --output value %q: must be %q or %q", outputMode, outputJSON, outputTable)
		}

		if dataPath == "" && knowledgePath == "" {
			return exitcode.UsageErrorf("must provide either --data (JSON) or --facts/--knowledge (Graph)")
		}

		progress := func(format string, a ...any) {
			if quiet {
				return
			}
			fmt.Fprintf(cmd.ErrOrStderr(), format+"\n", a...)
		}

		policyBytes, err := os.ReadFile(policyPath)
		if err != nil {
			return fmt.Errorf("failed to read policy file: %w", err)
		}

		var dataBytes []byte
		if dataPath != "" {
			dataBytes, err = os.ReadFile(dataPath)
			if err != nil {
				return fmt.Errorf("failed to read data file: %w", err)
			}
		}

		e, err := engine.New()
		if err != nil {
			return fmt.Errorf("failed to initialize engine: %w", err)
		}

		if knowledgePath != "" {

			triples, err := knowledge.ParseGraphFile(knowledgePath)
			if err != nil {
				return fmt.Errorf("failed to parse knowledge base: %w", err)
			}

			preds := knowledge.GetPredicates(triples)
			if len(preds) > 0 {
				var decls []string
				for _, p := range preds {

					decls = append(decls, fmt.Sprintf("Decl %s(S, O).", p))
				}
				schemaBlock := strings.Join(decls, "\n")

				if err := e.LoadPolicy(cmd.Context(), schemaBlock); err != nil {
					return fmt.Errorf("failed to inject schema declarations: %w", err)
				}
				progress("Injected %d schema declarations.", len(preds))
			}

			facts := knowledge.TriplesToFacts(triples)
			if err := e.LoadFacts(cmd.Context(), facts); err != nil {
				return fmt.Errorf("failed to load knowledge facts: %w", err)
			}
			progress("Loaded %d knowledge facts.", len(facts))
		}

		if err := e.LoadPolicy(cmd.Context(), string(policyBytes)); err != nil {

			return fmt.Errorf("failed to load policy: %w", err)
		}

		if dataPath != "" {
			var data any
			if err := json.Unmarshal(dataBytes, &data); err != nil {
				return fmt.Errorf("failed to parse data JSON: %w", err)
			}

			dataFacts, err := engine.Flatten("input", data)
			if err != nil {
				return fmt.Errorf("failed to flatten data: %w", err)
			}

			if err := e.LoadFacts(cmd.Context(), dataFacts); err != nil {
				return fmt.Errorf("failed to load data facts: %w", err)
			}
			progress("Loaded %d data facts.", len(dataFacts))
		}

		ctx := context.Background()

		if explain {
			explanation, err := e.Explain(ctx, nil, queryString)
			if err != nil {
				return fmt.Errorf("explanation failed: %w", err)
			}
			stdout := cmd.OutOrStdout()
			if outputMode == outputJSON {
				outputBytes, err := json.MarshalIndent(explanation, "", "  ")
				if err != nil {
					return fmt.Errorf("failed to format output: %w", err)
				}
				fmt.Fprintln(stdout, string(outputBytes))
			} else {
				fmt.Fprint(stdout, explanation.String())
			}
			return nil
		}

		results, err := e.Query(ctx, nil, queryString)
		if err != nil {
			return fmt.Errorf("query execution failed: %w", err)
		}

		stdout := cmd.OutOrStdout()
		switch outputMode {
		case outputJSON:

			outputBytes, err := json.MarshalIndent(results, "", "  ")
			if err != nil {
				return fmt.Errorf("failed to format output: %w", err)
			}
			fmt.Fprintln(stdout, string(outputBytes))
		default:
			if len(results) == 0 {
				progress("No results found.")
				return nil
			}
			printTable(stdout, results)
		}

		return nil
	},
}

Functions

func AddCommands

func AddCommands(rootCmd *cobra.Command)

Types

This section is empty.

Jump to

Keyboard shortcuts

? : This menu
/ : Search site
f or F : Jump to
y or Y : Canonical URL