npm package discovery and stats viewer.

Discover Tips

  • General search

    [free text search, go nuts!]

  • Package details

    pkg:[package-name]

  • User packages

    @[username]

Sponsor

Optimize Toolset

I’ve always been into building performant and accessible sites, but lately I’ve been taking it extremely seriously. So much so that I’ve been building a tool to help me optimize and monitor the sites that I build to make sure that I’m making an attempt to offer the best experience to those who visit them. If you’re into performant, accessible and SEO friendly sites, you might like it too! You can check it out at Optimize Toolset.

About

Hi, 👋, I’m Ryan Hefner  and I built this site for me, and you! The goal of this site was to provide an easy way for me to check the stats on my npm packages, both for prioritizing issues and updates, and to give me a little kick in the pants to keep up on stuff.

As I was building it, I realized that I was actually using the tool to build the tool, and figured I might as well put this out there and hopefully others will find it to be a fast and useful way to search and browse npm packages as I have.

If you’re interested in other things I’m working on, follow me on Twitter or check out the open source projects I’ve been publishing on GitHub.

I am also working on a Twitter bot for this site to tweet the most popular, newest, random packages from npm. Please follow that account now and it will start sending out packages soon–ish.

Open Software & Tools

This site wouldn’t be possible without the immense generosity and tireless efforts from the people who make contributions to the world and share their work via open source initiatives. Thank you 🙏

© 2025 – Pkg Stats / Ryan Hefner

@json-eval-rs/react-native

v0.0.30

Published

High-performance JSON Logic evaluator with schema validation for React Native

Readme

@json-eval-rs/react-native

High-performance JSON Logic evaluator with schema validation for React Native.

Built with Rust for maximum performance, with native Android (Kotlin + JNI) and iOS (Objective-C++) bindings. All operations run asynchronously on background threads to keep your UI responsive.

Features

  • 🚀 Native Performance - Built with Rust for iOS and Android
  • Schema Validation - Validate data against JSON schema rules
  • 🔄 Dependency Tracking - Auto-update dependent fields
  • 🎯 Type Safe - Full TypeScript support
  • ⚛️ React Hooks - Built-in useJSONEval hook
  • 📱 Cross-Platform - Works on iOS and Android
  • 🔥 Fast - Native performance, not JavaScript

Installation

yarn install @json-eval-rs/react-native

Or with Yarn:

yarn add @json-eval-rs/react-native

iOS

cd ios && pod install

Android

No additional steps required. The library uses autolinking.

Quick Start

Basic Usage

import { JSONEval } from '@json-eval-rs/react-native';

const schema = {
  type: 'object',
  properties: {
    user: {
      type: 'object',
      properties: {
        name: {
          type: 'string',
          rules: {
            required: { value: true, message: 'Name is required' },
            minLength: { value: 3, message: 'Min 3 characters' }
          }
        },
        age: {
          type: 'number',
          rules: {
            minValue: { value: 18, message: 'Must be 18+' }
          }
        }
      }
    }
  }
};

// Create evaluator
const eval = new JSONEval({ schema });

// Evaluate
const data = { user: { name: 'John', age: 25 } };
const result = await eval.evaluate({ data });
console.log('Evaluated:', result);

// Validate
const validation = await eval.validate({ data });
if (validation.hasError) {
  validation.errors.forEach(error => {
    console.error(`${error.path}: ${error.message}`);
  });
}

// Clean up
await eval.dispose();

Using React Hook

import React, { useState } from 'react';
import { View, TextInput, Button, Text } from 'react-native';
import { useJSONEval } from '@json-eval-rs/react-native';

const schema = {
  type: 'object',
  properties: {
    user: {
      type: 'object',
      properties: {
        name: {
          type: 'string',
          rules: {
            required: { value: true, message: 'Name is required' },
            minLength: { value: 3, message: 'Min 3 characters' }
          }
        }
      }
    }
  }
};

function MyForm() {
  const eval = useJSONEval({ schema });
  const [name, setName] = useState('');
  const [errors, setErrors] = useState<string[]>([]);

  const handleValidate = async () => {
    if (!eval) return;
    
    const data = { user: { name } };
    const validation = await eval.validate({ data });
    
    if (validation.hasError) {
      setErrors(validation.errors.map(e => e.message));
    } else {
      setErrors([]);
      console.log('Valid!');
    }
  };

  return (
    <View>
      <TextInput
        value={name}
        onChangeText={setName}
        placeholder="Enter name"
      />
      <Button title="Validate" onPress={handleValidate} />
      
      {errors.map((error, i) => (
        <Text key={i} style={{ color: 'red' }}>{error}</Text>
      ))}
    </View>
  );
}

Advanced: Dependent Fields

import React, { useState, useEffect } from 'react';
import { View, TextInput, Text } from 'react-native';
import { useJSONEval } from '@json-eval-rs/react-native';

const schema = {
  type: 'object',
  properties: {
    quantity: { type: 'number' },
    price: { type: 'number' },
    total: {
      type: 'number',
      $evaluation: {
        '*': [{ var: 'quantity' }, { var: 'price' }]
      }
    }
  }
};

function Calculator() {
  const eval = useJSONEval({ schema });
  const [quantity, setQuantity] = useState(1);
  const [price, setPrice] = useState(10);
  const [total, setTotal] = useState(0);

  useEffect(() => {
    if (!eval) return;
    
    const updateTotal = async () => {
      const data = { quantity, price };
      const result = await eval.evaluateDependents({
        changedPaths: ['quantity'],  // Array of changed field paths
        data,
        reEvaluate: false  // Optional: re-evaluate entire schema after dependents
      });
      
      setTotal(result.total);
    };
    
    updateTotal();
  }, [eval, quantity, price]);

  return (
    <View>
      <TextInput
        value={String(quantity)}
        onChangeText={(val) => setQuantity(Number(val))}
        keyboardType="numeric"
      />
      <TextInput
        value={String(price)}
        onChangeText={(val) => setPrice(Number(val))}
        keyboardType="numeric"
      />
      <Text>Total: {total}</Text>
    </View>
  );
}

API Reference

JSONEval Class

Constructor

constructor(options: {
  schema: string | object;
  context?: string | object;
  data?: string | object;
})

Creates a new evaluator instance.

Methods

evaluate(options)

Evaluates the schema with provided data.

async evaluate(options: {
  data: string | object;
  context?: string | object;
}): Promise<any>
validate(options)

Validates data against schema rules.

async validate(options: {
  data: string | object;
  context?: string | object;
}): Promise<ValidationResult>

Returns:

interface ValidationResult {
  hasError: boolean;
  errors: ValidationError[];
}

interface ValidationError {
  path: string;
  ruleType: string;
  message: string;
}
evaluateDependents(options)

Re-evaluates fields that depend on changed paths (processes transitively).

async evaluateDependents(options: {
  changedPaths: string[];      // Array of field paths that changed
  data?: string | object;       // Optional updated data
  context?: string | object;    // Optional context
  reEvaluate?: boolean;         // If true, performs full evaluation after dependents
}): Promise<any[]>

Parameters:

  • changedPaths: Array of field paths that changed (e.g., ['field1', 'nested.field2'])
  • data: Optional JSON data (string or object). If provided, replaces current data
  • context: Optional context data
  • reEvaluate: If true, performs full schema evaluation after processing dependents (default: false)

Returns: Array of dependent field change objects with $ref, value, $field, $parentField, and transitive properties.

Example:

// Update multiple fields and get their dependents
const result = await eval.evaluateDependents({
  changedPaths: ['illustration.insured.ins_dob', 'illustration.product_code'],
  data: updatedData,
  reEvaluate: true  // Re-run full evaluation after dependents
});

// Process the changes
result.forEach(change => {
  console.log(`Field ${change.$ref} changed:`, change.value);
});
dispose()

Frees native resources. Must be called when done.

async dispose(): Promise<void>
static version()

Gets the library version.

static async version(): Promise<string>

useJSONEval Hook

React hook for automatic lifecycle management.

function useJSONEval(options: JSONEvalOptions): JSONEval | null

Returns null until initialized, then returns the JSONEval instance. Automatically disposes on unmount.

Validation Rules

Supported validation rules:

  • required - Field must have a value
  • minLength / maxLength - String/array length validation
  • minValue / maxValue - Numeric range validation
  • pattern - Regex pattern matching

Platform Support

  • iOS: 11.0+
  • Android: API 21+ (Android 5.0)
  • React Native: 0.64+

Performance

Typical performance on modern devices:

  • Schema parsing: < 5ms
  • Evaluation: < 10ms for complex schemas
  • Validation: < 5ms

Native performance beats JavaScript-only solutions by 10-50x.

Sequential Processing

This library uses sequential processing by default, which is optimal for mobile devices. The Rust core supports an optional parallel feature using Rayon, but:

  • Mobile devices have limited cores and power constraints
  • Sequential processing is faster for typical mobile use cases (small to medium datasets)
  • Parallel overhead exceeds benefits for arrays < 1000 items
  • Battery life is better with sequential processing

The default configuration is optimized for mobile performance and battery efficiency.

Error Handling

All async methods can throw errors:

try {
  const result = await eval.evaluate({ data });
} catch (error) {
  console.error('Evaluation error:', error.message);
}

Memory Management

Always dispose of instances when done:

const eval = new JSONEval({ schema });
try {
  // Use eval
} finally {
  await eval.dispose(); // Important!
}

Or use the hook for automatic management:

function MyComponent() {
  const eval = useJSONEval({ schema }); // Auto-disposed on unmount
  // Use eval
}

TypeScript

Full TypeScript support included. All types are exported:

import type {
  JSONEval,
  ValidationError,
  ValidationResult,
  JSONEvalOptions,
  EvaluateOptions,
  EvaluateDependentsOptions
} from '@json-eval-rs/react-native';

Troubleshooting

iOS Build Errors

If you encounter build errors on iOS:

cd ios
rm -rf Pods Podfile.lock
pod install --repo-update

Android Build Errors

If you encounter build errors on Android:

cd android
./gradlew clean
cd ..

Then rebuild your app.

"Module not found" Error

Make sure you've:

  1. Installed the package
  2. Run pod install on iOS
  3. Rebuilt the app completely

Contributing

See the contributing guide to learn how to contribute to the repository and the development workflow.

License

MIT

Support

  • GitHub Issues: https://github.com/byrizki/json-eval-rs/issues
  • Documentation: https://github.com/byrizki/json-eval-rs