odin-foundation 1.0.4 → 1.2.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.
Files changed (40) hide show
  1. checksums.yaml +4 -4
  2. data/lib/odin/export.rb +1 -1
  3. data/lib/odin/forms/accessibility.rb +95 -0
  4. data/lib/odin/forms/css.rb +42 -0
  5. data/lib/odin/forms/parser.rb +719 -0
  6. data/lib/odin/forms/renderer.rb +534 -0
  7. data/lib/odin/forms/types.rb +102 -0
  8. data/lib/odin/forms/units.rb +41 -0
  9. data/lib/odin/forms.rb +55 -0
  10. data/lib/odin/parsing/parser.rb +25 -1
  11. data/lib/odin/parsing/tokenizer.rb +38 -20
  12. data/lib/odin/parsing/value_parser.rb +65 -7
  13. data/lib/odin/resolver/import_resolver.rb +40 -12
  14. data/lib/odin/resolver/type_registry.rb +54 -0
  15. data/lib/odin/transform/format_exporters.rb +88 -48
  16. data/lib/odin/transform/source_parsers.rb +2 -2
  17. data/lib/odin/transform/transform_engine.rb +1388 -246
  18. data/lib/odin/transform/transform_expr.rb +222 -0
  19. data/lib/odin/transform/transform_parser.rb +377 -19
  20. data/lib/odin/transform/transform_types.rb +23 -7
  21. data/lib/odin/transform/verb_context.rb +19 -1
  22. data/lib/odin/transform/verbs/aggregation_verbs.rb +2 -1
  23. data/lib/odin/transform/verbs/collection_verbs.rb +164 -89
  24. data/lib/odin/transform/verbs/datetime_verbs.rb +86 -15
  25. data/lib/odin/transform/verbs/extra_verbs.rb +613 -0
  26. data/lib/odin/transform/verbs/financial_verbs.rb +116 -27
  27. data/lib/odin/transform/verbs/geo_verbs.rb +7 -0
  28. data/lib/odin/transform/verbs/numeric_verbs.rb +85 -64
  29. data/lib/odin/transform/verbs/object_verbs.rb +31 -26
  30. data/lib/odin/types/errors.rb +9 -1
  31. data/lib/odin/types/schema.rb +20 -3
  32. data/lib/odin/utils/format_utils.rb +31 -15
  33. data/lib/odin/validation/format_validators.rb +7 -9
  34. data/lib/odin/validation/invariant_evaluator.rb +410 -0
  35. data/lib/odin/validation/schema_definition_validator.rb +357 -0
  36. data/lib/odin/validation/schema_parser.rb +234 -21
  37. data/lib/odin/validation/validator.rb +281 -123
  38. data/lib/odin/version.rb +1 -1
  39. data/lib/odin.rb +100 -4
  40. metadata +14 -2
data/lib/odin.rb CHANGED
@@ -19,12 +19,16 @@ require_relative "odin/types/schema"
19
19
  require_relative "odin/validation/redos_protection"
20
20
  require_relative "odin/validation/format_validators"
21
21
  require_relative "odin/validation/schema_parser"
22
+ require_relative "odin/validation/invariant_evaluator"
23
+ require_relative "odin/validation/schema_definition_validator"
22
24
  require_relative "odin/validation/validator"
23
25
  require_relative "odin/validation/schema_serializer"
26
+ require_relative "odin/resolver/type_registry"
24
27
  require_relative "odin/resolver/import_resolver"
25
28
  require_relative "odin/transform/source_parsers"
26
29
  require_relative "odin/transform/format_exporters"
27
30
  require_relative "odin/transform/transform_types"
31
+ require_relative "odin/transform/transform_expr"
28
32
  require_relative "odin/transform/verb_context"
29
33
  require_relative "odin/transform/transform_parser"
30
34
  require_relative "odin/transform/transform_engine"
@@ -35,7 +39,9 @@ require_relative "odin/transform/verbs/financial_verbs"
35
39
  require_relative "odin/transform/verbs/aggregation_verbs"
36
40
  require_relative "odin/transform/verbs/object_verbs"
37
41
  require_relative "odin/transform/verbs/geo_verbs"
42
+ require_relative "odin/transform/verbs/extra_verbs"
38
43
  require_relative "odin/export"
44
+ require_relative "odin/forms"
39
45
 
40
46
  module Odin
41
47
  class << self
@@ -44,6 +50,89 @@ module Odin
44
50
  Parsing::OdinParser.new.parse(text, options)
45
51
  end
46
52
 
53
+ # Parse a chained document (one or more documents separated by ---) into
54
+ # the full list of documents. A single document yields a one-element array.
55
+ def parse_documents(text, options = nil)
56
+ result = parse(text, options)
57
+ result.respond_to?(:documents) ? result.documents : [result]
58
+ end
59
+
60
+ # Collapse a chained ODIN document into its computed current state.
61
+ #
62
+ # Later documents overlay earlier ones, a repeated path replaces the earlier
63
+ # value, +field = ~+ removes the field and its descendants, and +field[] = ~+
64
+ # clears the array. The result carries the final document's metadata.
65
+ #
66
+ # Accepts chained ODIN text or a pre-parsed list of documents.
67
+ def collapse_chain(input, options = nil)
68
+ docs = input.is_a?(Array) ? input : parse_documents(input, options)
69
+ collapse_documents(docs)
70
+ end
71
+
72
+ private
73
+
74
+ def collapse_documents(docs)
75
+ assignments = {}
76
+ modifiers = {}
77
+ metadata = {}
78
+
79
+ docs.each do |doc|
80
+ metadata = doc.metadata.dup
81
+
82
+ doc.paths.each do |path|
83
+ value = doc.get(path)
84
+ next if value.nil?
85
+
86
+ if value.type == :null
87
+ if path.end_with?("[]")
88
+ clear_array(assignments, modifiers, path[0...-2])
89
+ else
90
+ remove_path(assignments, modifiers, path)
91
+ end
92
+ next
93
+ end
94
+
95
+ assignments[path] = value
96
+ mods = doc.modifiers_for(path)
97
+ if mods
98
+ modifiers[path] = mods
99
+ else
100
+ modifiers.delete(path)
101
+ end
102
+ end
103
+ end
104
+
105
+ Types::OdinDocument.new(
106
+ assignments: assignments,
107
+ metadata: metadata,
108
+ modifiers: modifiers,
109
+ comments: {}
110
+ )
111
+ end
112
+
113
+ # Remove a path and any nested descendants from the working maps.
114
+ def remove_path(assignments, modifiers, path)
115
+ assignments.keys.each do |key|
116
+ if key == path || key.start_with?("#{path}.") || key.start_with?("#{path}[")
117
+ assignments.delete(key)
118
+ modifiers.delete(key)
119
+ end
120
+ end
121
+ end
122
+
123
+ # Clear all indexed elements of an array path from the working maps.
124
+ def clear_array(assignments, modifiers, array_path)
125
+ prefix = "#{array_path}["
126
+ assignments.keys.each do |key|
127
+ if key.start_with?(prefix)
128
+ assignments.delete(key)
129
+ modifiers.delete(key)
130
+ end
131
+ end
132
+ end
133
+
134
+ public
135
+
47
136
  def stringify(doc, options = {})
48
137
  Serialization::Stringify.new(options).stringify(doc)
49
138
  end
@@ -57,8 +146,15 @@ module Odin
57
146
  Validation::SchemaParser.new.parse_schema(text)
58
147
  end
59
148
 
60
- def validate(doc, schema, options = {})
61
- Validation::Validator.new.validate(doc, schema, options)
149
+ def validate(doc, schema, options = {}, registry = nil)
150
+ Validation::Validator.new.validate(doc, schema, options, registry)
151
+ end
152
+
153
+ # Resolve a schema's imports into a type registry, then validate the document.
154
+ def validate_with_imports(doc, schema, base_path, options = {}, resolver_options = {})
155
+ _flattened, registry = Resolver::ImportResolver.new(**resolver_options)
156
+ .resolve_with_registry(schema, base_path: base_path)
157
+ validate(doc, schema, options, registry)
62
158
  end
63
159
 
64
160
  def diff(a, b)
@@ -78,8 +174,8 @@ module Odin
78
174
  Transform::TransformParser.new.parse(text)
79
175
  end
80
176
 
81
- def execute_transform(transform_def, source)
82
- Transform::TransformEngine.new.execute(transform_def, source)
177
+ def execute_transform(transform_def, source, import_resolver: nil)
178
+ Transform::TransformEngine.new.execute(transform_def, source, import_resolver: import_resolver)
83
179
  end
84
180
 
85
181
  def transform(transform_text, source)
metadata CHANGED
@@ -1,14 +1,14 @@
1
1
  --- !ruby/object:Gem::Specification
2
2
  name: odin-foundation
3
3
  version: !ruby/object:Gem::Version
4
- version: 1.0.4
4
+ version: 1.2.0
5
5
  platform: ruby
6
6
  authors:
7
7
  - ODIN Foundation
8
8
  autorequire:
9
9
  bindir: bin
10
10
  cert_chain: []
11
- date: 2026-04-07 00:00:00.000000000 Z
11
+ date: 2026-06-03 00:00:00.000000000 Z
12
12
  dependencies:
13
13
  - !ruby/object:Gem::Dependency
14
14
  name: bigdecimal
@@ -91,23 +91,33 @@ files:
91
91
  - lib/odin/diff/differ.rb
92
92
  - lib/odin/diff/patcher.rb
93
93
  - lib/odin/export.rb
94
+ - lib/odin/forms.rb
95
+ - lib/odin/forms/accessibility.rb
96
+ - lib/odin/forms/css.rb
97
+ - lib/odin/forms/parser.rb
98
+ - lib/odin/forms/renderer.rb
99
+ - lib/odin/forms/types.rb
100
+ - lib/odin/forms/units.rb
94
101
  - lib/odin/parsing/parser.rb
95
102
  - lib/odin/parsing/token.rb
96
103
  - lib/odin/parsing/token_type.rb
97
104
  - lib/odin/parsing/tokenizer.rb
98
105
  - lib/odin/parsing/value_parser.rb
99
106
  - lib/odin/resolver/import_resolver.rb
107
+ - lib/odin/resolver/type_registry.rb
100
108
  - lib/odin/serialization/canonicalize.rb
101
109
  - lib/odin/serialization/stringify.rb
102
110
  - lib/odin/transform/format_exporters.rb
103
111
  - lib/odin/transform/source_parsers.rb
104
112
  - lib/odin/transform/transform_engine.rb
113
+ - lib/odin/transform/transform_expr.rb
105
114
  - lib/odin/transform/transform_parser.rb
106
115
  - lib/odin/transform/transform_types.rb
107
116
  - lib/odin/transform/verb_context.rb
108
117
  - lib/odin/transform/verbs/aggregation_verbs.rb
109
118
  - lib/odin/transform/verbs/collection_verbs.rb
110
119
  - lib/odin/transform/verbs/datetime_verbs.rb
120
+ - lib/odin/transform/verbs/extra_verbs.rb
111
121
  - lib/odin/transform/verbs/financial_verbs.rb
112
122
  - lib/odin/transform/verbs/geo_verbs.rb
113
123
  - lib/odin/transform/verbs/numeric_verbs.rb
@@ -129,7 +139,9 @@ files:
129
139
  - lib/odin/utils/path_utils.rb
130
140
  - lib/odin/utils/security_limits.rb
131
141
  - lib/odin/validation/format_validators.rb
142
+ - lib/odin/validation/invariant_evaluator.rb
132
143
  - lib/odin/validation/redos_protection.rb
144
+ - lib/odin/validation/schema_definition_validator.rb
133
145
  - lib/odin/validation/schema_parser.rb
134
146
  - lib/odin/validation/schema_serializer.rb
135
147
  - lib/odin/validation/validator.rb