terminal-shop 0.1.0.pre.alpha.5

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 (276) hide show
  1. checksums.yaml +7 -0
  2. data/README.md +127 -0
  3. data/lib/terminal-shop/base_client.rb +452 -0
  4. data/lib/terminal-shop/base_model.rb +1189 -0
  5. data/lib/terminal-shop/base_page.rb +44 -0
  6. data/lib/terminal-shop/client.rb +135 -0
  7. data/lib/terminal-shop/errors.rb +187 -0
  8. data/lib/terminal-shop/extern.rb +10 -0
  9. data/lib/terminal-shop/models/address.rb +101 -0
  10. data/lib/terminal-shop/models/address_create_params.rb +86 -0
  11. data/lib/terminal-shop/models/address_create_response.rb +26 -0
  12. data/lib/terminal-shop/models/address_delete_params.rb +18 -0
  13. data/lib/terminal-shop/models/address_delete_response.rb +25 -0
  14. data/lib/terminal-shop/models/address_list_params.rb +18 -0
  15. data/lib/terminal-shop/models/address_list_response.rb +26 -0
  16. data/lib/terminal-shop/models/app.rb +44 -0
  17. data/lib/terminal-shop/models/app_create_params.rb +18 -0
  18. data/lib/terminal-shop/models/app_create_response.rb +54 -0
  19. data/lib/terminal-shop/models/app_delete_params.rb +18 -0
  20. data/lib/terminal-shop/models/app_delete_response.rb +25 -0
  21. data/lib/terminal-shop/models/app_get_params.rb +18 -0
  22. data/lib/terminal-shop/models/app_get_response.rb +26 -0
  23. data/lib/terminal-shop/models/app_list_params.rb +18 -0
  24. data/lib/terminal-shop/models/app_list_response.rb +26 -0
  25. data/lib/terminal-shop/models/card.rb +83 -0
  26. data/lib/terminal-shop/models/card_collect_params.rb +18 -0
  27. data/lib/terminal-shop/models/card_collect_response.rb +50 -0
  28. data/lib/terminal-shop/models/card_create_params.rb +26 -0
  29. data/lib/terminal-shop/models/card_create_response.rb +26 -0
  30. data/lib/terminal-shop/models/card_delete_params.rb +18 -0
  31. data/lib/terminal-shop/models/card_delete_response.rb +25 -0
  32. data/lib/terminal-shop/models/card_list_params.rb +18 -0
  33. data/lib/terminal-shop/models/card_list_response.rb +26 -0
  34. data/lib/terminal-shop/models/cart.rb +200 -0
  35. data/lib/terminal-shop/models/cart_convert_params.rb +18 -0
  36. data/lib/terminal-shop/models/cart_convert_response.rb +26 -0
  37. data/lib/terminal-shop/models/cart_get_params.rb +18 -0
  38. data/lib/terminal-shop/models/cart_get_response.rb +26 -0
  39. data/lib/terminal-shop/models/cart_set_address_params.rb +25 -0
  40. data/lib/terminal-shop/models/cart_set_address_response.rb +25 -0
  41. data/lib/terminal-shop/models/cart_set_card_params.rb +25 -0
  42. data/lib/terminal-shop/models/cart_set_card_response.rb +25 -0
  43. data/lib/terminal-shop/models/cart_set_item_params.rb +32 -0
  44. data/lib/terminal-shop/models/cart_set_item_response.rb +26 -0
  45. data/lib/terminal-shop/models/email_create_params.rb +25 -0
  46. data/lib/terminal-shop/models/email_create_response.rb +25 -0
  47. data/lib/terminal-shop/models/order.rb +303 -0
  48. data/lib/terminal-shop/models/order_get_params.rb +18 -0
  49. data/lib/terminal-shop/models/order_get_response.rb +26 -0
  50. data/lib/terminal-shop/models/order_list_params.rb +18 -0
  51. data/lib/terminal-shop/models/order_list_response.rb +26 -0
  52. data/lib/terminal-shop/models/product.rb +141 -0
  53. data/lib/terminal-shop/models/product_list_params.rb +18 -0
  54. data/lib/terminal-shop/models/product_list_response.rb +26 -0
  55. data/lib/terminal-shop/models/product_variant.rb +44 -0
  56. data/lib/terminal-shop/models/profile.rb +83 -0
  57. data/lib/terminal-shop/models/profile_me_params.rb +18 -0
  58. data/lib/terminal-shop/models/profile_me_response.rb +26 -0
  59. data/lib/terminal-shop/models/profile_update_params.rb +32 -0
  60. data/lib/terminal-shop/models/profile_update_response.rb +26 -0
  61. data/lib/terminal-shop/models/subscription.rb +113 -0
  62. data/lib/terminal-shop/models/subscription_create_params.rb +18 -0
  63. data/lib/terminal-shop/models/subscription_create_response.rb +25 -0
  64. data/lib/terminal-shop/models/subscription_delete_params.rb +18 -0
  65. data/lib/terminal-shop/models/subscription_delete_response.rb +25 -0
  66. data/lib/terminal-shop/models/subscription_list_params.rb +18 -0
  67. data/lib/terminal-shop/models/subscription_list_response.rb +26 -0
  68. data/lib/terminal-shop/models/token.rb +68 -0
  69. data/lib/terminal-shop/models/token_create_params.rb +18 -0
  70. data/lib/terminal-shop/models/token_create_response.rb +55 -0
  71. data/lib/terminal-shop/models/token_delete_params.rb +18 -0
  72. data/lib/terminal-shop/models/token_delete_response.rb +25 -0
  73. data/lib/terminal-shop/models/token_get_params.rb +18 -0
  74. data/lib/terminal-shop/models/token_get_response.rb +27 -0
  75. data/lib/terminal-shop/models/token_list_params.rb +18 -0
  76. data/lib/terminal-shop/models/token_list_response.rb +26 -0
  77. data/lib/terminal-shop/models/view_init_params.rb +18 -0
  78. data/lib/terminal-shop/models/view_init_response.rb +103 -0
  79. data/lib/terminal-shop/pooled_net_requester.rb +94 -0
  80. data/lib/terminal-shop/request_options.rb +115 -0
  81. data/lib/terminal-shop/resources/address.rb +84 -0
  82. data/lib/terminal-shop/resources/app.rb +93 -0
  83. data/lib/terminal-shop/resources/card.rb +89 -0
  84. data/lib/terminal-shop/resources/cart.rb +112 -0
  85. data/lib/terminal-shop/resources/email.rb +34 -0
  86. data/lib/terminal-shop/resources/order.rb +49 -0
  87. data/lib/terminal-shop/resources/product.rb +30 -0
  88. data/lib/terminal-shop/resources/profile.rb +53 -0
  89. data/lib/terminal-shop/resources/subscription.rb +82 -0
  90. data/lib/terminal-shop/resources/token.rb +85 -0
  91. data/lib/terminal-shop/resources/view.rb +31 -0
  92. data/lib/terminal-shop/util.rb +460 -0
  93. data/lib/terminal-shop/version.rb +5 -0
  94. data/lib/terminal-shop.rb +110 -0
  95. data/manifest.yaml +12 -0
  96. data/rbi/lib/terminal-shop/base_client.rbi +145 -0
  97. data/rbi/lib/terminal-shop/base_model.rbi +514 -0
  98. data/rbi/lib/terminal-shop/base_page.rbi +38 -0
  99. data/rbi/lib/terminal-shop/client.rbi +80 -0
  100. data/rbi/lib/terminal-shop/errors.rbi +133 -0
  101. data/rbi/lib/terminal-shop/extern.rbi +7 -0
  102. data/rbi/lib/terminal-shop/models/address.rbi +77 -0
  103. data/rbi/lib/terminal-shop/models/address_create_params.rbi +87 -0
  104. data/rbi/lib/terminal-shop/models/address_create_response.rbi +18 -0
  105. data/rbi/lib/terminal-shop/models/address_delete_params.rbi +18 -0
  106. data/rbi/lib/terminal-shop/models/address_delete_response.rbi +18 -0
  107. data/rbi/lib/terminal-shop/models/address_list_params.rbi +18 -0
  108. data/rbi/lib/terminal-shop/models/address_list_response.rbi +18 -0
  109. data/rbi/lib/terminal-shop/models/app.rbi +24 -0
  110. data/rbi/lib/terminal-shop/models/app_create_params.rbi +18 -0
  111. data/rbi/lib/terminal-shop/models/app_create_response.rbi +34 -0
  112. data/rbi/lib/terminal-shop/models/app_delete_params.rbi +18 -0
  113. data/rbi/lib/terminal-shop/models/app_delete_response.rbi +18 -0
  114. data/rbi/lib/terminal-shop/models/app_get_params.rbi +18 -0
  115. data/rbi/lib/terminal-shop/models/app_get_response.rbi +18 -0
  116. data/rbi/lib/terminal-shop/models/app_list_params.rbi +18 -0
  117. data/rbi/lib/terminal-shop/models/app_list_response.rbi +18 -0
  118. data/rbi/lib/terminal-shop/models/card.rbi +59 -0
  119. data/rbi/lib/terminal-shop/models/card_collect_params.rbi +18 -0
  120. data/rbi/lib/terminal-shop/models/card_collect_response.rbi +31 -0
  121. data/rbi/lib/terminal-shop/models/card_create_params.rbi +26 -0
  122. data/rbi/lib/terminal-shop/models/card_create_response.rbi +18 -0
  123. data/rbi/lib/terminal-shop/models/card_delete_params.rbi +18 -0
  124. data/rbi/lib/terminal-shop/models/card_delete_response.rbi +18 -0
  125. data/rbi/lib/terminal-shop/models/card_list_params.rbi +18 -0
  126. data/rbi/lib/terminal-shop/models/card_list_response.rbi +18 -0
  127. data/rbi/lib/terminal-shop/models/cart.rbi +127 -0
  128. data/rbi/lib/terminal-shop/models/cart_convert_params.rbi +18 -0
  129. data/rbi/lib/terminal-shop/models/cart_convert_response.rbi +18 -0
  130. data/rbi/lib/terminal-shop/models/cart_get_params.rbi +18 -0
  131. data/rbi/lib/terminal-shop/models/cart_get_response.rbi +18 -0
  132. data/rbi/lib/terminal-shop/models/cart_set_address_params.rbi +26 -0
  133. data/rbi/lib/terminal-shop/models/cart_set_address_response.rbi +18 -0
  134. data/rbi/lib/terminal-shop/models/cart_set_card_params.rbi +26 -0
  135. data/rbi/lib/terminal-shop/models/cart_set_card_response.rbi +18 -0
  136. data/rbi/lib/terminal-shop/models/cart_set_item_params.rbi +38 -0
  137. data/rbi/lib/terminal-shop/models/cart_set_item_response.rbi +18 -0
  138. data/rbi/lib/terminal-shop/models/email_create_params.rbi +26 -0
  139. data/rbi/lib/terminal-shop/models/email_create_response.rbi +18 -0
  140. data/rbi/lib/terminal-shop/models/order.rbi +216 -0
  141. data/rbi/lib/terminal-shop/models/order_get_params.rbi +18 -0
  142. data/rbi/lib/terminal-shop/models/order_get_response.rbi +18 -0
  143. data/rbi/lib/terminal-shop/models/order_list_params.rbi +18 -0
  144. data/rbi/lib/terminal-shop/models/order_list_response.rbi +18 -0
  145. data/rbi/lib/terminal-shop/models/product.rbi +94 -0
  146. data/rbi/lib/terminal-shop/models/product_list_params.rbi +18 -0
  147. data/rbi/lib/terminal-shop/models/product_list_response.rbi +18 -0
  148. data/rbi/lib/terminal-shop/models/product_variant.rbi +24 -0
  149. data/rbi/lib/terminal-shop/models/profile.rbi +61 -0
  150. data/rbi/lib/terminal-shop/models/profile_me_params.rbi +18 -0
  151. data/rbi/lib/terminal-shop/models/profile_me_response.rbi +18 -0
  152. data/rbi/lib/terminal-shop/models/profile_update_params.rbi +38 -0
  153. data/rbi/lib/terminal-shop/models/profile_update_response.rbi +18 -0
  154. data/rbi/lib/terminal-shop/models/subscription.rbi +75 -0
  155. data/rbi/lib/terminal-shop/models/subscription_create_params.rbi +18 -0
  156. data/rbi/lib/terminal-shop/models/subscription_create_response.rbi +18 -0
  157. data/rbi/lib/terminal-shop/models/subscription_delete_params.rbi +18 -0
  158. data/rbi/lib/terminal-shop/models/subscription_delete_response.rbi +18 -0
  159. data/rbi/lib/terminal-shop/models/subscription_list_params.rbi +18 -0
  160. data/rbi/lib/terminal-shop/models/subscription_list_response.rbi +18 -0
  161. data/rbi/lib/terminal-shop/models/token.rbi +37 -0
  162. data/rbi/lib/terminal-shop/models/token_create_params.rbi +18 -0
  163. data/rbi/lib/terminal-shop/models/token_create_response.rbi +34 -0
  164. data/rbi/lib/terminal-shop/models/token_delete_params.rbi +18 -0
  165. data/rbi/lib/terminal-shop/models/token_delete_response.rbi +18 -0
  166. data/rbi/lib/terminal-shop/models/token_get_params.rbi +18 -0
  167. data/rbi/lib/terminal-shop/models/token_get_response.rbi +18 -0
  168. data/rbi/lib/terminal-shop/models/token_list_params.rbi +18 -0
  169. data/rbi/lib/terminal-shop/models/token_list_response.rbi +18 -0
  170. data/rbi/lib/terminal-shop/models/view_init_params.rbi +18 -0
  171. data/rbi/lib/terminal-shop/models/view_init_response.rbi +91 -0
  172. data/rbi/lib/terminal-shop/request_options.rbi +40 -0
  173. data/rbi/lib/terminal-shop/resources/address.rbi +60 -0
  174. data/rbi/lib/terminal-shop/resources/app.rbi +54 -0
  175. data/rbi/lib/terminal-shop/resources/card.rbi +57 -0
  176. data/rbi/lib/terminal-shop/resources/cart.rbi +67 -0
  177. data/rbi/lib/terminal-shop/resources/email.rbi +20 -0
  178. data/rbi/lib/terminal-shop/resources/order.rbi +34 -0
  179. data/rbi/lib/terminal-shop/resources/product.rbi +25 -0
  180. data/rbi/lib/terminal-shop/resources/profile.rbi +35 -0
  181. data/rbi/lib/terminal-shop/resources/subscription.rbi +58 -0
  182. data/rbi/lib/terminal-shop/resources/token.rbi +57 -0
  183. data/rbi/lib/terminal-shop/resources/view.rbi +25 -0
  184. data/rbi/lib/terminal-shop/util.rbi +128 -0
  185. data/rbi/lib/terminal-shop/version.rbi +5 -0
  186. data/sig/terminal-shop/base_client.rbs +100 -0
  187. data/sig/terminal-shop/base_model.rbs +246 -0
  188. data/sig/terminal-shop/base_page.rbs +20 -0
  189. data/sig/terminal-shop/client.rbs +52 -0
  190. data/sig/terminal-shop/errors.rbs +98 -0
  191. data/sig/terminal-shop/extern.rbs +4 -0
  192. data/sig/terminal-shop/models/address.rbs +60 -0
  193. data/sig/terminal-shop/models/address_create_params.rbs +62 -0
  194. data/sig/terminal-shop/models/address_create_response.rbs +18 -0
  195. data/sig/terminal-shop/models/address_delete_params.rbs +19 -0
  196. data/sig/terminal-shop/models/address_delete_response.rbs +18 -0
  197. data/sig/terminal-shop/models/address_list_params.rbs +19 -0
  198. data/sig/terminal-shop/models/address_list_response.rbs +19 -0
  199. data/sig/terminal-shop/models/app.rbs +21 -0
  200. data/sig/terminal-shop/models/app_create_params.rbs +19 -0
  201. data/sig/terminal-shop/models/app_create_response.rbs +36 -0
  202. data/sig/terminal-shop/models/app_delete_params.rbs +19 -0
  203. data/sig/terminal-shop/models/app_delete_response.rbs +18 -0
  204. data/sig/terminal-shop/models/app_get_params.rbs +18 -0
  205. data/sig/terminal-shop/models/app_get_response.rbs +17 -0
  206. data/sig/terminal-shop/models/app_list_params.rbs +18 -0
  207. data/sig/terminal-shop/models/app_list_response.rbs +18 -0
  208. data/sig/terminal-shop/models/card.rbs +51 -0
  209. data/sig/terminal-shop/models/card_collect_params.rbs +19 -0
  210. data/sig/terminal-shop/models/card_collect_response.rbs +34 -0
  211. data/sig/terminal-shop/models/card_create_params.rbs +22 -0
  212. data/sig/terminal-shop/models/card_create_response.rbs +18 -0
  213. data/sig/terminal-shop/models/card_delete_params.rbs +19 -0
  214. data/sig/terminal-shop/models/card_delete_response.rbs +18 -0
  215. data/sig/terminal-shop/models/card_list_params.rbs +18 -0
  216. data/sig/terminal-shop/models/card_list_response.rbs +18 -0
  217. data/sig/terminal-shop/models/cart.rbs +119 -0
  218. data/sig/terminal-shop/models/cart_convert_params.rbs +19 -0
  219. data/sig/terminal-shop/models/cart_convert_response.rbs +18 -0
  220. data/sig/terminal-shop/models/cart_get_params.rbs +18 -0
  221. data/sig/terminal-shop/models/cart_get_response.rbs +18 -0
  222. data/sig/terminal-shop/models/cart_set_address_params.rbs +25 -0
  223. data/sig/terminal-shop/models/cart_set_address_response.rbs +18 -0
  224. data/sig/terminal-shop/models/cart_set_card_params.rbs +22 -0
  225. data/sig/terminal-shop/models/cart_set_card_response.rbs +18 -0
  226. data/sig/terminal-shop/models/cart_set_item_params.rbs +29 -0
  227. data/sig/terminal-shop/models/cart_set_item_response.rbs +18 -0
  228. data/sig/terminal-shop/models/email_create_params.rbs +22 -0
  229. data/sig/terminal-shop/models/email_create_response.rbs +18 -0
  230. data/sig/terminal-shop/models/order.rbs +179 -0
  231. data/sig/terminal-shop/models/order_get_params.rbs +18 -0
  232. data/sig/terminal-shop/models/order_get_response.rbs +18 -0
  233. data/sig/terminal-shop/models/order_list_params.rbs +19 -0
  234. data/sig/terminal-shop/models/order_list_response.rbs +18 -0
  235. data/sig/terminal-shop/models/product.rbs +76 -0
  236. data/sig/terminal-shop/models/product_list_params.rbs +19 -0
  237. data/sig/terminal-shop/models/product_list_response.rbs +19 -0
  238. data/sig/terminal-shop/models/product_variant.rbs +21 -0
  239. data/sig/terminal-shop/models/profile.rbs +53 -0
  240. data/sig/terminal-shop/models/profile_me_params.rbs +19 -0
  241. data/sig/terminal-shop/models/profile_me_response.rbs +18 -0
  242. data/sig/terminal-shop/models/profile_update_params.rbs +28 -0
  243. data/sig/terminal-shop/models/profile_update_response.rbs +18 -0
  244. data/sig/terminal-shop/models/subscription.rbs +60 -0
  245. data/sig/terminal-shop/models/subscription_create_params.rbs +19 -0
  246. data/sig/terminal-shop/models/subscription_create_response.rbs +18 -0
  247. data/sig/terminal-shop/models/subscription_delete_params.rbs +19 -0
  248. data/sig/terminal-shop/models/subscription_delete_response.rbs +18 -0
  249. data/sig/terminal-shop/models/subscription_list_params.rbs +19 -0
  250. data/sig/terminal-shop/models/subscription_list_response.rbs +19 -0
  251. data/sig/terminal-shop/models/token.rbs +40 -0
  252. data/sig/terminal-shop/models/token_create_params.rbs +19 -0
  253. data/sig/terminal-shop/models/token_create_response.rbs +36 -0
  254. data/sig/terminal-shop/models/token_delete_params.rbs +19 -0
  255. data/sig/terminal-shop/models/token_delete_response.rbs +18 -0
  256. data/sig/terminal-shop/models/token_get_params.rbs +18 -0
  257. data/sig/terminal-shop/models/token_get_response.rbs +18 -0
  258. data/sig/terminal-shop/models/token_list_params.rbs +19 -0
  259. data/sig/terminal-shop/models/token_list_response.rbs +18 -0
  260. data/sig/terminal-shop/models/view_init_params.rbs +18 -0
  261. data/sig/terminal-shop/models/view_init_response.rbs +71 -0
  262. data/sig/terminal-shop/request_options.rbs +42 -0
  263. data/sig/terminal-shop/resources/address.rbs +41 -0
  264. data/sig/terminal-shop/resources/app.rbs +46 -0
  265. data/sig/terminal-shop/resources/card.rbs +42 -0
  266. data/sig/terminal-shop/resources/cart.rbs +51 -0
  267. data/sig/terminal-shop/resources/email.rbs +16 -0
  268. data/sig/terminal-shop/resources/order.rbs +25 -0
  269. data/sig/terminal-shop/resources/product.rbs +15 -0
  270. data/sig/terminal-shop/resources/profile.rbs +25 -0
  271. data/sig/terminal-shop/resources/subscription.rbs +43 -0
  272. data/sig/terminal-shop/resources/token.rbs +43 -0
  273. data/sig/terminal-shop/resources/view.rbs +15 -0
  274. data/sig/terminal-shop/util.rbs +85 -0
  275. data/sig/terminal-shop/version.rbs +3 -0
  276. metadata +333 -0
checksums.yaml ADDED
@@ -0,0 +1,7 @@
1
+ ---
2
+ SHA256:
3
+ metadata.gz: e704b8a4a9cafad6a1d79786d5776fc7fe4d414891dc728dc2846fa97ad92d6b
4
+ data.tar.gz: ba8a7dd2383e49209caff17134baa50d22651eac0f85fb14be7f902f067209bd
5
+ SHA512:
6
+ metadata.gz: 1d15f11e333baa688f83beaf05a9128a47e24b0de5101cee4a18e4a276ec1a5cfd4c3cec242bdc4f0dd2be498af2fd5c64e27ea8a04df139698f76c3d2692b72
7
+ data.tar.gz: db877d28fa6cae93e9c80accaa44b16bda8fe1698c716dff9d9a83229f1a8ef1880e5ef78f35ee577450f1b2e0518f3f022e6dbaa2a6d82afb9d91ed8580703d
data/README.md ADDED
@@ -0,0 +1,127 @@
1
+ # Terminal Ruby API library
2
+
3
+ The Terminal Ruby library provides convenient access to the Terminal REST API from any Ruby 3.0+
4
+ application.
5
+
6
+ It is generated with [Stainless](https://www.stainlessapi.com/).
7
+
8
+ ## Documentation
9
+
10
+ Documentation for the most recent release of this gem can be found [on RubyDoc](https://gemdocs.org/gems/terminal-shop/latest).
11
+
12
+ The underlying REST API documentation can be found on [terminal.shop](https://terminal.shop/docs).
13
+
14
+ ## Installation
15
+
16
+ To use this gem during the beta, install directly from GitHub with Bundler by
17
+ adding the following to your application's `Gemfile`:
18
+
19
+ ```ruby
20
+ gem "terminal-shop", git: "https://github.com/terminaldotshop/terminal-sdk-ruby", branch: "main"
21
+ ```
22
+
23
+ To fetch an initial copy of the gem:
24
+
25
+ ```sh
26
+ bundle install
27
+ ```
28
+
29
+ To update the version used by your application when updates are pushed to
30
+ GitHub:
31
+
32
+ ```sh
33
+ bundle update terminal-shop
34
+ ```
35
+
36
+ ## Usage
37
+
38
+ ```ruby
39
+ require "bundler/setup"
40
+ require "terminal-shop"
41
+
42
+ terminal = TerminalShop::Client.new(
43
+ bearer_token: "My Bearer Token", # defaults to ENV["TERMINAL_BEARER_TOKEN"]
44
+ environment: "sandbox" # defaults to "production"
45
+ )
46
+
47
+ product = terminal.product.list
48
+
49
+ puts(product.data)
50
+ ```
51
+
52
+ ### Errors
53
+
54
+ When the library is unable to connect to the API, or if the API returns a
55
+ non-success status code (i.e., 4xx or 5xx response), a subclass of
56
+ `TerminalShop::Error` will be thrown:
57
+
58
+ ```ruby
59
+ begin
60
+ product = terminal.product.list
61
+ rescue TerminalShop::Error => e
62
+ puts(e.status) # 400
63
+ end
64
+ ```
65
+
66
+ Error codes are as followed:
67
+
68
+ | Cause | Error Type |
69
+ | ---------------- | -------------------------- |
70
+ | HTTP 400 | `BadRequestError` |
71
+ | HTTP 401 | `AuthenticationError` |
72
+ | HTTP 403 | `PermissionDeniedError` |
73
+ | HTTP 404 | `NotFoundError` |
74
+ | HTTP 409 | `ConflictError` |
75
+ | HTTP 422 | `UnprocessableEntityError` |
76
+ | HTTP 429 | `RateLimitError` |
77
+ | HTTP >=500 | `InternalServerError` |
78
+ | Other HTTP error | `APIStatusError` |
79
+ | Timeout | `APITimeoutError` |
80
+ | Network error | `APIConnectionError` |
81
+
82
+ ### Retries
83
+
84
+ Certain errors will be automatically retried 2 times by default, with a short
85
+ exponential backoff. Connection errors (for example, due to a network
86
+ connectivity problem), 408 Request Timeout, 409 Conflict, 429 Rate Limit, >=500 Internal errors,
87
+ and timeouts will all be retried by default.
88
+
89
+ You can use the `max_retries` option to configure or disable this:
90
+
91
+ ```ruby
92
+ # Configure the default for all requests:
93
+ terminal = TerminalShop::Client.new(
94
+ max_retries: 0 # default is 2
95
+ )
96
+
97
+ # Or, configure per-request:
98
+ terminal.product.list(request_options: {max_retries: 5})
99
+ ```
100
+
101
+ ### Timeouts
102
+
103
+ By default, requests will time out after 60 seconds.
104
+ Timeouts are applied separately to the initial connection and the overall request time,
105
+ so in some cases a request could wait 2\*timeout seconds before it fails.
106
+
107
+ You can use the `timeout` option to configure or disable this:
108
+
109
+ ```ruby
110
+ # Configure the default for all requests:
111
+ terminal = TerminalShop::Client.new(
112
+ timeout: nil # default is 60
113
+ )
114
+
115
+ # Or, configure per-request:
116
+ terminal.product.list(request_options: {timeout: 5})
117
+ ```
118
+
119
+ ## Versioning
120
+
121
+ This package follows [SemVer](https://semver.org/spec/v2.0.0.html) conventions. As the
122
+ library is in initial development and has a major version of `0`, APIs may change
123
+ at any time.
124
+
125
+ ## Requirements
126
+
127
+ Ruby 3.0 or higher.
@@ -0,0 +1,452 @@
1
+ # frozen_string_literal: true
2
+
3
+ module TerminalShop
4
+ # @private
5
+ #
6
+ # @abstract
7
+ #
8
+ class BaseClient
9
+ # from whatwg fetch spec
10
+ MAX_REDIRECTS = 20
11
+
12
+ # @private
13
+ #
14
+ # @param req [Hash{Symbol=>Object}]
15
+ #
16
+ # @raise [ArgumentError]
17
+ #
18
+ def self.validate!(req)
19
+ keys = [:method, :path, :query, :headers, :body, :unwrap, :page, :model, :options]
20
+ case req
21
+ in Hash
22
+ req.each_key do |k|
23
+ unless keys.include?(k)
24
+ raise ArgumentError.new("Request `req` keys must be one of #{keys}, got #{k.inspect}")
25
+ end
26
+ end
27
+ else
28
+ raise ArgumentError.new("Request `req` must be a Hash or RequestOptions, got #{req.inspect}")
29
+ end
30
+ end
31
+
32
+ # @private
33
+ #
34
+ # @return [TerminalShop::PooledNetRequester]
35
+ attr_accessor :requester
36
+
37
+ # @private
38
+ #
39
+ # @param base_url [String]
40
+ # @param timeout [Float]
41
+ # @param max_retries [Integer]
42
+ # @param initial_retry_delay [Float]
43
+ # @param max_retry_delay [Float]
44
+ # @param headers [Hash{String=>String, nil}]
45
+ # @param idempotency_header [String, nil]
46
+ #
47
+ def initialize(
48
+ base_url:,
49
+ timeout: 0.0,
50
+ max_retries: 0,
51
+ initial_retry_delay: 0.0,
52
+ max_retry_delay: 0.0,
53
+ headers: {},
54
+ idempotency_header: nil
55
+ )
56
+ @requester = TerminalShop::PooledNetRequester.new
57
+ @headers = TerminalShop::Util.normalized_headers(
58
+ {
59
+ "X-Stainless-Lang" => "ruby",
60
+ "X-Stainless-Package-Version" => TerminalShop::VERSION,
61
+ "X-Stainless-Runtime" => RUBY_ENGINE,
62
+ "X-Stainless-Runtime-Version" => RUBY_ENGINE_VERSION,
63
+ "Content-Type" => "application/json",
64
+ "Accept" => "application/json"
65
+ },
66
+ headers
67
+ )
68
+ @base_url = TerminalShop::Util.parse_uri(base_url)
69
+ @idempotency_header = idempotency_header&.to_s&.downcase
70
+ @max_retries = max_retries
71
+ @timeout = timeout
72
+ @initial_retry_delay = initial_retry_delay
73
+ @max_retry_delay = max_retry_delay
74
+ end
75
+
76
+ # @private
77
+ #
78
+ # @return [Hash{String=>String}]
79
+ #
80
+ private def auth_headers = {}
81
+
82
+ # @private
83
+ #
84
+ # @return [String]
85
+ #
86
+ private def generate_idempotency_key = "stainless-ruby-retry-#{SecureRandom.uuid}"
87
+
88
+ # @private
89
+ #
90
+ # @param req [Hash{Symbol=>Object}] .
91
+ #
92
+ # @option req [Symbol] :method
93
+ #
94
+ # @option req [String, Array<String>] :path
95
+ #
96
+ # @option req [Hash{String=>Array<String>, String, nil}, nil] :query
97
+ #
98
+ # @option req [Hash{String=>String, nil}, nil] :headers
99
+ #
100
+ # @option req [Object, nil] :body
101
+ #
102
+ # @option req [Symbol, nil] :unwrap
103
+ #
104
+ # @option req [Class, nil] :page
105
+ #
106
+ # @option req [TerminalShop::Converter, Class, nil] :model
107
+ #
108
+ # @param opts [Hash{Symbol=>Object}] .
109
+ #
110
+ # @option opts [String, nil] :idempotency_key
111
+ #
112
+ # @option opts [Hash{String=>Array<String>, String, nil}, nil] :extra_query
113
+ #
114
+ # @option opts [Hash{String=>String, nil}, nil] :extra_headers
115
+ #
116
+ # @option opts [Hash{Symbol=>Object}, nil] :extra_body
117
+ #
118
+ # @option opts [Integer, nil] :max_retries
119
+ #
120
+ # @option opts [Float, nil] :timeout
121
+ #
122
+ # @return [Hash{Symbol=>Object}]
123
+ #
124
+ private def build_request(req, opts)
125
+ method, uninterpolated_path = req.fetch_values(:method, :path)
126
+
127
+ path = TerminalShop::Util.interpolate_path(uninterpolated_path)
128
+
129
+ headers = TerminalShop::Util.normalized_headers(
130
+ @headers,
131
+ auth_headers,
132
+ *[req[:headers], opts[:extra_headers]].compact
133
+ )
134
+
135
+ if @idempotency_header &&
136
+ !headers.key?(@idempotency_header) &&
137
+ !Net::HTTP::IDEMPOTENT_METHODS_.include?(method.to_s.upcase)
138
+ headers[@idempotency_header] = opts.fetch(:idempotency_key) { generate_idempotency_key }
139
+ end
140
+
141
+ unless headers.key?("x-stainless-retry-count")
142
+ headers["x-stainless-retry-count"] = "0"
143
+ end
144
+
145
+ timeout = opts.fetch(:timeout, @timeout).to_f.clamp((0..))
146
+ unless headers.key?("x-stainless-read-timeout") || timeout.zero?
147
+ headers["x-stainless-read-timeout"] = timeout.to_s
148
+ end
149
+
150
+ headers.reject! { |_, v| v.to_s.empty? }
151
+
152
+ body =
153
+ case method
154
+ in :get | :head | :options | :trace
155
+ nil
156
+ else
157
+ TerminalShop::Util.deep_merge(*[req[:body], opts[:extra_body]].compact)
158
+ end
159
+
160
+ url = TerminalShop::Util.join_parsed_uri(@base_url, {**req, path: path})
161
+ headers, encoded = TerminalShop::Util.encode_content(headers, body)
162
+ max_retries = opts.fetch(:max_retries, @max_retries)
163
+ {method: method, url: url, headers: headers, body: encoded, max_retries: max_retries, timeout: timeout}
164
+ end
165
+
166
+ # @private
167
+ #
168
+ # @param status [Integer]
169
+ # @param headers [Hash{String=>String}]
170
+ #
171
+ # @return [Boolean]
172
+ #
173
+ private def should_retry?(status, headers:)
174
+ coerced = TerminalShop::Util.coerce_boolean(headers["x-should-retry"])
175
+ case [coerced, status]
176
+ in [true | false, _]
177
+ coerced
178
+ in [_, 408 | 409 | 429 | (500..)]
179
+ # retry on:
180
+ # 408: timeouts
181
+ # 409: locks
182
+ # 429: rate limits
183
+ # 500+: unknown errors
184
+ true
185
+ else
186
+ false
187
+ end
188
+ end
189
+
190
+ # @private
191
+ #
192
+ # @param headers [Hash{String=>String}]
193
+ # @param retry_count [Integer]
194
+ #
195
+ # @return [Float]
196
+ #
197
+ private def retry_delay(headers, retry_count:)
198
+ # Non-standard extension
199
+ span = Float(headers["retry-after-ms"], exception: false)&.then { _1 / 1000 }
200
+ return span if span
201
+
202
+ retry_header = headers["retry-after"]
203
+ return span if (span = Float(retry_header, exception: false))
204
+
205
+ span = retry_header && TerminalShop::Util.suppress(ArgumentError) do
206
+ Time.httpdate(retry_header) - Time.now
207
+ end
208
+ return span if span
209
+
210
+ scale = retry_count**2
211
+ jitter = 1 - (0.25 * rand)
212
+ (@initial_retry_delay * scale * jitter).clamp(0, @max_retry_delay)
213
+ end
214
+
215
+ # @private
216
+ #
217
+ # @param request [Hash{Symbol=>Object}] .
218
+ #
219
+ # @option request [Symbol] :method
220
+ #
221
+ # @option request [URI::Generic] :url
222
+ #
223
+ # @option request [Hash{String=>String}] :headers
224
+ #
225
+ # @option request [Object] :body
226
+ #
227
+ # @option request [Integer] :max_retries
228
+ #
229
+ # @option request [Float] :timeout
230
+ #
231
+ # @param status [Integer]
232
+ #
233
+ # @param location_header [String]
234
+ #
235
+ # @return [Hash{Symbol=>Object}]
236
+ #
237
+ private def follow_redirect(request, status:, location_header:)
238
+ method, url, headers = request.fetch_values(:method, :url, :headers)
239
+ location =
240
+ TerminalShop::Util.suppress(ArgumentError) do
241
+ URI.join(url, location_header)
242
+ end
243
+
244
+ unless location
245
+ message = "Server responded with status #{status} but no valid location header."
246
+ raise TerminalShop::APIConnectionError.new(url: url, message: message)
247
+ end
248
+
249
+ request = {**request, url: location}
250
+
251
+ case [url.scheme, location.scheme]
252
+ in ["https", "http"]
253
+ message = "Tried to redirect to a insecure URL"
254
+ raise TerminalShop::APIConnectionError.new(url: url, message: message)
255
+ else
256
+ nil
257
+ end
258
+
259
+ # from whatwg fetch spec
260
+ case [status, method]
261
+ in [301 | 302, :post] | [303, _]
262
+ drop = %w[content-encoding content-language content-length content-location content-type]
263
+ request = {
264
+ **request,
265
+ method: method == :head ? :head : :get,
266
+ headers: headers.except(*drop),
267
+ body: nil
268
+ }
269
+ else
270
+ end
271
+
272
+ # from undici
273
+ if TerminalShop::Util.uri_origin(url) != TerminalShop::Util.uri_origin(location)
274
+ drop = %w[authorization cookie host proxy-authorization]
275
+ request = {**request, headers: request.fetch(:headers).except(*drop)}
276
+ end
277
+
278
+ request
279
+ end
280
+
281
+ # @private
282
+ #
283
+ # @param request [Hash{Symbol=>Object}] .
284
+ #
285
+ # @option request [Symbol] :method
286
+ #
287
+ # @option request [URI::Generic] :url
288
+ #
289
+ # @option request [Hash{String=>String}] :headers
290
+ #
291
+ # @option request [Object] :body
292
+ #
293
+ # @option request [Integer] :max_retries
294
+ #
295
+ # @option request [Float] :timeout
296
+ #
297
+ # @param redirect_count [Integer]
298
+ #
299
+ # @param retry_count [Integer]
300
+ #
301
+ # @param send_retry_header [Boolean]
302
+ #
303
+ # @raise [TerminalShop::APIError]
304
+ # @return [Net::HTTPResponse]
305
+ #
306
+ private def send_request(request, redirect_count:, retry_count:, send_retry_header:)
307
+ url, headers, body, max_retries = request.fetch_values(:url, :headers, :body, :max_retries)
308
+ no_retry = retry_count >= max_retries || body.is_a?(IO) || body.is_a?(StringIO)
309
+
310
+ if send_retry_header
311
+ headers["x-stainless-retry-count"] = retry_count.to_s
312
+ end
313
+
314
+ begin
315
+ response = @requester.execute(request)
316
+ status = Integer(response.code)
317
+ rescue TerminalShop::APIConnectionError => e
318
+ status = e
319
+ end
320
+
321
+ case status
322
+ in ..299
323
+ response
324
+ in 300..399 if redirect_count >= MAX_REDIRECTS
325
+ message = "Failed to complete the request within #{MAX_REDIRECTS} redirects."
326
+ raise TerminalShop::APIConnectionError.new(url: url, message: message)
327
+ in 300..399
328
+ request = follow_redirect(request, status: status, location_header: response["location"])
329
+ send_request(
330
+ request,
331
+ redirect_count: redirect_count + 1,
332
+ retry_count: retry_count,
333
+ send_retry_header: send_retry_header
334
+ )
335
+ in TerminalShop::APIConnectionError if retry_count >= max_retries
336
+ raise status
337
+ in (400..) if no_retry || (response && !should_retry?(status, headers: response))
338
+ body = TerminalShop::Util.decode_content(response, suppress_error: true)
339
+
340
+ raise TerminalShop::APIStatusError.for(
341
+ url: url,
342
+ status: status,
343
+ body: body,
344
+ request: nil,
345
+ response: response
346
+ )
347
+ in (400..) | TerminalShop::APIConnectionError
348
+ delay = retry_delay(response, retry_count: retry_count)
349
+ sleep(delay)
350
+
351
+ send_request(
352
+ request,
353
+ redirect_count: redirect_count,
354
+ retry_count: retry_count + 1,
355
+ send_retry_header: send_retry_header
356
+ )
357
+ end
358
+ end
359
+
360
+ # @private
361
+ #
362
+ # @param req [Hash{Symbol=>Object}] .
363
+ #
364
+ # @option req [Symbol] :method
365
+ #
366
+ # @option req [String, Array<String>] :path
367
+ #
368
+ # @option req [Hash{String=>Array<String>, String, nil}, nil] :query
369
+ #
370
+ # @option req [Hash{String=>String, nil}, nil] :headers
371
+ #
372
+ # @option req [Object, nil] :body
373
+ #
374
+ # @option req [Symbol, nil] :unwrap
375
+ #
376
+ # @option req [Class, nil] :page
377
+ #
378
+ # @option req [TerminalShop::Converter, Class, nil] :model
379
+ #
380
+ # @option req [TerminalShop::RequestOptions, Hash{Symbol=>Object}, nil] :options
381
+ #
382
+ # @param response [nil]
383
+ #
384
+ # @return [Object]
385
+ #
386
+ private def parse_response(req, response)
387
+ parsed = TerminalShop::Util.decode_content(response)
388
+ unwrapped = TerminalShop::Util.dig(parsed, req[:unwrap])
389
+
390
+ page = req[:page]
391
+ model = req.fetch(:model, TerminalShop::Unknown)
392
+ case [page, model]
393
+ in [Class, Class | TerminalShop::Converter | nil]
394
+ page.new(client: self, req: req, headers: response, unwrapped: unwrapped)
395
+ in [nil, Class | TerminalShop::Converter]
396
+ TerminalShop::Converter.coerce(model, unwrapped)
397
+ in [nil, nil]
398
+ unwrapped
399
+ end
400
+ end
401
+
402
+ # Execute the request specified by `req`. This is the method that all resource
403
+ # methods call into.
404
+ #
405
+ # @param req [Hash{Symbol=>Object}] .
406
+ #
407
+ # @option req [Symbol] :method
408
+ #
409
+ # @option req [String, Array<String>] :path
410
+ #
411
+ # @option req [Hash{String=>Array<String>, String, nil}, nil] :query
412
+ #
413
+ # @option req [Hash{String=>String, nil}, nil] :headers
414
+ #
415
+ # @option req [Object, nil] :body
416
+ #
417
+ # @option req [Symbol, nil] :unwrap
418
+ #
419
+ # @option req [Class, nil] :page
420
+ #
421
+ # @option req [TerminalShop::Converter, Class, nil] :model
422
+ #
423
+ # @option req [TerminalShop::RequestOptions, Hash{Symbol=>Object}, nil] :options
424
+ #
425
+ # @raise [TerminalShop::APIError]
426
+ # @return [Object]
427
+ #
428
+ def request(req)
429
+ self.class.validate!(req)
430
+ opts = req[:options].to_h
431
+ TerminalShop::RequestOptions.validate!(opts)
432
+ request = build_request(req, opts)
433
+
434
+ # Don't send the current retry count in the headers if the caller modified the header defaults.
435
+ send_retry_header = request.fetch(:headers)["x-stainless-retry-count"] == "0"
436
+ response = send_request(
437
+ request,
438
+ redirect_count: 0,
439
+ retry_count: 0,
440
+ send_retry_header: send_retry_header
441
+ )
442
+ parse_response(req, response)
443
+ end
444
+
445
+ # @return [String]
446
+ #
447
+ def inspect
448
+ base_url = TerminalShop::Util.unparse_uri(@base_url)
449
+ "#<#{self.class.name}:0x#{object_id.to_s(16)} base_url=#{base_url} max_retries=#{@max_retries} timeout=#{@timeout}>"
450
+ end
451
+ end
452
+ end