terminal-shop 2.0.0 → 2.1.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.
- checksums.yaml +4 -4
- data/README.md +2 -8
- data/lib/terminal-shop/client.rb +1 -1
- data/lib/terminal-shop/models/address_create_params.rb +1 -1
- data/lib/terminal-shop/models/address_delete_params.rb +1 -1
- data/lib/terminal-shop/models/address_get_params.rb +1 -1
- data/lib/terminal-shop/models/address_list_params.rb +1 -1
- data/lib/terminal-shop/models/app_create_params.rb +1 -1
- data/lib/terminal-shop/models/app_delete_params.rb +1 -1
- data/lib/terminal-shop/models/app_get_params.rb +1 -1
- data/lib/terminal-shop/models/app_list_params.rb +1 -1
- data/lib/terminal-shop/models/card_collect_params.rb +1 -1
- data/lib/terminal-shop/models/card_create_params.rb +1 -1
- data/lib/terminal-shop/models/card_delete_params.rb +1 -1
- data/lib/terminal-shop/models/card_get_params.rb +1 -1
- data/lib/terminal-shop/models/card_list_params.rb +1 -1
- data/lib/terminal-shop/models/cart_clear_params.rb +1 -1
- data/lib/terminal-shop/models/cart_convert_params.rb +1 -1
- data/lib/terminal-shop/models/cart_get_params.rb +1 -1
- data/lib/terminal-shop/models/cart_set_address_params.rb +1 -1
- data/lib/terminal-shop/models/cart_set_card_params.rb +1 -1
- data/lib/terminal-shop/models/cart_set_item_params.rb +1 -1
- data/lib/terminal-shop/models/email_create_params.rb +1 -1
- data/lib/terminal-shop/models/order_create_params.rb +1 -1
- data/lib/terminal-shop/models/order_get_params.rb +1 -1
- data/lib/terminal-shop/models/order_list_params.rb +1 -1
- data/lib/terminal-shop/models/product_get_params.rb +1 -1
- data/lib/terminal-shop/models/product_list_params.rb +1 -1
- data/lib/terminal-shop/models/profile_me_params.rb +1 -1
- data/lib/terminal-shop/models/profile_update_params.rb +1 -1
- data/lib/terminal-shop/models/subscription_create_params.rb +1 -1
- data/lib/terminal-shop/models/subscription_delete_params.rb +1 -1
- data/lib/terminal-shop/models/subscription_get_params.rb +1 -1
- data/lib/terminal-shop/models/subscription_list_params.rb +1 -1
- data/lib/terminal-shop/models/token_create_params.rb +1 -1
- data/lib/terminal-shop/models/token_delete_params.rb +1 -1
- data/lib/terminal-shop/models/token_get_params.rb +1 -1
- data/lib/terminal-shop/models/token_list_params.rb +1 -1
- data/lib/terminal-shop/models/view_init_params.rb +1 -1
- data/lib/terminal-shop/request_options.rb +0 -33
- data/lib/terminal-shop/transport/base_client.rb +459 -0
- data/lib/terminal-shop/transport/pooled_net_requester.rb +182 -0
- data/lib/terminal-shop/type/array_of.rb +110 -0
- data/lib/terminal-shop/type/base_model.rb +362 -0
- data/lib/terminal-shop/type/base_page.rb +61 -0
- data/lib/terminal-shop/type/boolean_model.rb +52 -0
- data/lib/terminal-shop/type/converter.rb +217 -0
- data/lib/terminal-shop/type/enum.rb +101 -0
- data/lib/terminal-shop/type/hash_of.rb +136 -0
- data/lib/terminal-shop/type/request_parameters.rb +38 -0
- data/lib/terminal-shop/type/union.rb +183 -0
- data/lib/terminal-shop/type/unknown.rb +56 -0
- data/lib/terminal-shop/type.rb +23 -0
- data/lib/terminal-shop/util.rb +3 -5
- data/lib/terminal-shop/version.rb +1 -1
- data/lib/terminal-shop.rb +14 -6
- data/rbi/lib/terminal-shop/client.rbi +1 -1
- data/rbi/lib/terminal-shop/models/address_create_params.rbi +12 -2
- data/rbi/lib/terminal-shop/models/address_delete_params.rbi +1 -1
- data/rbi/lib/terminal-shop/models/address_get_params.rbi +1 -1
- data/rbi/lib/terminal-shop/models/address_list_params.rbi +1 -1
- data/rbi/lib/terminal-shop/models/app_create_params.rbi +1 -1
- data/rbi/lib/terminal-shop/models/app_delete_params.rbi +1 -1
- data/rbi/lib/terminal-shop/models/app_get_params.rbi +1 -1
- data/rbi/lib/terminal-shop/models/app_list_params.rbi +1 -1
- data/rbi/lib/terminal-shop/models/card_collect_params.rbi +1 -1
- data/rbi/lib/terminal-shop/models/card_create_params.rbi +1 -1
- data/rbi/lib/terminal-shop/models/card_delete_params.rbi +1 -1
- data/rbi/lib/terminal-shop/models/card_get_params.rbi +1 -1
- data/rbi/lib/terminal-shop/models/card_list_params.rbi +1 -1
- data/rbi/lib/terminal-shop/models/cart_clear_params.rbi +1 -1
- data/rbi/lib/terminal-shop/models/cart_convert_params.rbi +1 -1
- data/rbi/lib/terminal-shop/models/cart_get_params.rbi +1 -1
- data/rbi/lib/terminal-shop/models/cart_set_address_params.rbi +1 -1
- data/rbi/lib/terminal-shop/models/cart_set_card_params.rbi +1 -1
- data/rbi/lib/terminal-shop/models/cart_set_item_params.rbi +1 -1
- data/rbi/lib/terminal-shop/models/email_create_params.rbi +1 -1
- data/rbi/lib/terminal-shop/models/order_create_params.rbi +1 -1
- data/rbi/lib/terminal-shop/models/order_get_params.rbi +1 -1
- data/rbi/lib/terminal-shop/models/order_list_params.rbi +1 -1
- data/rbi/lib/terminal-shop/models/product_get_params.rbi +1 -1
- data/rbi/lib/terminal-shop/models/product_list_params.rbi +1 -1
- data/rbi/lib/terminal-shop/models/profile_me_params.rbi +1 -1
- data/rbi/lib/terminal-shop/models/profile_update_params.rbi +1 -1
- data/rbi/lib/terminal-shop/models/subscription_create_params.rbi +1 -1
- data/rbi/lib/terminal-shop/models/subscription_delete_params.rbi +1 -1
- data/rbi/lib/terminal-shop/models/subscription_get_params.rbi +1 -1
- data/rbi/lib/terminal-shop/models/subscription_list_params.rbi +1 -1
- data/rbi/lib/terminal-shop/models/token_create_params.rbi +1 -1
- data/rbi/lib/terminal-shop/models/token_delete_params.rbi +1 -1
- data/rbi/lib/terminal-shop/models/token_get_params.rbi +1 -1
- data/rbi/lib/terminal-shop/models/token_list_params.rbi +1 -1
- data/rbi/lib/terminal-shop/models/view_init_params.rbi +1 -1
- data/rbi/lib/terminal-shop/models/view_init_response.rbi +12 -1
- data/rbi/lib/terminal-shop/request_options.rbi +0 -15
- data/rbi/lib/terminal-shop/transport/base_client.rbi +208 -0
- data/rbi/lib/terminal-shop/transport/pooled_net_requester.rbi +64 -0
- data/rbi/lib/terminal-shop/type/array_of.rbi +82 -0
- data/rbi/lib/terminal-shop/type/base_model.rbi +194 -0
- data/rbi/lib/terminal-shop/type/base_page.rbi +38 -0
- data/rbi/lib/terminal-shop/type/boolean_model.rbi +41 -0
- data/rbi/lib/terminal-shop/type/converter.rbi +101 -0
- data/rbi/lib/terminal-shop/type/enum.rbi +58 -0
- data/rbi/lib/terminal-shop/type/hash_of.rbi +85 -0
- data/rbi/lib/terminal-shop/type/request_parameters.rbi +20 -0
- data/rbi/lib/terminal-shop/type/union.rbi +68 -0
- data/rbi/lib/terminal-shop/type/unknown.rbi +37 -0
- data/rbi/lib/terminal-shop/type.rbi +23 -0
- data/rbi/lib/terminal-shop/version.rbi +1 -1
- data/sig/terminal-shop/client.rbs +1 -1
- data/sig/terminal-shop/models/address_create_params.rbs +1 -1
- data/sig/terminal-shop/models/address_delete_params.rbs +1 -1
- data/sig/terminal-shop/models/address_get_params.rbs +1 -1
- data/sig/terminal-shop/models/address_list_params.rbs +1 -1
- data/sig/terminal-shop/models/app_create_params.rbs +1 -1
- data/sig/terminal-shop/models/app_delete_params.rbs +1 -1
- data/sig/terminal-shop/models/app_get_params.rbs +1 -1
- data/sig/terminal-shop/models/app_list_params.rbs +1 -1
- data/sig/terminal-shop/models/card_collect_params.rbs +1 -1
- data/sig/terminal-shop/models/card_create_params.rbs +1 -1
- data/sig/terminal-shop/models/card_delete_params.rbs +1 -1
- data/sig/terminal-shop/models/card_get_params.rbs +1 -1
- data/sig/terminal-shop/models/card_list_params.rbs +1 -1
- data/sig/terminal-shop/models/cart_clear_params.rbs +1 -1
- data/sig/terminal-shop/models/cart_convert_params.rbs +1 -1
- data/sig/terminal-shop/models/cart_get_params.rbs +1 -1
- data/sig/terminal-shop/models/cart_set_address_params.rbs +1 -1
- data/sig/terminal-shop/models/cart_set_card_params.rbs +1 -1
- data/sig/terminal-shop/models/cart_set_item_params.rbs +1 -1
- data/sig/terminal-shop/models/email_create_params.rbs +1 -1
- data/sig/terminal-shop/models/order_create_params.rbs +1 -1
- data/sig/terminal-shop/models/order_get_params.rbs +1 -1
- data/sig/terminal-shop/models/order_list_params.rbs +1 -1
- data/sig/terminal-shop/models/product_get_params.rbs +1 -1
- data/sig/terminal-shop/models/product_list_params.rbs +1 -1
- data/sig/terminal-shop/models/profile_me_params.rbs +1 -1
- data/sig/terminal-shop/models/profile_update_params.rbs +1 -1
- data/sig/terminal-shop/models/subscription_create_params.rbs +1 -1
- data/sig/terminal-shop/models/subscription_delete_params.rbs +1 -1
- data/sig/terminal-shop/models/subscription_get_params.rbs +1 -1
- data/sig/terminal-shop/models/subscription_list_params.rbs +1 -1
- data/sig/terminal-shop/models/token_create_params.rbs +1 -1
- data/sig/terminal-shop/models/token_delete_params.rbs +1 -1
- data/sig/terminal-shop/models/token_get_params.rbs +1 -1
- data/sig/terminal-shop/models/token_list_params.rbs +1 -1
- data/sig/terminal-shop/models/view_init_params.rbs +1 -1
- data/sig/terminal-shop/request_options.rbs +0 -10
- data/sig/terminal-shop/transport/base_client.rbs +110 -0
- data/sig/terminal-shop/transport/pooled_net_requester.rbs +39 -0
- data/sig/terminal-shop/type/array_of.rbs +36 -0
- data/sig/terminal-shop/type/base_model.rbs +73 -0
- data/sig/terminal-shop/type/base_page.rbs +22 -0
- data/sig/terminal-shop/type/boolean_model.rbs +18 -0
- data/sig/terminal-shop/type/converter.rbs +42 -0
- data/sig/terminal-shop/type/enum.rbs +22 -0
- data/sig/terminal-shop/type/hash_of.rbs +36 -0
- data/sig/terminal-shop/type/request_parameters.rbs +13 -0
- data/sig/terminal-shop/type/union.rbs +40 -0
- data/sig/terminal-shop/type/unknown.rbs +18 -0
- data/sig/terminal-shop/type.rbs +22 -0
- data/sig/terminal-shop/version.rbs +1 -1
- metadata +41 -17
- data/lib/terminal-shop/base_client.rb +0 -457
- data/lib/terminal-shop/base_model.rb +0 -1201
- data/lib/terminal-shop/base_page.rb +0 -59
- data/lib/terminal-shop/extern.rb +0 -7
- data/lib/terminal-shop/pooled_net_requester.rb +0 -180
- data/rbi/lib/terminal-shop/base_client.rbi +0 -197
- data/rbi/lib/terminal-shop/base_model.rbi +0 -645
- data/rbi/lib/terminal-shop/base_page.rbi +0 -36
- data/rbi/lib/terminal-shop/extern.rbi +0 -7
- data/rbi/lib/terminal-shop/pooled_net_requester.rbi +0 -59
- data/sig/terminal-shop/base_client.rbs +0 -108
- data/sig/terminal-shop/base_model.rbs +0 -262
- data/sig/terminal-shop/base_page.rbs +0 -20
- data/sig/terminal-shop/extern.rbs +0 -4
- data/sig/terminal-shop/pooled_net_requester.rbs +0 -37
@@ -0,0 +1,217 @@
|
|
1
|
+
# frozen_string_literal: true
|
2
|
+
|
3
|
+
module TerminalShop
|
4
|
+
module Type
|
5
|
+
# rubocop:disable Metrics/ModuleLength
|
6
|
+
# @api private
|
7
|
+
module Converter
|
8
|
+
# rubocop:disable Lint/UnusedMethodArgument
|
9
|
+
|
10
|
+
# @api private
|
11
|
+
#
|
12
|
+
# @param value [Object]
|
13
|
+
#
|
14
|
+
# @param state [Hash{Symbol=>Object}] .
|
15
|
+
#
|
16
|
+
# @option state [Boolean, :strong] :strictness
|
17
|
+
#
|
18
|
+
# @option state [Hash{Symbol=>Object}] :exactness
|
19
|
+
#
|
20
|
+
# @option state [Integer] :branched
|
21
|
+
#
|
22
|
+
# @return [Object]
|
23
|
+
def coerce(value, state:) = (raise NotImplementedError)
|
24
|
+
|
25
|
+
# @api private
|
26
|
+
#
|
27
|
+
# @param value [Object]
|
28
|
+
#
|
29
|
+
# @return [Object]
|
30
|
+
def dump(value)
|
31
|
+
case value
|
32
|
+
in Array
|
33
|
+
value.map { TerminalShop::Unknown.dump(_1) }
|
34
|
+
in Hash
|
35
|
+
value.transform_values { TerminalShop::Unknown.dump(_1) }
|
36
|
+
in TerminalShop::BaseModel
|
37
|
+
value.class.dump(value)
|
38
|
+
else
|
39
|
+
value
|
40
|
+
end
|
41
|
+
end
|
42
|
+
|
43
|
+
# rubocop:enable Lint/UnusedMethodArgument
|
44
|
+
|
45
|
+
class << self
|
46
|
+
# @api private
|
47
|
+
#
|
48
|
+
# @param spec [Hash{Symbol=>Object}, Proc, TerminalShop::Type::Converter, Class] .
|
49
|
+
#
|
50
|
+
# @option spec [NilClass, TrueClass, FalseClass, Integer, Float, Symbol] :const
|
51
|
+
#
|
52
|
+
# @option spec [Proc] :enum
|
53
|
+
#
|
54
|
+
# @option spec [Proc] :union
|
55
|
+
#
|
56
|
+
# @option spec [Boolean] :"nil?"
|
57
|
+
#
|
58
|
+
# @return [Proc]
|
59
|
+
def type_info(spec)
|
60
|
+
case spec
|
61
|
+
in Proc
|
62
|
+
spec
|
63
|
+
in Hash
|
64
|
+
type_info(spec.slice(:const, :enum, :union).first&.last)
|
65
|
+
in true | false
|
66
|
+
-> { TerminalShop::BooleanModel }
|
67
|
+
in TerminalShop::Type::Converter | Class | Symbol
|
68
|
+
-> { spec }
|
69
|
+
in NilClass | Integer | Float
|
70
|
+
-> { spec.class }
|
71
|
+
end
|
72
|
+
end
|
73
|
+
|
74
|
+
# @api private
|
75
|
+
#
|
76
|
+
# Based on `target`, transform `value` into `target`, to the extent possible:
|
77
|
+
#
|
78
|
+
# 1. if the given `value` conforms to `target` already, return the given `value`
|
79
|
+
# 2. if it's possible and safe to convert the given `value` to `target`, then the
|
80
|
+
# converted value
|
81
|
+
# 3. otherwise, the given `value` unaltered
|
82
|
+
#
|
83
|
+
# The coercion process is subject to improvement between minor release versions.
|
84
|
+
# See https://docs.pydantic.dev/latest/concepts/unions/#smart-mode
|
85
|
+
#
|
86
|
+
# @param target [TerminalShop::Type::Converter, Class]
|
87
|
+
#
|
88
|
+
# @param value [Object]
|
89
|
+
#
|
90
|
+
# @param state [Hash{Symbol=>Object}] The `strictness` is one of `true`, `false`, or `:strong`. This informs the
|
91
|
+
# coercion strategy when we have to decide between multiple possible conversion
|
92
|
+
# targets:
|
93
|
+
#
|
94
|
+
# - `true`: the conversion must be exact, with minimum coercion.
|
95
|
+
# - `false`: the conversion can be approximate, with some coercion.
|
96
|
+
# - `:strong`: the conversion must be exact, with no coercion, and raise an error
|
97
|
+
# if not possible.
|
98
|
+
#
|
99
|
+
# The `exactness` is `Hash` with keys being one of `yes`, `no`, or `maybe`. For
|
100
|
+
# any given conversion attempt, the exactness will be updated based on how closely
|
101
|
+
# the value recursively matches the target type:
|
102
|
+
#
|
103
|
+
# - `yes`: the value can be converted to the target type with minimum coercion.
|
104
|
+
# - `maybe`: the value can be converted to the target type with some reasonable
|
105
|
+
# coercion.
|
106
|
+
# - `no`: the value cannot be converted to the target type.
|
107
|
+
#
|
108
|
+
# See implementation below for more details.
|
109
|
+
#
|
110
|
+
# @option state [Boolean, :strong] :strictness
|
111
|
+
#
|
112
|
+
# @option state [Hash{Symbol=>Object}] :exactness
|
113
|
+
#
|
114
|
+
# @option state [Integer] :branched
|
115
|
+
#
|
116
|
+
# @return [Object]
|
117
|
+
def coerce(
|
118
|
+
target,
|
119
|
+
value,
|
120
|
+
state: {strictness: true, exactness: {yes: 0, no: 0, maybe: 0}, branched: 0}
|
121
|
+
)
|
122
|
+
# rubocop:disable Lint/SuppressedException
|
123
|
+
# rubocop:disable Metrics/BlockNesting
|
124
|
+
strictness, exactness = state.fetch_values(:strictness, :exactness)
|
125
|
+
|
126
|
+
case target
|
127
|
+
in TerminalShop::Type::Converter
|
128
|
+
return target.coerce(value, state: state)
|
129
|
+
in Class
|
130
|
+
if value.is_a?(target)
|
131
|
+
exactness[:yes] += 1
|
132
|
+
return value
|
133
|
+
end
|
134
|
+
|
135
|
+
case target
|
136
|
+
in -> { _1 <= NilClass }
|
137
|
+
exactness[value.nil? ? :yes : :maybe] += 1
|
138
|
+
return nil
|
139
|
+
in -> { _1 <= Integer }
|
140
|
+
if value.is_a?(Integer)
|
141
|
+
exactness[:yes] += 1
|
142
|
+
return value
|
143
|
+
elsif strictness == :strong
|
144
|
+
message = "no implicit conversion of #{value.class} into #{target.inspect}"
|
145
|
+
raise TypeError.new(message)
|
146
|
+
else
|
147
|
+
Kernel.then do
|
148
|
+
return Integer(value).tap { exactness[:maybe] += 1 }
|
149
|
+
rescue ArgumentError, TypeError
|
150
|
+
end
|
151
|
+
end
|
152
|
+
in -> { _1 <= Float }
|
153
|
+
if value.is_a?(Numeric)
|
154
|
+
exactness[:yes] += 1
|
155
|
+
return Float(value)
|
156
|
+
elsif strictness == :strong
|
157
|
+
message = "no implicit conversion of #{value.class} into #{target.inspect}"
|
158
|
+
raise TypeError.new(message)
|
159
|
+
else
|
160
|
+
Kernel.then do
|
161
|
+
return Float(value).tap { exactness[:maybe] += 1 }
|
162
|
+
rescue ArgumentError, TypeError
|
163
|
+
end
|
164
|
+
end
|
165
|
+
in -> { _1 <= String }
|
166
|
+
case value
|
167
|
+
in String | Symbol | Numeric
|
168
|
+
exactness[value.is_a?(Numeric) ? :maybe : :yes] += 1
|
169
|
+
return value.to_s
|
170
|
+
else
|
171
|
+
if strictness == :strong
|
172
|
+
message = "no implicit conversion of #{value.class} into #{target.inspect}"
|
173
|
+
raise TypeError.new(message)
|
174
|
+
end
|
175
|
+
end
|
176
|
+
in -> { _1 <= Date || _1 <= Time }
|
177
|
+
Kernel.then do
|
178
|
+
return target.parse(value).tap { exactness[:yes] += 1 }
|
179
|
+
rescue ArgumentError, TypeError => e
|
180
|
+
raise e if strictness == :strong
|
181
|
+
end
|
182
|
+
in -> { _1 <= IO } if value.is_a?(String)
|
183
|
+
exactness[:yes] += 1
|
184
|
+
return StringIO.new(value.b)
|
185
|
+
else
|
186
|
+
end
|
187
|
+
in Symbol
|
188
|
+
if (value.is_a?(Symbol) || value.is_a?(String)) && value.to_sym == target
|
189
|
+
exactness[:yes] += 1
|
190
|
+
return target
|
191
|
+
elsif strictness == :strong
|
192
|
+
message = "cannot convert non-matching #{value.class} into #{target.inspect}"
|
193
|
+
raise ArgumentError.new(message)
|
194
|
+
end
|
195
|
+
else
|
196
|
+
end
|
197
|
+
|
198
|
+
exactness[:no] += 1
|
199
|
+
value
|
200
|
+
# rubocop:enable Metrics/BlockNesting
|
201
|
+
# rubocop:enable Lint/SuppressedException
|
202
|
+
end
|
203
|
+
|
204
|
+
# @api private
|
205
|
+
#
|
206
|
+
# @param target [TerminalShop::Type::Converter, Class]
|
207
|
+
# @param value [Object]
|
208
|
+
#
|
209
|
+
# @return [Object]
|
210
|
+
def dump(target, value)
|
211
|
+
target.is_a?(TerminalShop::Type::Converter) ? target.dump(value) : TerminalShop::Unknown.dump(value)
|
212
|
+
end
|
213
|
+
end
|
214
|
+
end
|
215
|
+
# rubocop:enable Metrics/ModuleLength
|
216
|
+
end
|
217
|
+
end
|
@@ -0,0 +1,101 @@
|
|
1
|
+
# frozen_string_literal: true
|
2
|
+
|
3
|
+
module TerminalShop
|
4
|
+
module Type
|
5
|
+
# @api private
|
6
|
+
#
|
7
|
+
# A value from among a specified list of options. OpenAPI enum values map to Ruby
|
8
|
+
# values in the SDK as follows:
|
9
|
+
#
|
10
|
+
# 1. boolean => true | false
|
11
|
+
# 2. integer => Integer
|
12
|
+
# 3. float => Float
|
13
|
+
# 4. string => Symbol
|
14
|
+
#
|
15
|
+
# We can therefore convert string values to Symbols, but can't convert other
|
16
|
+
# values safely.
|
17
|
+
#
|
18
|
+
# @example
|
19
|
+
# # `region` is a `TerminalShop::Models::Region`
|
20
|
+
# case region
|
21
|
+
# when TerminalShop::Models::Region::EU
|
22
|
+
# # ...
|
23
|
+
# when TerminalShop::Models::Region::NA
|
24
|
+
# # ...
|
25
|
+
# else
|
26
|
+
# puts(region)
|
27
|
+
# end
|
28
|
+
#
|
29
|
+
# @example
|
30
|
+
# case region
|
31
|
+
# in :eu
|
32
|
+
# # ...
|
33
|
+
# in :na
|
34
|
+
# # ...
|
35
|
+
# else
|
36
|
+
# puts(region)
|
37
|
+
# end
|
38
|
+
module Enum
|
39
|
+
include TerminalShop::Type::Converter
|
40
|
+
|
41
|
+
# All of the valid Symbol values for this enum.
|
42
|
+
#
|
43
|
+
# @return [Array<NilClass, Boolean, Integer, Float, Symbol>]
|
44
|
+
def values = (@values ||= constants.map { const_get(_1) })
|
45
|
+
|
46
|
+
# @api private
|
47
|
+
#
|
48
|
+
# Guard against thread safety issues by instantiating `@values`.
|
49
|
+
private def finalize! = values
|
50
|
+
|
51
|
+
# @param other [Object]
|
52
|
+
#
|
53
|
+
# @return [Boolean]
|
54
|
+
def ===(other) = values.include?(other)
|
55
|
+
|
56
|
+
# @param other [Object]
|
57
|
+
#
|
58
|
+
# @return [Boolean]
|
59
|
+
def ==(other)
|
60
|
+
other.is_a?(Module) && other.singleton_class <= TerminalShop::Enum && other.values.to_set == values.to_set
|
61
|
+
end
|
62
|
+
|
63
|
+
# @api private
|
64
|
+
#
|
65
|
+
# Unlike with primitives, `Enum` additionally validates that the value is a member
|
66
|
+
# of the enum.
|
67
|
+
#
|
68
|
+
# @param value [String, Symbol, Object]
|
69
|
+
#
|
70
|
+
# @param state [Hash{Symbol=>Object}] .
|
71
|
+
#
|
72
|
+
# @option state [Boolean, :strong] :strictness
|
73
|
+
#
|
74
|
+
# @option state [Hash{Symbol=>Object}] :exactness
|
75
|
+
#
|
76
|
+
# @option state [Integer] :branched
|
77
|
+
#
|
78
|
+
# @return [Symbol, Object]
|
79
|
+
def coerce(value, state:)
|
80
|
+
exactness = state.fetch(:exactness)
|
81
|
+
val = value.is_a?(String) ? value.to_sym : value
|
82
|
+
|
83
|
+
if values.include?(val)
|
84
|
+
exactness[:yes] += 1
|
85
|
+
val
|
86
|
+
else
|
87
|
+
exactness[values.first&.class == val.class ? :maybe : :no] += 1
|
88
|
+
value
|
89
|
+
end
|
90
|
+
end
|
91
|
+
|
92
|
+
# @!parse
|
93
|
+
# # @api private
|
94
|
+
# #
|
95
|
+
# # @param value [Symbol, Object]
|
96
|
+
# #
|
97
|
+
# # @return [Symbol, Object]
|
98
|
+
# def dump(value) = super
|
99
|
+
end
|
100
|
+
end
|
101
|
+
end
|
@@ -0,0 +1,136 @@
|
|
1
|
+
# frozen_string_literal: true
|
2
|
+
|
3
|
+
module TerminalShop
|
4
|
+
module Type
|
5
|
+
# @api private
|
6
|
+
#
|
7
|
+
# @abstract
|
8
|
+
#
|
9
|
+
# Hash of items of a given type.
|
10
|
+
class HashOf
|
11
|
+
include TerminalShop::Type::Converter
|
12
|
+
|
13
|
+
# @param type_info [Hash{Symbol=>Object}, Proc, TerminalShop::Type::Converter, Class]
|
14
|
+
#
|
15
|
+
# @param spec [Hash{Symbol=>Object}] .
|
16
|
+
#
|
17
|
+
# @option spec [NilClass, TrueClass, FalseClass, Integer, Float, Symbol] :const
|
18
|
+
#
|
19
|
+
# @option spec [Proc] :enum
|
20
|
+
#
|
21
|
+
# @option spec [Proc] :union
|
22
|
+
#
|
23
|
+
# @option spec [Boolean] :"nil?"
|
24
|
+
def self.[](type_info, spec = {}) = new(type_info, spec)
|
25
|
+
|
26
|
+
# @param other [Object]
|
27
|
+
#
|
28
|
+
# @return [Boolean]
|
29
|
+
def ===(other)
|
30
|
+
type = item_type
|
31
|
+
case other
|
32
|
+
in Hash
|
33
|
+
other.all? do |key, val|
|
34
|
+
case [key, val]
|
35
|
+
in [Symbol | String, ^type]
|
36
|
+
true
|
37
|
+
else
|
38
|
+
false
|
39
|
+
end
|
40
|
+
end
|
41
|
+
else
|
42
|
+
false
|
43
|
+
end
|
44
|
+
end
|
45
|
+
|
46
|
+
# @param other [Object]
|
47
|
+
#
|
48
|
+
# @return [Boolean]
|
49
|
+
def ==(other) = other.is_a?(TerminalShop::HashOf) && other.nilable? == nilable? && other.item_type == item_type
|
50
|
+
|
51
|
+
# @api private
|
52
|
+
#
|
53
|
+
# @param value [Hash{Object=>Object}, Object]
|
54
|
+
#
|
55
|
+
# @param state [Hash{Symbol=>Object}] .
|
56
|
+
#
|
57
|
+
# @option state [Boolean, :strong] :strictness
|
58
|
+
#
|
59
|
+
# @option state [Hash{Symbol=>Object}] :exactness
|
60
|
+
#
|
61
|
+
# @option state [Integer] :branched
|
62
|
+
#
|
63
|
+
# @return [Hash{Symbol=>Object}, Object]
|
64
|
+
def coerce(value, state:)
|
65
|
+
exactness = state.fetch(:exactness)
|
66
|
+
|
67
|
+
unless value.is_a?(Hash)
|
68
|
+
exactness[:no] += 1
|
69
|
+
return value
|
70
|
+
end
|
71
|
+
|
72
|
+
target = item_type
|
73
|
+
exactness[:yes] += 1
|
74
|
+
value
|
75
|
+
.to_h do |key, val|
|
76
|
+
k = key.is_a?(String) ? key.to_sym : key
|
77
|
+
v =
|
78
|
+
case [nilable?, val]
|
79
|
+
in [true, nil]
|
80
|
+
exactness[:yes] += 1
|
81
|
+
nil
|
82
|
+
else
|
83
|
+
TerminalShop::Type::Converter.coerce(target, val, state: state)
|
84
|
+
end
|
85
|
+
|
86
|
+
exactness[:no] += 1 unless k.is_a?(Symbol)
|
87
|
+
[k, v]
|
88
|
+
end
|
89
|
+
end
|
90
|
+
|
91
|
+
# @api private
|
92
|
+
#
|
93
|
+
# @param value [Hash{Object=>Object}, Object]
|
94
|
+
#
|
95
|
+
# @return [Hash{Symbol=>Object}, Object]
|
96
|
+
def dump(value)
|
97
|
+
target = item_type
|
98
|
+
if value.is_a?(Hash)
|
99
|
+
value.transform_values do
|
100
|
+
TerminalShop::Type::Converter.dump(target, _1)
|
101
|
+
end
|
102
|
+
else
|
103
|
+
super
|
104
|
+
end
|
105
|
+
end
|
106
|
+
|
107
|
+
# @api private
|
108
|
+
#
|
109
|
+
# @return [TerminalShop::Type::Converter, Class]
|
110
|
+
protected def item_type = @item_type_fn.call
|
111
|
+
|
112
|
+
# @api private
|
113
|
+
#
|
114
|
+
# @return [Boolean]
|
115
|
+
protected def nilable? = @nilable
|
116
|
+
|
117
|
+
# @api private
|
118
|
+
#
|
119
|
+
# @param type_info [Hash{Symbol=>Object}, Proc, TerminalShop::Type::Converter, Class]
|
120
|
+
#
|
121
|
+
# @param spec [Hash{Symbol=>Object}] .
|
122
|
+
#
|
123
|
+
# @option spec [NilClass, TrueClass, FalseClass, Integer, Float, Symbol] :const
|
124
|
+
#
|
125
|
+
# @option spec [Proc] :enum
|
126
|
+
#
|
127
|
+
# @option spec [Proc] :union
|
128
|
+
#
|
129
|
+
# @option spec [Boolean] :"nil?"
|
130
|
+
def initialize(type_info, spec = {})
|
131
|
+
@item_type_fn = TerminalShop::Type::Converter.type_info(type_info || spec)
|
132
|
+
@nilable = spec[:nil?]
|
133
|
+
end
|
134
|
+
end
|
135
|
+
end
|
136
|
+
end
|
@@ -0,0 +1,38 @@
|
|
1
|
+
# frozen_string_literal: true
|
2
|
+
|
3
|
+
module TerminalShop
|
4
|
+
module Type
|
5
|
+
# @api private
|
6
|
+
module RequestParameters
|
7
|
+
# @!parse
|
8
|
+
# # Options to specify HTTP behaviour for this request.
|
9
|
+
# # @return [TerminalShop::RequestOptions, Hash{Symbol=>Object}]
|
10
|
+
# attr_accessor :request_options
|
11
|
+
|
12
|
+
# @param mod [Module]
|
13
|
+
def self.included(mod)
|
14
|
+
return unless mod <= TerminalShop::BaseModel
|
15
|
+
|
16
|
+
mod.extend(TerminalShop::Type::RequestParameters::Converter)
|
17
|
+
mod.optional(:request_options, TerminalShop::RequestOptions)
|
18
|
+
end
|
19
|
+
|
20
|
+
# @api private
|
21
|
+
module Converter
|
22
|
+
# @api private
|
23
|
+
#
|
24
|
+
# @param params [Object]
|
25
|
+
#
|
26
|
+
# @return [Array(Object, Hash{Symbol=>Object})]
|
27
|
+
def dump_request(params)
|
28
|
+
case (dumped = dump(params))
|
29
|
+
in Hash
|
30
|
+
[dumped.except(:request_options), dumped[:request_options]]
|
31
|
+
else
|
32
|
+
[dumped, nil]
|
33
|
+
end
|
34
|
+
end
|
35
|
+
end
|
36
|
+
end
|
37
|
+
end
|
38
|
+
end
|
@@ -0,0 +1,183 @@
|
|
1
|
+
# frozen_string_literal: true
|
2
|
+
|
3
|
+
module TerminalShop
|
4
|
+
module Type
|
5
|
+
# @api private
|
6
|
+
module Union
|
7
|
+
include TerminalShop::Type::Converter
|
8
|
+
|
9
|
+
# @api private
|
10
|
+
#
|
11
|
+
# All of the specified variant info for this union.
|
12
|
+
#
|
13
|
+
# @return [Array<Array(Symbol, Proc)>]
|
14
|
+
private def known_variants = (@known_variants ||= [])
|
15
|
+
|
16
|
+
# @api private
|
17
|
+
#
|
18
|
+
# @return [Array<Array(Symbol, Object)>]
|
19
|
+
protected def derefed_variants
|
20
|
+
@known_variants.map { |key, variant_fn| [key, variant_fn.call] }
|
21
|
+
end
|
22
|
+
|
23
|
+
# All of the specified variants for this union.
|
24
|
+
#
|
25
|
+
# @return [Array<Object>]
|
26
|
+
def variants = derefed_variants.map(&:last)
|
27
|
+
|
28
|
+
# @api private
|
29
|
+
#
|
30
|
+
# @param property [Symbol]
|
31
|
+
private def discriminator(property)
|
32
|
+
case property
|
33
|
+
in Symbol
|
34
|
+
@discriminator = property
|
35
|
+
end
|
36
|
+
end
|
37
|
+
|
38
|
+
# @api private
|
39
|
+
#
|
40
|
+
# @param key [Symbol, Hash{Symbol=>Object}, Proc, TerminalShop::Type::Converter, Class]
|
41
|
+
#
|
42
|
+
# @param spec [Hash{Symbol=>Object}, Proc, TerminalShop::Type::Converter, Class] .
|
43
|
+
#
|
44
|
+
# @option spec [NilClass, TrueClass, FalseClass, Integer, Float, Symbol] :const
|
45
|
+
#
|
46
|
+
# @option spec [Proc] :enum
|
47
|
+
#
|
48
|
+
# @option spec [Proc] :union
|
49
|
+
#
|
50
|
+
# @option spec [Boolean] :"nil?"
|
51
|
+
private def variant(key, spec = nil)
|
52
|
+
variant_info =
|
53
|
+
case key
|
54
|
+
in Symbol
|
55
|
+
[key, TerminalShop::Type::Converter.type_info(spec)]
|
56
|
+
in Proc | TerminalShop::Type::Converter | Class | Hash
|
57
|
+
[nil, TerminalShop::Type::Converter.type_info(key)]
|
58
|
+
end
|
59
|
+
|
60
|
+
known_variants << variant_info
|
61
|
+
end
|
62
|
+
|
63
|
+
# @api private
|
64
|
+
#
|
65
|
+
# @param value [Object]
|
66
|
+
#
|
67
|
+
# @return [TerminalShop::Type::Converter, Class, nil]
|
68
|
+
private def resolve_variant(value)
|
69
|
+
case [@discriminator, value]
|
70
|
+
in [_, TerminalShop::BaseModel]
|
71
|
+
value.class
|
72
|
+
in [Symbol, Hash]
|
73
|
+
key = value.fetch(@discriminator) do
|
74
|
+
value.fetch(@discriminator.to_s, TerminalShop::Util::OMIT)
|
75
|
+
end
|
76
|
+
|
77
|
+
return nil if key == TerminalShop::Util::OMIT
|
78
|
+
|
79
|
+
key = key.to_sym if key.is_a?(String)
|
80
|
+
known_variants.find { |k,| k == key }&.last&.call
|
81
|
+
else
|
82
|
+
nil
|
83
|
+
end
|
84
|
+
end
|
85
|
+
|
86
|
+
# rubocop:disable Style/HashEachMethods
|
87
|
+
# rubocop:disable Style/CaseEquality
|
88
|
+
|
89
|
+
# @param other [Object]
|
90
|
+
#
|
91
|
+
# @return [Boolean]
|
92
|
+
def ===(other)
|
93
|
+
known_variants.any? do |_, variant_fn|
|
94
|
+
variant_fn.call === other
|
95
|
+
end
|
96
|
+
end
|
97
|
+
|
98
|
+
# @param other [Object]
|
99
|
+
#
|
100
|
+
# @return [Boolean]
|
101
|
+
def ==(other)
|
102
|
+
other.is_a?(Module) && other.singleton_class <= TerminalShop::Union && other.derefed_variants == derefed_variants
|
103
|
+
end
|
104
|
+
|
105
|
+
# @api private
|
106
|
+
#
|
107
|
+
# @param value [Object]
|
108
|
+
#
|
109
|
+
# @param state [Hash{Symbol=>Object}] .
|
110
|
+
#
|
111
|
+
# @option state [Boolean, :strong] :strictness
|
112
|
+
#
|
113
|
+
# @option state [Hash{Symbol=>Object}] :exactness
|
114
|
+
#
|
115
|
+
# @option state [Integer] :branched
|
116
|
+
#
|
117
|
+
# @return [Object]
|
118
|
+
def coerce(value, state:)
|
119
|
+
if (target = resolve_variant(value))
|
120
|
+
return TerminalShop::Type::Converter.coerce(target, value, state: state)
|
121
|
+
end
|
122
|
+
|
123
|
+
strictness = state.fetch(:strictness)
|
124
|
+
exactness = state.fetch(:exactness)
|
125
|
+
state[:strictness] = strictness == :strong ? true : strictness
|
126
|
+
|
127
|
+
alternatives = []
|
128
|
+
known_variants.each do |_, variant_fn|
|
129
|
+
target = variant_fn.call
|
130
|
+
exact = state[:exactness] = {yes: 0, no: 0, maybe: 0}
|
131
|
+
state[:branched] += 1
|
132
|
+
|
133
|
+
coerced = TerminalShop::Type::Converter.coerce(target, value, state: state)
|
134
|
+
yes, no, maybe = exact.values
|
135
|
+
if (no + maybe).zero? || (!strictness && yes.positive?)
|
136
|
+
exact.each { exactness[_1] += _2 }
|
137
|
+
state[:exactness] = exactness
|
138
|
+
return coerced
|
139
|
+
elsif maybe.positive?
|
140
|
+
alternatives << [[-yes, -maybe, no], exact, coerced]
|
141
|
+
end
|
142
|
+
end
|
143
|
+
|
144
|
+
case alternatives.sort_by(&:first)
|
145
|
+
in []
|
146
|
+
exactness[:no] += 1
|
147
|
+
if strictness == :strong
|
148
|
+
message = "no possible conversion of #{value.class} into a variant of #{target.inspect}"
|
149
|
+
raise ArgumentError.new(message)
|
150
|
+
end
|
151
|
+
value
|
152
|
+
in [[_, exact, coerced], *]
|
153
|
+
exact.each { exactness[_1] += _2 }
|
154
|
+
coerced
|
155
|
+
end
|
156
|
+
.tap { state[:exactness] = exactness }
|
157
|
+
ensure
|
158
|
+
state[:strictness] = strictness
|
159
|
+
end
|
160
|
+
|
161
|
+
# @api private
|
162
|
+
#
|
163
|
+
# @param value [Object]
|
164
|
+
#
|
165
|
+
# @return [Object]
|
166
|
+
def dump(value)
|
167
|
+
if (target = resolve_variant(value))
|
168
|
+
return TerminalShop::Type::Converter.dump(target, value)
|
169
|
+
end
|
170
|
+
|
171
|
+
known_variants.each do
|
172
|
+
target = _2.call
|
173
|
+
return TerminalShop::Type::Converter.dump(target, value) if target === value
|
174
|
+
end
|
175
|
+
|
176
|
+
super
|
177
|
+
end
|
178
|
+
|
179
|
+
# rubocop:enable Style/CaseEquality
|
180
|
+
# rubocop:enable Style/HashEachMethods
|
181
|
+
end
|
182
|
+
end
|
183
|
+
end
|