terminal-shop 1.0.0 → 1.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 +27 -19
- data/lib/terminal-shop/base_model.rb +448 -438
- data/lib/terminal-shop/models/cart.rb +35 -2
- data/lib/terminal-shop/models/cart_convert_params.rb +11 -1
- data/lib/terminal-shop/models/cart_redeem_gift_card_params.rb +24 -0
- data/lib/terminal-shop/models/cart_redeem_gift_card_response.rb +48 -0
- data/lib/terminal-shop/models/cart_remove_gift_card_params.rb +18 -0
- data/lib/terminal-shop/models/cart_remove_gift_card_response.rb +19 -0
- data/lib/terminal-shop/models/product.rb +11 -6
- data/lib/terminal-shop/resources/cart.rb +43 -1
- data/lib/terminal-shop/util.rb +3 -3
- data/lib/terminal-shop/version.rb +1 -1
- data/lib/terminal-shop.rb +4 -0
- data/rbi/lib/terminal-shop/base_client.rbi +23 -21
- data/rbi/lib/terminal-shop/base_model.rbi +235 -217
- data/rbi/lib/terminal-shop/client.rbi +2 -2
- data/rbi/lib/terminal-shop/errors.rbi +8 -8
- data/rbi/lib/terminal-shop/models/address.rbi +2 -2
- data/rbi/lib/terminal-shop/models/address_create_params.rbi +3 -13
- data/rbi/lib/terminal-shop/models/address_create_response.rbi +2 -2
- data/rbi/lib/terminal-shop/models/address_delete_params.rbi +5 -2
- data/rbi/lib/terminal-shop/models/address_delete_response.rbi +2 -2
- data/rbi/lib/terminal-shop/models/address_get_params.rbi +5 -2
- data/rbi/lib/terminal-shop/models/address_get_response.rbi +2 -2
- data/rbi/lib/terminal-shop/models/address_list_params.rbi +5 -2
- data/rbi/lib/terminal-shop/models/address_list_response.rbi +2 -2
- data/rbi/lib/terminal-shop/models/app.rbi +2 -2
- data/rbi/lib/terminal-shop/models/app_create_params.rbi +2 -2
- data/rbi/lib/terminal-shop/models/app_create_response.rbi +4 -4
- data/rbi/lib/terminal-shop/models/app_delete_params.rbi +5 -2
- data/rbi/lib/terminal-shop/models/app_delete_response.rbi +2 -2
- data/rbi/lib/terminal-shop/models/app_get_params.rbi +5 -2
- data/rbi/lib/terminal-shop/models/app_get_response.rbi +2 -2
- data/rbi/lib/terminal-shop/models/app_list_params.rbi +5 -2
- data/rbi/lib/terminal-shop/models/app_list_response.rbi +2 -2
- data/rbi/lib/terminal-shop/models/card.rbi +4 -4
- data/rbi/lib/terminal-shop/models/card_collect_params.rbi +5 -2
- data/rbi/lib/terminal-shop/models/card_collect_response.rbi +4 -4
- data/rbi/lib/terminal-shop/models/card_create_params.rbi +2 -2
- data/rbi/lib/terminal-shop/models/card_create_response.rbi +2 -2
- data/rbi/lib/terminal-shop/models/card_delete_params.rbi +5 -2
- data/rbi/lib/terminal-shop/models/card_delete_response.rbi +2 -2
- data/rbi/lib/terminal-shop/models/card_get_params.rbi +5 -2
- data/rbi/lib/terminal-shop/models/card_get_response.rbi +2 -2
- data/rbi/lib/terminal-shop/models/card_list_params.rbi +5 -2
- data/rbi/lib/terminal-shop/models/card_list_response.rbi +2 -2
- data/rbi/lib/terminal-shop/models/cart.rbi +45 -9
- data/rbi/lib/terminal-shop/models/cart_convert_params.rbi +17 -3
- data/rbi/lib/terminal-shop/models/cart_convert_response.rbi +2 -2
- data/rbi/lib/terminal-shop/models/cart_get_params.rbi +5 -2
- data/rbi/lib/terminal-shop/models/cart_get_response.rbi +2 -2
- data/rbi/lib/terminal-shop/models/cart_redeem_gift_card_params.rbi +32 -0
- data/rbi/lib/terminal-shop/models/cart_redeem_gift_card_response.rbi +66 -0
- data/rbi/lib/terminal-shop/models/cart_remove_gift_card_params.rbi +21 -0
- data/rbi/lib/terminal-shop/models/cart_remove_gift_card_response.rbi +23 -0
- data/rbi/lib/terminal-shop/models/cart_set_address_params.rbi +2 -2
- data/rbi/lib/terminal-shop/models/cart_set_address_response.rbi +2 -2
- data/rbi/lib/terminal-shop/models/cart_set_card_params.rbi +2 -2
- data/rbi/lib/terminal-shop/models/cart_set_card_response.rbi +2 -2
- data/rbi/lib/terminal-shop/models/cart_set_item_params.rbi +2 -2
- data/rbi/lib/terminal-shop/models/cart_set_item_response.rbi +2 -2
- data/rbi/lib/terminal-shop/models/email_create_params.rbi +2 -2
- data/rbi/lib/terminal-shop/models/email_create_response.rbi +2 -2
- data/rbi/lib/terminal-shop/models/order.rbi +10 -10
- data/rbi/lib/terminal-shop/models/order_create_params.rbi +2 -2
- data/rbi/lib/terminal-shop/models/order_create_response.rbi +2 -2
- data/rbi/lib/terminal-shop/models/order_get_params.rbi +5 -2
- data/rbi/lib/terminal-shop/models/order_get_response.rbi +2 -2
- data/rbi/lib/terminal-shop/models/order_list_params.rbi +5 -2
- data/rbi/lib/terminal-shop/models/order_list_response.rbi +2 -2
- data/rbi/lib/terminal-shop/models/product.rbi +29 -14
- data/rbi/lib/terminal-shop/models/product_get_params.rbi +5 -2
- data/rbi/lib/terminal-shop/models/product_get_response.rbi +2 -2
- data/rbi/lib/terminal-shop/models/product_list_params.rbi +5 -2
- data/rbi/lib/terminal-shop/models/product_list_response.rbi +2 -2
- data/rbi/lib/terminal-shop/models/product_variant.rbi +2 -2
- data/rbi/lib/terminal-shop/models/profile.rbi +4 -4
- data/rbi/lib/terminal-shop/models/profile_me_params.rbi +5 -2
- data/rbi/lib/terminal-shop/models/profile_me_response.rbi +2 -2
- data/rbi/lib/terminal-shop/models/profile_update_params.rbi +2 -2
- data/rbi/lib/terminal-shop/models/profile_update_response.rbi +2 -2
- data/rbi/lib/terminal-shop/models/subscription.rbi +15 -13
- data/rbi/lib/terminal-shop/models/subscription_create_params.rbi +5 -2
- data/rbi/lib/terminal-shop/models/subscription_create_response.rbi +2 -2
- data/rbi/lib/terminal-shop/models/subscription_delete_params.rbi +5 -2
- data/rbi/lib/terminal-shop/models/subscription_delete_response.rbi +2 -2
- data/rbi/lib/terminal-shop/models/subscription_get_params.rbi +5 -2
- data/rbi/lib/terminal-shop/models/subscription_get_response.rbi +2 -2
- data/rbi/lib/terminal-shop/models/subscription_list_params.rbi +5 -2
- data/rbi/lib/terminal-shop/models/subscription_list_response.rbi +2 -2
- data/rbi/lib/terminal-shop/models/token.rbi +2 -2
- data/rbi/lib/terminal-shop/models/token_create_params.rbi +5 -2
- data/rbi/lib/terminal-shop/models/token_create_response.rbi +4 -4
- data/rbi/lib/terminal-shop/models/token_delete_params.rbi +5 -2
- data/rbi/lib/terminal-shop/models/token_delete_response.rbi +2 -2
- data/rbi/lib/terminal-shop/models/token_get_params.rbi +5 -2
- data/rbi/lib/terminal-shop/models/token_get_response.rbi +2 -2
- data/rbi/lib/terminal-shop/models/token_list_params.rbi +5 -2
- data/rbi/lib/terminal-shop/models/token_list_response.rbi +2 -2
- data/rbi/lib/terminal-shop/models/view_init_params.rbi +5 -2
- data/rbi/lib/terminal-shop/models/view_init_response.rbi +5 -15
- data/rbi/lib/terminal-shop/pooled_net_requester.rbi +12 -10
- data/rbi/lib/terminal-shop/request_options.rbi +4 -0
- data/rbi/lib/terminal-shop/resources/address.rbi +2 -2
- data/rbi/lib/terminal-shop/resources/app.rbi +2 -2
- data/rbi/lib/terminal-shop/resources/card.rbi +2 -2
- data/rbi/lib/terminal-shop/resources/cart.rbi +24 -4
- data/rbi/lib/terminal-shop/resources/email.rbi +2 -2
- data/rbi/lib/terminal-shop/resources/order.rbi +2 -2
- data/rbi/lib/terminal-shop/resources/product.rbi +2 -2
- data/rbi/lib/terminal-shop/resources/profile.rbi +2 -2
- data/rbi/lib/terminal-shop/resources/subscription.rbi +2 -2
- data/rbi/lib/terminal-shop/resources/token.rbi +2 -2
- data/rbi/lib/terminal-shop/resources/view.rbi +2 -2
- data/rbi/lib/terminal-shop/util.rbi +146 -126
- data/rbi/lib/terminal-shop/version.rbi +1 -1
- data/sig/terminal-shop/models/cart.rbs +27 -2
- data/sig/terminal-shop/models/cart_convert_params.rbs +10 -2
- data/sig/terminal-shop/models/cart_redeem_gift_card_params.rbs +25 -0
- data/sig/terminal-shop/models/cart_redeem_gift_card_response.rbs +47 -0
- data/sig/terminal-shop/models/cart_remove_gift_card_params.rbs +19 -0
- data/sig/terminal-shop/models/cart_remove_gift_card_response.rbs +18 -0
- data/sig/terminal-shop/models/product.rbs +8 -2
- data/sig/terminal-shop/request_options.rbs +4 -0
- data/sig/terminal-shop/resources/cart.rbs +20 -0
- data/sig/terminal-shop/version.rbs +1 -1
- metadata +14 -2
@@ -155,7 +155,7 @@ module TerminalShop
|
|
155
155
|
in [-> { _1 <= Date || _1 <= Time }, String]
|
156
156
|
Kernel.then do
|
157
157
|
[true, target.parse(value), 1]
|
158
|
-
rescue ArgumentError
|
158
|
+
rescue ArgumentError
|
159
159
|
[false, false, 0]
|
160
160
|
end
|
161
161
|
in [_, ^target]
|
@@ -192,33 +192,35 @@ module TerminalShop
|
|
192
192
|
#
|
193
193
|
def self.==(other) = other.is_a?(Class) && other <= TerminalShop::Unknown
|
194
194
|
|
195
|
-
|
196
|
-
|
197
|
-
|
198
|
-
|
199
|
-
|
200
|
-
|
201
|
-
|
202
|
-
|
203
|
-
|
204
|
-
|
205
|
-
|
206
|
-
|
207
|
-
|
208
|
-
|
209
|
-
|
210
|
-
|
211
|
-
|
195
|
+
class << self
|
196
|
+
# @!parse
|
197
|
+
# # @private
|
198
|
+
# #
|
199
|
+
# # @param value [Object]
|
200
|
+
# #
|
201
|
+
# # @return [Object]
|
202
|
+
# #
|
203
|
+
# def coerce(value) = super
|
204
|
+
|
205
|
+
# @!parse
|
206
|
+
# # @private
|
207
|
+
# #
|
208
|
+
# # @param value [Object]
|
209
|
+
# #
|
210
|
+
# # @return [Object]
|
211
|
+
# #
|
212
|
+
# def dump(value) = super
|
212
213
|
|
213
|
-
|
214
|
-
|
215
|
-
|
216
|
-
|
217
|
-
|
218
|
-
|
219
|
-
|
220
|
-
|
221
|
-
|
214
|
+
# @private
|
215
|
+
#
|
216
|
+
# @param value [Object]
|
217
|
+
#
|
218
|
+
# @return [Array(true, Object, nil), Array(false, Boolean, Integer)]
|
219
|
+
#
|
220
|
+
def try_strict_coerce(value)
|
221
|
+
# prevent unknown variant from being chosen during the first coercion pass
|
222
|
+
[false, true, 0]
|
223
|
+
end
|
222
224
|
end
|
223
225
|
|
224
226
|
# rubocop:enable Lint/UnusedMethodArgument
|
@@ -246,36 +248,38 @@ module TerminalShop
|
|
246
248
|
#
|
247
249
|
def self.==(other) = other.is_a?(Class) && other <= TerminalShop::BooleanModel
|
248
250
|
|
249
|
-
|
250
|
-
|
251
|
-
|
252
|
-
|
253
|
-
|
254
|
-
|
255
|
-
|
256
|
-
|
257
|
-
|
258
|
-
|
259
|
-
|
260
|
-
|
261
|
-
|
262
|
-
|
263
|
-
|
264
|
-
|
265
|
-
|
251
|
+
class << self
|
252
|
+
# @!parse
|
253
|
+
# # @private
|
254
|
+
# #
|
255
|
+
# # @param value [Boolean, Object]
|
256
|
+
# #
|
257
|
+
# # @return [Boolean, Object]
|
258
|
+
# #
|
259
|
+
# def coerce(value) = super
|
260
|
+
|
261
|
+
# @!parse
|
262
|
+
# # @private
|
263
|
+
# #
|
264
|
+
# # @param value [Boolean, Object]
|
265
|
+
# #
|
266
|
+
# # @return [Boolean, Object]
|
267
|
+
# #
|
268
|
+
# def dump(value) = super
|
266
269
|
|
267
|
-
|
268
|
-
|
269
|
-
|
270
|
-
|
271
|
-
|
272
|
-
|
273
|
-
|
274
|
-
|
275
|
-
|
276
|
-
|
277
|
-
|
278
|
-
|
270
|
+
# @private
|
271
|
+
#
|
272
|
+
# @param value [Object]
|
273
|
+
#
|
274
|
+
# @return [Array(true, Object, nil), Array(false, Boolean, Integer)]
|
275
|
+
#
|
276
|
+
def try_strict_coerce(value)
|
277
|
+
case value
|
278
|
+
in true | false
|
279
|
+
[true, value, 1]
|
280
|
+
else
|
281
|
+
[false, false, 0]
|
282
|
+
end
|
279
283
|
end
|
280
284
|
end
|
281
285
|
end
|
@@ -297,17 +301,19 @@ module TerminalShop
|
|
297
301
|
class Enum
|
298
302
|
extend TerminalShop::Converter
|
299
303
|
|
300
|
-
|
301
|
-
|
302
|
-
|
303
|
-
|
304
|
-
|
304
|
+
class << self
|
305
|
+
# All of the valid Symbol values for this enum.
|
306
|
+
#
|
307
|
+
# @return [Array<NilClass, Boolean, Integer, Float, Symbol>]
|
308
|
+
#
|
309
|
+
def values = (@values ||= constants.map { const_get(_1) })
|
305
310
|
|
306
|
-
|
307
|
-
|
308
|
-
|
309
|
-
|
310
|
-
|
311
|
+
# @private
|
312
|
+
#
|
313
|
+
# Guard against thread safety issues by instantiating `@values`.
|
314
|
+
#
|
315
|
+
private def finalize! = values
|
316
|
+
end
|
311
317
|
|
312
318
|
private_class_method :new
|
313
319
|
|
@@ -325,41 +331,43 @@ module TerminalShop
|
|
325
331
|
other.is_a?(Class) && other <= TerminalShop::Enum && other.values.to_set == values.to_set
|
326
332
|
end
|
327
333
|
|
328
|
-
|
329
|
-
|
330
|
-
|
331
|
-
|
332
|
-
|
333
|
-
|
334
|
-
|
334
|
+
class << self
|
335
|
+
# @private
|
336
|
+
#
|
337
|
+
# @param value [String, Symbol, Object]
|
338
|
+
#
|
339
|
+
# @return [Symbol, Object]
|
340
|
+
#
|
341
|
+
def coerce(value) = (value.is_a?(String) ? value.to_sym : value)
|
335
342
|
|
336
|
-
|
337
|
-
|
338
|
-
|
339
|
-
|
340
|
-
|
341
|
-
|
342
|
-
|
343
|
-
|
343
|
+
# @!parse
|
344
|
+
# # @private
|
345
|
+
# #
|
346
|
+
# # @param value [Symbol, Object]
|
347
|
+
# #
|
348
|
+
# # @return [Symbol, Object]
|
349
|
+
# #
|
350
|
+
# def dump(value) = super
|
344
351
|
|
345
|
-
|
346
|
-
|
347
|
-
|
348
|
-
|
349
|
-
|
350
|
-
|
351
|
-
|
352
|
-
|
352
|
+
# @private
|
353
|
+
#
|
354
|
+
# @param value [Object]
|
355
|
+
#
|
356
|
+
# @return [Array(true, Object, nil), Array(false, Boolean, Integer)]
|
357
|
+
#
|
358
|
+
def try_strict_coerce(value)
|
359
|
+
return [true, value, 1] if values.include?(value)
|
353
360
|
|
354
|
-
|
355
|
-
|
356
|
-
|
357
|
-
else
|
358
|
-
case [value, values.first]
|
359
|
-
in [true | false, true | false] | [Integer, Integer] | [Symbol | String, Symbol]
|
360
|
-
[false, true, 0]
|
361
|
+
case value
|
362
|
+
in String if values.include?(val = value.to_sym)
|
363
|
+
[true, val, 1]
|
361
364
|
else
|
362
|
-
[
|
365
|
+
case [value, values.first]
|
366
|
+
in [true | false, true | false] | [Integer, Integer] | [Symbol | String, Symbol]
|
367
|
+
[false, true, 0]
|
368
|
+
else
|
369
|
+
[false, false, 0]
|
370
|
+
end
|
363
371
|
end
|
364
372
|
end
|
365
373
|
end
|
@@ -372,15 +380,15 @@ module TerminalShop
|
|
372
380
|
class Union
|
373
381
|
extend TerminalShop::Converter
|
374
382
|
|
375
|
-
# @private
|
376
|
-
#
|
377
|
-
# All of the specified variant info for this union.
|
378
|
-
#
|
379
|
-
# @return [Array<Array(Symbol, Proc)>]
|
380
|
-
#
|
381
|
-
private_class_method def self.known_variants = (@known_variants ||= [])
|
382
|
-
|
383
383
|
class << self
|
384
|
+
# @private
|
385
|
+
#
|
386
|
+
# All of the specified variant info for this union.
|
387
|
+
#
|
388
|
+
# @return [Array<Array(Symbol, Proc)>]
|
389
|
+
#
|
390
|
+
private def known_variants = (@known_variants ||= [])
|
391
|
+
|
384
392
|
# @private
|
385
393
|
#
|
386
394
|
# All of the specified variants for this union.
|
@@ -390,68 +398,68 @@ module TerminalShop
|
|
390
398
|
protected def variants
|
391
399
|
@known_variants.map { |key, variant_fn| [key, variant_fn.call] }
|
392
400
|
end
|
393
|
-
end
|
394
401
|
|
395
|
-
|
396
|
-
|
397
|
-
|
398
|
-
|
399
|
-
|
400
|
-
|
401
|
-
in Symbol
|
402
|
-
@discriminator = property
|
403
|
-
end
|
404
|
-
end
|
405
|
-
|
406
|
-
# @private
|
407
|
-
#
|
408
|
-
# @param key [Symbol, Hash{Symbol=>Object}, Proc, TerminalShop::Converter, Class]
|
409
|
-
#
|
410
|
-
# @param spec [Hash{Symbol=>Object}, Proc, TerminalShop::Converter, Class] .
|
411
|
-
#
|
412
|
-
# @option spec [NilClass, TrueClass, FalseClass, Integer, Float, Symbol] :const
|
413
|
-
#
|
414
|
-
# @option spec [Proc] :enum
|
415
|
-
#
|
416
|
-
# @option spec [Proc] :union
|
417
|
-
#
|
418
|
-
# @option spec [Boolean] :"nil?"
|
419
|
-
#
|
420
|
-
private_class_method def self.variant(key, spec = nil)
|
421
|
-
variant_info =
|
422
|
-
case key
|
402
|
+
# @private
|
403
|
+
#
|
404
|
+
# @param property [Symbol]
|
405
|
+
#
|
406
|
+
private def discriminator(property)
|
407
|
+
case property
|
423
408
|
in Symbol
|
424
|
-
|
425
|
-
in Proc | TerminalShop::Converter | Class | Hash
|
426
|
-
[nil, TerminalShop::Converter.type_info(key)]
|
409
|
+
@discriminator = property
|
427
410
|
end
|
411
|
+
end
|
428
412
|
|
429
|
-
|
430
|
-
|
431
|
-
|
432
|
-
|
433
|
-
|
434
|
-
|
435
|
-
|
436
|
-
|
437
|
-
|
438
|
-
|
439
|
-
|
440
|
-
|
441
|
-
|
442
|
-
|
443
|
-
|
444
|
-
|
445
|
-
|
446
|
-
|
447
|
-
|
413
|
+
# @private
|
414
|
+
#
|
415
|
+
# @param key [Symbol, Hash{Symbol=>Object}, Proc, TerminalShop::Converter, Class]
|
416
|
+
#
|
417
|
+
# @param spec [Hash{Symbol=>Object}, Proc, TerminalShop::Converter, Class] .
|
418
|
+
#
|
419
|
+
# @option spec [NilClass, TrueClass, FalseClass, Integer, Float, Symbol] :const
|
420
|
+
#
|
421
|
+
# @option spec [Proc] :enum
|
422
|
+
#
|
423
|
+
# @option spec [Proc] :union
|
424
|
+
#
|
425
|
+
# @option spec [Boolean] :"nil?"
|
426
|
+
#
|
427
|
+
private def variant(key, spec = nil)
|
428
|
+
variant_info =
|
429
|
+
case key
|
430
|
+
in Symbol
|
431
|
+
[key, TerminalShop::Converter.type_info(spec)]
|
432
|
+
in Proc | TerminalShop::Converter | Class | Hash
|
433
|
+
[nil, TerminalShop::Converter.type_info(key)]
|
448
434
|
end
|
449
435
|
|
450
|
-
|
451
|
-
|
452
|
-
|
453
|
-
|
454
|
-
|
436
|
+
known_variants << variant_info
|
437
|
+
end
|
438
|
+
|
439
|
+
# @private
|
440
|
+
#
|
441
|
+
# @param value [Object]
|
442
|
+
#
|
443
|
+
# @return [TerminalShop::Converter, Class, nil]
|
444
|
+
#
|
445
|
+
private def resolve_variant(value)
|
446
|
+
case [@discriminator, value]
|
447
|
+
in [_, TerminalShop::BaseModel]
|
448
|
+
value.class
|
449
|
+
in [Symbol, Hash]
|
450
|
+
key =
|
451
|
+
if value.key?(@discriminator)
|
452
|
+
value.fetch(@discriminator)
|
453
|
+
elsif value.key?((discriminator = @discriminator.to_s))
|
454
|
+
value.fetch(discriminator)
|
455
|
+
end
|
456
|
+
|
457
|
+
key = key.to_sym if key.is_a?(String)
|
458
|
+
_, resolved = known_variants.find { |k,| k == key }
|
459
|
+
resolved.nil? ? TerminalShop::Unknown : resolved.call
|
460
|
+
else
|
461
|
+
nil
|
462
|
+
end
|
455
463
|
end
|
456
464
|
end
|
457
465
|
|
@@ -478,87 +486,89 @@ module TerminalShop
|
|
478
486
|
other.is_a?(Class) && other <= TerminalShop::Union && other.variants == variants
|
479
487
|
end
|
480
488
|
|
481
|
-
|
482
|
-
|
483
|
-
|
484
|
-
|
485
|
-
|
486
|
-
|
487
|
-
|
488
|
-
|
489
|
-
|
490
|
-
|
489
|
+
class << self
|
490
|
+
# @private
|
491
|
+
#
|
492
|
+
# @param value [Object]
|
493
|
+
#
|
494
|
+
# @return [Object]
|
495
|
+
#
|
496
|
+
def coerce(value)
|
497
|
+
if (variant = resolve_variant(value))
|
498
|
+
return TerminalShop::Converter.coerce(variant, value)
|
499
|
+
end
|
491
500
|
|
492
|
-
|
501
|
+
matches = []
|
493
502
|
|
494
|
-
|
495
|
-
|
503
|
+
known_variants.each do |_, variant_fn|
|
504
|
+
variant = variant_fn.call
|
496
505
|
|
497
|
-
|
498
|
-
|
499
|
-
|
500
|
-
|
501
|
-
|
502
|
-
|
503
|
-
|
506
|
+
case TerminalShop::Converter.try_strict_coerce(variant, value)
|
507
|
+
in [true, coerced, _]
|
508
|
+
return coerced
|
509
|
+
in [false, true, score]
|
510
|
+
matches << [score, variant]
|
511
|
+
in [false, false, _]
|
512
|
+
nil
|
513
|
+
end
|
504
514
|
end
|
505
|
-
end
|
506
|
-
|
507
|
-
_, variant = matches.sort! { _2.first <=> _1.first }.find { |score,| !score.zero? }
|
508
|
-
variant.nil? ? value : TerminalShop::Converter.coerce(variant, value)
|
509
|
-
end
|
510
515
|
|
511
|
-
|
512
|
-
|
513
|
-
# @param value [Object]
|
514
|
-
#
|
515
|
-
# @return [Object]
|
516
|
-
#
|
517
|
-
def self.dump(value)
|
518
|
-
if (variant = resolve_variant(value))
|
519
|
-
return TerminalShop::Converter.dump(variant, value)
|
516
|
+
_, variant = matches.sort! { _2.first <=> _1.first }.find { |score,| !score.zero? }
|
517
|
+
variant.nil? ? value : TerminalShop::Converter.coerce(variant, value)
|
520
518
|
end
|
521
519
|
|
522
|
-
|
523
|
-
|
524
|
-
|
520
|
+
# @private
|
521
|
+
#
|
522
|
+
# @param value [Object]
|
523
|
+
#
|
524
|
+
# @return [Object]
|
525
|
+
#
|
526
|
+
def dump(value)
|
527
|
+
if (variant = resolve_variant(value))
|
525
528
|
return TerminalShop::Converter.dump(variant, value)
|
526
529
|
end
|
527
|
-
end
|
528
|
-
value
|
529
|
-
end
|
530
530
|
|
531
|
-
|
532
|
-
|
533
|
-
|
534
|
-
|
535
|
-
|
536
|
-
|
537
|
-
|
538
|
-
# TODO(ruby) this will result in super linear decoding behaviour for nested unions
|
539
|
-
# follow up with a decoding context that captures current strictness levels
|
540
|
-
if (variant = resolve_variant(value))
|
541
|
-
return Converter.try_strict_coerce(variant, value)
|
531
|
+
known_variants.each do |_, variant_fn|
|
532
|
+
variant = variant_fn.call
|
533
|
+
if variant === value
|
534
|
+
return TerminalShop::Converter.dump(variant, value)
|
535
|
+
end
|
536
|
+
end
|
537
|
+
value
|
542
538
|
end
|
543
539
|
|
544
|
-
|
545
|
-
|
540
|
+
# @private
|
541
|
+
#
|
542
|
+
# @param value [Object]
|
543
|
+
#
|
544
|
+
# @return [Array(true, Object, nil), Array(false, Boolean, Integer)]
|
545
|
+
#
|
546
|
+
def try_strict_coerce(value)
|
547
|
+
# TODO(ruby) this will result in super linear decoding behaviour for nested unions
|
548
|
+
# follow up with a decoding context that captures current strictness levels
|
549
|
+
if (variant = resolve_variant(value))
|
550
|
+
return Converter.try_strict_coerce(variant, value)
|
551
|
+
end
|
546
552
|
|
547
|
-
|
548
|
-
|
553
|
+
coercible = false
|
554
|
+
max_score = 0
|
549
555
|
|
550
|
-
|
551
|
-
|
552
|
-
|
553
|
-
|
554
|
-
|
555
|
-
|
556
|
-
|
557
|
-
|
556
|
+
known_variants.each do |_, variant_fn|
|
557
|
+
variant = variant_fn.call
|
558
|
+
|
559
|
+
case TerminalShop::Converter.try_strict_coerce(variant, value)
|
560
|
+
in [true, coerced, score]
|
561
|
+
return [true, coerced, score]
|
562
|
+
in [false, true, score]
|
563
|
+
coercible = true
|
564
|
+
max_score = [max_score, score].max
|
565
|
+
in [false, false, _]
|
566
|
+
nil
|
567
|
+
end
|
558
568
|
end
|
559
|
-
end
|
560
569
|
|
561
|
-
|
570
|
+
[false, coercible, max_score]
|
571
|
+
end
|
562
572
|
end
|
563
573
|
|
564
574
|
# rubocop:enable Style/CaseEquality
|
@@ -851,20 +861,18 @@ module TerminalShop
|
|
851
861
|
class BaseModel
|
852
862
|
extend TerminalShop::Converter
|
853
863
|
|
854
|
-
# @private
|
855
|
-
#
|
856
|
-
# Assumes superclass fields are totally defined before fields are accessed /
|
857
|
-
# defined on subclasses.
|
858
|
-
#
|
859
|
-
# @return [Hash{Symbol=>Hash{Symbol=>Object}}]
|
860
|
-
#
|
861
|
-
def self.known_fields
|
862
|
-
@known_fields ||= (self < TerminalShop::BaseModel ? superclass.known_fields.dup : {})
|
863
|
-
end
|
864
|
-
|
865
864
|
class << self
|
866
865
|
# @private
|
867
866
|
#
|
867
|
+
# Assumes superclass fields are totally defined before fields are accessed /
|
868
|
+
# defined on subclasses.
|
869
|
+
#
|
870
|
+
# @return [Hash{Symbol=>Hash{Symbol=>Object}}]
|
871
|
+
#
|
872
|
+
def known_fields
|
873
|
+
@known_fields ||= (self < TerminalShop::BaseModel ? superclass.known_fields.dup : {})
|
874
|
+
end
|
875
|
+
|
868
876
|
# @return [Hash{Symbol=>Hash{Symbol=>Object}}]
|
869
877
|
#
|
870
878
|
def fields
|
@@ -872,135 +880,135 @@ module TerminalShop
|
|
872
880
|
{**field.except(:type_fn), type: field.fetch(:type_fn).call}
|
873
881
|
end
|
874
882
|
end
|
875
|
-
end
|
876
883
|
|
877
|
-
|
878
|
-
|
879
|
-
|
880
|
-
|
881
|
-
|
884
|
+
# @private
|
885
|
+
#
|
886
|
+
# @return [Hash{Symbol=>Proc}]
|
887
|
+
#
|
888
|
+
def defaults = (@defaults ||= {})
|
882
889
|
|
883
|
-
|
884
|
-
|
885
|
-
|
886
|
-
|
887
|
-
|
888
|
-
|
889
|
-
|
890
|
-
|
891
|
-
|
892
|
-
|
893
|
-
|
894
|
-
|
895
|
-
|
896
|
-
|
897
|
-
|
898
|
-
|
899
|
-
|
900
|
-
|
901
|
-
|
902
|
-
|
903
|
-
|
904
|
-
|
905
|
-
|
906
|
-
|
907
|
-
|
908
|
-
|
890
|
+
# @private
|
891
|
+
#
|
892
|
+
# @param name_sym [Symbol]
|
893
|
+
#
|
894
|
+
# @param required [Boolean]
|
895
|
+
#
|
896
|
+
# @param type_info [Hash{Symbol=>Object}, Proc, TerminalShop::Converter, Class]
|
897
|
+
#
|
898
|
+
# @param spec [Hash{Symbol=>Object}] .
|
899
|
+
#
|
900
|
+
# @option spec [NilClass, TrueClass, FalseClass, Integer, Float, Symbol] :const
|
901
|
+
#
|
902
|
+
# @option spec [Proc] :enum
|
903
|
+
#
|
904
|
+
# @option spec [Proc] :union
|
905
|
+
#
|
906
|
+
# @option spec [Boolean] :"nil?"
|
907
|
+
#
|
908
|
+
private def add_field(name_sym, required:, type_info:, spec:)
|
909
|
+
type_fn, info =
|
910
|
+
case type_info
|
911
|
+
in Proc | Class | TerminalShop::Converter
|
912
|
+
[TerminalShop::Converter.type_info({**spec, union: type_info}), spec]
|
913
|
+
in Hash
|
914
|
+
[TerminalShop::Converter.type_info(type_info), type_info]
|
915
|
+
end
|
909
916
|
|
910
|
-
|
911
|
-
|
917
|
+
fallback = info[:const]
|
918
|
+
defaults[name_sym] = fallback if required && !info[:nil?] && info.key?(:const)
|
912
919
|
|
913
|
-
|
914
|
-
|
920
|
+
key = info.fetch(:api_name, name_sym)
|
921
|
+
setter = "#{name_sym}="
|
915
922
|
|
916
|
-
|
917
|
-
|
918
|
-
|
923
|
+
if known_fields.key?(name_sym)
|
924
|
+
[name_sym, setter].each { undef_method(_1) }
|
925
|
+
end
|
919
926
|
|
920
|
-
|
927
|
+
known_fields[name_sym] = {mode: @mode, key: key, required: required, type_fn: type_fn}
|
921
928
|
|
922
|
-
|
923
|
-
|
924
|
-
|
929
|
+
define_method(setter) do |val|
|
930
|
+
@data[key] = val
|
931
|
+
end
|
925
932
|
|
926
|
-
|
927
|
-
|
928
|
-
|
929
|
-
|
930
|
-
|
931
|
-
|
932
|
-
|
933
|
-
|
934
|
-
|
935
|
-
|
933
|
+
define_method(name_sym) do
|
934
|
+
field_type = type_fn.call
|
935
|
+
value = @data.fetch(key) { self.class.defaults[key] }
|
936
|
+
TerminalShop::Converter.coerce(field_type, value)
|
937
|
+
rescue StandardError
|
938
|
+
name = self.class.name.split("::").last
|
939
|
+
raise TerminalShop::ConversionError.new(
|
940
|
+
"Failed to parse #{name}.#{name_sym} as #{field_type.inspect}. " \
|
941
|
+
"To get the unparsed API response, use #{name}[:#{key}]."
|
942
|
+
)
|
943
|
+
end
|
936
944
|
end
|
937
|
-
end
|
938
945
|
|
939
|
-
|
940
|
-
|
941
|
-
|
942
|
-
|
943
|
-
|
944
|
-
|
945
|
-
|
946
|
-
|
947
|
-
|
948
|
-
|
949
|
-
|
950
|
-
|
951
|
-
|
952
|
-
|
953
|
-
|
954
|
-
|
955
|
-
|
956
|
-
|
957
|
-
|
946
|
+
# @private
|
947
|
+
#
|
948
|
+
# @param name_sym [Symbol]
|
949
|
+
#
|
950
|
+
# @param type_info [Hash{Symbol=>Object}, Proc, TerminalShop::Converter, Class]
|
951
|
+
#
|
952
|
+
# @param spec [Hash{Symbol=>Object}] .
|
953
|
+
#
|
954
|
+
# @option spec [NilClass, TrueClass, FalseClass, Integer, Float, Symbol] :const
|
955
|
+
#
|
956
|
+
# @option spec [Proc] :enum
|
957
|
+
#
|
958
|
+
# @option spec [Proc] :union
|
959
|
+
#
|
960
|
+
# @option spec [Boolean] :"nil?"
|
961
|
+
#
|
962
|
+
def required(name_sym, type_info, spec = {})
|
963
|
+
add_field(name_sym, required: true, type_info: type_info, spec: spec)
|
964
|
+
end
|
958
965
|
|
959
|
-
|
960
|
-
|
961
|
-
|
962
|
-
|
963
|
-
|
964
|
-
|
965
|
-
|
966
|
-
|
967
|
-
|
968
|
-
|
969
|
-
|
970
|
-
|
971
|
-
|
972
|
-
|
973
|
-
|
974
|
-
|
975
|
-
|
976
|
-
|
977
|
-
|
966
|
+
# @private
|
967
|
+
#
|
968
|
+
# @param name_sym [Symbol]
|
969
|
+
#
|
970
|
+
# @param type_info [Hash{Symbol=>Object}, Proc, TerminalShop::Converter, Class]
|
971
|
+
#
|
972
|
+
# @param spec [Hash{Symbol=>Object}] .
|
973
|
+
#
|
974
|
+
# @option spec [NilClass, TrueClass, FalseClass, Integer, Float, Symbol] :const
|
975
|
+
#
|
976
|
+
# @option spec [Proc] :enum
|
977
|
+
#
|
978
|
+
# @option spec [Proc] :union
|
979
|
+
#
|
980
|
+
# @option spec [Boolean] :"nil?"
|
981
|
+
#
|
982
|
+
def optional(name_sym, type_info, spec = {})
|
983
|
+
add_field(name_sym, required: false, type_info: type_info, spec: spec)
|
984
|
+
end
|
978
985
|
|
979
|
-
|
980
|
-
|
981
|
-
|
982
|
-
|
983
|
-
|
984
|
-
|
985
|
-
|
986
|
-
|
987
|
-
|
988
|
-
|
989
|
-
|
990
|
-
|
991
|
-
|
986
|
+
# @private
|
987
|
+
#
|
988
|
+
# `request_only` attributes not excluded from `.#coerce` when receiving responses
|
989
|
+
# even if well behaved servers should not send them
|
990
|
+
#
|
991
|
+
# @param blk [Proc]
|
992
|
+
#
|
993
|
+
private def request_only(&blk)
|
994
|
+
@mode = :dump
|
995
|
+
blk.call
|
996
|
+
ensure
|
997
|
+
@mode = nil
|
998
|
+
end
|
992
999
|
|
993
|
-
|
994
|
-
|
995
|
-
|
996
|
-
|
997
|
-
|
998
|
-
|
999
|
-
|
1000
|
-
|
1001
|
-
|
1002
|
-
|
1003
|
-
|
1000
|
+
# @private
|
1001
|
+
#
|
1002
|
+
# `response_only` attributes are omitted from `.#dump` when making requests
|
1003
|
+
#
|
1004
|
+
# @param blk [Proc]
|
1005
|
+
#
|
1006
|
+
private def response_only(&blk)
|
1007
|
+
@mode = :coerce
|
1008
|
+
blk.call
|
1009
|
+
ensure
|
1010
|
+
@mode = nil
|
1011
|
+
end
|
1004
1012
|
end
|
1005
1013
|
|
1006
1014
|
# @param other [Object]
|
@@ -1016,108 +1024,110 @@ module TerminalShop
|
|
1016
1024
|
end
|
1017
1025
|
end
|
1018
1026
|
|
1019
|
-
|
1020
|
-
|
1021
|
-
|
1022
|
-
|
1023
|
-
|
1024
|
-
|
1025
|
-
|
1026
|
-
|
1027
|
-
|
1028
|
-
|
1029
|
-
|
1030
|
-
|
1027
|
+
class << self
|
1028
|
+
# @private
|
1029
|
+
#
|
1030
|
+
# @param value [TerminalShop::BaseModel, Hash{Object=>Object}, Object]
|
1031
|
+
#
|
1032
|
+
# @return [TerminalShop::BaseModel, Object]
|
1033
|
+
#
|
1034
|
+
def coerce(value)
|
1035
|
+
case TerminalShop::Util.coerce_hash(value)
|
1036
|
+
in Hash => coerced
|
1037
|
+
new(coerced)
|
1038
|
+
else
|
1039
|
+
value
|
1040
|
+
end
|
1031
1041
|
end
|
1032
|
-
end
|
1033
1042
|
|
1034
|
-
|
1035
|
-
|
1036
|
-
|
1037
|
-
|
1038
|
-
|
1039
|
-
|
1040
|
-
|
1041
|
-
|
1042
|
-
|
1043
|
-
|
1043
|
+
# @private
|
1044
|
+
#
|
1045
|
+
# @param value [TerminalShop::BaseModel, Object]
|
1046
|
+
#
|
1047
|
+
# @return [Hash{Object=>Object}, Object]
|
1048
|
+
#
|
1049
|
+
def dump(value)
|
1050
|
+
unless (coerced = TerminalShop::Util.coerce_hash(value)).is_a?(Hash)
|
1051
|
+
return value
|
1052
|
+
end
|
1044
1053
|
|
1045
|
-
|
1046
|
-
|
1047
|
-
|
1048
|
-
|
1049
|
-
|
1050
|
-
else
|
1051
|
-
mode, type_fn, api_name = field.fetch_values(:mode, :type_fn, :key)
|
1052
|
-
case mode
|
1053
|
-
in :coerce
|
1054
|
-
next
|
1054
|
+
values = coerced.filter_map do |key, val|
|
1055
|
+
name = key.to_sym
|
1056
|
+
case (field = known_fields[name])
|
1057
|
+
in nil
|
1058
|
+
[name, val]
|
1055
1059
|
else
|
1056
|
-
|
1057
|
-
|
1060
|
+
mode, type_fn, api_name = field.fetch_values(:mode, :type_fn, :key)
|
1061
|
+
case mode
|
1062
|
+
in :coerce
|
1063
|
+
next
|
1064
|
+
else
|
1065
|
+
target = type_fn.call
|
1066
|
+
[api_name, TerminalShop::Converter.dump(target, val)]
|
1067
|
+
end
|
1058
1068
|
end
|
1059
|
-
end
|
1060
|
-
end.to_h
|
1069
|
+
end.to_h
|
1061
1070
|
|
1062
|
-
|
1063
|
-
|
1071
|
+
defaults.each do |key, val|
|
1072
|
+
next if values.key?(key)
|
1064
1073
|
|
1065
|
-
|
1066
|
-
|
1067
|
-
|
1068
|
-
values
|
1069
|
-
end
|
1074
|
+
values[key] = val
|
1075
|
+
end
|
1070
1076
|
|
1071
|
-
|
1072
|
-
#
|
1073
|
-
# @param value [Object]
|
1074
|
-
#
|
1075
|
-
# @return [Array(true, Object, nil), Array(false, Boolean, Integer)]
|
1076
|
-
#
|
1077
|
-
def self.try_strict_coerce(value)
|
1078
|
-
case value
|
1079
|
-
in Hash | TerminalShop::BaseModel
|
1080
|
-
value = value.to_h
|
1081
|
-
else
|
1082
|
-
return [false, false, 0]
|
1077
|
+
values
|
1083
1078
|
end
|
1084
1079
|
|
1085
|
-
|
1086
|
-
|
1087
|
-
|
1088
|
-
|
1080
|
+
# @private
|
1081
|
+
#
|
1082
|
+
# @param value [Object]
|
1083
|
+
#
|
1084
|
+
# @return [Array(true, Object, nil), Array(false, Boolean, Integer)]
|
1085
|
+
#
|
1086
|
+
def try_strict_coerce(value)
|
1087
|
+
case value
|
1088
|
+
in Hash | TerminalShop::BaseModel
|
1089
|
+
value = value.to_h
|
1090
|
+
else
|
1091
|
+
return [false, false, 0]
|
1092
|
+
end
|
1093
|
+
|
1094
|
+
keys = value.keys.to_set
|
1095
|
+
great_success = true
|
1096
|
+
tally = 0
|
1097
|
+
acc = {}
|
1089
1098
|
|
1090
|
-
|
1091
|
-
|
1092
|
-
|
1099
|
+
known_fields.each_value do |field|
|
1100
|
+
mode, required, type_fn, api_name = field.fetch_values(:mode, :required, :type_fn, :key)
|
1101
|
+
keys.delete(api_name)
|
1093
1102
|
|
1094
|
-
|
1095
|
-
|
1096
|
-
|
1097
|
-
|
1098
|
-
|
1099
|
-
|
1100
|
-
|
1101
|
-
|
1102
|
-
|
1103
|
+
case [required && mode != :dump, value.key?(api_name)]
|
1104
|
+
in [_, true]
|
1105
|
+
target = type_fn.call
|
1106
|
+
item = value.fetch(api_name)
|
1107
|
+
case TerminalShop::Converter.try_strict_coerce(target, item)
|
1108
|
+
in [true, coerced, score]
|
1109
|
+
tally += score
|
1110
|
+
acc[api_name] = coerced
|
1111
|
+
in [false, true, score]
|
1112
|
+
great_success = false
|
1113
|
+
tally += score
|
1114
|
+
acc[api_name] = item
|
1115
|
+
in [false, false, _]
|
1116
|
+
great_success &&= item.nil?
|
1117
|
+
end
|
1118
|
+
in [true, false]
|
1103
1119
|
great_success = false
|
1104
|
-
|
1105
|
-
|
1106
|
-
in [false, false, _]
|
1107
|
-
great_success &&= item.nil?
|
1120
|
+
in [false, false]
|
1121
|
+
nil
|
1108
1122
|
end
|
1109
|
-
in [true, false]
|
1110
|
-
great_success = false
|
1111
|
-
in [false, false]
|
1112
|
-
nil
|
1113
1123
|
end
|
1114
|
-
end
|
1115
1124
|
|
1116
|
-
|
1117
|
-
|
1118
|
-
|
1125
|
+
keys.each do |key|
|
1126
|
+
acc[key] = value.fetch(key)
|
1127
|
+
end
|
1119
1128
|
|
1120
|
-
|
1129
|
+
great_success ? [true, new(acc), tally] : [false, true, tally]
|
1130
|
+
end
|
1121
1131
|
end
|
1122
1132
|
|
1123
1133
|
# Returns the raw value associated with the given key, if found. Otherwise, nil is
|