schema-model 0.6.11 → 0.7.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
@@ -19,8 +19,8 @@ module Schema
19
19
  kls
20
20
  end
21
21
 
22
- def default_type(options = {}, &block)
23
- add_type(:default, options, &block)
22
+ def default_type(options = {}, &)
23
+ add_type(:default, options, &)
24
24
  end
25
25
 
26
26
  def dynamic_types
@@ -34,9 +34,7 @@ module Schema
34
34
  private
35
35
 
36
36
  def schema_dynamic_type_class_name(type)
37
- ::Schema::Utils.classify_name(schema_name.to_s) +
38
- 'AssociationType' +
39
- ::Schema::Utils.classify_name(type.to_s)
37
+ "#{::Schema::Utils.classify_name(schema_name.to_s)}AssociationType#{::Schema::Utils.classify_name(type.to_s)}"
40
38
  end
41
39
 
42
40
  def schema_add_dynamic_type(type, class_name)
@@ -10,12 +10,11 @@ module Schema
10
10
 
11
11
  # no-doc
12
12
  module ClassMethods
13
- # rubocop:disable Naming/PredicateName
14
13
  def has_many(name, options = {}, &block)
15
14
  options = ::Schema::Utils.add_association_class(self, name, :has_many, options)
16
15
 
17
16
  class_eval(
18
- <<-STR, __FILE__, __LINE__ + 1
17
+ <<-STR, __FILE__, __LINE__ + 1
19
18
  def #{options[:getter]}
20
19
  #{options[:instance_variable]}
21
20
  end
@@ -32,7 +31,7 @@ module Schema
32
31
  #{options[:instance_variable]} ||= []
33
32
  #{options[:instance_variable]} << #{name}_schema_creator.create_schema(self, v, nil, skip_fields)
34
33
  end
35
- STR
34
+ STR
36
35
  )
37
36
 
38
37
  kls = const_get(options[:class_name])
@@ -44,7 +43,6 @@ STR
44
43
  add_aliases(name, options)
45
44
  kls
46
45
  end
47
- # rubocop:enable Naming/PredicateName
48
46
  end
49
47
  end
50
48
  end
@@ -10,12 +10,11 @@ module Schema
10
10
 
11
11
  # no-doc
12
12
  module ClassMethods
13
- # rubocop:disable Naming/PredicateName
14
13
  def has_one(name, options = {}, &block)
15
14
  options = ::Schema::Utils.add_association_class(self, name, :has_one, options)
16
15
 
17
16
  class_eval(
18
- <<-STR, __FILE__, __LINE__ + 1
17
+ <<-STR, __FILE__, __LINE__ + 1
19
18
  def #{options[:getter]}
20
19
  #{options[:instance_variable]}
21
20
  end
@@ -27,19 +26,18 @@ module Schema
27
26
  def #{options[:setter]}(v, skip_fields = [])
28
27
  #{options[:instance_variable]} = #{name}_schema_creator.create_schema(self, v, nil, skip_fields)
29
28
  end
30
- STR
29
+ STR
31
30
  )
32
31
 
33
32
  kls = const_get(options[:class_name])
34
33
  kls.class_eval(&block) if block
35
34
  if options[:default]
36
- options[:default_code] = options[:class_name] + '.new'
35
+ options[:default_code] = "#{options[:class_name]}.new"
37
36
  ::Schema::Utils.add_association_default_methods(self, options)
38
37
  end
39
38
  add_aliases(name, options)
40
39
  kls
41
40
  end
42
- # rubocop:enable Naming/PredicateName
43
41
  end
44
42
  end
45
43
  end
@@ -27,7 +27,7 @@ module Schema
27
27
  add_parsing_error(base_schema, error_name, INVALID) unless schema.parsing_errors.empty?
28
28
  schema
29
29
  elsif !data.nil?
30
- add_parsing_error(base_schema, error_name, INCOMPATABLE)
30
+ add_parsing_error(base_schema, error_name, INCOMPATIBLE)
31
31
  nil
32
32
  end
33
33
  end
@@ -42,7 +42,7 @@ module Schema
42
42
  schema
43
43
  end
44
44
  elsif !list.nil?
45
- add_parsing_error(base_schema, @schema_name, INCOMPATABLE)
45
+ add_parsing_error(base_schema, @schema_name, INCOMPATIBLE)
46
46
  nil
47
47
  end
48
48
  end
@@ -32,7 +32,7 @@ module Schema
32
32
 
33
33
  def get_mapped_headers(mapped_headers)
34
34
  indexed_headers = []
35
- mapped_headers.each do |_, info|
35
+ mapped_headers.each_value do |info|
36
36
  if (index = info[:index])
37
37
  indexed_headers << @headers[index]
38
38
  elsif (indexes = info[:indexes])
data/lib/schema/model.rb CHANGED
@@ -69,7 +69,7 @@ module Schema
69
69
 
70
70
  add_value_to_class_method(:schema, name => options)
71
71
  add_attribute_methods(name, options)
72
- ::Schema::Utils.add_attribute_default_methods(self, options) if options.has_key?(:default)
72
+ ::Schema::Utils.add_attribute_default_methods(self, options) if options.key?(:default)
73
73
  add_aliases(name, options)
74
74
  end
75
75
 
@@ -82,7 +82,8 @@ module Schema
82
82
  config[:schema_includes] = config[:schema_includes] + [mod]
83
83
  redefine_class_method(:schema_config, config.freeze)
84
84
  include mod
85
- schema.values.each do |field_options|
85
+
86
+ schema.each_value do |field_options|
86
87
  next unless field_options[:association]
87
88
 
88
89
  const_get(field_options[:class_name]).schema_include(mod)
@@ -91,7 +92,7 @@ module Schema
91
92
 
92
93
  def add_attribute_methods(name, options)
93
94
  class_eval(
94
- <<-STR, __FILE__, __LINE__ + 1
95
+ <<-STR, __FILE__, __LINE__ + 1
95
96
  def #{options[:getter]}
96
97
  #{options[:instance_variable]}
97
98
  end
@@ -99,7 +100,11 @@ module Schema
99
100
  def #{options[:setter]}(v)
100
101
  #{options[:instance_variable]} = #{options[:parser]}(#{name.inspect}, parsing_errors, v)
101
102
  end
102
- STR
103
+
104
+ def #{options[:getter]}_was_set?
105
+ instance_variable_defined?(:#{options[:instance_variable]})
106
+ end
107
+ STR
103
108
  )
104
109
  end
105
110
 
@@ -123,18 +128,18 @@ STR
123
128
 
124
129
  def as_json(opts = {})
125
130
  self.class.schema.each_with_object({}) do |(field_name, field_options), memo|
126
- unless field_options[:alias_of]
127
- value = public_send(field_options[:getter])
128
- next if value.nil? && !opts[:include_nils]
129
- next if opts[:select_filter] && !opts[:select_filter].call(field_name, value, field_options)
130
- next if opts[:reject_filter] && opts[:reject_filter].call(field_name, value, field_options)
131
-
132
- if value.is_a?(Array)
133
- memo[field_name] = value.map { |e| e.as_json(opts) }
134
- else
135
- memo[field_name] = value.respond_to?(:as_json) ? value.as_json(opts) : value
136
- end
137
- end
131
+ next if field_options[:alias_of]
132
+
133
+ value = public_send(field_options[:getter])
134
+ next if value.nil? && !opts[:include_nils]
135
+ next if opts[:select_filter] && !opts[:select_filter].call(field_name, value, field_options)
136
+ next if opts[:reject_filter]&.call(field_name, value, field_options)
137
+
138
+ memo[field_name] = if value.is_a?(Array)
139
+ value.map { |e| e.as_json(opts) }
140
+ else
141
+ value.respond_to?(:as_json) ? value.as_json(opts) : value
142
+ end
138
143
  end
139
144
  end
140
145
 
@@ -156,12 +161,12 @@ STR
156
161
  private
157
162
 
158
163
  def get_schema(data)
159
- data.each_key do |key|
160
- break unless key.is_a?(Symbol)
164
+ return self.class.schema_with_string_keys unless data.is_a?(Hash)
161
165
 
162
- return self.class.schema
163
- end
164
- self.class.schema_with_string_keys
166
+ first_key = data.each_key.first
167
+ return self.class.schema_with_string_keys unless first_key.is_a?(Symbol)
168
+
169
+ self.class.schema
165
170
  end
166
171
 
167
172
  def update_model_attributes(schema, data, skip_fields)
@@ -15,10 +15,10 @@ module Schema
15
15
  return data
16
16
  end
17
17
 
18
- parsing_errors.add(field_name, ::Schema::ParsingErrors::INCOMPATABLE)
18
+ parsing_errors.add(field_name, ::Schema::ParsingErrors::INCOMPATIBLE)
19
19
  nil
20
20
  else
21
- parsing_errors.add(field_name, ::Schema::ParsingErrors::INCOMPATABLE)
21
+ parsing_errors.add(field_name, ::Schema::ParsingErrors::INCOMPATIBLE)
22
22
  nil
23
23
  end
24
24
  end
@@ -6,11 +6,10 @@ module Schema
6
6
  module Parsers
7
7
  # Schema::Parsers::Common are parser methods for basic types
8
8
  module Common
9
- INTEGER_REGEX = /^[-+]?(?:[1-9]\d*|0)(?:\.0+)?$/.freeze
10
- FLOAT_REGEX = /^[-+]?(?:[1-9]\d*|0)(?:\.\d+)?([Ee]-?\d+)?$/.freeze
11
- BOOLEAN_REGEX = /^(?:1|t|true|on|y|yes)$/i.freeze
9
+ INTEGER_REGEX = /^[-+]?(?:[1-9]\d*|0)(?:\.0+)?$/
10
+ FLOAT_REGEX = /^[-+]?(?:[1-9]\d*|0)(?:\.\d+)?([Ee]-?\d+)?$/
11
+ BOOLEAN_REGEX = /^(?:1|t|true|on|y|yes)$/i
12
12
 
13
- # rubocop:disable Metrics/CyclomaticComplexity
14
13
  def parse_integer(field_name, parsing_errors, value)
15
14
  case value
16
15
  when Integer
@@ -23,7 +22,7 @@ module Schema
23
22
  nil
24
23
  end
25
24
  when Float
26
- parsing_errors.add(field_name, ::Schema::ParsingErrors::INCOMPATABLE) if (value % 1) > 0.0
25
+ parsing_errors.add(field_name, ::Schema::ParsingErrors::INCOMPATIBLE) if (value % 1) > 0.0
27
26
  value.to_i
28
27
  when nil
29
28
  nil
@@ -32,14 +31,13 @@ module Schema
32
31
  nil
33
32
  end
34
33
  end
35
- # rubocop:enable Metrics/CyclomaticComplexity
36
34
 
37
35
  def parse_string(field_name, parsing_errors, value)
38
36
  case value
39
37
  when String
40
38
  value
41
39
  when ::Hash, ::Array
42
- parsing_errors.add(field_name, ::Schema::ParsingErrors::INCOMPATABLE)
40
+ parsing_errors.add(field_name, ::Schema::ParsingErrors::INCOMPATIBLE)
43
41
  nil
44
42
  when nil
45
43
  nil
@@ -54,7 +52,7 @@ module Schema
54
52
  when String
55
53
  value.empty? ? nil : value
56
54
  when ::Hash, ::Array
57
- parsing_errors.add(field_name, ::Schema::ParsingErrors::INCOMPATABLE)
55
+ parsing_errors.add(field_name, ::Schema::ParsingErrors::INCOMPATIBLE)
58
56
  nil
59
57
  when nil
60
58
  nil
@@ -9,7 +9,7 @@ module Schema
9
9
  when ::Hash
10
10
  value
11
11
  else
12
- parsing_errors.add(field_name, ::Schema::ParsingErrors::INCOMPATABLE)
12
+ parsing_errors.add(field_name, ::Schema::ParsingErrors::INCOMPATIBLE)
13
13
  nil
14
14
  end
15
15
  end
@@ -16,7 +16,7 @@ module Schema
16
16
  nil
17
17
  end
18
18
  else
19
- parsing_errors.add(field_name, ::Schema::ParsingErrors::INCOMPATABLE)
19
+ parsing_errors.add(field_name, ::Schema::ParsingErrors::INCOMPATIBLE)
20
20
  nil
21
21
  end
22
22
  end
@@ -4,7 +4,7 @@ module Schema
4
4
  # Schema::ParsingErrors is a collection of parsing error messages
5
5
  module ParsingErrors
6
6
  INVALID = 'invalid'
7
- INCOMPATABLE = 'incompatable'
7
+ INCOMPATIBLE = 'incompatible'
8
8
  UNKNOWN = 'unknown'
9
9
  UNKNOWN_ATTRIBUTE = 'unknown_attribute'
10
10
  UNHANDLED_TYPE = 'unhandled_type'
data/lib/schema/utils.rb CHANGED
@@ -25,7 +25,7 @@ module Schema
25
25
  end
26
26
 
27
27
  def association_options(schema_name, schema_type, options)
28
- options[:class_name] ||= 'Schema' + classify_name(schema_type.to_s) + classify_name(schema_name.to_s)
28
+ options[:class_name] ||= "Schema#{classify_name(schema_type.to_s)}#{classify_name(schema_name.to_s)}"
29
29
  options[:association] = true
30
30
  options[:aliases] = [options[:alias]] if options.key?(:alias)
31
31
  options[:hash_key_field] ||= :id if options[:from] == :hash
@@ -58,7 +58,7 @@ module Schema
58
58
 
59
59
  def add_attribute_default_methods(kls, options)
60
60
  kls.class_eval(
61
- <<-STR, __FILE__, __LINE__ + 1
61
+ <<-STR, __FILE__, __LINE__ + 1
62
62
  def #{options[:default_method]}
63
63
  #{options[:default].inspect}
64
64
  end
@@ -70,13 +70,13 @@ module Schema
70
70
  #{options[:instance_variable]}
71
71
  end
72
72
  end
73
- STR
73
+ STR
74
74
  )
75
75
  end
76
76
 
77
77
  def add_association_default_methods(kls, options)
78
78
  kls.class_eval(
79
- <<-STR, __FILE__, __LINE__ + 1
79
+ <<-STR, __FILE__, __LINE__ + 1
80
80
  def #{options[:default_method]}
81
81
  #{options[:default_code]}
82
82
  end
@@ -84,7 +84,7 @@ STR
84
84
  def #{options[:getter]}
85
85
  #{options[:instance_variable]} ||= #{options[:default_method]}
86
86
  end
87
- STR
87
+ STR
88
88
  )
89
89
  end
90
90
  end
data/lib/schema-model.rb CHANGED
@@ -14,6 +14,7 @@ module Schema
14
14
  @errors = errors
15
15
  end
16
16
  end
17
+
17
18
  class ParsingException < SchemaException; end
18
19
  class ValidationException < SchemaException; end
19
20
 
data/schema-model.gemspec CHANGED
@@ -2,10 +2,11 @@
2
2
 
3
3
  Gem::Specification.new do |s|
4
4
  s.name = 'schema-model'
5
- s.version = '0.6.11'
5
+ s.version = '0.7.0'
6
6
  s.licenses = ['MIT']
7
- s.summary = 'Schema Model'
8
- s.description = 'Easy way to create models from payloads'
7
+ s.summary = 'Data transformation, validation, and type safety for Ruby'
8
+ s.description = 'A flexible DSL for defining strongly-typed data models with automatic parsing, ' \
9
+ 'nested associations, dynamic types, and ActiveModel validations'
9
10
  s.authors = ['Doug Youch']
10
11
  s.email = 'dougyouch@gmail.com'
11
12
  s.homepage = 'https://github.com/dougyouch/schema'
@@ -13,5 +14,6 @@ Gem::Specification.new do |s|
13
14
  s.bindir = 'bin'
14
15
  s.executables = s.files.grep(%r{^bin/}) { |f| File.basename(f) }
15
16
 
16
- s.add_runtime_dependency 'inheritance-helper'
17
+ s.add_dependency 'inheritance-helper'
18
+ s.metadata['rubygems_mfa_required'] = 'true'
17
19
  end
metadata CHANGED
@@ -1,13 +1,13 @@
1
1
  --- !ruby/object:Gem::Specification
2
2
  name: schema-model
3
3
  version: !ruby/object:Gem::Version
4
- version: 0.6.11
4
+ version: 0.7.0
5
5
  platform: ruby
6
6
  authors:
7
7
  - Doug Youch
8
8
  bindir: bin
9
9
  cert_chain: []
10
- date: 2025-06-21 00:00:00.000000000 Z
10
+ date: 2026-02-01 00:00:00.000000000 Z
11
11
  dependencies:
12
12
  - !ruby/object:Gem::Dependency
13
13
  name: inheritance-helper
@@ -23,26 +23,26 @@ dependencies:
23
23
  - - ">="
24
24
  - !ruby/object:Gem::Version
25
25
  version: '0'
26
- description: Easy way to create models from payloads
26
+ description: A flexible DSL for defining strongly-typed data models with automatic
27
+ parsing, nested associations, dynamic types, and ActiveModel validations
27
28
  email: dougyouch@gmail.com
28
29
  executables:
29
30
  - schema-json2csv
30
31
  extensions: []
31
32
  extra_rdoc_files: []
32
33
  files:
33
- - ".cursor-rules"
34
+ - ".github/workflows/ci.yml"
34
35
  - ".gitignore"
35
36
  - ".rubocop.yml"
36
37
  - ".ruby-gemset"
37
38
  - ".ruby-version"
38
- - ".travis.yml"
39
+ - ARCHITECTURE.md
40
+ - CLAUDE.md
39
41
  - Gemfile
40
42
  - Gemfile.lock
41
43
  - LICENSE.txt
42
44
  - README.md
43
- - Rakefile
44
45
  - bin/schema-json2csv
45
- - docs/ARCHITECTURE.md
46
46
  - lib/schema-model.rb
47
47
  - lib/schema/active_model_validations.rb
48
48
  - lib/schema/all.rb
@@ -65,13 +65,12 @@ files:
65
65
  - lib/schema/utils.rb
66
66
  - lib/schema_validator.rb
67
67
  - schema-model.gemspec
68
- - script/bundle_install_all_versions
69
68
  - script/console
70
- - script/rspec_all_versions
71
69
  homepage: https://github.com/dougyouch/schema
72
70
  licenses:
73
71
  - MIT
74
- metadata: {}
72
+ metadata:
73
+ rubygems_mfa_required: 'true'
75
74
  rdoc_options: []
76
75
  require_paths:
77
76
  - lib
@@ -88,5 +87,5 @@ required_rubygems_version: !ruby/object:Gem::Requirement
88
87
  requirements: []
89
88
  rubygems_version: 3.6.2
90
89
  specification_version: 4
91
- summary: Schema Model
90
+ summary: Data transformation, validation, and type safety for Ruby
92
91
  test_files: []
data/.cursor-rules DELETED
@@ -1,39 +0,0 @@
1
- # Cursor Rules Configuration
2
-
3
- # Ignore common development and system files
4
- ignore {
5
- ".git/"
6
- ".DS_Store"
7
- "*.log"
8
- "tmp/"
9
- "node_modules/"
10
- "coverage/"
11
- }
12
-
13
- # Define common code block markers
14
- markers {
15
- start "# START"
16
- end "# END"
17
- }
18
-
19
- # Define language-specific comment styles
20
- comments {
21
- ruby "#"
22
- javascript "//"
23
- python "#"
24
- html "<!--"
25
- css "/*"
26
- }
27
-
28
- # Define safe edit boundaries
29
- boundaries {
30
- function_start "^(def|function|class) "
31
- block_start "^(if|while|for|begin|module) "
32
- }
33
-
34
- # Define merge conflict markers to avoid
35
- conflicts {
36
- start "<<<<<<< "
37
- middle "======="
38
- end ">>>>>>> "
39
- }
data/.travis.yml DELETED
@@ -1,14 +0,0 @@
1
- env:
2
- global:
3
- - CC_TEST_REPORTER_ID=f06234974aa4c4c52d14cb9ef800df79de52013c38e1d149fd04f2284e722f57
4
- rvm:
5
- - 3.1.0
6
- language: ruby
7
- before_script:
8
- - curl -L https://codeclimate.com/downloads/test-reporter/test-reporter-latest-linux-amd64 > ./cc-test-reporter
9
- - chmod +x ./cc-test-reporter
10
- - ./cc-test-reporter before-build
11
- script:
12
- - bundle exec rspec
13
- after_script:
14
- - ./cc-test-reporter after-build --exit-code $TRAVIS_TEST_RESULT
data/Rakefile DELETED
@@ -1,11 +0,0 @@
1
- # frozen_string_literal: true
2
-
3
- require 'rubygems'
4
- require 'bundler/setup'
5
- require 'rake'
6
- require 'rspec/core/rake_task'
7
- RSpec::Core::RakeTask.new(:spec) do |t|
8
- t.pattern = Dir.glob('spec/**/*_spec.rb')
9
- t.rspec_opts = '--format documentation'
10
- end
11
- task default: :spec
data/docs/ARCHITECTURE.md DELETED
@@ -1,171 +0,0 @@
1
- # Schema Architecture Documentation
2
-
3
- ## Overview
4
-
5
- Schema is a Ruby gem that provides a robust framework for data transformation, validation, and type safety. It follows a modular architecture that allows for flexible and extensible data modeling.
6
-
7
- ## Core Components
8
-
9
- ### 1. Model System (`lib/schema/model.rb`)
10
-
11
- The foundation of the Schema system, providing:
12
- - Attribute definition and management
13
- - Type system integration
14
- - Data parsing and validation
15
- - Association handling
16
-
17
- Key features:
18
- - Dynamic attribute registration
19
- - Type coercion and validation
20
- - Nested model support
21
- - Error collection and reporting
22
-
23
- ### 2. Association System (`lib/schema/associations/`)
24
-
25
- Handles relationships between models:
26
- - `has_one`: Single nested model
27
- - `has_many`: Multiple nested models
28
- - Dynamic associations based on type fields
29
- - Hash-based associations
30
-
31
- ### 3. Parser System (`lib/schema/parsers/`)
32
-
33
- Responsible for data type conversion and validation:
34
- - Built-in parsers for common types (string, integer, float, etc.)
35
- - Custom parser support
36
- - Array parsing with separators
37
- - CSV data parsing
38
-
39
- ### 4. Validation System (`lib/schema/active_model_validations.rb`)
40
-
41
- Integrates with ActiveModel validations to provide:
42
- - Attribute presence validation
43
- - Format validation
44
- - Custom validation rules
45
- - Nested model validation
46
-
47
- ### 5. Error Handling (`lib/schema/errors.rb`, `lib/schema/parsing_errors.rb`)
48
-
49
- Comprehensive error management:
50
- - Parsing errors
51
- - Validation errors
52
- - Nested model errors
53
- - Error message formatting
54
-
55
- ## Data Flow
56
-
57
- 1. **Initialization**
58
- - Schema class definition
59
- - Attribute registration
60
- - Association setup
61
- - Validation rules configuration
62
-
63
- 2. **Data Processing**
64
- - Input data parsing
65
- - Type coercion
66
- - Association resolution
67
- - Validation execution
68
-
69
- 3. **Error Collection**
70
- - Parsing error collection
71
- - Validation error aggregation
72
- - Nested model error propagation
73
-
74
- ## Extension Points
75
-
76
- ### Custom Parsers
77
-
78
- ```ruby
79
- module Schema::Parsers
80
- class CustomParser
81
- def self.parse(field_name, errors, value)
82
- # Custom parsing logic
83
- end
84
- end
85
- end
86
- ```
87
-
88
- ### Custom Validators
89
-
90
- ```ruby
91
- class CustomValidator < ActiveModel::Validator
92
- def validate(record)
93
- # Custom validation logic
94
- end
95
- end
96
- ```
97
-
98
- ### Custom Associations
99
-
100
- ```ruby
101
- module Schema::Associations
102
- class CustomAssociation < Base
103
- def initialize(name, options = {}, &block)
104
- # Custom association logic
105
- end
106
- end
107
- end
108
- ```
109
-
110
- ## Performance Considerations
111
-
112
- 1. **Attribute Access**
113
- - Dynamic method generation for attribute accessors
114
- - Caching of parsed values
115
- - Lazy loading of associations
116
-
117
- 2. **Validation**
118
- - Early termination on first error
119
- - Parallel validation of independent attributes
120
- - Caching of validation results
121
-
122
- 3. **Memory Management**
123
- - Efficient error object creation
124
- - Minimal object allocation during parsing
125
- - Garbage collection optimization
126
-
127
- ## Security Considerations
128
-
129
- 1. **Data Validation**
130
- - Strict type checking
131
- - Input sanitization
132
- - Size limits on collections
133
-
134
- 2. **Error Handling**
135
- - Safe error message generation
136
- - No sensitive data exposure
137
- - Controlled error propagation
138
-
139
- ## Testing Strategy
140
-
141
- 1. **Unit Tests**
142
- - Individual component testing
143
- - Mock dependencies
144
- - Edge case coverage
145
-
146
- 2. **Integration Tests**
147
- - Component interaction testing
148
- - Real-world usage scenarios
149
- - Performance benchmarks
150
-
151
- 3. **Regression Tests**
152
- - Backward compatibility
153
- - Bug fixes verification
154
- - Performance regression detection
155
-
156
- ## Future Considerations
157
-
158
- 1. **Planned Features**
159
- - JSON Schema integration
160
- - GraphQL type generation
161
- - Async validation support
162
-
163
- 2. **Performance Improvements**
164
- - Parallel processing
165
- - Memory optimization
166
- - Caching strategies
167
-
168
- 3. **API Evolution**
169
- - Backward compatibility
170
- - Deprecation strategy
171
- - Version management