{"id":36389571,"url":"https://github.com/gosuperscript/axiom","last_synced_at":"2026-02-10T12:04:55.189Z","repository":{"id":331889130,"uuid":"976610561","full_name":"gosuperscript/axiom","owner":"gosuperscript","description":null,"archived":false,"fork":false,"pushed_at":"2026-01-07T10:35:18.000Z","size":190,"stargazers_count":0,"open_issues_count":3,"forks_count":0,"subscribers_count":1,"default_branch":"main","last_synced_at":"2026-01-11T17:44:51.777Z","etag":null,"topics":[],"latest_commit_sha":null,"homepage":null,"language":"PHP","has_issues":true,"has_wiki":null,"has_pages":null,"mirror_url":null,"source_name":null,"license":"mit","status":null,"scm":"git","pull_requests_enabled":true,"icon_url":"https://github.com/gosuperscript.png","metadata":{"files":{"readme":"README.md","changelog":"CHANGELOG.md","contributing":"CONTRIBUTING.md","funding":null,"license":"LICENSE","code_of_conduct":null,"threat_model":null,"audit":null,"citation":null,"codeowners":null,"security":"SECURITY.md","support":null,"governance":null,"roadmap":null,"authors":null,"dei":null,"publiccode":null,"codemeta":null,"zenodo":null,"notice":null,"maintainers":null,"copyright":null,"agents":null,"dco":null,"cla":null}},"created_at":"2025-05-02T12:23:06.000Z","updated_at":"2026-01-07T10:35:18.000Z","dependencies_parsed_at":null,"dependency_job_id":null,"html_url":"https://github.com/gosuperscript/axiom","commit_stats":null,"previous_names":["gosuperscript/axiom"],"tags_count":3,"template":false,"template_full_name":null,"purl":"pkg:github/gosuperscript/axiom","repository_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/gosuperscript%2Faxiom","tags_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/gosuperscript%2Faxiom/tags","releases_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/gosuperscript%2Faxiom/releases","manifests_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/gosuperscript%2Faxiom/manifests","owner_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/owners/gosuperscript","download_url":"https://codeload.github.com/gosuperscript/axiom/tar.gz/refs/heads/main","sbom_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/gosuperscript%2Faxiom/sbom","scorecard":null,"host":{"name":"GitHub","url":"https://github.com","kind":"github","repositories_count":286080680,"owners_count":28408336,"icon_url":"https://github.com/github.png","version":null,"created_at":"2022-05-30T11:31:42.601Z","updated_at":"2026-01-14T00:40:43.272Z","status":"ssl_error","status_checked_at":"2026-01-14T00:40:42.636Z","response_time":56,"last_error":"SSL_connect returned=1 errno=0 peeraddr=140.82.121.5:443 state=error: unexpected eof while reading","robots_txt_status":"success","robots_txt_updated_at":"2025-07-24T06:49:26.215Z","robots_txt_url":"https://github.com/robots.txt","online":false,"can_crawl_api":true,"host_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub","repositories_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories","repository_names_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repository_names","owners_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/owners"}},"keywords":[],"created_at":"2026-01-11T15:50:10.733Z","updated_at":"2026-01-14T01:31:39.870Z","avatar_url":"https://github.com/gosuperscript.png","language":"PHP","funding_links":[],"categories":[],"sub_categories":[],"readme":"# Axiom Library\n\nA powerful PHP library for data transformation, type validation, and expression evaluation. This library provides a flexible framework for defining data schemas, transforming values, and evaluating complex expressions with type safety.\n\n## Features\n\n- **Type System**: Robust type validation and transformation for numbers, strings, booleans, lists, and dictionaries\n- **Expression Evaluation**: Support for infix expressions with custom operators\n- **Resolver Pattern**: Pluggable resolver system for different data sources\n- **Symbol Registry**: Named value resolution and reuse\n- **Operator Overloading**: Extensible operator system for custom evaluation logic\n- **Monadic Error Handling**: Built on functional programming principles using Result and Option types\n\n## Requirements\n\n- PHP 8.4 or higher\n- ext-intl extension\n\n## Installation\n\n```bash\ncomposer require gosuperscript/axiom\n```\n\n## Quick Start\n\n### Basic Type Transformation\n\n```php\n\u003c?php\n\nuse Superscript\\Axiom\\Types\\NumberType;\nuse Superscript\\Axiom\\Sources\\StaticSource;\nuse Superscript\\Axiom\\Sources\\TypeDefinition;\nuse Superscript\\Axiom\\Resolvers\\DelegatingResolver;\nuse Superscript\\Axiom\\Resolvers\\StaticResolver;\nuse Superscript\\Axiom\\Resolvers\\ValueResolver;\n\n// Create a resolver with basic capabilities\n$resolver = new DelegatingResolver([\n    StaticResolver::class,\n    ValueResolver::class,\n]);\n\n// Transform a string to a number\n$source = new TypeDefinition(\n    type: new NumberType(),\n    source: new StaticSource('42')\n);\n\n$result = $resolver-\u003eresolve($source);\n$value = $result-\u003eunwrap()-\u003eunwrap(); // 42 (as integer)\n```\n\n### Expression Evaluation\n\n```php\n\u003c?php\n\nuse Superscript\\Axiom\\Sources\\InfixExpression;\nuse Superscript\\Axiom\\Sources\\StaticSource;\nuse Superscript\\Axiom\\Sources\\SymbolSource;\nuse Superscript\\Axiom\\SymbolRegistry;\nuse Superscript\\Axiom\\Resolvers\\DelegatingResolver;\nuse Superscript\\Axiom\\Resolvers\\InfixResolver;\nuse Superscript\\Axiom\\Resolvers\\SymbolResolver;\n\n// Set up resolver with symbol support\n$resolver = new DelegatingResolver([\n    StaticResolver::class,\n    InfixResolver::class,\n    SymbolResolver::class,\n]);\n\n// Register symbols\n$resolver-\u003einstance(SymbolRegistry::class, new SymbolRegistry([\n    'PI' =\u003e new StaticSource(3.14159),\n    'radius' =\u003e new StaticSource(5),\n]));\n\n// Calculate: PI * radius * radius (area of circle)\n$expression = new InfixExpression(\n    left: new SymbolSource('PI'),\n    operator: '*',\n    right: new InfixExpression(\n        left: new SymbolSource('radius'),\n        operator: '*',\n        right: new SymbolSource('radius')\n    )\n);\n\n$result = $resolver-\u003eresolve($expression);\n$area = $result-\u003eunwrap()-\u003eunwrap(); // ~78.54\n```\n\n### Using Namespaced Symbols\n\nThe `SymbolRegistry` supports namespaces to organize related symbols:\n\n```php\n\u003c?php\n\nuse Superscript\\Axiom\\Sources\\StaticSource;\nuse Superscript\\Axiom\\Sources\\SymbolSource;\nuse Superscript\\Axiom\\SymbolRegistry;\n\n// Create registry with namespaced symbols\n$registry = new SymbolRegistry([\n    // Global symbols (no namespace)\n    'version' =\u003e new StaticSource('1.0.0'),\n    'debug' =\u003e new StaticSource(true),\n    \n    // Math namespace\n    'math' =\u003e [\n        'pi' =\u003e new StaticSource(3.14159),\n        'e' =\u003e new StaticSource(2.71828),\n        'phi' =\u003e new StaticSource(1.61803),\n    ],\n    \n    // Constants namespace\n    'physics' =\u003e [\n        'c' =\u003e new StaticSource(299792458),      // Speed of light\n        'g' =\u003e new StaticSource(9.80665),        // Gravitational acceleration\n    ],\n]);\n\n// Access global symbols\n$version = $registry-\u003eget('version');           // Some('1.0.0')\n\n// Access namespaced symbols\n$pi = $registry-\u003eget('pi', 'math');            // Some(3.14159)\n$c = $registry-\u003eget('c', 'physics');           // Some(299792458)\n\n// Using with SymbolSource\n$symbolSource = new SymbolSource('pi', 'math');\n$result = $resolver-\u003eresolve($symbolSource);   // ~3.14159\n\n// Namespaces provide isolation\n$registry-\u003eget('pi');                           // None (no global 'pi')\n$registry-\u003eget('c', 'math');                   // None (no 'c' in math namespace)\n```\n\n## Core Concepts\n\n### Types\n\nThe library provides several built-in types for data validation and coercion:\n\n#### NumberType\nValidates and coerces values to numeric types (int/float):\n- Numeric strings: `\"42\"` → `42`\n- Percentage strings: `\"50%\"` → `0.5`\n- Numbers: `42.5` → `42.5`\n\n#### StringType\nValidates and coerces values to strings:\n- Numbers: `42` → `\"42\"`\n- Stringable objects: converted to string representation\n- Special handling for null and empty values\n\n#### BooleanType\nValidates and coerces values to boolean:\n- Truthy/falsy evaluation\n- String representations: `\"true\"`, `\"false\"`\n\n#### ListType and DictType\nFor collections and associative arrays with nested type validation.\n\n### Type API: Assert vs Coerce\n\nThe `Type` interface provides two methods for value processing, following the [@azjezz/psl](https://github.com/azjezz/psl) pattern:\n\n- **`assert(T $value): Result\u003cOption\u003cT\u003e\u003e`** - Validates that a value is already of the correct type\n- **`coerce(mixed $value): Result\u003cOption\u003cT\u003e\u003e`** - Attempts to convert a value from any type to the target type\n\n**When to use:**\n- Use `assert()` when you expect a value to already be the correct type and want strict validation\n- Use `coerce()` when you want to transform values from various input types (permissive conversion)\n\n**Example:**\n```php\n$numberType = new NumberType();\n\n// Assert - only accepts int/float\n$result = $numberType-\u003eassert(42);      // Ok(Some(42))\n$result = $numberType-\u003eassert('42');    // Err(TransformValueException)\n\n// Coerce - converts compatible types\n$result = $numberType-\u003ecoerce(42);      // Ok(Some(42))\n$result = $numberType-\u003ecoerce('42');    // Ok(Some(42))\n$result = $numberType-\u003ecoerce('45%');   // Ok(Some(0.45))\n```\n\nBoth methods return `Result\u003cOption\u003cT\u003e, Throwable\u003e` where:\n- `Ok(Some(value))` - successful validation/coercion with a value\n- `Ok(None())` - successful but no value (e.g., empty strings)\n- `Err(exception)` - failed validation/coercion\n\n**Note:** The `coerce()` method provides the same functionality as the previous `transform()` method.\n\n### Sources\n\nSources represent different ways to provide data:\n\n- **StaticSource**: Direct values\n- **SymbolSource**: Named references to other sources (with optional namespace support)\n- **TypeDefinition**: Combines a type with a source for validation and coercion\n- **InfixExpression**: Mathematical/logical expressions\n- **UnaryExpression**: Single-operand expressions\n\n### Symbol Registry\n\nThe `SymbolRegistry` provides a centralized way to manage named values and organize them using namespaces:\n\n**Key Features:**\n- **Global Symbols**: Direct symbol registration without namespace isolation\n- **Namespaced Symbols**: Group related symbols under namespaces for better organization\n- **Isolation**: Symbols in different namespaces are isolated from each other\n- **Type Safety**: Only `Source` instances can be registered\n\n**Registration Format:**\n```php\nnew SymbolRegistry([\n    'globalSymbol' =\u003e new StaticSource(value),    // Global scope\n    'namespace' =\u003e [                               // Namespaced scope\n        'symbol1' =\u003e new StaticSource(value1),\n        'symbol2' =\u003e new StaticSource(value2),\n    ],\n])\n```\n\n**Use Cases:**\n- Organize constants by category (math, physics, config)\n- Prevent naming conflicts between different domains\n- Create clear separation between different symbol contexts\n- Improve code maintainability with logical grouping\n\n### Resolvers\n\nResolvers handle the evaluation of sources:\n\n- **StaticResolver**: Resolves static values\n- **ValueResolver**: Applies type coercion using the `coerce()` method\n- **InfixResolver**: Evaluates binary expressions\n- **SymbolResolver**: Looks up named symbols\n- **DelegatingResolver**: Chains multiple resolvers together\n\n### Operators\n\nThe library supports various operators through the overloader system:\n\n- **Binary**: `+`, `-`, `*`, `/`, `%`, `**`\n- **Comparison**: `==`, `!=`, `\u003c`, `\u003c=`, `\u003e`, `\u003e=`\n- **Logical**: `\u0026\u0026`, `||`\n- **Special**: `has`, `in`, `intersects`\n\n## Advanced Usage\n\n### Custom Types\n\nImplement the `Type` interface to create custom data validations and coercions:\n\n```php\n\u003c?php\n\nuse Superscript\\Axiom\\Types\\Type;\nuse Superscript\\Monads\\Result\\Result;\nuse Superscript\\Monads\\Result\\Err;\nuse Superscript\\Axiom\\Exceptions\\TransformValueException;\nuse function Superscript\\Monads\\Result\\Ok;\nuse function Superscript\\Monads\\Option\\Some;\n\nclass EmailType implements Type\n{\n    public function assert(mixed $value): Result\n    {\n        // Strict validation - only accepts valid email strings\n        if (is_string($value) \u0026\u0026 filter_var($value, FILTER_VALIDATE_EMAIL)) {\n            return Ok(Some($value));\n        }\n        \n        return new Err(new TransformValueException(type: 'email', value: $value));\n    }\n    \n    public function coerce(mixed $value): Result\n    {\n        // Permissive conversion - attempts to convert to email format\n        $stringValue = is_string($value) ? $value : strval($value);\n        $trimmed = trim($stringValue);\n        \n        if (filter_var($trimmed, FILTER_VALIDATE_EMAIL)) {\n            return Ok(Some($trimmed));\n        }\n        \n        return new Err(new TransformValueException(type: 'email', value: $value));\n    }\n    \n    public function compare(mixed $a, mixed $b): bool\n    {\n        return $a === $b;\n    }\n    \n    public function format(mixed $value): string\n    {\n        return (string) $value;\n    }\n}\n```\n\n### Custom Resolvers\n\nCreate specialized resolvers for specific data sources:\n\n```php\n\u003c?php\n\nuse Superscript\\Axiom\\Resolvers\\Resolver;\nuse Superscript\\Axiom\\Source;\nuse Superscript\\Monads\\Result\\Result;\n\nclass DatabaseResolver implements Resolver\n{\n    public function resolve(Source $source): Result\n    {\n        // Custom resolution logic\n        // Connect to database, fetch data, etc.\n    }\n    \n    public static function supports(Source $source): bool\n    {\n        return $source instanceof DatabaseSource;\n    }\n}\n```\n\n## Development\n\n### Setup\n\n1. Clone the repository\n2. Install dependencies: `composer install`\n3. Run tests: `composer test`\n\n### Testing\n\nThe library uses PHPUnit for testing with 100% code coverage requirements:\n\n```bash\n# Run all tests\ncomposer test\n\n# Individual test suites\ncomposer test:unit      # Unit tests\ncomposer test:types     # Static analysis (PHPStan)\ncomposer test:infection # Mutation testing\n```\n\n### Code Quality\n\n- **PHPStan**: Level max static analysis\n- **Infection**: Mutation testing for test quality\n- **Laravel Pint**: Code formatting\n- **100% Code Coverage**: Required for all new code\n\n## Architecture\n\nThe library follows several design patterns:\n\n- **Strategy Pattern**: Different resolvers for different source types\n- **Chain of Responsibility**: DelegatingResolver chains multiple resolvers\n- **Factory Pattern**: Type system for creating appropriate transformations\n- **Functional Programming**: Extensive use of Result and Option monads\n\n## Error Handling\n\nAll type validation and coercion operations return `Result\u003cOption\u003cT\u003e, Throwable\u003e` types:\n\n- `Result::Ok(Some(value))`: Successful validation/coercion with value\n- `Result::Ok(None())`: Successful validation/coercion with no value (null/empty)\n- `Result::Err(exception)`: Validation/coercion failed with error\n\nThis approach ensures:\n- No exceptions for normal control flow\n- Explicit handling of success/failure cases\n- Type-safe null handling\n\n## License\n\nThis library is open-sourced software licensed under the [MIT license](LICENSE).\n\n## Contributing\n\nContributions are welcome! Please see [CONTRIBUTING.md](CONTRIBUTING.md) for details on how to contribute to this project.\n\n## Security\n\nIf you discover any security-related issues, please review our [Security Policy](SECURITY.md) for information on how to responsibly report vulnerabilities.","project_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Fgosuperscript%2Faxiom","html_url":"https://awesome.ecosyste.ms/projects/github.com%2Fgosuperscript%2Faxiom","lists_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Fgosuperscript%2Faxiom/lists"}