literal 0.2.1 → 1.0.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.
data/lib/literal/types.rb CHANGED
@@ -25,7 +25,6 @@ module Literal::Types
25
25
  autoload :ProcableType, "literal/types/procable_type"
26
26
  autoload :RangeType, "literal/types/range_type"
27
27
  autoload :SetType, "literal/types/set_type"
28
- autoload :ShapeType, "literal/types/shape_type"
29
28
  autoload :StringType, "literal/types/string_type"
30
29
  autoload :SymbolType, "literal/types/symbol_type"
31
30
  autoload :TruthyType, "literal/types/truthy_type"
@@ -33,68 +32,144 @@ module Literal::Types
33
32
  autoload :UnionType, "literal/types/union_type"
34
33
  autoload :VoidType, "literal/types/void_type"
35
34
 
36
- # Matches any value except `nil`. Use `_Nilable(_Any)` or `_Void` to match any value including `nil`.
35
+ NilableBooleanType = NilableType.new(BooleanType)
36
+ NilableCallableType = NilableType.new(CallableType)
37
+ NilableJSONDataType = NilableType.new(JSONDataType)
38
+ NilableLambdaType = NilableType.new(LambdaType)
39
+ NilableProcableType = NilableType.new(ProcableType)
40
+
41
+ # Matches any value except `nil`. Use `_Any?` or `_Unit` to match any value including `nil`.
37
42
  def _Any
38
- Literal::Types::AnyType
43
+ AnyType
44
+ end
45
+
46
+ def _Any?
47
+ VoidType
39
48
  end
40
49
 
41
50
  # Matches if the value is an `Array` and all the elements match the given type.
42
51
  def _Array(...)
43
- Literal::Types::ArrayType.new(...)
52
+ ArrayType.new(...)
53
+ end
54
+
55
+ # Nilable version of `_Array`
56
+ def _Array?(...)
57
+ NilableType.new(
58
+ ArrayType.new(...),
59
+ )
44
60
  end
45
61
 
46
62
  # Matches if the value is `true` or `false`.
47
63
  def _Boolean
48
- Literal::Types::BooleanType
64
+ BooleanType
65
+ end
66
+
67
+ # Nilable version of `_Boolean`
68
+ def _Boolean?
69
+ NilableBooleanType
49
70
  end
50
71
 
51
72
  # Matches if the value responds to `#call`.
52
73
  def _Callable
53
- Literal::Types::CallableType
74
+ CallableType
75
+ end
76
+
77
+ # Nilabl version of `_Callable`
78
+ def _Callable?
79
+ NilableCallableType
54
80
  end
55
81
 
56
82
  # Matches if the value either the given class or a subclass of it.
57
83
  def _Class(...)
58
- Literal::Types::ClassType.new(...)
84
+ ClassType.new(...)
85
+ end
86
+
87
+ # Nilable version of `_Class`
88
+ def _Class?(...)
89
+ NilableType.new(
90
+ ClassType.new(...),
91
+ )
59
92
  end
60
93
 
61
94
  # Similar to `_Intersection`, but allows you to specify attribute constraints as keyword arguments.
62
95
  # @example
63
96
  # _Constraint(Array, size: 1..3)
64
97
  def _Constraint(...)
65
- Literal::Types::ConstraintType.new(...)
98
+ ConstraintType.new(...)
99
+ end
100
+
101
+ # Nilable version of `_Constraint`
102
+ def _Constraint?(...)
103
+ NilableType.new(
104
+ ConstraintType.new(...),
105
+ )
66
106
  end
67
107
 
68
108
  # Matches if the value is a descendant of the given class.
69
109
  def _Descendant(...)
70
- Literal::Types::DescendantType.new(...)
110
+ DescendantType.new(...)
111
+ end
112
+
113
+ # Nilable version of `_Descendant`
114
+ def _Descendant?(...)
115
+ NilableType.new(
116
+ DescendantType.new(...),
117
+ )
71
118
  end
72
119
 
73
120
  #  Matches if the value is an `Enumerable` and all its elements match the given type.
74
121
  def _Enumerable(...)
75
- Literal::Types::EnumerableType.new(...)
122
+ EnumerableType.new(...)
123
+ end
124
+
125
+ # Nilable version of `_Enumerable`
126
+ def _Enumerable?(...)
127
+ NilableType.new(
128
+ EnumerableType.new(...),
129
+ )
76
130
  end
77
131
 
78
132
  # Matches *"falsy"* values (`nil` and `false`).
79
133
  def _Falsy
80
- Literal::Types::FalsyType
134
+ FalsyType
81
135
  end
82
136
 
83
137
  # Matches if the value is a `Float` and matches the given constraint.
84
138
  # You could use a `Range`, for example, as a constraint.
85
139
  # If you don't need a constraint, use `Float` instead of `_Float`.
86
140
  def _Float(...)
87
- Literal::Types::FloatType.new(...)
141
+ FloatType.new(...)
142
+ end
143
+
144
+ # Nilable version of `_Float`
145
+ def _Float?(...)
146
+ NilableType.new(
147
+ FloatType.new(...),
148
+ )
88
149
  end
89
150
 
90
151
  # Matches if the value is *frozen*.
91
152
  def _Frozen(...)
92
- Literal::Types::FrozenType.new(...)
153
+ FrozenType.new(...)
154
+ end
155
+
156
+ # Nilable version of `_Frozen`
157
+ def _Frozen?(...)
158
+ NilableType.new(
159
+ FrozenType.new(...),
160
+ )
93
161
  end
94
162
 
95
163
  # Matches if the value is a `Hash` and all the keys and values match the given types.
96
164
  def _Hash(...)
97
- Literal::Types::HashType.new(...)
165
+ HashType.new(...)
166
+ end
167
+
168
+ # Nilable version of `_Hash`
169
+ def _Hash?
170
+ NilableType.new(
171
+ HashType.new,
172
+ )
98
173
  end
99
174
 
100
175
  # Matches if the value is an `Integer` and matches the given constraint.
@@ -103,95 +178,175 @@ module Literal::Types
103
178
  # @example
104
179
  # attribute :age, _Integer(18..127)
105
180
  def _Integer(...)
106
- Literal::Types::IntegerType.new(...)
181
+ IntegerType.new(...)
182
+ end
183
+
184
+ # Nilable version of `_Integer`
185
+ def _Integer?(...)
186
+ NilableType.new(
187
+ IntegerType(...),
188
+ )
107
189
  end
108
190
 
109
191
  # Matches if the value responds to all the given methods.
110
192
  def _Interface(...)
111
- Literal::Types::InterfaceType.new(...)
193
+ InterfaceType.new(...)
194
+ end
195
+
196
+ # Nilable version of `_Interface`
197
+ def _Interface?(...)
198
+ NilableType.new(
199
+ InterfaceType.new(...),
200
+ )
112
201
  end
113
202
 
114
203
  # Matches if *all* given types are matched.
115
204
  def _Intersection(...)
116
- Literal::Types::IntersectionType.new(...)
205
+ IntersectionType.new(...)
206
+ end
207
+
208
+ # Nilable version of `_Intersection`
209
+ def _Intersection?(...)
210
+ NilableType.new(
211
+ IntersectionType.new(...),
212
+ )
117
213
  end
118
214
 
119
215
  # Ensures the value is valid JSON data (i.e. it came from JSON.parse).
120
216
  def _JSONData
121
- Literal::Types::JSONDataType
217
+ JSONDataType
218
+ end
219
+
220
+ # Nilable version of `_JSONData`
221
+ def _JSONData?
222
+ NilableJSONDataType
122
223
  end
123
224
 
124
225
  # Matches if the value is a `Proc` and `#lambda?` returns truthy.
125
226
  def _Lambda
126
- Literal::Types::LambdaType
227
+ LambdaType
228
+ end
229
+
230
+ # Nilable version of `_Lambda`
231
+ def _Lambda?
232
+ NilableLambdaType
127
233
  end
128
234
 
129
235
  def _Map(...)
130
- Literal::Types::MapType.new(...)
236
+ MapType.new(...)
237
+ end
238
+
239
+ # Nilable version of `_Map`
240
+ def _Map?(...)
241
+ NilableType.new(
242
+ MapType.new(...),
243
+ )
131
244
  end
132
245
 
133
246
  # Never matches any value.
134
247
  def _Never
135
- Literal::Types::NeverType
248
+ NeverType
136
249
  end
137
250
 
138
251
  # Matches if the value is either `nil` or the given type.
139
252
  def _Nilable(...)
140
- Literal::Types::NilableType.new(...)
253
+ NilableType.new(...)
141
254
  end
142
255
 
143
256
  # Matches if the given type is *not* matched.
144
257
  def _Not(...)
145
- Literal::Types::NotType.new(...)
258
+ NotType.new(...)
146
259
  end
147
260
 
148
261
  # Matches if the value is a `Proc` or responds to `#to_proc`.
149
262
  def _Procable
150
- Literal::Types::ProcableType
263
+ ProcableType
264
+ end
265
+
266
+ # Nilable version ofo `_Procable`
267
+ def _Procable?
268
+ NilableProcableType
151
269
  end
152
270
 
153
271
  # Matches if the value is a `Range` of the given type.
154
272
  def _Range(...)
155
- Literal::Types::RangeType.new(...)
273
+ RangeType.new(...)
274
+ end
275
+
276
+ # Nilable version of `_Range`
277
+ def _Range?(...)
278
+ NilableType.new(
279
+ RangeType.new(...),
280
+ )
156
281
  end
157
282
 
158
283
  # Matches if the value is a `Set` and all the elements match the given type.
159
284
  def _Set(...)
160
- Literal::Types::SetType.new(...)
285
+ SetType.new(...)
161
286
  end
162
287
 
163
- # Ensures a value matches the given shape of a Hash
164
- def _Shape(...)
165
- Literal::Types::ShapeType.new(...)
288
+ # Nilable version of `_Set`
289
+ def _Set?(...)
290
+ NilableType.new(
291
+ SetType.new(...),
292
+ )
166
293
  end
167
294
 
168
295
  # Matches if the value is a `String` and matches the given constraints.
169
296
  # If you don't need any constraints, use `String` instead of `_String`.
170
297
  def _String(...)
171
- Literal::Types::StringType.new(...)
298
+ StringType.new(...)
299
+ end
300
+
301
+ # Nilable version of `_String`
302
+ def _String?(...)
303
+ NilableType.new(
304
+ StringType.new(...),
305
+ )
172
306
  end
173
307
 
174
308
  # Matches if the value is a `Symbol` and matches the given constraint.
175
309
  def _Symbol(...)
176
- Literal::Types::SymbolType.new(...)
310
+ SymbolType.new(...)
311
+ end
312
+
313
+ # Nilable version of `_Symbol`
314
+ def _Symbol?(...)
315
+ NilableType.new(
316
+ SymbolType.new(...),
317
+ )
177
318
  end
178
319
 
179
320
  # Matches *"truthy"* values (anything except `nil` and `false`).
180
321
  def _Truthy
181
- Literal::Types::TruthyType
322
+ TruthyType
182
323
  end
183
324
 
184
325
  # Matches if the value is an `Array` and each element matches the given types in order.
185
326
  def _Tuple(...)
186
- Literal::Types::TupleType.new(...)
327
+ TupleType.new(...)
328
+ end
329
+
330
+ # Nilable version of `_Typle`
331
+ def _Tuple?(...)
332
+ NilableType.new(
333
+ TupleType.new(...),
334
+ )
187
335
  end
188
336
 
189
337
  # Matches if *any* given type is matched.
190
338
  def _Union(...)
191
- Literal::Types::UnionType.new(...)
339
+ UnionType.new(...)
340
+ end
341
+
342
+ # Nilable version of `_Union`
343
+ def _Union?(...)
344
+ NilableType.new(
345
+ UnionType.new(...),
346
+ )
192
347
  end
193
348
 
194
349
  def _Void
195
- Literal::Types::VoidType
350
+ VoidType
196
351
  end
197
352
  end
@@ -1,5 +1,5 @@
1
1
  # frozen_string_literal: true
2
2
 
3
3
  module Literal
4
- VERSION = "0.2.1"
4
+ VERSION = "1.0.0"
5
5
  end
data/lib/literal.rb CHANGED
@@ -25,11 +25,16 @@ module Literal
25
25
  end
26
26
  end
27
27
 
28
- def self.check(value, type)
29
- if TYPE_CHECKS_DISABLED || type === value
28
+ def self.check(actual:, expected:)
29
+ if expected === actual
30
30
  true
31
31
  else
32
- raise Literal::TypeError.expected(value, to_be_a: type)
32
+ context = Literal::TypeError::Context.new(expected:, actual:)
33
+ expected.record_literal_type_errors(context) if expected.respond_to?(:record_literal_type_errors)
34
+ yield context if block_given?
35
+ raise Literal::TypeError.new(context:)
33
36
  end
34
37
  end
35
38
  end
39
+
40
+ require_relative "literal/rails" if defined?(Rails)
metadata CHANGED
@@ -1,16 +1,16 @@
1
1
  --- !ruby/object:Gem::Specification
2
2
  name: literal
3
3
  version: !ruby/object:Gem::Version
4
- version: 0.2.1
4
+ version: 1.0.0
5
5
  platform: ruby
6
6
  authors:
7
7
  - Joel Drapper
8
8
  autorequire:
9
9
  bindir: bin
10
10
  cert_chain: []
11
- date: 2024-06-30 00:00:00.000000000 Z
11
+ date: 2024-11-01 00:00:00.000000000 Z
12
12
  dependencies: []
13
- description: ''
13
+ description: A literal Ruby gem.
14
14
  email:
15
15
  - joel@drapper.me
16
16
  executables: []
@@ -20,7 +20,6 @@ files:
20
20
  - LICENSE.txt
21
21
  - README.md
22
22
  - lib/literal.rb
23
- - lib/literal.test.rb
24
23
  - lib/literal/data.rb
25
24
  - lib/literal/data_property.rb
26
25
  - lib/literal/data_structure.rb
@@ -34,6 +33,11 @@ files:
34
33
  - lib/literal/properties/data_schema.rb
35
34
  - lib/literal/properties/schema.rb
36
35
  - lib/literal/property.rb
36
+ - lib/literal/rails.rb
37
+ - lib/literal/rails/enum_serializer.rb
38
+ - lib/literal/rails/enum_type.rb
39
+ - lib/literal/rails/patches/active_record.rb
40
+ - lib/literal/railtie.rb
37
41
  - lib/literal/struct.rb
38
42
  - lib/literal/types.rb
39
43
  - lib/literal/types/any_type.rb
@@ -67,11 +71,11 @@ files:
67
71
  - lib/literal/types/union_type.rb
68
72
  - lib/literal/types/void_type.rb
69
73
  - lib/literal/version.rb
70
- homepage: https://github.com/joeldrapper/literal
74
+ homepage: https://literal.fun
71
75
  licenses:
72
76
  - MIT
73
77
  metadata:
74
- homepage_uri: https://github.com/joeldrapper/literal
78
+ homepage_uri: https://literal.fun
75
79
  source_code_uri: https://github.com/joeldrapper/literal
76
80
  changelog_uri: https://github.com/joeldrapper/literal/blob/main/CHANGELOG.md
77
81
  funding_uri: https://github.com/sponsors/joeldrapper
@@ -91,8 +95,8 @@ required_rubygems_version: !ruby/object:Gem::Requirement
91
95
  - !ruby/object:Gem::Version
92
96
  version: '0'
93
97
  requirements: []
94
- rubygems_version: 3.5.13
98
+ rubygems_version: 3.5.18
95
99
  signing_key:
96
100
  specification_version: 4
97
- summary: A literal Ruby gem
101
+ summary: Enums, properties, generics, structured objects and runtime type checking.
98
102
  test_files: []
data/lib/literal.test.rb DELETED
@@ -1,5 +0,0 @@
1
- # frozen_string_literal: true
2
-
3
- test do
4
- expect(Literal::VERSION).to_be_a String
5
- end