Skip to content

Commit 1cc019c

Browse files
committed
Update architecture doc
1 parent 473bc22 commit 1cc019c

File tree

1 file changed

+154
-7
lines changed

1 file changed

+154
-7
lines changed

ARCHITECTURE.md

Lines changed: 154 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -165,15 +165,27 @@ Given this JSON Schema:
165165
## Implementation Status
166166

167167
### Test Results
168-
- **Total tests**: 1355 (999 active, 356 skipped)
169-
- **Passing**: 999 tests
170-
- **Failing**: 0 tests
171-
- **Skipped**: 356 tests (JSON Schema features not supported by Zod)
168+
- **Total tests**: 1418 (1172 passing, 246 skipped)
169+
- **Passing**: 1172 tests
170+
- **Failing**: 0 tests
171+
- **Skipped**: 246 tests (JSON Schema features not yet implemented)
172+
- **Code Coverage**: 100% (statements, branches, functions, lines)
173+
174+
### Recently Implemented Features
175+
- **Boolean property schemas**: Support for `true`/`false` as property schemas
176+
- **Escaped character properties**: Validation of properties with escape sequences
177+
- **Contains constraints**: Array validation with `contains`, `minContains`, `maxContains`
178+
- **Property count validation**: `minProperties` and `maxProperties` constraints
179+
- **Unicode string length**: Proper grapheme cluster counting for international text
180+
- **Floating-point precision**: Robust `multipleOf` validation with proper precision handling
181+
- **OneOf semantics**: Correct "exactly one must match" validation logic
172182

173183
### Known Limitations
174-
1. **`__proto__` property validation**: Zod's `passthrough()` strips this property for security. Solved with ProtoRequiredHandler using `z.any()` when `__proto__` is required.
175-
2. **Unicode grapheme counting**: JavaScript uses UTF-16 code units instead of grapheme clusters. Test added to skip list as platform limitation.
176-
3. **Complex schema combinations**: Some edge cases with deeply nested `allOf`, `anyOf`, `oneOf` combinations may not perfectly match JSON Schema semantics.
184+
1. **JavaScript special properties**: Zod filters `__proto__`, `constructor`, `toString` for security
185+
2. **Complex schema combinations**: Some edge cases with deeply nested logical combinations
186+
3. **Reference resolution**: `$ref`, `$defs`, and remote references not yet implemented
187+
4. **Conditional schemas**: `if`/`then`/`else` constructs not supported
188+
5. **Advanced object validation**: `patternProperties`, `dependentSchemas`, `unevaluatedProperties`
177189

178190
## Benefits
179191

@@ -262,13 +274,148 @@ export class MyRefinementHandler implements RefinementHandler {
262274
- General refinements (Not, UniqueItems)
263275
- Metadata handlers last
264276

277+
## Advanced Architectural Insights
278+
279+
### Handler State Management Pattern
280+
281+
The `TypeSchemas` object functions as a sophisticated state machine with three distinct states per type:
282+
283+
```typescript
284+
// State meanings:
285+
undefined // "not yet determined" - type still under consideration
286+
false // "explicitly disabled" - type ruled out by constraints
287+
ZodType // "enabled with constraints" - type with accumulated validation
288+
```
289+
290+
This pattern enables powerful composition:
291+
```typescript
292+
// Respecting previous decisions
293+
if (types.object === false) return;
294+
295+
// Building incrementally
296+
types.object = types.object || z.object({}).passthrough();
297+
298+
// Applying refinements to existing schemas
299+
types.object = baseObject.refine(validationFn, errorMessage);
300+
```
301+
302+
### Critical Handler Execution Order
303+
304+
Handler order is architectural, not arbitrary. Key dependencies:
305+
306+
```typescript
307+
// 1. Type constraints must run first
308+
new ConstHandler(), // Creates literal types
309+
new EnumHandler(), // Creates enum constraints
310+
new TypeHandler(), // Disables non-matching types
311+
312+
// 2. Implicit detection before specific constraints
313+
new ImplicitStringHandler(), // Must run before string constraints
314+
new ImplicitArrayHandler(), // Must run before array constraints
315+
new ImplicitObjectHandler(), // Must run before object constraints
316+
317+
// 3. Tuple before Items (array specialization)
318+
new TupleHandler(), // Detects tuple patterns
319+
new ItemsHandler(), // General array item validation
320+
```
321+
322+
### Zod vs JSON Schema Impedance Mismatch
323+
324+
**Fundamental Architectural Tension:**
325+
326+
- **JSON Schema**: "Describe any data shape, support any property name"
327+
- **Zod**: "Create type-safe schemas, prevent dangerous operations"
328+
329+
**Resolution Strategies:**
330+
331+
1. **Security-First Approach**: Accept Zod's filtering of dangerous properties (`__proto__`)
332+
2. **Graceful Degradation**: Skip unsupported features rather than failing
333+
3. **Hybrid Validation**: Use refinements for operations Zod can't express natively
334+
335+
### Boolean Schema Architecture
336+
337+
JSON Schema's boolean schemas create unique challenges:
338+
```typescript
339+
true // "Allow anything" → z.any()
340+
false // "Allow nothing" → z.never()
341+
342+
// In property schemas:
343+
{ properties: { foo: true, bar: false } }
344+
// foo: any value allowed, bar: property must not exist
345+
```
346+
347+
Our architecture handles this through the boolean schema detection in the converter's main flow.
348+
349+
### Union Schema vs Object Schema Decision Tree
350+
351+
The architecture makes critical decisions about schema structure:
352+
353+
```typescript
354+
// When to create union schemas:
355+
allowedSchemas.length > 1z.union([...])
356+
357+
// When to create object schemas:
358+
zodSchema instanceof z.ZodObjectbuild proper object shape
359+
360+
// When to use refinements:
361+
!(zodSchema instanceof z.ZodObject) → apply property validation via refinement
362+
```
363+
364+
This pattern appears throughout the refinement handlers and explains why some validations work differently in different contexts.
365+
366+
### Refinement Composition Architecture
367+
368+
Refinements **compose** rather than replace, enabling complex validation stacks:
369+
370+
```typescript
371+
// Multiple refinements stack cleanly:
372+
schema
373+
.refine(oneOfValidation, "oneOf constraint")
374+
.refine(allOfValidation, "allOf constraint")
375+
.refine(propertyValidation, "property constraint")
376+
.refine(customValidation, "custom constraint")
377+
```
378+
379+
This architectural choice allows JSON Schema's additive constraint model to work naturally.
380+
381+
### Coverage-Driven Architecture Validation
382+
383+
Our comprehensive coverage work revealed the architecture has **multiple code paths** for similar operations:
384+
385+
- Object creation via primitive handlers vs refinement handlers
386+
- Type union creation vs single type schemas
387+
- Boolean schema handling in different contexts
388+
389+
This redundancy provides **flexibility** but requires **comprehensive testing** to ensure all paths work correctly.
390+
391+
### Defensive Programming Architecture
392+
393+
Consistent patterns throughout the codebase prioritize **robustness**:
394+
395+
```typescript
396+
// Type safety guards
397+
if (typeof value !== "object" || value === null || Array.isArray(value)) {
398+
return true; // Safe fallback
399+
}
400+
401+
// Robust property detection
402+
const propExists = Object.getOwnPropertyDescriptor(value, propName) !== undefined;
403+
404+
// Safe composition
405+
types.object = types.object || z.object({}).passthrough();
406+
```
407+
408+
This reveals the architecture's **production-first mindset** - prioritizing correctness over performance.
409+
265410
## Future Enhancements
266411

267412
1. **Additional JSON Schema Keywords**: Support for more keywords like `dependencies`, `if/then/else`, `contentMediaType`, etc.
268413
2. **Performance Optimization**: Cache converted schemas for repeated conversions
269414
3. **Better Error Messages**: Provide more descriptive validation error messages
270415
4. **Schema Version Support**: Handle different JSON Schema draft versions
271416
5. **Bidirectional Conversion**: Improve Zod to JSON Schema conversion fidelity
417+
6. **Advanced Union Handling**: Better support for complex union scenarios that arise from JSON Schema's flexibility
418+
7. **Security Model Documentation**: Formal documentation of security vs compatibility tradeoffs
272419

273420
## Architectural Evolution
274421

0 commit comments

Comments
 (0)