diff --git a/comp_test.go b/comp_test.go index 14d3816..976147a 100644 --- a/comp_test.go +++ b/comp_test.go @@ -6,7 +6,7 @@ import ( "github.com/stretchr/testify/assert" - "github.com/diegoholiveira/jsonlogic/v3" + jsonlogic "github.com/diegoholiveira/jsonlogic/v3" ) func TestHardEqualsWithNonSliceValues(t *testing.T) { diff --git a/internal/testing.go b/internal/testing.go index 3ca3a02..8691a72 100644 --- a/internal/testing.go +++ b/internal/testing.go @@ -21,10 +21,9 @@ type ( Tests []Test ) -// This gets the tests.json file that we've proposed become the new official one in +// GetScenariosFromProposedOfficialTestSuite reads the tests.json file that we've proposed become the new official one in // https://github.com/jwadhams/json-logic/pull/48 but that hasn't merged yet. func GetScenariosFromProposedOfficialTestSuite() Tests { - var err error buffer, err := os.ReadFile("internal/json_logic_pr_48_tests.json") if err != nil { log.Fatal(err) @@ -33,18 +32,25 @@ func GetScenariosFromProposedOfficialTestSuite() Tests { return getScenariosFromFile(buffer) } +// GetScenariosFromOfficialTestSuite fetches test scenarios from the official JSON Logic test suite. +// It makes an HTTP request to jsonlogic.com to retrieve the latest test cases. func GetScenariosFromOfficialTestSuite() Tests { - response, err := http.Get("http://jsonlogic.com/tests.json") + req, err := http.NewRequest("GET", "http://jsonlogic.com/tests.json", nil) if err != nil { log.Fatal(err) } + response, err := http.DefaultClient.Do(req) + if err != nil { + log.Fatal(err) + } + defer response.Body.Close() + buffer, err := io.ReadAll(response.Body) if err != nil { log.Fatal(err) } - response.Body.Close() return getScenariosFromFile(buffer) } diff --git a/internal/typing/typing_test.go b/internal/typing/typing_test.go index 80066ff..ca95444 100644 --- a/internal/typing/typing_test.go +++ b/internal/typing/typing_test.go @@ -259,4 +259,4 @@ func TestToString(t *testing.T) { assert.Equal(t, tt.expected, result) }) } -} \ No newline at end of file +} diff --git a/issues_test.go b/issues_test.go index c2a289b..fe53c15 100644 --- a/issues_test.go +++ b/issues_test.go @@ -8,7 +8,7 @@ import ( "github.com/stretchr/testify/assert" - "github.com/diegoholiveira/jsonlogic/v3" + jsonlogic "github.com/diegoholiveira/jsonlogic/v3" ) func TestIssue50(t *testing.T) { @@ -198,7 +198,6 @@ func TestJsonLogicWithSolvedVars(t *testing.T) { data := json.RawMessage(`{"foo": 34359738368, "bar": 10, "is_foo": false, "is_bar": true}`) output, err := jsonlogic.GetJsonLogicWithSolvedVars(rule, data) - if err != nil { t.Fatal(err) } @@ -255,7 +254,6 @@ func TestIssue79(t *testing.T) { var result bytes.Buffer err := jsonlogic.Apply(rule, data, &result) - if err != nil { t.Fatal(err) } @@ -385,7 +383,7 @@ func TestIssue125_CustomOperatorWithVarsInSlice(t *testing.T) { parsed := values.([]any) needle := parsed[0] haystack := parsed[1].([]any) - + for _, item := range haystack { if item == needle { return true diff --git a/jsonlogic.go b/jsonlogic.go index 541b272..ab210f8 100644 --- a/jsonlogic.go +++ b/jsonlogic.go @@ -1,3 +1,25 @@ +// Package jsonlogic provides a Go implementation of JSONLogic rules engine. +// JSONLogic is a way to write rules that involve logic (boolean and mathematical operations), +// consistently in JSON. It's designed to be a lightweight, portable way to share logic +// between front-end and back-end systems. +// +// The package supports all standard JSONLogic operators and allows for custom operator registration. +// Rules can be applied to data using various input/output formats including io.Reader/Writer, +// json.RawMessage, and native Go interfaces. +// +// Basic usage: +// +// rule := strings.NewReader(`{"==":[{"var":"name"}, "John"]}`) +// data := strings.NewReader(`{"name":"John"}`) +// var result strings.Builder +// +// err := jsonlogic.Apply(rule, data, &result) +// if err != nil { +// log.Fatal(err) +// } +// // result.String() will be "true" +// +// For more examples and documentation, see: https://jsonlogic.com package jsonlogic import ( @@ -119,6 +141,18 @@ func ApplyInterface(rule, data any) (output any, err error) { return rule, err } +// GetJsonLogicWithSolvedVars processes a JSON Logic rule by resolving variables with actual data values. +// It returns the rule with variables substituted but maintains the JSON Logic structure. +// +// Parameters: +// - rule: json.RawMessage containing the JSON Logic rule +// - data: json.RawMessage containing the data context for variable resolution +// +// Returns: +// - []byte: the processed rule with resolved variables as JSON bytes +// - error: error if unmarshaling or processing fails +// +// This is useful for debugging or when you need to see the rule with variables resolved. func GetJsonLogicWithSolvedVars(rule, data json.RawMessage) ([]byte, error) { if data == nil { data = json.RawMessage("{}") diff --git a/jsonlogic_test.go b/jsonlogic_test.go index e27590c..135c449 100644 --- a/jsonlogic_test.go +++ b/jsonlogic_test.go @@ -9,7 +9,7 @@ import ( "github.com/stretchr/testify/assert" - "github.com/diegoholiveira/jsonlogic/v3" + jsonlogic "github.com/diegoholiveira/jsonlogic/v3" "github.com/diegoholiveira/jsonlogic/v3/internal" ) diff --git a/lists.go b/lists.go index 9ab20db..76fb8ba 100644 --- a/lists.go +++ b/lists.go @@ -7,6 +7,8 @@ import ( "github.com/diegoholiveira/jsonlogic/v3/internal/typing" ) +// ErrReduceDataType represents an error when an unsupported data type is used in reduce operations. +// It contains the data type name that caused the error. type ErrReduceDataType struct { dataType string } diff --git a/lists_test.go b/lists_test.go index 9500820..999b74a 100644 --- a/lists_test.go +++ b/lists_test.go @@ -7,7 +7,7 @@ import ( "github.com/stretchr/testify/assert" - "github.com/diegoholiveira/jsonlogic/v3" + jsonlogic "github.com/diegoholiveira/jsonlogic/v3" ) func TestFilterParseTheSubjectFromFirstPosition(t *testing.T) { diff --git a/math_test.go b/math_test.go index 4ee5137..8df65ab 100644 --- a/math_test.go +++ b/math_test.go @@ -6,7 +6,7 @@ import ( "github.com/stretchr/testify/assert" - "github.com/diegoholiveira/jsonlogic/v3" + jsonlogic "github.com/diegoholiveira/jsonlogic/v3" ) func TestSubOperation(t *testing.T) { diff --git a/operation.go b/operation.go index 7255d14..20f306e 100644 --- a/operation.go +++ b/operation.go @@ -7,8 +7,12 @@ import ( "github.com/diegoholiveira/jsonlogic/v3/internal/typing" ) +// OperatorFn defines the signature for custom operator functions. +// It takes values and data as input and returns a result. type OperatorFn func(values, data any) (result any) +// ErrInvalidOperator represents an error when an unsupported operator is used. +// It contains the operator name that caused the error. type ErrInvalidOperator struct { operator string } @@ -19,9 +23,17 @@ func (e ErrInvalidOperator) Error() string { // operators holds custom operators var operators = make(map[string]OperatorFn) + var operatorsLock = &sync.RWMutex{} -// AddOperator allows for custom operators to be used +// AddOperator registers a custom operator with the given key and function. +// The operator function will be called with parsed values and the original data context. +// +// Parameters: +// - key: the operator name to register (e.g., "custom_op") +// - cb: the function to execute when the operator is encountered +// +// Concurrency: This function is safe for concurrent use as it properly locks the operators map. func AddOperator(key string, cb OperatorFn) { operatorsLock.Lock() defer operatorsLock.Unlock() diff --git a/strings_test.go b/strings_test.go index 0481336..d5f75e6 100644 --- a/strings_test.go +++ b/strings_test.go @@ -6,7 +6,7 @@ import ( "github.com/stretchr/testify/assert" - "github.com/diegoholiveira/jsonlogic/v3" + jsonlogic "github.com/diegoholiveira/jsonlogic/v3" ) func TestCat(t *testing.T) { diff --git a/validator.go b/validator.go index 068edc2..ffe3488 100644 --- a/validator.go +++ b/validator.go @@ -7,7 +7,16 @@ import ( "github.com/diegoholiveira/jsonlogic/v3/internal/typing" ) -// IsValid reads a JSON Logic rule from io.Reader and validates it +// IsValid reads a JSON Logic rule from io.Reader and validates its syntax. +// It checks if the rule conforms to valid JSON Logic format and uses supported operators. +// +// Parameters: +// - rule: io.Reader containing the JSON Logic rule to validate +// +// Returns: +// - bool: true if the rule is valid, false otherwise +// +// The function returns false if the JSON cannot be parsed or if the rule contains invalid operators. func IsValid(rule io.Reader) bool { var _rule any @@ -20,6 +29,16 @@ func IsValid(rule io.Reader) bool { return ValidateJsonLogic(_rule) } +// ValidateJsonLogic validates if the given rules conform to JSON Logic format. +// It recursively checks the structure and ensures all operators are supported. +// +// Parameters: +// - rules: any value representing the JSON Logic rule to validate +// +// Returns: +// - bool: true if the rules are valid JSON Logic, false otherwise +// +// The function handles primitives, maps (operators), slices (arrays), and variable references. func ValidateJsonLogic(rules any) bool { if isVar(rules) { return true diff --git a/validator_test.go b/validator_test.go index b7cbf57..40d7223 100644 --- a/validator_test.go +++ b/validator_test.go @@ -8,7 +8,7 @@ import ( "github.com/stretchr/testify/assert" - "github.com/diegoholiveira/jsonlogic/v3" + jsonlogic "github.com/diegoholiveira/jsonlogic/v3" ) func TestJSONLogicValidator(t *testing.T) { diff --git a/vars.go b/vars.go index 18dceb4..581c31d 100644 --- a/vars.go +++ b/vars.go @@ -5,7 +5,7 @@ import ( "strconv" "strings" - "github.com/barkimedes/go-deepcopy" + deepcopy "github.com/barkimedes/go-deepcopy" "github.com/diegoholiveira/jsonlogic/v3/internal/typing" ) @@ -129,7 +129,6 @@ func solveVarsBackToJsonLogic(rule, data any) (json.RawMessage, error) { // we need to use Unquote due to unicode characters (example \u003e= need to be >=) // used for prettier json.RawMessage resultEscaped, err := strconv.Unquote(strings.Replace(strconv.Quote(string(resultJson)), `\\u`, `\u`, -1)) - if err != nil { return nil, err } diff --git a/vars_test.go b/vars_test.go index 8c82352..ec4a195 100644 --- a/vars_test.go +++ b/vars_test.go @@ -6,7 +6,7 @@ import ( "github.com/stretchr/testify/assert" - "github.com/diegoholiveira/jsonlogic/v3" + jsonlogic "github.com/diegoholiveira/jsonlogic/v3" ) func TestSetProperty(t *testing.T) {