{"_id":"@bakes/dastardly-validation","name":"@bakes/dastardly-validation","dist-tags":{"latest":"1.0.0"},"versions":{"1.0.0":{"name":"@bakes/dastardly-validation","version":"1.0.0","description":"JSON Schema validator for dASTardly ASTs","type":"module","main":"dist/index.js","types":"dist/index.d.ts","exports":{".":{"types":"./dist/index.d.ts","import":"./dist/index.js","default":"./dist/index.js"}},"keywords":["json-schema","validator","validation","ast"],"author":{"name":"The Software Bakery"},"license":"MIT","repository":{"type":"git","url":"git+https://github.com/thesoftwarebakery/dastardly.git","directory":"packages/validation"},"homepage":"https://github.com/thesoftwarebakery/dastardly#readme","bugs":{"url":"https://github.com/thesoftwarebakery/dastardly/issues"},"publishConfig":{"access":"public"},"dependencies":{"@types/json-schema":"^7.0.15","@bakes/dastardly-core":"^1.0.0"},"devDependencies":{"@json-schema-org/tests":"^1.0.0","@types/benchmark":"^2.1.5","@vitest/ui":"^1.6.1","ajv":"^8.17.1","ajv-formats":"^3.0.1","benchmark":"^2.1.4","typescript":"^5.3.0","vitest":"^1.6.1","@bakes/dastardly-json":"^1.0.0"},"scripts":{"build":"tsc","typecheck":"tsc --noEmit","test":"vitest run","test:watch":"vitest","benchmark":"pnpm build && npx tsx benchmarks/run.ts"},"_id":"@bakes/dastardly-validation@1.0.0","_integrity":"sha512-u6tmBYqhFdvM3wr8SaK7dsAOlduPXgxY12fCJ3yfcg631l8zs6f6g2+2VQu4EjLV5070nj811jpI+e4XHS2Nww==","_resolved":"/tmp/1a4cf8290fc5b61249e786a211d55abf/bakes-dastardly-validation-1.0.0.tgz","_from":"file:bakes-dastardly-validation-1.0.0.tgz","_nodeVersion":"20.19.5","_npmVersion":"10.8.2","dist":{"integrity":"sha512-u6tmBYqhFdvM3wr8SaK7dsAOlduPXgxY12fCJ3yfcg631l8zs6f6g2+2VQu4EjLV5070nj811jpI+e4XHS2Nww==","shasum":"c1bafbcb3e54e1c68039e508c892a0484a1d259a","tarball":"https://registry.npmjs.org/@bakes/dastardly-validation/-/dastardly-validation-1.0.0.tgz","fileCount":83,"unpackedSize":174870,"attestations":{"url":"https://registry.npmjs.org/-/npm/v1/attestations/@bakes%2fdastardly-validation@1.0.0","provenance":{"predicateType":"https://slsa.dev/provenance/v1"}},"signatures":[{"keyid":"SHA256:DhQ8wR5APBvFHLF/+Tc+AYvPOdTpcIDqOhxsBHRwC7U","sig":"MEYCIQCzu9HmnI6kj48u527dEA5Amvrt/5bumcZkrBevCCJpQAIhAP9/mKlqvWY7G0QvqaXSw5jjdDzDUCb93fYXTCBZY44d"}]},"_npmUser":{"name":"georgewaters","email":"george@bakes.software"},"directories":{},"maintainers":[{"name":"georgewaters","email":"george@bakes.software"}],"_npmOperationalInternal":{"host":"s3://npm-registry-packages-npm-production","tmp":"tmp/dastardly-validation_1.0.0_1763161282272_0.32703846251828206"},"_hasShrinkwrap":false}},"time":{"created":"2025-11-14T23:01:22.174Z","1.0.0":"2025-11-14T23:01:22.482Z","modified":"2025-11-14T23:01:23.075Z"},"maintainers":[{"name":"georgewaters","email":"george@bakes.software"}],"description":"JSON Schema validator for dASTardly ASTs","homepage":"https://github.com/thesoftwarebakery/dastardly#readme","keywords":["json-schema","validator","validation","ast"],"repository":{"type":"git","url":"git+https://github.com/thesoftwarebakery/dastardly.git","directory":"packages/validation"},"author":{"name":"The Software Bakery"},"bugs":{"url":"https://github.com/thesoftwarebakery/dastardly/issues"},"license":"MIT","readme":"# @bakes/dastardly-validation\n\nJSON Schema validator for dASTardly ASTs with comprehensive Draft 7 support.\n\n## Features\n\n- ✅ **86.1% JSON Schema Draft 7 compliance** (488/567 official test suite tests passing)\n- ✅ **High-performance schema compilation** - AJV-inspired architecture with validator caching\n- ✅ **Precise error reporting** - Source location tracking with line/column/offset information\n- ✅ **Content-addressable caching** - Automatic validation result caching for identical nodes\n- ✅ **Modular validators** - Clean separation of concerns, testable in isolation\n- ✅ **Full recursive validation** - Nested objects, arrays, and complex schemas\n- ✅ **$ref support** - Local JSON Pointer references with automatic resolution\n- ✅ **Conditional validation** - if/then/else schema logic\n\n## Installation\n\n```bash\npnpm add @bakes/dastardly-validation\n```\n\n## Quick Start\n\n```typescript\nimport { json } from '@bakes/dastardly-json';\nimport { Validator } from '@bakes/dastardly-validation';\n\n// Define your JSON Schema\nconst schema = {\n  type: 'object',\n  properties: {\n    name: { type: 'string', minLength: 1 },\n    age: { type: 'number', minimum: 0 },\n    email: { type: 'string', pattern: '^[^@]+@[^@]+$' }\n  },\n  required: ['name', 'email']\n};\n\n// Parse your data to AST\nconst document = json.parse(`{\n  \"name\": \"Alice\",\n  \"age\": 30,\n  \"email\": \"alice@example.com\"\n}`);\n\n// Create validator and validate\nconst validator = new Validator(schema);\nconst result = validator.validate(document);\n\nif (result.valid) {\n  console.log('Valid!');\n} else {\n  for (const error of result.errors) {\n    console.error(`${error.path}: ${error.message}`);\n    console.error(`  at line ${error.location.start.line}, column ${error.location.start.column}`);\n  }\n}\n```\n\n## Supported Keywords\n\n### Type Validation\n- `type` - Type checking (string, number, integer, boolean, object, array, null)\n- `enum` - Enumeration validation\n- `const` - Constant value validation\n\n### String Validation\n- `minLength`, `maxLength` - Length constraints\n- `pattern` - Regular expression validation\n\n### Number Validation\n- `minimum`, `maximum` - Inclusive bounds\n- `exclusiveMinimum`, `exclusiveMaximum` - Exclusive bounds\n- `multipleOf` - Divisibility validation\n\n### Array Validation\n- `minItems`, `maxItems` - Length constraints\n- `uniqueItems` - Uniqueness validation\n- `items` - Element schema validation (single schema or tuple)\n- `additionalItems` - Extra elements beyond tuple schema\n- `contains` - At least one matching element\n\n### Object Validation\n- `properties` - Property schema validation\n- `patternProperties` - Regex-based property validation\n- `additionalProperties` - Extra properties validation\n- `required` - Required properties\n- `minProperties`, `maxProperties` - Property count constraints\n- `dependencies` - Property and schema dependencies\n\n### Combinators\n- `allOf` - Must match all schemas\n- `anyOf` - Must match at least one schema\n- `oneOf` - Must match exactly one schema\n- `not` - Must not match schema\n\n### Conditional\n- `if`/`then`/`else` - Conditional schema application\n\n### References\n- `$ref` - Local JSON Pointer references (e.g., `#/definitions/address`)\n\n### Boolean Schemas\n- `true` - Always valid\n- `false` - Always invalid\n\n## Validator Options\n\n```typescript\nconst validator = new Validator(schema, {\n  // Enable/disable validation result caching (default: true)\n  cache: true,\n\n  // Maximum cache size (default: 1000)\n  cacheSize: 1000,\n\n  // Stop on first error (default: false)\n  failFast: false\n});\n```\n\n## Validation Result\n\n```typescript\ninterface ValidationResult {\n  valid: boolean;\n  errors: ValidationError[];\n}\n\ninterface ValidationError {\n  path: string;              // JSON Pointer to error location\n  message: string;           // Human-readable error message\n  keyword: string;           // Schema keyword that failed\n  schemaPath: string;        // Path in schema\n  location: SourceLocation;  // Source code location\n  params: Record<string, unknown>; // Additional context\n}\n```\n\n## Architecture\n\n### Schema Compilation\n\nSchemas are compiled once into optimized validator functions:\n\n```typescript\n// Schema is compiled on validator creation\nconst validator = new Validator(schema);\n\n// Compiled validators are cached by reference\n// Multiple validations reuse the same compiled validators\nvalidator.validate(doc1);\nvalidator.validate(doc2);\n```\n\n### Validation Caching\n\nValidation results are automatically cached using content-based hashing:\n\n```typescript\nconst validator = new Validator(schema);\n\n// First validation computes and caches result\nconst result1 = validator.validate(document);\n\n// Second validation with identical AST node reuses cached result\nconst result2 = validator.validate(document);\n```\n\n### Modular Validators\n\nEach JSON Schema keyword is implemented as an independent validator:\n\n```typescript\n// Type validator\ncreateTypeValidator('string')\n\n// Number range validator\ncreateMinimumValidator(10)\n\n// Nested validation\ncreatePropertiesValidator(propertiesSchema, compiler)\n```\n\nValidators are composable and testable in isolation.\n\n## Testing\n\nThe validator is tested against the [official JSON Schema Test Suite](https://github.com/json-schema-org/JSON-Schema-Test-Suite):\n\n```bash\npnpm test json-schema-test-suite.test.ts\n```\n\n**Current Status:** 536/567 tests passing (94.5%)\n\n### Test Failure Breakdown\n\nThe 31 remaining test failures fall into the following categories:\n\n| Category | Tests | Status | Notes |\n|----------|-------|--------|-------|\n| Remote `$ref` / `$id` | 11 | ❌ Not supported by design | External schema references (http://), named schema resolution via `$id`, and meta-schema validation are intentionally not implemented |\n| BigNum precision | 7 | ⚠️ JSON parser limitation | Numbers with very large exponents (>10^52) exceed JavaScript `Number` precision - would require BigInt support in parser |\n| Content validation | 4 | ⚠️ Optional feature | `contentMediaType`/`contentEncoding` keywords are optional per spec - low priority |\n| Format edge cases | 6 | ⚠️ Strict compliance | Internationalized formats (IRI, IDN hostname) and very strict RFC compliance edge cases |\n| Regex compatibility | 1 | ❌ JavaScript limitation | .NET-specific regex features (`\\Z` anchor) not supported by JavaScript |\n| Date-time strict | 1 | ⚠️ Strict RFC compliance | Very specific timezone offset format validation |\n| IDN hostname strict | 1 | ⚠️ Strict compliance | Unicode normalization and illegal character detection |\n\n**Legend:**\n- ❌ = Not supported by design or language limitation (11 tests)\n- ⚠️ = Optional feature, strict compliance, or external limitation (19 tests)\n- ✅ = All realistically fixable issues have been addressed (1 test remaining is a format edge case)\n\n### What's Implemented\n\n✅ **Core Validation (32 keywords):**\n- Type checking: `type`, `enum`, `const`\n- Strings: `minLength`, `maxLength`, `pattern`, `format` (17 formats)\n- Numbers: `minimum`, `maximum`, `exclusiveMinimum`, `exclusiveMaximum`, `multipleOf`\n- Arrays: `minItems`, `maxItems`, `uniqueItems`, `items`, `additionalItems`, `contains`\n- Objects: `required`, `minProperties`, `maxProperties`, `properties`, `patternProperties`, `additionalProperties`, `dependencies`, `propertyNames`\n- Combinators: `allOf`, `anyOf`, `oneOf`, `not`\n- Conditional: `if`/`then`/`else`\n- References: `$ref` (local JSON Pointers)\n- Boolean schemas: `true`/`false`\n\n### What's Not Implemented\n\n❌ **Intentional Limitations:**\n- Remote `$ref` - External schema references (security/simplicity)\n- Very strict format validation edge cases (low real-world impact)\n\n⚠️ **Optional Features (JSON Schema spec):**\n- `contentMediaType`, `contentEncoding` - Content validation\n- Strict internationalized format validation (IRI, IDN edge cases)\n\n⚠️ **External Limitations:**\n- BigNum precision - JavaScript `Number` limitation\n- Unicode code point counting - Currently counts UTF-16 code units\n- .NET regex features - JavaScript regex engine differences\n\n## Limitations\n\n### Known Issues\n- **BigNum:** Very large exponent numbers (>10^52) may fail to parse (JSON parser limitation)\n- **Remote refs:** External schema references via http:// are not supported by design\n- **Named schemas:** Schema resolution via `$id` is not supported (requires schema registry)\n\n## Performance\n\n### Schema Compilation\n- Schemas are compiled once and cached by reference\n- Compilation creates optimized validator functions\n- Validators apply only to applicable node types\n\n### Validation Caching\n- Content-addressable caching using node identity hashes\n- Identical subtrees skip re-validation\n- Cache is LRU-based with configurable size\n\n### Optimization Tips\n1. Reuse validator instances across multiple validations\n2. Enable caching for repeated validations (default: enabled)\n3. Use `failFast: true` if you only need to know if validation fails\n\n## Examples\n\n### Nested Objects\n\n```typescript\nconst schema = {\n  type: 'object',\n  properties: {\n    user: {\n      type: 'object',\n      properties: {\n        name: { type: 'string' },\n        address: {\n          type: 'object',\n          properties: {\n            street: { type: 'string' },\n            city: { type: 'string' }\n          },\n          required: ['city']\n        }\n      }\n    }\n  }\n};\n```\n\n### Arrays with Tuples\n\n```typescript\nconst schema = {\n  type: 'array',\n  items: [\n    { type: 'string' },   // First element must be string\n    { type: 'number' }    // Second element must be number\n  ],\n  additionalItems: false  // No additional elements allowed\n};\n```\n\n### References\n\n```typescript\nconst schema = {\n  definitions: {\n    address: {\n      type: 'object',\n      properties: {\n        street: { type: 'string' },\n        city: { type: 'string' }\n      }\n    }\n  },\n  type: 'object',\n  properties: {\n    home: { $ref: '#/definitions/address' },\n    work: { $ref: '#/definitions/address' }\n  }\n};\n```\n\n### Conditional Validation\n\n```typescript\nconst schema = {\n  type: 'object',\n  properties: {\n    country: { type: 'string' }\n  },\n  if: {\n    properties: { country: { const: 'US' } }\n  },\n  then: {\n    properties: {\n      postalCode: { pattern: '^[0-9]{5}$' }\n    }\n  },\n  else: {\n    properties: {\n      postalCode: { type: 'string' }\n    }\n  }\n};\n```\n\n## License\n\nMIT\n","readmeFilename":"README.md","_rev":"1-1684755217f4a396394af57936e6134c"}