terminal-shop 1.8.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.
Files changed (299) hide show
  1. checksums.yaml +4 -4
  2. data/README.md +16 -8
  3. data/lib/terminal-shop/client.rb +2 -1
  4. data/lib/terminal-shop/models/address_create_params.rb +1 -1
  5. data/lib/terminal-shop/models/address_delete_params.rb +1 -1
  6. data/lib/terminal-shop/models/address_get_params.rb +1 -1
  7. data/lib/terminal-shop/models/address_list_params.rb +1 -1
  8. data/lib/terminal-shop/models/app_create_params.rb +1 -1
  9. data/lib/terminal-shop/models/app_delete_params.rb +1 -1
  10. data/lib/terminal-shop/models/app_get_params.rb +1 -1
  11. data/lib/terminal-shop/models/app_list_params.rb +1 -1
  12. data/lib/terminal-shop/models/card_collect_params.rb +1 -1
  13. data/lib/terminal-shop/models/card_create_params.rb +1 -1
  14. data/lib/terminal-shop/models/card_delete_params.rb +1 -1
  15. data/lib/terminal-shop/models/card_get_params.rb +1 -1
  16. data/lib/terminal-shop/models/card_list_params.rb +1 -1
  17. data/lib/terminal-shop/models/cart_clear_params.rb +1 -1
  18. data/lib/terminal-shop/models/cart_convert_params.rb +1 -1
  19. data/lib/terminal-shop/models/cart_get_params.rb +1 -1
  20. data/lib/terminal-shop/models/cart_set_address_params.rb +1 -1
  21. data/lib/terminal-shop/models/cart_set_card_params.rb +1 -1
  22. data/lib/terminal-shop/models/cart_set_item_params.rb +1 -1
  23. data/lib/terminal-shop/models/email_create_params.rb +1 -1
  24. data/lib/terminal-shop/models/order_create_params.rb +1 -1
  25. data/lib/terminal-shop/models/order_get_params.rb +1 -1
  26. data/lib/terminal-shop/models/order_list_params.rb +1 -1
  27. data/lib/terminal-shop/models/product.rb +7 -3
  28. data/lib/terminal-shop/models/product_get_params.rb +1 -1
  29. data/lib/terminal-shop/models/product_list_params.rb +1 -1
  30. data/lib/terminal-shop/models/profile_me_params.rb +1 -1
  31. data/lib/terminal-shop/models/profile_update_params.rb +1 -1
  32. data/lib/terminal-shop/models/region.rb +7 -3
  33. data/lib/terminal-shop/models/subscription.rb +5 -7
  34. data/lib/terminal-shop/models/subscription_create_params.rb +1 -1
  35. data/lib/terminal-shop/models/subscription_delete_params.rb +1 -1
  36. data/lib/terminal-shop/models/subscription_get_params.rb +1 -1
  37. data/lib/terminal-shop/models/subscription_list_params.rb +1 -1
  38. data/lib/terminal-shop/models/token_create_params.rb +1 -1
  39. data/lib/terminal-shop/models/token_delete_params.rb +1 -1
  40. data/lib/terminal-shop/models/token_get_params.rb +1 -1
  41. data/lib/terminal-shop/models/token_list_params.rb +1 -1
  42. data/lib/terminal-shop/models/view_init_params.rb +1 -1
  43. data/lib/terminal-shop/request_options.rb +1 -34
  44. data/lib/terminal-shop/transport/base_client.rb +459 -0
  45. data/lib/terminal-shop/transport/pooled_net_requester.rb +182 -0
  46. data/lib/terminal-shop/type/array_of.rb +110 -0
  47. data/lib/terminal-shop/type/base_model.rb +362 -0
  48. data/lib/terminal-shop/type/base_page.rb +61 -0
  49. data/lib/terminal-shop/type/boolean_model.rb +52 -0
  50. data/lib/terminal-shop/type/converter.rb +217 -0
  51. data/lib/terminal-shop/type/enum.rb +101 -0
  52. data/lib/terminal-shop/type/hash_of.rb +136 -0
  53. data/lib/terminal-shop/type/request_parameters.rb +38 -0
  54. data/lib/terminal-shop/type/union.rb +183 -0
  55. data/lib/terminal-shop/type/unknown.rb +56 -0
  56. data/lib/terminal-shop/type.rb +23 -0
  57. data/lib/terminal-shop/util.rb +19 -12
  58. data/lib/terminal-shop/version.rb +1 -1
  59. data/lib/terminal-shop.rb +28 -5
  60. data/rbi/lib/terminal-shop/client.rbi +19 -31
  61. data/rbi/lib/terminal-shop/errors.rbi +7 -42
  62. data/rbi/lib/terminal-shop/models/address.rbi +15 -51
  63. data/rbi/lib/terminal-shop/models/address_create_params.rbi +27 -48
  64. data/rbi/lib/terminal-shop/models/address_create_response.rbi +1 -6
  65. data/rbi/lib/terminal-shop/models/address_delete_params.rbi +2 -2
  66. data/rbi/lib/terminal-shop/models/address_delete_response.rbi +1 -6
  67. data/rbi/lib/terminal-shop/models/address_get_params.rbi +2 -2
  68. data/rbi/lib/terminal-shop/models/address_get_response.rbi +7 -6
  69. data/rbi/lib/terminal-shop/models/address_list_params.rbi +2 -2
  70. data/rbi/lib/terminal-shop/models/address_list_response.rbi +4 -6
  71. data/rbi/lib/terminal-shop/models/app.rbi +4 -24
  72. data/rbi/lib/terminal-shop/models/app_create_params.rbi +4 -14
  73. data/rbi/lib/terminal-shop/models/app_create_response.rbi +8 -20
  74. data/rbi/lib/terminal-shop/models/app_delete_params.rbi +2 -2
  75. data/rbi/lib/terminal-shop/models/app_delete_response.rbi +1 -6
  76. data/rbi/lib/terminal-shop/models/app_get_params.rbi +2 -2
  77. data/rbi/lib/terminal-shop/models/app_get_response.rbi +4 -6
  78. data/rbi/lib/terminal-shop/models/app_list_params.rbi +2 -2
  79. data/rbi/lib/terminal-shop/models/app_list_response.rbi +4 -6
  80. data/rbi/lib/terminal-shop/models/card.rbi +14 -36
  81. data/rbi/lib/terminal-shop/models/card_collect_params.rbi +2 -2
  82. data/rbi/lib/terminal-shop/models/card_collect_response.rbi +7 -14
  83. data/rbi/lib/terminal-shop/models/card_create_params.rbi +3 -8
  84. data/rbi/lib/terminal-shop/models/card_create_response.rbi +1 -6
  85. data/rbi/lib/terminal-shop/models/card_delete_params.rbi +2 -2
  86. data/rbi/lib/terminal-shop/models/card_delete_response.rbi +1 -6
  87. data/rbi/lib/terminal-shop/models/card_get_params.rbi +2 -2
  88. data/rbi/lib/terminal-shop/models/card_get_response.rbi +4 -6
  89. data/rbi/lib/terminal-shop/models/card_list_params.rbi +2 -2
  90. data/rbi/lib/terminal-shop/models/card_list_response.rbi +4 -6
  91. data/rbi/lib/terminal-shop/models/cart.rbi +34 -88
  92. data/rbi/lib/terminal-shop/models/cart_clear_params.rbi +2 -2
  93. data/rbi/lib/terminal-shop/models/cart_clear_response.rbi +1 -6
  94. data/rbi/lib/terminal-shop/models/cart_convert_params.rbi +2 -2
  95. data/rbi/lib/terminal-shop/models/cart_convert_response.rbi +4 -6
  96. data/rbi/lib/terminal-shop/models/cart_get_params.rbi +2 -2
  97. data/rbi/lib/terminal-shop/models/cart_get_response.rbi +4 -6
  98. data/rbi/lib/terminal-shop/models/cart_set_address_params.rbi +3 -8
  99. data/rbi/lib/terminal-shop/models/cart_set_address_response.rbi +1 -6
  100. data/rbi/lib/terminal-shop/models/cart_set_card_params.rbi +3 -8
  101. data/rbi/lib/terminal-shop/models/cart_set_card_response.rbi +1 -6
  102. data/rbi/lib/terminal-shop/models/cart_set_item_params.rbi +4 -14
  103. data/rbi/lib/terminal-shop/models/cart_set_item_response.rbi +4 -6
  104. data/rbi/lib/terminal-shop/models/email_create_params.rbi +3 -8
  105. data/rbi/lib/terminal-shop/models/email_create_response.rbi +1 -6
  106. data/rbi/lib/terminal-shop/models/order.rbi +52 -139
  107. data/rbi/lib/terminal-shop/models/order_create_params.rbi +5 -20
  108. data/rbi/lib/terminal-shop/models/order_create_response.rbi +1 -6
  109. data/rbi/lib/terminal-shop/models/order_get_params.rbi +2 -2
  110. data/rbi/lib/terminal-shop/models/order_get_response.rbi +4 -6
  111. data/rbi/lib/terminal-shop/models/order_list_params.rbi +2 -2
  112. data/rbi/lib/terminal-shop/models/order_list_response.rbi +4 -6
  113. data/rbi/lib/terminal-shop/models/product.rbi +43 -77
  114. data/rbi/lib/terminal-shop/models/product_get_params.rbi +2 -2
  115. data/rbi/lib/terminal-shop/models/product_get_response.rbi +7 -6
  116. data/rbi/lib/terminal-shop/models/product_list_params.rbi +2 -2
  117. data/rbi/lib/terminal-shop/models/product_list_response.rbi +4 -6
  118. data/rbi/lib/terminal-shop/models/product_variant.rbi +3 -18
  119. data/rbi/lib/terminal-shop/models/profile.rbi +12 -36
  120. data/rbi/lib/terminal-shop/models/profile_me_params.rbi +2 -2
  121. data/rbi/lib/terminal-shop/models/profile_me_response.rbi +7 -6
  122. data/rbi/lib/terminal-shop/models/profile_update_params.rbi +4 -14
  123. data/rbi/lib/terminal-shop/models/profile_update_response.rbi +7 -6
  124. data/rbi/lib/terminal-shop/models/region.rbi +10 -5
  125. data/rbi/lib/terminal-shop/models/subscription.rbi +28 -75
  126. data/rbi/lib/terminal-shop/models/subscription_create_params.rbi +2 -2
  127. data/rbi/lib/terminal-shop/models/subscription_create_response.rbi +1 -6
  128. data/rbi/lib/terminal-shop/models/subscription_delete_params.rbi +2 -2
  129. data/rbi/lib/terminal-shop/models/subscription_delete_response.rbi +1 -6
  130. data/rbi/lib/terminal-shop/models/subscription_get_params.rbi +2 -2
  131. data/rbi/lib/terminal-shop/models/subscription_get_response.rbi +7 -6
  132. data/rbi/lib/terminal-shop/models/subscription_list_params.rbi +2 -2
  133. data/rbi/lib/terminal-shop/models/subscription_list_response.rbi +3 -8
  134. data/rbi/lib/terminal-shop/models/token.rbi +3 -18
  135. data/rbi/lib/terminal-shop/models/token_create_params.rbi +2 -2
  136. data/rbi/lib/terminal-shop/models/token_create_response.rbi +8 -20
  137. data/rbi/lib/terminal-shop/models/token_delete_params.rbi +2 -2
  138. data/rbi/lib/terminal-shop/models/token_delete_response.rbi +1 -6
  139. data/rbi/lib/terminal-shop/models/token_get_params.rbi +2 -2
  140. data/rbi/lib/terminal-shop/models/token_get_response.rbi +4 -6
  141. data/rbi/lib/terminal-shop/models/token_list_params.rbi +2 -2
  142. data/rbi/lib/terminal-shop/models/token_list_response.rbi +4 -6
  143. data/rbi/lib/terminal-shop/models/view_init_params.rbi +2 -2
  144. data/rbi/lib/terminal-shop/models/view_init_response.rbi +44 -82
  145. data/rbi/lib/terminal-shop/request_options.rbi +8 -67
  146. data/rbi/lib/terminal-shop/resources/address.rbi +4 -4
  147. data/rbi/lib/terminal-shop/resources/app.rbi +4 -4
  148. data/rbi/lib/terminal-shop/resources/card.rbi +5 -5
  149. data/rbi/lib/terminal-shop/resources/cart.rbi +6 -6
  150. data/rbi/lib/terminal-shop/resources/email.rbi +1 -1
  151. data/rbi/lib/terminal-shop/resources/order.rbi +3 -3
  152. data/rbi/lib/terminal-shop/resources/product.rbi +2 -2
  153. data/rbi/lib/terminal-shop/resources/profile.rbi +2 -2
  154. data/rbi/lib/terminal-shop/resources/subscription.rbi +5 -4
  155. data/rbi/lib/terminal-shop/resources/token.rbi +4 -4
  156. data/rbi/lib/terminal-shop/resources/view.rbi +1 -1
  157. data/rbi/lib/terminal-shop/transport/base_client.rbi +208 -0
  158. data/rbi/lib/terminal-shop/transport/pooled_net_requester.rbi +64 -0
  159. data/rbi/lib/terminal-shop/type/array_of.rbi +82 -0
  160. data/rbi/lib/terminal-shop/type/base_model.rbi +194 -0
  161. data/rbi/lib/terminal-shop/type/base_page.rbi +38 -0
  162. data/rbi/lib/terminal-shop/type/boolean_model.rbi +41 -0
  163. data/rbi/lib/terminal-shop/type/converter.rbi +101 -0
  164. data/rbi/lib/terminal-shop/type/enum.rbi +58 -0
  165. data/rbi/lib/terminal-shop/type/hash_of.rbi +85 -0
  166. data/rbi/lib/terminal-shop/type/request_parameters.rbi +20 -0
  167. data/rbi/lib/terminal-shop/type/union.rbi +68 -0
  168. data/rbi/lib/terminal-shop/type/unknown.rbi +37 -0
  169. data/rbi/lib/terminal-shop/type.rbi +23 -0
  170. data/rbi/lib/terminal-shop/util.rbi +24 -13
  171. data/rbi/lib/terminal-shop/version.rbi +1 -1
  172. data/sig/terminal-shop/client.rbs +9 -9
  173. data/sig/terminal-shop/errors.rbs +17 -17
  174. data/sig/terminal-shop/models/address.rbs +11 -15
  175. data/sig/terminal-shop/models/address_create_params.rbs +12 -17
  176. data/sig/terminal-shop/models/address_create_response.rbs +1 -6
  177. data/sig/terminal-shop/models/address_delete_params.rbs +2 -7
  178. data/sig/terminal-shop/models/address_delete_response.rbs +1 -6
  179. data/sig/terminal-shop/models/address_get_params.rbs +2 -7
  180. data/sig/terminal-shop/models/address_get_response.rbs +1 -6
  181. data/sig/terminal-shop/models/address_list_params.rbs +2 -7
  182. data/sig/terminal-shop/models/address_list_response.rbs +1 -6
  183. data/sig/terminal-shop/models/app.rbs +6 -5
  184. data/sig/terminal-shop/models/app_create_params.rbs +6 -11
  185. data/sig/terminal-shop/models/app_create_response.rbs +4 -12
  186. data/sig/terminal-shop/models/app_delete_params.rbs +2 -7
  187. data/sig/terminal-shop/models/app_delete_response.rbs +1 -6
  188. data/sig/terminal-shop/models/app_get_params.rbs +2 -6
  189. data/sig/terminal-shop/models/app_get_response.rbs +1 -5
  190. data/sig/terminal-shop/models/app_list_params.rbs +2 -6
  191. data/sig/terminal-shop/models/app_list_response.rbs +1 -6
  192. data/sig/terminal-shop/models/card.rbs +7 -16
  193. data/sig/terminal-shop/models/card_collect_params.rbs +2 -7
  194. data/sig/terminal-shop/models/card_collect_response.rbs +4 -12
  195. data/sig/terminal-shop/models/card_create_params.rbs +5 -7
  196. data/sig/terminal-shop/models/card_create_response.rbs +1 -6
  197. data/sig/terminal-shop/models/card_delete_params.rbs +2 -7
  198. data/sig/terminal-shop/models/card_delete_response.rbs +1 -6
  199. data/sig/terminal-shop/models/card_get_params.rbs +2 -6
  200. data/sig/terminal-shop/models/card_get_response.rbs +1 -6
  201. data/sig/terminal-shop/models/card_list_params.rbs +2 -6
  202. data/sig/terminal-shop/models/card_list_response.rbs +1 -6
  203. data/sig/terminal-shop/models/cart.rbs +20 -34
  204. data/sig/terminal-shop/models/cart_clear_params.rbs +2 -7
  205. data/sig/terminal-shop/models/cart_clear_response.rbs +1 -6
  206. data/sig/terminal-shop/models/cart_convert_params.rbs +2 -7
  207. data/sig/terminal-shop/models/cart_convert_response.rbs +1 -6
  208. data/sig/terminal-shop/models/cart_get_params.rbs +2 -6
  209. data/sig/terminal-shop/models/cart_get_response.rbs +1 -6
  210. data/sig/terminal-shop/models/cart_set_address_params.rbs +5 -10
  211. data/sig/terminal-shop/models/cart_set_address_response.rbs +1 -6
  212. data/sig/terminal-shop/models/cart_set_card_params.rbs +5 -7
  213. data/sig/terminal-shop/models/cart_set_card_response.rbs +1 -6
  214. data/sig/terminal-shop/models/cart_set_item_params.rbs +6 -11
  215. data/sig/terminal-shop/models/cart_set_item_response.rbs +1 -6
  216. data/sig/terminal-shop/models/email_create_params.rbs +5 -7
  217. data/sig/terminal-shop/models/email_create_response.rbs +1 -6
  218. data/sig/terminal-shop/models/order.rbs +31 -50
  219. data/sig/terminal-shop/models/order_create_params.rbs +7 -12
  220. data/sig/terminal-shop/models/order_create_response.rbs +1 -6
  221. data/sig/terminal-shop/models/order_get_params.rbs +2 -6
  222. data/sig/terminal-shop/models/order_get_response.rbs +1 -6
  223. data/sig/terminal-shop/models/order_list_params.rbs +2 -7
  224. data/sig/terminal-shop/models/order_list_response.rbs +1 -6
  225. data/sig/terminal-shop/models/product.rbs +20 -27
  226. data/sig/terminal-shop/models/product_get_params.rbs +2 -7
  227. data/sig/terminal-shop/models/product_get_response.rbs +1 -6
  228. data/sig/terminal-shop/models/product_list_params.rbs +2 -7
  229. data/sig/terminal-shop/models/product_list_response.rbs +1 -6
  230. data/sig/terminal-shop/models/product_variant.rbs +1 -5
  231. data/sig/terminal-shop/models/profile.rbs +8 -17
  232. data/sig/terminal-shop/models/profile_me_params.rbs +2 -7
  233. data/sig/terminal-shop/models/profile_me_response.rbs +1 -6
  234. data/sig/terminal-shop/models/profile_update_params.rbs +6 -11
  235. data/sig/terminal-shop/models/profile_update_response.rbs +1 -6
  236. data/sig/terminal-shop/models/region.rbs +4 -2
  237. data/sig/terminal-shop/models/subscription.rbs +15 -27
  238. data/sig/terminal-shop/models/subscription_create_params.rbs +2 -7
  239. data/sig/terminal-shop/models/subscription_create_response.rbs +1 -6
  240. data/sig/terminal-shop/models/subscription_delete_params.rbs +2 -7
  241. data/sig/terminal-shop/models/subscription_delete_response.rbs +1 -6
  242. data/sig/terminal-shop/models/subscription_get_params.rbs +2 -7
  243. data/sig/terminal-shop/models/subscription_get_response.rbs +1 -6
  244. data/sig/terminal-shop/models/subscription_list_params.rbs +2 -7
  245. data/sig/terminal-shop/models/subscription_list_response.rbs +3 -6
  246. data/sig/terminal-shop/models/token.rbs +1 -5
  247. data/sig/terminal-shop/models/token_create_params.rbs +2 -7
  248. data/sig/terminal-shop/models/token_create_response.rbs +4 -12
  249. data/sig/terminal-shop/models/token_delete_params.rbs +2 -7
  250. data/sig/terminal-shop/models/token_delete_response.rbs +1 -6
  251. data/sig/terminal-shop/models/token_get_params.rbs +2 -6
  252. data/sig/terminal-shop/models/token_get_response.rbs +1 -6
  253. data/sig/terminal-shop/models/token_list_params.rbs +2 -7
  254. data/sig/terminal-shop/models/token_list_response.rbs +1 -6
  255. data/sig/terminal-shop/models/view_init_params.rbs +2 -6
  256. data/sig/terminal-shop/models/view_init_response.rbs +15 -23
  257. data/sig/terminal-shop/request_options.rbs +2 -12
  258. data/sig/terminal-shop/resources/address.rbs +22 -41
  259. data/sig/terminal-shop/resources/app.rbs +16 -34
  260. data/sig/terminal-shop/resources/card.rbs +18 -40
  261. data/sig/terminal-shop/resources/cart.rbs +22 -47
  262. data/sig/terminal-shop/resources/email.rbs +4 -8
  263. data/sig/terminal-shop/resources/order.rbs +13 -26
  264. data/sig/terminal-shop/resources/product.rbs +7 -16
  265. data/sig/terminal-shop/resources/profile.rbs +8 -16
  266. data/sig/terminal-shop/resources/subscription.rbs +21 -43
  267. data/sig/terminal-shop/resources/token.rbs +14 -32
  268. data/sig/terminal-shop/resources/view.rbs +3 -7
  269. data/sig/terminal-shop/transport/base_client.rbs +110 -0
  270. data/sig/terminal-shop/transport/pooled_net_requester.rbs +39 -0
  271. data/sig/terminal-shop/type/array_of.rbs +36 -0
  272. data/sig/terminal-shop/type/base_model.rbs +73 -0
  273. data/sig/terminal-shop/type/base_page.rbs +22 -0
  274. data/sig/terminal-shop/type/boolean_model.rbs +18 -0
  275. data/sig/terminal-shop/type/converter.rbs +42 -0
  276. data/sig/terminal-shop/type/enum.rbs +22 -0
  277. data/sig/terminal-shop/type/hash_of.rbs +36 -0
  278. data/sig/terminal-shop/type/request_parameters.rbs +13 -0
  279. data/sig/terminal-shop/type/union.rbs +40 -0
  280. data/sig/terminal-shop/type/unknown.rbs +18 -0
  281. data/sig/terminal-shop/type.rbs +22 -0
  282. data/sig/terminal-shop/util.rbs +5 -5
  283. data/sig/terminal-shop/version.rbs +1 -1
  284. metadata +41 -17
  285. data/lib/terminal-shop/base_client.rb +0 -456
  286. data/lib/terminal-shop/base_model.rb +0 -1188
  287. data/lib/terminal-shop/base_page.rb +0 -60
  288. data/lib/terminal-shop/extern.rb +0 -7
  289. data/lib/terminal-shop/pooled_net_requester.rb +0 -169
  290. data/rbi/lib/terminal-shop/base_client.rbi +0 -198
  291. data/rbi/lib/terminal-shop/base_model.rbi +0 -622
  292. data/rbi/lib/terminal-shop/base_page.rbi +0 -38
  293. data/rbi/lib/terminal-shop/extern.rbi +0 -7
  294. data/rbi/lib/terminal-shop/pooled_net_requester.rbi +0 -48
  295. data/sig/terminal-shop/base_client.rbs +0 -108
  296. data/sig/terminal-shop/base_model.rbs +0 -246
  297. data/sig/terminal-shop/base_page.rbs +0 -20
  298. data/sig/terminal-shop/extern.rbs +0 -4
  299. data/sig/terminal-shop/pooled_net_requester.rbs +0 -35
@@ -1,1188 +0,0 @@
1
- # frozen_string_literal: true
2
-
3
- module TerminalShop
4
- # @api private
5
- module Converter
6
- # rubocop:disable Lint/UnusedMethodArgument
7
-
8
- # @api private
9
- #
10
- # @param value [Object]
11
- #
12
- # @return [Object]
13
- def coerce(value) = value
14
-
15
- # @api private
16
- #
17
- # @param value [Object]
18
- #
19
- # @return [Object]
20
- def dump(value) = value
21
-
22
- # @api private
23
- #
24
- # @param value [Object]
25
- #
26
- # @return [Array(true, Object, nil), Array(false, Boolean, Integer)]
27
- def try_strict_coerce(value) = (raise NotImplementedError)
28
-
29
- # rubocop:enable Lint/UnusedMethodArgument
30
-
31
- class << self
32
- # @api private
33
- #
34
- # @param spec [Hash{Symbol=>Object}, Proc, TerminalShop::Converter, Class] .
35
- #
36
- # @option spec [NilClass, TrueClass, FalseClass, Integer, Float, Symbol] :const
37
- #
38
- # @option spec [Proc] :enum
39
- #
40
- # @option spec [Proc] :union
41
- #
42
- # @option spec [Boolean] :"nil?"
43
- #
44
- # @return [Proc]
45
- def type_info(spec)
46
- case spec
47
- in Hash
48
- type_info(spec.slice(:const, :enum, :union).first&.last)
49
- in Proc
50
- spec
51
- in TerminalShop::Converter | Class | Symbol
52
- -> { spec }
53
- in true | false
54
- -> { TerminalShop::BooleanModel }
55
- in NilClass | Integer | Float
56
- -> { spec.class }
57
- end
58
- end
59
-
60
- # @api private
61
- #
62
- # Based on `target`, transform `value` into `target`, to the extent possible:
63
- #
64
- # 1. if the given `value` conforms to `target` already, return the given `value`
65
- # 2. if it's possible and safe to convert the given `value` to `target`, then the
66
- # converted value
67
- # 3. otherwise, the given `value` unaltered
68
- #
69
- # @param target [TerminalShop::Converter, Class]
70
- # @param value [Object]
71
- #
72
- # @return [Object]
73
- def coerce(target, value)
74
- case target
75
- in TerminalShop::Converter
76
- target.coerce(value)
77
- in Symbol
78
- case value
79
- in Symbol | String if (val = value.to_sym) == target
80
- val
81
- else
82
- value
83
- end
84
- in Class
85
- case target
86
- in -> { _1 <= NilClass }
87
- nil
88
- in -> { _1 <= Integer }
89
- value.is_a?(Numeric) ? Integer(value) : value
90
- in -> { _1 <= Float }
91
- value.is_a?(Numeric) ? Float(value) : value
92
- in -> { _1 <= Symbol }
93
- value.is_a?(String) ? value.to_sym : value
94
- in -> { _1 <= String }
95
- value.is_a?(Symbol) ? value.to_s : value
96
- in -> { _1 <= Date || _1 <= Time }
97
- value.is_a?(String) ? target.parse(value) : value
98
- in -> { _1 <= IO }
99
- value.is_a?(String) ? StringIO.new(value) : value
100
- else
101
- value
102
- end
103
- end
104
- end
105
-
106
- # @api private
107
- #
108
- # @param target [TerminalShop::Converter, Class]
109
- # @param value [Object]
110
- #
111
- # @return [Object]
112
- def dump(target, value)
113
- case target
114
- in TerminalShop::Converter
115
- target.dump(value)
116
- else
117
- value
118
- end
119
- end
120
-
121
- # @api private
122
- #
123
- # The underlying algorithm for computing maximal compatibility is subject to
124
- # future improvements.
125
- #
126
- # Similar to `#.coerce`, used to determine the best union variant to decode into.
127
- #
128
- # 1. determine if strict-ish coercion is possible
129
- # 2. return either result of successful coercion or if loose coercion is possible
130
- # 3. return a score for recursively tallied count for fields that can be coerced
131
- #
132
- # @param target [TerminalShop::Converter, Class]
133
- # @param value [Object]
134
- #
135
- # @return [Object]
136
- def try_strict_coerce(target, value)
137
- case target
138
- in TerminalShop::Converter
139
- target.try_strict_coerce(value)
140
- in Symbol
141
- case value
142
- in Symbol | String if (val = value.to_sym) == target
143
- [true, val, 1]
144
- else
145
- [false, false, 0]
146
- end
147
- in Class
148
- case [target, value]
149
- in [-> { _1 <= NilClass }, _]
150
- [true, nil, value.nil? ? 1 : 0]
151
- in [-> { _1 <= Integer }, Numeric]
152
- [true, Integer(value), 1]
153
- in [-> { _1 <= Float }, Numeric]
154
- [true, Float(value), 1]
155
- in [-> { _1 <= Symbol }, String]
156
- [true, value.to_sym, 1]
157
- in [-> { _1 <= String }, Symbol]
158
- [true, value.to_s, 1]
159
- in [-> { _1 <= Date || _1 <= Time }, String]
160
- Kernel.then do
161
- [true, target.parse(value), 1]
162
- rescue ArgumentError
163
- [false, false, 0]
164
- end
165
- in [_, ^target]
166
- [true, value, 1]
167
- else
168
- [false, false, 0]
169
- end
170
- end
171
- end
172
- end
173
- end
174
-
175
- # @api private
176
- #
177
- # @abstract
178
- #
179
- # When we don't know what to expect for the value.
180
- class Unknown
181
- extend TerminalShop::Converter
182
-
183
- # rubocop:disable Lint/UnusedMethodArgument
184
-
185
- private_class_method :new
186
-
187
- # @param other [Object]
188
- #
189
- # @return [Boolean]
190
- def self.===(other) = true
191
-
192
- # @param other [Object]
193
- #
194
- # @return [Boolean]
195
- def self.==(other) = other.is_a?(Class) && other <= TerminalShop::Unknown
196
-
197
- class << self
198
- # @!parse
199
- # # @api private
200
- # #
201
- # # @param value [Object]
202
- # #
203
- # # @return [Object]
204
- # def coerce(value) = super
205
-
206
- # @!parse
207
- # # @api private
208
- # #
209
- # # @param value [Object]
210
- # #
211
- # # @return [Object]
212
- # def dump(value) = super
213
-
214
- # @api private
215
- #
216
- # @param value [Object]
217
- #
218
- # @return [Array(true, Object, nil), Array(false, Boolean, Integer)]
219
- def try_strict_coerce(value)
220
- # prevent unknown variant from being chosen during the first coercion pass
221
- [false, true, 0]
222
- end
223
- end
224
-
225
- # rubocop:enable Lint/UnusedMethodArgument
226
- end
227
-
228
- # @api private
229
- #
230
- # @abstract
231
- #
232
- # Ruby has no Boolean class; this is something for models to refer to.
233
- class BooleanModel
234
- extend TerminalShop::Converter
235
-
236
- private_class_method :new
237
-
238
- # @param other [Object]
239
- #
240
- # @return [Boolean]
241
- def self.===(other) = other == true || other == false
242
-
243
- # @param other [Object]
244
- #
245
- # @return [Boolean]
246
- def self.==(other) = other.is_a?(Class) && other <= TerminalShop::BooleanModel
247
-
248
- class << self
249
- # @!parse
250
- # # @api private
251
- # #
252
- # # @param value [Boolean, Object]
253
- # #
254
- # # @return [Boolean, Object]
255
- # def coerce(value) = super
256
-
257
- # @!parse
258
- # # @api private
259
- # #
260
- # # @param value [Boolean, Object]
261
- # #
262
- # # @return [Boolean, Object]
263
- # def dump(value) = super
264
-
265
- # @api private
266
- #
267
- # @param value [Object]
268
- #
269
- # @return [Array(true, Object, nil), Array(false, Boolean, Integer)]
270
- def try_strict_coerce(value)
271
- case value
272
- in true | false
273
- [true, value, 1]
274
- else
275
- [false, false, 0]
276
- end
277
- end
278
- end
279
- end
280
-
281
- # @api private
282
- #
283
- # @abstract
284
- #
285
- # A value from among a specified list of options. OpenAPI enum values map to Ruby
286
- # values in the SDK as follows:
287
- #
288
- # 1. boolean => true | false
289
- # 2. integer => Integer
290
- # 3. float => Float
291
- # 4. string => Symbol
292
- #
293
- # We can therefore convert string values to Symbols, but can't convert other
294
- # values safely.
295
- #
296
- # @example
297
- # ```ruby
298
- # # `region` is a `TerminalShop::Models::Region`
299
- # case region
300
- # when TerminalShop::Models::Region::EU
301
- # # ...
302
- # when TerminalShop::Models::Region::NA
303
- # # ...
304
- # else
305
- # puts(region)
306
- # end
307
- # ```
308
- #
309
- # @example
310
- # ```ruby
311
- # case region
312
- # in :eu
313
- # # ...
314
- # in :na
315
- # # ...
316
- # else
317
- # puts(region)
318
- # end
319
- # ```
320
- class Enum
321
- extend TerminalShop::Converter
322
-
323
- class << self
324
- # All of the valid Symbol values for this enum.
325
- #
326
- # @return [Array<NilClass, Boolean, Integer, Float, Symbol>]
327
- def values = (@values ||= constants.map { const_get(_1) })
328
-
329
- # @api private
330
- #
331
- # Guard against thread safety issues by instantiating `@values`.
332
- private def finalize! = values
333
- end
334
-
335
- private_class_method :new
336
-
337
- # @param other [Object]
338
- #
339
- # @return [Boolean]
340
- def self.===(other) = values.include?(other)
341
-
342
- # @param other [Object]
343
- #
344
- # @return [Boolean]
345
- def self.==(other)
346
- other.is_a?(Class) && other <= TerminalShop::Enum && other.values.to_set == values.to_set
347
- end
348
-
349
- class << self
350
- # @api private
351
- #
352
- # @param value [String, Symbol, Object]
353
- #
354
- # @return [Symbol, Object]
355
- def coerce(value)
356
- case value
357
- in Symbol | String if values.include?(val = value.to_sym)
358
- val
359
- else
360
- value
361
- end
362
- end
363
-
364
- # @!parse
365
- # # @api private
366
- # #
367
- # # @param value [Symbol, Object]
368
- # #
369
- # # @return [Symbol, Object]
370
- # def dump(value) = super
371
-
372
- # @api private
373
- #
374
- # @param value [Object]
375
- #
376
- # @return [Array(true, Object, nil), Array(false, Boolean, Integer)]
377
- def try_strict_coerce(value)
378
- return [true, value, 1] if values.include?(value)
379
-
380
- case value
381
- in Symbol | String if values.include?(val = value.to_sym)
382
- [true, val, 1]
383
- else
384
- case [value, values.first]
385
- in [true | false, true | false] | [Integer, Integer] | [Symbol | String, Symbol]
386
- [false, true, 0]
387
- else
388
- [false, false, 0]
389
- end
390
- end
391
- end
392
- end
393
- end
394
-
395
- # @api private
396
- #
397
- # @abstract
398
- class Union
399
- extend TerminalShop::Converter
400
-
401
- class << self
402
- # @api private
403
- #
404
- # All of the specified variant info for this union.
405
- #
406
- # @return [Array<Array(Symbol, Proc)>]
407
- private def known_variants = (@known_variants ||= [])
408
-
409
- # @api private
410
- #
411
- # @return [Array<Array(Symbol, Object)>]
412
- protected def derefed_variants
413
- @known_variants.map { |key, variant_fn| [key, variant_fn.call] }
414
- end
415
-
416
- # All of the specified variants for this union.
417
- #
418
- # @return [Array<Object>]
419
- def variants
420
- derefed_variants.map(&:last)
421
- end
422
-
423
- # @api private
424
- #
425
- # @param property [Symbol]
426
- private def discriminator(property)
427
- case property
428
- in Symbol
429
- @discriminator = property
430
- end
431
- end
432
-
433
- # @api private
434
- #
435
- # @param key [Symbol, Hash{Symbol=>Object}, Proc, TerminalShop::Converter, Class]
436
- #
437
- # @param spec [Hash{Symbol=>Object}, Proc, TerminalShop::Converter, Class] .
438
- #
439
- # @option spec [NilClass, TrueClass, FalseClass, Integer, Float, Symbol] :const
440
- #
441
- # @option spec [Proc] :enum
442
- #
443
- # @option spec [Proc] :union
444
- #
445
- # @option spec [Boolean] :"nil?"
446
- private def variant(key, spec = nil)
447
- variant_info =
448
- case key
449
- in Symbol
450
- [key, TerminalShop::Converter.type_info(spec)]
451
- in Proc | TerminalShop::Converter | Class | Hash
452
- [nil, TerminalShop::Converter.type_info(key)]
453
- end
454
-
455
- known_variants << variant_info
456
- end
457
-
458
- # @api private
459
- #
460
- # @param value [Object]
461
- #
462
- # @return [TerminalShop::Converter, Class, nil]
463
- private def resolve_variant(value)
464
- case [@discriminator, value]
465
- in [_, TerminalShop::BaseModel]
466
- value.class
467
- in [Symbol, Hash]
468
- key =
469
- if value.key?(@discriminator)
470
- value.fetch(@discriminator)
471
- elsif value.key?((discriminator = @discriminator.to_s))
472
- value.fetch(discriminator)
473
- end
474
-
475
- key = key.to_sym if key.is_a?(String)
476
- _, resolved = known_variants.find { |k,| k == key }
477
- resolved.nil? ? TerminalShop::Unknown : resolved.call
478
- else
479
- nil
480
- end
481
- end
482
- end
483
-
484
- # rubocop:disable Style/HashEachMethods
485
- # rubocop:disable Style/CaseEquality
486
-
487
- private_class_method :new
488
-
489
- # @param other [Object]
490
- #
491
- # @return [Boolean]
492
- def self.===(other)
493
- known_variants.any? do |_, variant_fn|
494
- variant_fn.call === other
495
- end
496
- end
497
-
498
- # @param other [Object]
499
- #
500
- # @return [Boolean]
501
- def self.==(other)
502
- other.is_a?(Class) && other <= TerminalShop::Union && other.derefed_variants == derefed_variants
503
- end
504
-
505
- class << self
506
- # @api private
507
- #
508
- # @param value [Object]
509
- #
510
- # @return [Object]
511
- def coerce(value)
512
- if (variant = resolve_variant(value))
513
- return TerminalShop::Converter.coerce(variant, value)
514
- end
515
-
516
- matches = []
517
-
518
- known_variants.each do |_, variant_fn|
519
- variant = variant_fn.call
520
-
521
- case TerminalShop::Converter.try_strict_coerce(variant, value)
522
- in [true, coerced, _]
523
- return coerced
524
- in [false, true, score]
525
- matches << [score, variant]
526
- in [false, false, _]
527
- nil
528
- end
529
- end
530
-
531
- _, variant = matches.sort! { _2.first <=> _1.first }.find { |score,| !score.zero? }
532
- variant.nil? ? value : TerminalShop::Converter.coerce(variant, value)
533
- end
534
-
535
- # @api private
536
- #
537
- # @param value [Object]
538
- #
539
- # @return [Object]
540
- def dump(value)
541
- if (variant = resolve_variant(value))
542
- return TerminalShop::Converter.dump(variant, value)
543
- end
544
-
545
- known_variants.each do |_, variant_fn|
546
- variant = variant_fn.call
547
- if variant === value
548
- return TerminalShop::Converter.dump(variant, value)
549
- end
550
- end
551
- value
552
- end
553
-
554
- # @api private
555
- #
556
- # @param value [Object]
557
- #
558
- # @return [Array(true, Object, nil), Array(false, Boolean, Integer)]
559
- def try_strict_coerce(value)
560
- # TODO(ruby) this will result in super linear decoding behaviour for nested unions
561
- # follow up with a decoding context that captures current strictness levels
562
- if (variant = resolve_variant(value))
563
- return Converter.try_strict_coerce(variant, value)
564
- end
565
-
566
- coercible = false
567
- max_score = 0
568
-
569
- known_variants.each do |_, variant_fn|
570
- variant = variant_fn.call
571
-
572
- case TerminalShop::Converter.try_strict_coerce(variant, value)
573
- in [true, coerced, score]
574
- return [true, coerced, score]
575
- in [false, true, score]
576
- coercible = true
577
- max_score = [max_score, score].max
578
- in [false, false, _]
579
- nil
580
- end
581
- end
582
-
583
- [false, coercible, max_score]
584
- end
585
- end
586
-
587
- # rubocop:enable Style/CaseEquality
588
- # rubocop:enable Style/HashEachMethods
589
- end
590
-
591
- # @api private
592
- #
593
- # @abstract
594
- #
595
- # Array of items of a given type.
596
- class ArrayOf
597
- include TerminalShop::Converter
598
-
599
- private_class_method :new
600
-
601
- def self.[](...) = new(...)
602
-
603
- # @param other [Object]
604
- #
605
- # @return [Boolean]
606
- def ===(other)
607
- type = item_type
608
- case other
609
- in Array
610
- # rubocop:disable Style/CaseEquality
611
- other.all? { type === _1 }
612
- # rubocop:enable Style/CaseEquality
613
- else
614
- false
615
- end
616
- end
617
-
618
- # @param other [Object]
619
- #
620
- # @return [Boolean]
621
- def ==(other) = other.is_a?(TerminalShop::ArrayOf) && other.item_type == item_type
622
-
623
- # @api private
624
- #
625
- # @param value [Enumerable, Object]
626
- #
627
- # @return [Array<Object>, Object]
628
- def coerce(value)
629
- type = item_type
630
- case value
631
- in Enumerable unless value.is_a?(Hash)
632
- value.map { TerminalShop::Converter.coerce(type, _1) }
633
- else
634
- value
635
- end
636
- end
637
-
638
- # @api private
639
- #
640
- # @param value [Enumerable, Object]
641
- #
642
- # @return [Array<Object>, Object]
643
- def dump(value)
644
- type = item_type
645
- case value
646
- in Enumerable unless value.is_a?(Hash)
647
- value.map { TerminalShop::Converter.dump(type, _1) }.to_a
648
- else
649
- value
650
- end
651
- end
652
-
653
- # @api private
654
- #
655
- # @param value [Object]
656
- #
657
- # @return [Array(true, Object, nil), Array(false, Boolean, Integer)]
658
- def try_strict_coerce(value)
659
- case value
660
- in Array
661
- type = item_type
662
- great_success = true
663
- tally = 0
664
-
665
- mapped =
666
- value.map do |item|
667
- case TerminalShop::Converter.try_strict_coerce(type, item)
668
- in [true, coerced, score]
669
- tally += score
670
- coerced
671
- in [false, true, score]
672
- great_success = false
673
- tally += score
674
- item
675
- in [false, false, _]
676
- great_success &&= item.nil?
677
- item
678
- end
679
- end
680
-
681
- if great_success
682
- [true, mapped, tally]
683
- else
684
- [false, true, tally]
685
- end
686
- else
687
- [false, false, 0]
688
- end
689
- end
690
-
691
- # @api private
692
- #
693
- # @return [TerminalShop::Converter, Class]
694
- protected def item_type = @item_type_fn.call
695
-
696
- # @api private
697
- #
698
- # @param type_info [Hash{Symbol=>Object}, Proc, TerminalShop::Converter, Class]
699
- #
700
- # @param spec [Hash{Symbol=>Object}] .
701
- #
702
- # @option spec [NilClass, TrueClass, FalseClass, Integer, Float, Symbol] :const
703
- #
704
- # @option spec [Proc] :enum
705
- #
706
- # @option spec [Proc] :union
707
- #
708
- # @option spec [Boolean] :"nil?"
709
- def initialize(type_info, spec = {})
710
- @item_type_fn = TerminalShop::Converter.type_info(type_info || spec)
711
- end
712
- end
713
-
714
- # @api private
715
- #
716
- # @abstract
717
- #
718
- # Hash of items of a given type.
719
- class HashOf
720
- include TerminalShop::Converter
721
-
722
- private_class_method :new
723
-
724
- def self.[](...) = new(...)
725
-
726
- # @param other [Object]
727
- #
728
- # @return [Boolean]
729
- def ===(other)
730
- type = item_type
731
- case other
732
- in Hash
733
- other.all? do |key, val|
734
- case [key, val]
735
- in [Symbol | String, ^type]
736
- true
737
- else
738
- false
739
- end
740
- end
741
- else
742
- false
743
- end
744
- end
745
-
746
- # @param other [Object]
747
- #
748
- # @return [Boolean]
749
- def ==(other) = other.is_a?(TerminalShop::HashOf) && other.item_type == item_type
750
-
751
- # @api private
752
- #
753
- # @param value [Hash{Object=>Object}, Object]
754
- #
755
- # @return [Hash{Symbol=>Object}, Object]
756
- def coerce(value)
757
- type = item_type
758
- case value
759
- in Hash
760
- value.to_h do |key, val|
761
- coerced = TerminalShop::Converter.coerce(type, val)
762
- [key.is_a?(String) ? key.to_sym : key, coerced]
763
- end
764
- else
765
- value
766
- end
767
- end
768
-
769
- # @api private
770
- #
771
- # @param value [Hash{Object=>Object}, Object]
772
- #
773
- # @return [Hash{Symbol=>Object}, Object]
774
- def dump(value)
775
- type = item_type
776
- case value
777
- in Hash
778
- value.transform_values do |val|
779
- TerminalShop::Converter.dump(type, val)
780
- end
781
- else
782
- value
783
- end
784
- end
785
-
786
- # @api private
787
- #
788
- # @param value [Object]
789
- #
790
- # @return [Array(true, Object, nil), Array(false, Boolean, Integer)]
791
- def try_strict_coerce(value)
792
- case value
793
- in Hash
794
- type = item_type
795
- great_success = true
796
- tally = 0
797
-
798
- mapped =
799
- value.transform_values do |val|
800
- case TerminalShop::Converter.try_strict_coerce(type, val)
801
- in [true, coerced, score]
802
- tally += score
803
- coerced
804
- in [false, true, score]
805
- great_success = false
806
- tally += score
807
- val
808
- in [false, false, _]
809
- great_success &&= val.nil?
810
- val
811
- end
812
- end
813
-
814
- if great_success
815
- [true, mapped, tally]
816
- else
817
- [false, true, tally]
818
- end
819
- else
820
- [false, false, 0]
821
- end
822
- end
823
-
824
- # @api private
825
- #
826
- # @return [TerminalShop::Converter, Class]
827
- protected def item_type = @item_type_fn.call
828
-
829
- # @api private
830
- #
831
- # @param type_info [Hash{Symbol=>Object}, Proc, TerminalShop::Converter, Class]
832
- #
833
- # @param spec [Hash{Symbol=>Object}] .
834
- #
835
- # @option spec [NilClass, TrueClass, FalseClass, Integer, Float, Symbol] :const
836
- #
837
- # @option spec [Proc] :enum
838
- #
839
- # @option spec [Proc] :union
840
- #
841
- # @option spec [Boolean] :"nil?"
842
- def initialize(type_info, spec = {})
843
- @item_type_fn = TerminalShop::Converter.type_info(type_info || spec)
844
- end
845
- end
846
-
847
- # @abstract
848
- #
849
- # @example
850
- # ```ruby
851
- # # `product_api` is a `TerminalShop::Models::ProductAPI`
852
- # product_api => {
853
- # id: id,
854
- # description: description,
855
- # name: name
856
- # }
857
- # ```
858
- class BaseModel
859
- extend TerminalShop::Converter
860
-
861
- class << self
862
- # @api private
863
- #
864
- # Assumes superclass fields are totally defined before fields are accessed /
865
- # defined on subclasses.
866
- #
867
- # @return [Hash{Symbol=>Hash{Symbol=>Object}}]
868
- def known_fields
869
- @known_fields ||= (self < TerminalShop::BaseModel ? superclass.known_fields.dup : {})
870
- end
871
-
872
- # @api private
873
- #
874
- # @return [Hash{Symbol=>Hash{Symbol=>Object}}]
875
- def fields
876
- known_fields.transform_values do |field|
877
- {**field.except(:type_fn), type: field.fetch(:type_fn).call}
878
- end
879
- end
880
-
881
- # @api private
882
- #
883
- # @return [Hash{Symbol=>Proc}]
884
- def defaults = (@defaults ||= {})
885
-
886
- # @api private
887
- #
888
- # @param name_sym [Symbol]
889
- #
890
- # @param required [Boolean]
891
- #
892
- # @param type_info [Hash{Symbol=>Object}, Proc, TerminalShop::Converter, Class]
893
- #
894
- # @param spec [Hash{Symbol=>Object}] .
895
- #
896
- # @option spec [NilClass, TrueClass, FalseClass, Integer, Float, Symbol] :const
897
- #
898
- # @option spec [Proc] :enum
899
- #
900
- # @option spec [Proc] :union
901
- #
902
- # @option spec [Boolean] :"nil?"
903
- private def add_field(name_sym, required:, type_info:, spec:)
904
- type_fn, info =
905
- case type_info
906
- in Proc | Class | TerminalShop::Converter
907
- [TerminalShop::Converter.type_info({**spec, union: type_info}), spec]
908
- in Hash
909
- [TerminalShop::Converter.type_info(type_info), type_info]
910
- end
911
-
912
- fallback = info[:const]
913
- defaults[name_sym] = fallback if required && !info[:nil?] && info.key?(:const)
914
-
915
- key = info.fetch(:api_name, name_sym)
916
- setter = "#{name_sym}="
917
-
918
- if known_fields.key?(name_sym)
919
- [name_sym, setter].each { undef_method(_1) }
920
- end
921
-
922
- known_fields[name_sym] = {mode: @mode, key: key, required: required, type_fn: type_fn}
923
-
924
- define_method(setter) do |val|
925
- @data[key] = val
926
- end
927
-
928
- define_method(name_sym) do
929
- field_type = type_fn.call
930
- value = @data.fetch(key) { self.class.defaults[key] }
931
- TerminalShop::Converter.coerce(field_type, value)
932
- rescue StandardError
933
- name = self.class.name.split("::").last
934
- raise TerminalShop::ConversionError.new(
935
- "Failed to parse #{name}.#{name_sym} as #{field_type.inspect}. " \
936
- "To get the unparsed API response, use #{name}[:#{key}]."
937
- )
938
- end
939
- end
940
-
941
- # @api private
942
- #
943
- # @param name_sym [Symbol]
944
- #
945
- # @param type_info [Hash{Symbol=>Object}, Proc, TerminalShop::Converter, Class]
946
- #
947
- # @param spec [Hash{Symbol=>Object}] .
948
- #
949
- # @option spec [NilClass, TrueClass, FalseClass, Integer, Float, Symbol] :const
950
- #
951
- # @option spec [Proc] :enum
952
- #
953
- # @option spec [Proc] :union
954
- #
955
- # @option spec [Boolean] :"nil?"
956
- def required(name_sym, type_info, spec = {})
957
- add_field(name_sym, required: true, type_info: type_info, spec: spec)
958
- end
959
-
960
- # @api private
961
- #
962
- # @param name_sym [Symbol]
963
- #
964
- # @param type_info [Hash{Symbol=>Object}, Proc, TerminalShop::Converter, Class]
965
- #
966
- # @param spec [Hash{Symbol=>Object}] .
967
- #
968
- # @option spec [NilClass, TrueClass, FalseClass, Integer, Float, Symbol] :const
969
- #
970
- # @option spec [Proc] :enum
971
- #
972
- # @option spec [Proc] :union
973
- #
974
- # @option spec [Boolean] :"nil?"
975
- def optional(name_sym, type_info, spec = {})
976
- add_field(name_sym, required: false, type_info: type_info, spec: spec)
977
- end
978
-
979
- # @api private
980
- #
981
- # `request_only` attributes not excluded from `.#coerce` when receiving responses
982
- # even if well behaved servers should not send them
983
- #
984
- # @param blk [Proc]
985
- private def request_only(&blk)
986
- @mode = :dump
987
- blk.call
988
- ensure
989
- @mode = nil
990
- end
991
-
992
- # @api private
993
- #
994
- # `response_only` attributes are omitted from `.#dump` when making requests
995
- #
996
- # @param blk [Proc]
997
- private def response_only(&blk)
998
- @mode = :coerce
999
- blk.call
1000
- ensure
1001
- @mode = nil
1002
- end
1003
- end
1004
-
1005
- # @param other [Object]
1006
- #
1007
- # @return [Boolean]
1008
- def ==(other)
1009
- case other
1010
- in TerminalShop::BaseModel
1011
- self.class.fields == other.class.fields && @data == other.to_h
1012
- else
1013
- false
1014
- end
1015
- end
1016
-
1017
- class << self
1018
- # @api private
1019
- #
1020
- # @param value [TerminalShop::BaseModel, Hash{Object=>Object}, Object]
1021
- #
1022
- # @return [TerminalShop::BaseModel, Object]
1023
- def coerce(value)
1024
- case TerminalShop::Util.coerce_hash(value)
1025
- in Hash => coerced
1026
- new(coerced)
1027
- else
1028
- value
1029
- end
1030
- end
1031
-
1032
- # @api private
1033
- #
1034
- # @param value [TerminalShop::BaseModel, Object]
1035
- #
1036
- # @return [Hash{Object=>Object}, Object]
1037
- def dump(value)
1038
- unless (coerced = TerminalShop::Util.coerce_hash(value)).is_a?(Hash)
1039
- return value
1040
- end
1041
-
1042
- values = coerced.filter_map do |key, val|
1043
- name = key.to_sym
1044
- case (field = known_fields[name])
1045
- in nil
1046
- [name, val]
1047
- else
1048
- mode, type_fn, api_name = field.fetch_values(:mode, :type_fn, :key)
1049
- case mode
1050
- in :coerce
1051
- next
1052
- else
1053
- target = type_fn.call
1054
- [api_name, TerminalShop::Converter.dump(target, val)]
1055
- end
1056
- end
1057
- end.to_h
1058
-
1059
- defaults.each do |key, val|
1060
- next if values.key?(key)
1061
-
1062
- values[key] = val
1063
- end
1064
-
1065
- values
1066
- end
1067
-
1068
- # @api private
1069
- #
1070
- # @param value [Object]
1071
- #
1072
- # @return [Array(true, Object, nil), Array(false, Boolean, Integer)]
1073
- def try_strict_coerce(value)
1074
- case value
1075
- in Hash | TerminalShop::BaseModel
1076
- value = value.to_h
1077
- else
1078
- return [false, false, 0]
1079
- end
1080
-
1081
- keys = value.keys.to_set
1082
- great_success = true
1083
- tally = 0
1084
- acc = {}
1085
-
1086
- known_fields.each_value do |field|
1087
- mode, required, type_fn, api_name = field.fetch_values(:mode, :required, :type_fn, :key)
1088
- keys.delete(api_name)
1089
-
1090
- case [required && mode != :dump, value.key?(api_name)]
1091
- in [_, true]
1092
- target = type_fn.call
1093
- item = value.fetch(api_name)
1094
- case TerminalShop::Converter.try_strict_coerce(target, item)
1095
- in [true, coerced, score]
1096
- tally += score
1097
- acc[api_name] = coerced
1098
- in [false, true, score]
1099
- great_success = false
1100
- tally += score
1101
- acc[api_name] = item
1102
- in [false, false, _]
1103
- great_success &&= item.nil?
1104
- end
1105
- in [true, false]
1106
- great_success = false
1107
- in [false, false]
1108
- nil
1109
- end
1110
- end
1111
-
1112
- keys.each do |key|
1113
- acc[key] = value.fetch(key)
1114
- end
1115
-
1116
- great_success ? [true, new(acc), tally] : [false, true, tally]
1117
- end
1118
- end
1119
-
1120
- # Returns the raw value associated with the given key, if found. Otherwise, nil is
1121
- # returned.
1122
- #
1123
- # It is valid to lookup keys that are not in the API spec, for example to access
1124
- # undocumented features. This method does not parse response data into
1125
- # higher-level types. Lookup by anything other than a Symbol is an ArgumentError.
1126
- #
1127
- # @param key [Symbol]
1128
- #
1129
- # @return [Object, nil]
1130
- def [](key)
1131
- unless key.instance_of?(Symbol)
1132
- raise ArgumentError.new("Expected symbol key for lookup, got #{key.inspect}")
1133
- end
1134
-
1135
- @data[key]
1136
- end
1137
-
1138
- # Returns a Hash of the data underlying this object. O(1)
1139
- #
1140
- # Keys are Symbols and values are the raw values from the response. The return
1141
- # value indicates which values were ever set on the object. i.e. there will be a
1142
- # key in this hash if they ever were, even if the set value was nil.
1143
- #
1144
- # This method is not recursive. The returned value is shared by the object, so it
1145
- # should not be mutated.
1146
- #
1147
- # @return [Hash{Symbol=>Object}]
1148
- def to_h = @data
1149
-
1150
- alias_method :to_hash, :to_h
1151
-
1152
- # @param keys [Array<Symbol>, nil]
1153
- #
1154
- # @return [Hash{Symbol=>Object}]
1155
- def deconstruct_keys(keys)
1156
- (keys || self.class.known_fields.keys).filter_map do |k|
1157
- unless self.class.known_fields.key?(k)
1158
- next
1159
- end
1160
-
1161
- [k, method(k).call]
1162
- end
1163
- .to_h
1164
- end
1165
-
1166
- # Create a new instance of a model.
1167
- #
1168
- # @param data [Hash{Symbol=>Object}, TerminalShop::BaseModel]
1169
- def initialize(data = {})
1170
- case TerminalShop::Util.coerce_hash(data)
1171
- in Hash => coerced
1172
- @data = coerced.transform_keys(&:to_sym)
1173
- else
1174
- raise ArgumentError.new("Expected a #{Hash} or #{TerminalShop::BaseModel}, got #{data.inspect}")
1175
- end
1176
- end
1177
-
1178
- # @return [String]
1179
- def to_s = @data.to_s
1180
-
1181
- # @return [String]
1182
- def inspect
1183
- "#<#{self.class.name}:0x#{object_id.to_s(16)} #{deconstruct_keys(nil).map do |k, v|
1184
- "#{k}=#{v.inspect}"
1185
- end.join(' ')}>"
1186
- end
1187
- end
1188
- end