konstruo 1.0.2 → 1.0.3
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.
- checksums.yaml +4 -4
- data/CHANGELOG.md +12 -0
- data/README.md +18 -1
- data/lib/konstruo/mapper.rb +8 -2
- data/lib/konstruo/version.rb +1 -1
- data/lib/tapioca/dsl/compilers/konstruo_mapper.rb +1 -1
- data/sorbet/rbi/dsl/nullable_mapper.rbi +38 -0
- metadata +3 -2
checksums.yaml
CHANGED
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
---
|
|
2
2
|
SHA256:
|
|
3
|
-
metadata.gz:
|
|
4
|
-
data.tar.gz:
|
|
3
|
+
metadata.gz: 54c20c9b4279be4b434685e57738654da55fbb75fe21e5bc8d4286bdd292aaf4
|
|
4
|
+
data.tar.gz: e924f4facbf95273bc16585e994c455877d28723763c05ce223e38e05a451ece
|
|
5
5
|
SHA512:
|
|
6
|
-
metadata.gz:
|
|
7
|
-
data.tar.gz:
|
|
6
|
+
metadata.gz: c04a03b2187dc910e08e38fa4a27619d9b0d935a7fb518af14061c8780773c768b3dc435194c3aa14abc60ff94afca2bcdc448e25c2ae14bf0d0fcf052fe484d
|
|
7
|
+
data.tar.gz: 0f03affbf375f28e6fdaa2b7b17638df508cdd7d384631130677ba2e6de57e8b49fd81be59c476974d236391974f40956ea5498386ab0ea16d25ab1a9026ded6
|
data/CHANGELOG.md
CHANGED
|
@@ -1,5 +1,17 @@
|
|
|
1
1
|
# Changelog
|
|
2
2
|
|
|
3
|
+
## [1.0.3](https://github.com/DashBrains/konstruo/compare/v1.0.2...v1.0.3) (2026-04-01)
|
|
4
|
+
|
|
5
|
+
|
|
6
|
+
### Features
|
|
7
|
+
|
|
8
|
+
* add nilable field ([c3422ea](https://github.com/DashBrains/konstruo/commit/c3422ea68611223f77bfcdee2b6497a302bfc975))
|
|
9
|
+
|
|
10
|
+
|
|
11
|
+
### Miscellaneous Chores
|
|
12
|
+
|
|
13
|
+
* **release:** 1.0.3 ([86ae552](https://github.com/DashBrains/konstruo/commit/86ae552f0aff66bbdbdda20a06e549f5e38bff51))
|
|
14
|
+
|
|
3
15
|
## [1.0.2](https://github.com/DashBrains/konstruo/compare/v1.0.1...v1.0.2) (2026-03-31)
|
|
4
16
|
|
|
5
17
|
|
data/README.md
CHANGED
|
@@ -96,7 +96,7 @@ payload.name # => "Jane"
|
|
|
96
96
|
Field API:
|
|
97
97
|
|
|
98
98
|
```ruby
|
|
99
|
-
field(name, type, required: false, custom_name: nil, mapper: nil, error_message: nil)
|
|
99
|
+
field(name, type, required: false, nullable: nil, custom_name: nil, mapper: nil, error_message: nil)
|
|
100
100
|
```
|
|
101
101
|
|
|
102
102
|
Options:
|
|
@@ -104,6 +104,7 @@ Options:
|
|
|
104
104
|
- `name` (`Symbol`): Ruby attribute name.
|
|
105
105
|
- `type` (`Class` or `[Class]`): Expected value type.
|
|
106
106
|
- `required` (`Boolean`): Raises `Konstruo::ValidationError` when missing.
|
|
107
|
+
- `nullable` (`Boolean`, optional): Controls whether a present key can have `nil` value.
|
|
107
108
|
- `custom_name` (`String`): External key name to read from input.
|
|
108
109
|
- `mapper` (`Proc`): Converts raw input value before assignment.
|
|
109
110
|
- `error_message` (`String`): Custom validation error message.
|
|
@@ -118,6 +119,11 @@ Supported type patterns:
|
|
|
118
119
|
|
|
119
120
|
Array type declarations must contain exactly one element class (for example `[String]`).
|
|
120
121
|
|
|
122
|
+
`nullable` default behavior:
|
|
123
|
+
|
|
124
|
+
- If `required: true` and `nullable` is omitted, `nullable` defaults to `false`.
|
|
125
|
+
- If `required: false` and `nullable` is omitted, `nullable` defaults to `true`.
|
|
126
|
+
|
|
121
127
|
## Parsing Input
|
|
122
128
|
|
|
123
129
|
Konstruo supports three entry points:
|
|
@@ -158,6 +164,17 @@ Default message format:
|
|
|
158
164
|
Missing required field: field_name
|
|
159
165
|
```
|
|
160
166
|
|
|
167
|
+
### Nullability
|
|
168
|
+
|
|
169
|
+
When a key is present with `nil` value:
|
|
170
|
+
|
|
171
|
+
- `nullable: true` allows it.
|
|
172
|
+
- `nullable: false` raises:
|
|
173
|
+
|
|
174
|
+
```text
|
|
175
|
+
Field cannot be nil: field_name
|
|
176
|
+
```
|
|
177
|
+
|
|
161
178
|
### Type errors
|
|
162
179
|
|
|
163
180
|
Type mismatches raise `Konstruo::ValidationError` with details like:
|
data/lib/konstruo/mapper.rb
CHANGED
|
@@ -16,6 +16,7 @@ module Konstruo
|
|
|
16
16
|
const :name, Symbol
|
|
17
17
|
const :type, FieldType
|
|
18
18
|
const :required, T::Boolean
|
|
19
|
+
const :nullable, T::Boolean
|
|
19
20
|
const :custom_name, String
|
|
20
21
|
const :mapper, T.nilable(T.proc.params(value: T.untyped).returns(T.untyped))
|
|
21
22
|
const :error_message, T.nilable(String)
|
|
@@ -52,20 +53,23 @@ module Konstruo
|
|
|
52
53
|
name: Symbol,
|
|
53
54
|
type: FieldType,
|
|
54
55
|
required: T::Boolean,
|
|
56
|
+
nullable: T.nilable(T::Boolean),
|
|
55
57
|
custom_name: T.nilable(String),
|
|
56
58
|
mapper: T.nilable(T.proc.params(value: T.untyped).returns(T.untyped)),
|
|
57
59
|
error_message: T.nilable(String)
|
|
58
60
|
).void
|
|
59
61
|
end
|
|
60
|
-
def field(name, type, required: false, custom_name: nil, mapper: nil, error_message: nil)
|
|
62
|
+
def field(name, type, required: false, nullable: nil, custom_name: nil, mapper: nil, error_message: nil)
|
|
61
63
|
attr_accessor name unless method_defined?(name)
|
|
62
64
|
|
|
63
65
|
validate_field_type!(type)
|
|
66
|
+
resolved_nullable = nullable.nil? ? !required : nullable
|
|
64
67
|
|
|
65
68
|
fields << FieldDefinition.new(
|
|
66
69
|
name: name,
|
|
67
70
|
type: type,
|
|
68
71
|
required: required,
|
|
72
|
+
nullable: resolved_nullable,
|
|
69
73
|
custom_name: custom_name || name.to_s,
|
|
70
74
|
mapper: mapper,
|
|
71
75
|
error_message: error_message
|
|
@@ -146,7 +150,9 @@ module Konstruo
|
|
|
146
150
|
value = has_string_key ? hash[key] : hash[symbol_key]
|
|
147
151
|
|
|
148
152
|
if value.nil?
|
|
149
|
-
raise Konstruo::ValidationError, (field.error_message || "
|
|
153
|
+
raise Konstruo::ValidationError, (field.error_message || "Field cannot be nil: #{key}") unless field.nullable
|
|
154
|
+
|
|
155
|
+
send(:"#{field.name}=", nil)
|
|
150
156
|
else
|
|
151
157
|
assign_value(field.name, field.type, value, field.mapper, field.error_message)
|
|
152
158
|
end
|
data/lib/konstruo/version.rb
CHANGED
|
@@ -34,7 +34,7 @@ module Tapioca
|
|
|
34
34
|
root.create_path(constant) do |klass|
|
|
35
35
|
constant.fields.each do |field|
|
|
36
36
|
field_type = as_type_string(field.type)
|
|
37
|
-
accessor_type = field.required ? field_type : "T.nilable(#{field_type})"
|
|
37
|
+
accessor_type = (field.required && !field.nullable) ? field_type : "T.nilable(#{field_type})"
|
|
38
38
|
field_name = field.name.to_s
|
|
39
39
|
|
|
40
40
|
klass.create_method(field_name, return_type: accessor_type)
|
|
@@ -0,0 +1,38 @@
|
|
|
1
|
+
# typed: true
|
|
2
|
+
|
|
3
|
+
# DO NOT EDIT MANUALLY
|
|
4
|
+
# This is an autogenerated file for dynamic methods in `NullableMapper`.
|
|
5
|
+
# Please instead update this file by running `bin/tapioca dsl NullableMapper`.
|
|
6
|
+
|
|
7
|
+
|
|
8
|
+
class NullableMapper
|
|
9
|
+
sig { returns(T.nilable(String)) }
|
|
10
|
+
def optional_non_nullable; end
|
|
11
|
+
|
|
12
|
+
sig { params(value: T.nilable(String)).returns(T.nilable(String)) }
|
|
13
|
+
def optional_non_nullable=(value); end
|
|
14
|
+
|
|
15
|
+
sig { returns(T.nilable(String)) }
|
|
16
|
+
def optional_nullable_default; end
|
|
17
|
+
|
|
18
|
+
sig { params(value: T.nilable(String)).returns(T.nilable(String)) }
|
|
19
|
+
def optional_nullable_default=(value); end
|
|
20
|
+
|
|
21
|
+
sig { returns(String) }
|
|
22
|
+
def required_non_nullable; end
|
|
23
|
+
|
|
24
|
+
sig { params(value: String).returns(String) }
|
|
25
|
+
def required_non_nullable=(value); end
|
|
26
|
+
|
|
27
|
+
sig { returns(String) }
|
|
28
|
+
def required_non_nullable_default; end
|
|
29
|
+
|
|
30
|
+
sig { params(value: String).returns(String) }
|
|
31
|
+
def required_non_nullable_default=(value); end
|
|
32
|
+
|
|
33
|
+
sig { returns(T.nilable(String)) }
|
|
34
|
+
def required_nullable; end
|
|
35
|
+
|
|
36
|
+
sig { params(value: T.nilable(String)).returns(T.nilable(String)) }
|
|
37
|
+
def required_nullable=(value); end
|
|
38
|
+
end
|
metadata
CHANGED
|
@@ -1,14 +1,14 @@
|
|
|
1
1
|
--- !ruby/object:Gem::Specification
|
|
2
2
|
name: konstruo
|
|
3
3
|
version: !ruby/object:Gem::Version
|
|
4
|
-
version: 1.0.
|
|
4
|
+
version: 1.0.3
|
|
5
5
|
platform: ruby
|
|
6
6
|
authors:
|
|
7
7
|
- DashBrains
|
|
8
8
|
autorequire:
|
|
9
9
|
bindir: exe
|
|
10
10
|
cert_chain: []
|
|
11
|
-
date: 2026-
|
|
11
|
+
date: 2026-04-01 00:00:00.000000000 Z
|
|
12
12
|
dependencies:
|
|
13
13
|
- !ruby/object:Gem::Dependency
|
|
14
14
|
name: actionpack
|
|
@@ -90,6 +90,7 @@ files:
|
|
|
90
90
|
- sorbet/rbi/dsl/inheritance_child_mapper.rbi
|
|
91
91
|
- sorbet/rbi/dsl/invalid_field_definition_mapper.rbi
|
|
92
92
|
- sorbet/rbi/dsl/loose_person_mapper.rbi
|
|
93
|
+
- sorbet/rbi/dsl/nullable_mapper.rbi
|
|
93
94
|
- sorbet/rbi/dsl/person.rbi
|
|
94
95
|
- sorbet/rbi/dsl/strict_person_mapper.rbi
|
|
95
96
|
- sorbet/rbi/gems/.gitattributes
|