terminal-shop 3.7.0 → 3.8.1

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 (159) hide show
  1. checksums.yaml +4 -4
  2. data/CHANGELOG.md +42 -0
  3. data/README.md +81 -53
  4. data/SECURITY.md +2 -2
  5. data/lib/terminal_shop/client.rb +4 -4
  6. data/lib/terminal_shop/internal/transport/pooled_net_requester.rb +3 -1
  7. data/lib/terminal_shop/internal/type/array_of.rb +8 -0
  8. data/lib/terminal_shop/internal/type/base_model.rb +15 -0
  9. data/lib/terminal_shop/internal/type/boolean.rb +8 -0
  10. data/lib/terminal_shop/internal/type/enum.rb +12 -0
  11. data/lib/terminal_shop/internal/type/file_input.rb +7 -0
  12. data/lib/terminal_shop/internal/type/hash_of.rb +8 -0
  13. data/lib/terminal_shop/internal/type/union.rb +12 -0
  14. data/lib/terminal_shop/internal/type/unknown.rb +8 -0
  15. data/lib/terminal_shop/internal/util.rb +50 -1
  16. data/lib/terminal_shop/internal.rb +3 -0
  17. data/lib/terminal_shop/models/address.rb +2 -2
  18. data/lib/terminal_shop/models/address_get_response.rb +2 -2
  19. data/lib/terminal_shop/models/address_list_response.rb +2 -2
  20. data/lib/terminal_shop/models/app.rb +2 -2
  21. data/lib/terminal_shop/models/app_get_response.rb +2 -2
  22. data/lib/terminal_shop/models/app_list_response.rb +2 -2
  23. data/lib/terminal_shop/models/card.rb +5 -5
  24. data/lib/terminal_shop/models/card_get_response.rb +2 -2
  25. data/lib/terminal_shop/models/card_list_response.rb +2 -2
  26. data/lib/terminal_shop/models/cart.rb +9 -9
  27. data/lib/terminal_shop/models/cart_convert_response.rb +2 -2
  28. data/lib/terminal_shop/models/cart_get_response.rb +2 -2
  29. data/lib/terminal_shop/models/cart_set_item_response.rb +2 -2
  30. data/lib/terminal_shop/models/order.rb +17 -17
  31. data/lib/terminal_shop/models/order_get_response.rb +2 -2
  32. data/lib/terminal_shop/models/order_list_response.rb +2 -2
  33. data/lib/terminal_shop/models/product.rb +10 -10
  34. data/lib/terminal_shop/models/product_get_response.rb +2 -2
  35. data/lib/terminal_shop/models/product_list_response.rb +2 -2
  36. data/lib/terminal_shop/models/product_variant.rb +4 -4
  37. data/lib/terminal_shop/models/profile.rb +4 -4
  38. data/lib/terminal_shop/models/profile_me_response.rb +2 -2
  39. data/lib/terminal_shop/models/profile_update_response.rb +2 -2
  40. data/lib/terminal_shop/models/subscription.rb +5 -14
  41. data/lib/terminal_shop/models/subscription_get_response.rb +2 -2
  42. data/lib/terminal_shop/models/subscription_list_response.rb +2 -2
  43. data/lib/terminal_shop/models/subscription_update_params.rb +3 -12
  44. data/lib/terminal_shop/models/subscription_update_response.rb +2 -2
  45. data/lib/terminal_shop/models/token.rb +2 -2
  46. data/lib/terminal_shop/models/token_get_response.rb +2 -2
  47. data/lib/terminal_shop/models/token_list_response.rb +2 -2
  48. data/lib/terminal_shop/models/view_init_response.rb +20 -20
  49. data/lib/terminal_shop/models.rb +30 -19
  50. data/lib/terminal_shop/resources/subscription.rb +2 -2
  51. data/lib/terminal_shop/version.rb +1 -1
  52. data/rbi/terminal_shop/internal/transport/pooled_net_requester.rbi +5 -1
  53. data/rbi/terminal_shop/internal/type/array_of.rbi +6 -0
  54. data/rbi/terminal_shop/internal/type/base_model.rbi +5 -0
  55. data/rbi/terminal_shop/internal/type/boolean.rbi +6 -0
  56. data/rbi/terminal_shop/internal/type/enum.rbi +5 -0
  57. data/rbi/terminal_shop/internal/type/file_input.rbi +5 -0
  58. data/rbi/terminal_shop/internal/type/hash_of.rbi +6 -0
  59. data/rbi/terminal_shop/internal/type/union.rbi +5 -0
  60. data/rbi/terminal_shop/internal/type/unknown.rbi +6 -0
  61. data/rbi/terminal_shop/internal/util.rbi +34 -0
  62. data/rbi/terminal_shop/internal.rbi +5 -0
  63. data/rbi/terminal_shop/models/subscription.rbi +2 -13
  64. data/sig/terminal_shop/internal/transport/pooled_net_requester.rbs +2 -0
  65. data/sig/terminal_shop/internal/type/array_of.rbs +3 -0
  66. data/sig/terminal_shop/internal/type/base_model.rbs +2 -0
  67. data/sig/terminal_shop/internal/type/boolean.rbs +3 -0
  68. data/sig/terminal_shop/internal/type/enum.rbs +2 -0
  69. data/sig/terminal_shop/internal/type/file_input.rbs +2 -0
  70. data/sig/terminal_shop/internal/type/hash_of.rbs +3 -0
  71. data/sig/terminal_shop/internal/type/union.rbs +2 -0
  72. data/sig/terminal_shop/internal/type/unknown.rbs +3 -0
  73. data/sig/terminal_shop/internal/util.rbs +12 -0
  74. data/sig/terminal_shop/internal.rbs +2 -0
  75. data/sig/terminal_shop/models/address.rbs +13 -0
  76. data/sig/terminal_shop/models/address_create_params.rbs +12 -0
  77. data/sig/terminal_shop/models/address_create_response.rbs +2 -0
  78. data/sig/terminal_shop/models/address_delete_params.rbs +2 -0
  79. data/sig/terminal_shop/models/address_delete_response.rbs +2 -0
  80. data/sig/terminal_shop/models/address_get_params.rbs +2 -0
  81. data/sig/terminal_shop/models/address_get_response.rbs +2 -0
  82. data/sig/terminal_shop/models/address_list_params.rbs +2 -0
  83. data/sig/terminal_shop/models/address_list_response.rbs +2 -0
  84. data/sig/terminal_shop/models/app.rbs +7 -0
  85. data/sig/terminal_shop/models/app_create_params.rbs +6 -0
  86. data/sig/terminal_shop/models/app_create_response.rbs +4 -0
  87. data/sig/terminal_shop/models/app_delete_params.rbs +2 -0
  88. data/sig/terminal_shop/models/app_delete_response.rbs +2 -0
  89. data/sig/terminal_shop/models/app_get_params.rbs +2 -0
  90. data/sig/terminal_shop/models/app_get_response.rbs +2 -0
  91. data/sig/terminal_shop/models/app_list_params.rbs +2 -0
  92. data/sig/terminal_shop/models/app_list_response.rbs +2 -0
  93. data/sig/terminal_shop/models/card.rbs +10 -0
  94. data/sig/terminal_shop/models/card_collect_params.rbs +2 -0
  95. data/sig/terminal_shop/models/card_collect_response.rbs +4 -0
  96. data/sig/terminal_shop/models/card_create_params.rbs +5 -0
  97. data/sig/terminal_shop/models/card_create_response.rbs +2 -0
  98. data/sig/terminal_shop/models/card_delete_params.rbs +2 -0
  99. data/sig/terminal_shop/models/card_delete_response.rbs +2 -0
  100. data/sig/terminal_shop/models/card_get_params.rbs +2 -0
  101. data/sig/terminal_shop/models/card_get_response.rbs +2 -0
  102. data/sig/terminal_shop/models/card_list_params.rbs +2 -0
  103. data/sig/terminal_shop/models/card_list_response.rbs +2 -0
  104. data/sig/terminal_shop/models/cart.rbs +20 -0
  105. data/sig/terminal_shop/models/cart_clear_params.rbs +2 -0
  106. data/sig/terminal_shop/models/cart_clear_response.rbs +2 -0
  107. data/sig/terminal_shop/models/cart_convert_params.rbs +2 -0
  108. data/sig/terminal_shop/models/cart_convert_response.rbs +2 -0
  109. data/sig/terminal_shop/models/cart_get_params.rbs +2 -0
  110. data/sig/terminal_shop/models/cart_get_response.rbs +2 -0
  111. data/sig/terminal_shop/models/cart_set_address_params.rbs +5 -0
  112. data/sig/terminal_shop/models/cart_set_address_response.rbs +2 -0
  113. data/sig/terminal_shop/models/cart_set_card_params.rbs +5 -0
  114. data/sig/terminal_shop/models/cart_set_card_response.rbs +2 -0
  115. data/sig/terminal_shop/models/cart_set_item_params.rbs +6 -0
  116. data/sig/terminal_shop/models/cart_set_item_response.rbs +2 -0
  117. data/sig/terminal_shop/models/email_create_params.rbs +5 -0
  118. data/sig/terminal_shop/models/email_create_response.rbs +2 -0
  119. data/sig/terminal_shop/models/order.rbs +46 -6
  120. data/sig/terminal_shop/models/order_create_params.rbs +7 -0
  121. data/sig/terminal_shop/models/order_create_response.rbs +2 -0
  122. data/sig/terminal_shop/models/order_get_params.rbs +2 -0
  123. data/sig/terminal_shop/models/order_get_response.rbs +2 -0
  124. data/sig/terminal_shop/models/order_list_params.rbs +2 -0
  125. data/sig/terminal_shop/models/order_list_response.rbs +2 -0
  126. data/sig/terminal_shop/models/product.rbs +25 -6
  127. data/sig/terminal_shop/models/product_get_params.rbs +2 -0
  128. data/sig/terminal_shop/models/product_get_response.rbs +2 -0
  129. data/sig/terminal_shop/models/product_list_params.rbs +2 -0
  130. data/sig/terminal_shop/models/product_list_response.rbs +2 -0
  131. data/sig/terminal_shop/models/product_variant.rbs +15 -0
  132. data/sig/terminal_shop/models/profile.rbs +10 -0
  133. data/sig/terminal_shop/models/profile_me_params.rbs +2 -0
  134. data/sig/terminal_shop/models/profile_me_response.rbs +2 -0
  135. data/sig/terminal_shop/models/profile_update_params.rbs +6 -0
  136. data/sig/terminal_shop/models/profile_update_response.rbs +2 -0
  137. data/sig/terminal_shop/models/subscription.rbs +22 -6
  138. data/sig/terminal_shop/models/subscription_create_params.rbs +2 -0
  139. data/sig/terminal_shop/models/subscription_create_response.rbs +2 -0
  140. data/sig/terminal_shop/models/subscription_delete_params.rbs +2 -0
  141. data/sig/terminal_shop/models/subscription_delete_response.rbs +2 -0
  142. data/sig/terminal_shop/models/subscription_get_params.rbs +2 -0
  143. data/sig/terminal_shop/models/subscription_get_response.rbs +2 -0
  144. data/sig/terminal_shop/models/subscription_list_params.rbs +2 -0
  145. data/sig/terminal_shop/models/subscription_list_response.rbs +2 -0
  146. data/sig/terminal_shop/models/subscription_update_params.rbs +11 -0
  147. data/sig/terminal_shop/models/subscription_update_response.rbs +2 -0
  148. data/sig/terminal_shop/models/token.rbs +2 -0
  149. data/sig/terminal_shop/models/token_create_params.rbs +2 -0
  150. data/sig/terminal_shop/models/token_create_response.rbs +4 -0
  151. data/sig/terminal_shop/models/token_delete_params.rbs +2 -0
  152. data/sig/terminal_shop/models/token_delete_response.rbs +2 -0
  153. data/sig/terminal_shop/models/token_get_params.rbs +2 -0
  154. data/sig/terminal_shop/models/token_get_response.rbs +2 -0
  155. data/sig/terminal_shop/models/token_list_params.rbs +2 -0
  156. data/sig/terminal_shop/models/token_list_response.rbs +2 -0
  157. data/sig/terminal_shop/models/view_init_params.rbs +2 -0
  158. data/sig/terminal_shop/models/view_init_response.rbs +15 -0
  159. metadata +2 -2
checksums.yaml CHANGED
@@ -1,7 +1,7 @@
1
1
  ---
2
2
  SHA256:
3
- metadata.gz: ec0b2f09a8009870055d5b2a868a6078adb11504f48eba5eea34b84ff89ba60f
4
- data.tar.gz: f2e9a51a8c54a1eb7f07f40485b89b93218ba1055a8b0498a11f97caa15d5c71
3
+ metadata.gz: 599e129d7291d6af08b3d81afb02569f0b59daf1db3ab1b9e0aab5eb8420c8b1
4
+ data.tar.gz: 80ac8c28092fb302019fc19c536258f4fae23ce8777108dde50898fe49f6572e
5
5
  SHA512:
6
- metadata.gz: 1144da9caada255b1fd2a9856dd8a2d5e6375c0322e369d761289b41c8aa2fe1ba318add613dc0f1cbcd1031badc4576d27084c635921cd063848dbcae5a9ea9
7
- data.tar.gz: e5271523d7d53bcd460ea32453cab3b764009685b290344dcbc07def5ebe9133dd0e8cf55cb3ea72b2491cfb47488c21cdab21c67c0ca4e9b5add53c266ee185
6
+ metadata.gz: 1214379df3ea55463a0e23d01249c474ad3ca6e29c70d127e153787a59cbb82552ec12818867948f7a90774fff3fe571d22c09a2d7c6a6c31b7ad8048f1f57c6
7
+ data.tar.gz: '0592dcc2f02b159ea20773cd02caaf9c3d49d9a6ed27ff72b8e824455f30468f608f649e8bb4f97d7821a55c5ede02908920aa1b7b5ecb9f61774c73d40fe722'
data/CHANGELOG.md CHANGED
@@ -1,5 +1,47 @@
1
1
  # Changelog
2
2
 
3
+ ## 3.8.1 (2025-05-24)
4
+
5
+ Full Changelog: [v3.8.0...v3.8.1](https://github.com/terminaldotshop/terminal-sdk-ruby/compare/v3.8.0...v3.8.1)
6
+
7
+ ### Bug Fixes
8
+
9
+ * prevent rubocop from mangling `===` to `is_a?` check ([ef67cc1](https://github.com/terminaldotshop/terminal-sdk-ruby/commit/ef67cc123e98b33e690847f476fec8301fb48081))
10
+
11
+
12
+ ### Chores
13
+
14
+ * force utf-8 locale via `RUBYOPT` when formatting ([f38a6fe](https://github.com/terminaldotshop/terminal-sdk-ruby/commit/f38a6feeb6dd8fc0771bb885cdd61c6d2cdedd84))
15
+ * **internal:** codegen related update ([ed70989](https://github.com/terminaldotshop/terminal-sdk-ruby/commit/ed70989fc05a5d6e3736656467c9b838757db6eb))
16
+ * use fully qualified names for yard annotations and rbs aliases ([ea3d97a](https://github.com/terminaldotshop/terminal-sdk-ruby/commit/ea3d97acf7a9d7d01d5e10f6f5f990c0994c396f))
17
+
18
+ ## 3.8.0 (2025-05-22)
19
+
20
+ Full Changelog: [v3.7.0...v3.8.0](https://github.com/terminaldotshop/terminal-sdk-ruby/compare/v3.7.0...v3.8.0)
21
+
22
+ ### Features
23
+
24
+ * bump default connection pool size limit to minimum of 99 ([81feb3e](https://github.com/terminaldotshop/terminal-sdk-ruby/commit/81feb3eb7e2d0c5b1df983647c436ebf966ece2c))
25
+
26
+
27
+ ### Bug Fixes
28
+
29
+ * correctly instantiate sorbet type aliases for enums and unions ([2698489](https://github.com/terminaldotshop/terminal-sdk-ruby/commit/2698489f9f63ced3353196009dc2329e20f8cff5))
30
+
31
+
32
+ ### Chores
33
+
34
+ * **docs:** grammar improvements ([841d9a7](https://github.com/terminaldotshop/terminal-sdk-ruby/commit/841d9a7d18776a55e947cee60233d0756579b22c))
35
+ * **internal:** codegen related update ([68a3efa](https://github.com/terminaldotshop/terminal-sdk-ruby/commit/68a3efaf40e8944faf60b604b5aa33b46c1aedf0))
36
+ * refine Yard and Sorbet types and ensure linting is turned on for examples ([41916e7](https://github.com/terminaldotshop/terminal-sdk-ruby/commit/41916e7b6c195ae8085ac89393b0893b42bf72bc))
37
+ * use sorbet union aliases where available ([046dd18](https://github.com/terminaldotshop/terminal-sdk-ruby/commit/046dd183ff9c9826d45fdcf73a6512effd343ca5))
38
+ * whitespaces ([88c3862](https://github.com/terminaldotshop/terminal-sdk-ruby/commit/88c38620dbdceefd1eb268b457a464a0b59daa6c))
39
+
40
+
41
+ ### Documentation
42
+
43
+ * rewrite much of README.md for readability ([564f4f7](https://github.com/terminaldotshop/terminal-sdk-ruby/commit/564f4f7b65f67c1f4f17f6a06c952a570263d4d1))
44
+
3
45
  ## 3.7.0 (2025-05-14)
4
46
 
5
47
  Full Changelog: [v3.6.2...v3.7.0](https://github.com/terminaldotshop/terminal-sdk-ruby/compare/v3.6.2...v3.7.0)
data/README.md CHANGED
@@ -1,6 +1,6 @@
1
1
  # Terminal Ruby API library
2
2
 
3
- The Terminal Ruby library provides convenient access to the Terminal REST API from any Ruby 3.2.0+ application.
3
+ The Terminal Ruby library provides convenient access to the Terminal REST API from any Ruby 3.2.0+ application. It ships with comprehensive types & docstrings in Yard, RBS, and RBI – [see below](https://github.com/terminaldotshop/terminal-sdk-ruby#Sorbet) for usage with Sorbet. The standard library's `net/http` is used as the HTTP transport, with connection pooling via the `connection_pool` gem.
4
4
 
5
5
  It is generated with [Stainless](https://www.stainless.com/).
6
6
 
@@ -17,7 +17,7 @@ To use this gem, install via Bundler by adding the following to your application
17
17
  <!-- x-release-please-start-version -->
18
18
 
19
19
  ```ruby
20
- gem "terminal-shop", "~> 3.7.0"
20
+ gem "terminal-shop", "~> 3.8.1"
21
21
  ```
22
22
 
23
23
  <!-- x-release-please-end -->
@@ -38,25 +38,21 @@ products = terminal.product.list
38
38
  puts(products.data)
39
39
  ```
40
40
 
41
- ## Sorbet
42
-
43
- This library is written with [Sorbet type definitions](https://sorbet.org/docs/rbi). However, there is no runtime dependency on the `sorbet-runtime`.
44
-
45
- When using sorbet, it is recommended to use model classes as below. This provides stronger type checking and tooling integration.
46
-
47
- ```ruby
48
- terminal.product.list
49
- ```
50
-
51
- ### Errors
41
+ ### Handling errors
52
42
 
53
43
  When the library is unable to connect to the API, or if the API returns a non-success status code (i.e., 4xx or 5xx response), a subclass of `TerminalShop::Errors::APIError` will be thrown:
54
44
 
55
45
  ```ruby
56
46
  begin
57
47
  product = terminal.product.list
58
- rescue TerminalShop::Errors::APIError => e
59
- puts(e.status) # 400
48
+ rescue TerminalShop::Errors::APIConnectionError => e
49
+ puts("The server could not be reached")
50
+ puts(e.cause) # an underlying Exception, likely raised within `net/http`
51
+ rescue TerminalShop::Errors::RateLimitError => e
52
+ puts("A 429 status code was received; we should back off a bit.")
53
+ rescue TerminalShop::Errors::APIStatusError => e
54
+ puts("Another non-200-range status code was received")
55
+ puts(e.status)
60
56
  end
61
57
  ```
62
58
 
@@ -96,11 +92,7 @@ terminal.product.list(request_options: {max_retries: 5})
96
92
 
97
93
  ### Timeouts
98
94
 
99
- By default, requests will time out after 60 seconds.
100
-
101
- Timeouts are applied separately to the initial connection and the overall request time, so in some cases a request could wait 2\*timeout seconds before it fails.
102
-
103
- You can use the `timeout` option to configure or disable this:
95
+ By default, requests will time out after 60 seconds. You can use the timeout option to configure or disable this:
104
96
 
105
97
  ```ruby
106
98
  # Configure the default for all requests:
@@ -112,39 +104,52 @@ terminal = TerminalShop::Client.new(
112
104
  terminal.product.list(request_options: {timeout: 5})
113
105
  ```
114
106
 
115
- ## Model DSL
107
+ On timeout, `TerminalShop::Errors::APITimeoutError` is raised.
116
108
 
117
- This library uses a simple DSL to represent request parameters and response shapes in `lib/terminal_shop/models`.
109
+ Note that requests that time out are retried by default.
118
110
 
119
- With the right [editor plugins](https://shopify.github.io/ruby-lsp), you can ctrl-click on elements of the DSL to navigate around and explore the library.
111
+ ## Advanced concepts
120
112
 
121
- In all places where a `BaseModel` type is specified, vanilla Ruby `Hash` can also be used. For example, the following are interchangeable as arguments:
113
+ ### BaseModel
122
114
 
123
- ```ruby
124
- # This has tooling readability, for auto-completion, static analysis, and goto definition with supported language services
125
- params = TerminalShop::Models::ProductListParams.new
115
+ All parameter and response objects inherit from `TerminalShop::Internal::Type::BaseModel`, which provides several conveniences, including:
126
116
 
127
- # This also works
128
- params = {
117
+ 1. All fields, including unknown ones, are accessible with `obj[:prop]` syntax, and can be destructured with `obj => {prop: prop}` or pattern-matching syntax.
129
118
 
130
- }
131
- ```
119
+ 2. Structural equivalence for equality; if two API calls return the same values, comparing the responses with == will return true.
132
120
 
133
- ## Editor support
121
+ 3. Both instances and the classes themselves can be pretty-printed.
134
122
 
135
- A combination of [Shopify LSP](https://shopify.github.io/ruby-lsp) and [Solargraph](https://solargraph.org/) is recommended for non-[Sorbet](https://sorbet.org) users. The former is especially good at go to definition, while the latter has much better auto-completion support.
123
+ 4. Helpers such as `#to_h`, `#deep_to_h`, `#to_json`, and `#to_yaml`.
136
124
 
137
- ## Advanced concepts
125
+ ### Making custom or undocumented requests
126
+
127
+ #### Undocumented properties
138
128
 
139
- ### Making custom/undocumented requests
129
+ You can send undocumented parameters to any endpoint, and read undocumented response properties, like so:
130
+
131
+ Note: the `extra_` parameters of the same name overrides the documented parameters.
132
+
133
+ ```ruby
134
+ products =
135
+ terminal.product.list(
136
+ request_options: {
137
+ extra_query: {my_query_parameter: value},
138
+ extra_body: {my_body_parameter: value},
139
+ extra_headers: {"my-header": value}
140
+ }
141
+ )
142
+
143
+ puts(products[:my_undocumented_property])
144
+ ```
140
145
 
141
146
  #### Undocumented request params
142
147
 
143
- If you want to explicitly send an extra param, you can do so with the `extra_query`, `extra_body`, and `extra_headers` under the `request_options:` parameter when making a requests as seen in examples above.
148
+ If you want to explicitly send an extra param, you can do so with the `extra_query`, `extra_body`, and `extra_headers` under the `request_options:` parameter when making a request, as seen in the examples above.
144
149
 
145
150
  #### Undocumented endpoints
146
151
 
147
- To make requests to undocumented endpoints, you can make requests using `client.request`. Options on the client will be respected (such as retries) when making this request.
152
+ To make requests to undocumented endpoints while retaining the benefit of auth, retries, and so on, you can make requests using `client.request`, like so:
148
153
 
149
154
  ```ruby
150
155
  response = client.request(
@@ -152,42 +157,65 @@ response = client.request(
152
157
  path: '/undocumented/endpoint',
153
158
  query: {"dog": "woof"},
154
159
  headers: {"useful-header": "interesting-value"},
155
- body: {"he": "llo"},
160
+ body: {"hello": "world"}
156
161
  )
157
162
  ```
158
163
 
159
164
  ### Concurrency & connection pooling
160
165
 
161
- The `TerminalShop::Client` instances are thread-safe, and should be re-used across multiple threads. By default, each `Client` have their own HTTP connection pool, with a maximum number of connections equal to thread count.
166
+ The `TerminalShop::Client` instances are threadsafe, but are only are fork-safe when there are no in-flight HTTP requests.
162
167
 
163
- When the maximum number of connections has been checked out from the connection pool, the `Client` will wait for an in use connection to become available. The queue time for this mechanism is accounted for by the per-request timeout.
168
+ Each instance of `TerminalShop::Client` has its own HTTP connection pool with a default size of 99. As such, we recommend instantiating the client once per application in most settings.
169
+
170
+ When all available connections from the pool are checked out, requests wait for a new connection to become available, with queue time counting towards the request timeout.
164
171
 
165
172
  Unless otherwise specified, other classes in the SDK do not have locks protecting their underlying data structure.
166
173
 
167
- Currently, `TerminalShop::Client` instances are only fork-safe if there are no in-flight HTTP requests.
174
+ ## Sorbet
168
175
 
169
- ### Sorbet
176
+ This library provides comprehensive [RBI](https://sorbet.org/docs/rbi) definitions, and has no dependency on sorbet-runtime.
170
177
 
171
- #### Enums
178
+ You can provide typesafe request parameters like so:
172
179
 
173
- Sorbet's typed enums require sub-classing of the [`T::Enum` class](https://sorbet.org/docs/tenum) from the `sorbet-runtime` gem.
180
+ ```ruby
181
+ terminal.product.list
182
+ ```
174
183
 
175
- Since this library does not depend on `sorbet-runtime`, it uses a [`T.all` intersection type](https://sorbet.org/docs/intersection-types) with a ruby primitive type to construct a "tagged alias" instead.
184
+ Or, equivalently:
176
185
 
177
186
  ```ruby
178
- module TerminalShop::Region
179
- # This alias aids language service driven navigation.
180
- TaggedSymbol = T.type_alias { T.all(Symbol, TerminalShop::Region) }
181
- end
187
+ # Hashes work, but are not typesafe:
188
+ terminal.product.list
189
+
190
+ # You can also splat a full Params class:
191
+ params = TerminalShop::ProductListParams.new
192
+ terminal.product.list(**params)
182
193
  ```
183
194
 
184
- #### Argument passing trick
195
+ ### Enums
185
196
 
186
- It is possible to pass a compatible model / parameter class to a method that expects keyword arguments by using the `**` splat operator.
197
+ Since this library does not depend on `sorbet-runtime`, it cannot provide [`T::Enum`](https://sorbet.org/docs/tenum) instances. Instead, we provide "tagged symbols" instead, which is always a primitive at runtime:
187
198
 
188
199
  ```ruby
189
- params = TerminalShop::Models::ProductListParams.new
190
- terminal.product.list(**params)
200
+ # :allowed
201
+ puts(TerminalShop::ProductAPI::Subscription::ALLOWED)
202
+
203
+ # Revealed type: `T.all(TerminalShop::ProductAPI::Subscription, Symbol)`
204
+ T.reveal_type(TerminalShop::ProductAPI::Subscription::ALLOWED)
205
+ ```
206
+
207
+ Enum parameters have a "relaxed" type, so you can either pass in enum constants or their literal value:
208
+
209
+ ```ruby
210
+ TerminalShop::ProductAPI.new(
211
+ subscription: TerminalShop::ProductAPI::Subscription::ALLOWED,
212
+ # …
213
+ )
214
+
215
+ TerminalShop::ProductAPI.new(
216
+ subscription: :allowed,
217
+ # …
218
+ )
191
219
  ```
192
220
 
193
221
  ## Versioning
data/SECURITY.md CHANGED
@@ -16,11 +16,11 @@ before making any information public.
16
16
  ## Reporting Non-SDK Related Security Issues
17
17
 
18
18
  If you encounter security issues that are not directly related to SDKs but pertain to the services
19
- or products provided by Terminal please follow the respective company's security reporting guidelines.
19
+ or products provided by Terminal, please follow the respective company's security reporting guidelines.
20
20
 
21
21
  ### Terminal Terms and Policies
22
22
 
23
- Please contact dev@terminal.com for any questions or concerns regarding security of our services.
23
+ Please contact dev@terminal.com for any questions or concerns regarding the security of our services.
24
24
 
25
25
  ---
26
26
 
@@ -96,10 +96,10 @@ module TerminalShop
96
96
  app_id: nil,
97
97
  environment: nil,
98
98
  base_url: ENV["TERMINAL_BASE_URL"],
99
- max_retries: TerminalShop::Client::DEFAULT_MAX_RETRIES,
100
- timeout: TerminalShop::Client::DEFAULT_TIMEOUT_IN_SECONDS,
101
- initial_retry_delay: TerminalShop::Client::DEFAULT_INITIAL_RETRY_DELAY,
102
- max_retry_delay: TerminalShop::Client::DEFAULT_MAX_RETRY_DELAY
99
+ max_retries: self.class::DEFAULT_MAX_RETRIES,
100
+ timeout: self.class::DEFAULT_TIMEOUT_IN_SECONDS,
101
+ initial_retry_delay: self.class::DEFAULT_INITIAL_RETRY_DELAY,
102
+ max_retry_delay: self.class::DEFAULT_MAX_RETRY_DELAY
103
103
  )
104
104
  base_url ||= TerminalShop::Client::ENVIRONMENTS.fetch(environment&.to_sym || :production) do
105
105
  message = "environment must be one of #{TerminalShop::Client::ENVIRONMENTS.keys}, got #{environment}"
@@ -11,6 +11,8 @@ module TerminalShop
11
11
  # https://github.com/golang/go/blob/c8eced8580028328fde7c03cbfcb720ce15b2358/src/net/http/transport.go#L49
12
12
  KEEP_ALIVE_TIMEOUT = 30
13
13
 
14
+ DEFAULT_MAX_CONNECTIONS = [Etc.nprocessors, 99].max
15
+
14
16
  class << self
15
17
  # @api private
16
18
  #
@@ -184,7 +186,7 @@ module TerminalShop
184
186
  # @api private
185
187
  #
186
188
  # @param size [Integer]
187
- def initialize(size: Etc.nprocessors)
189
+ def initialize(size: self.class::DEFAULT_MAX_CONNECTIONS)
188
190
  @mutex = Mutex.new
189
191
  @size = size
190
192
  @pools = {}
@@ -12,6 +12,7 @@ module TerminalShop
12
12
  # Array of items of a given type.
13
13
  class ArrayOf
14
14
  include TerminalShop::Internal::Type::Converter
15
+ include TerminalShop::Internal::Util::SorbetRuntimeSupport
15
16
 
16
17
  private_class_method :new
17
18
 
@@ -110,6 +111,13 @@ module TerminalShop
110
111
  end
111
112
  end
112
113
 
114
+ # @api private
115
+ #
116
+ # @return [Object]
117
+ def to_sorbet_type
118
+ T::Array[TerminalShop::Internal::Util::SorbetRuntimeSupport.to_sorbet_type(item_type)]
119
+ end
120
+
113
121
  # @api private
114
122
  #
115
123
  # @return [generic<Elem>]
@@ -309,6 +309,13 @@ module TerminalShop
309
309
 
310
310
  acc
311
311
  end
312
+
313
+ # @api private
314
+ #
315
+ # @return [Object]
316
+ def to_sorbet_type
317
+ self
318
+ end
312
319
  end
313
320
 
314
321
  class << self
@@ -391,6 +398,14 @@ module TerminalShop
391
398
  # @param keys [Array<Symbol>, nil]
392
399
  #
393
400
  # @return [Hash{Symbol=>Object}]
401
+ #
402
+ # @example
403
+ # # `product_api` is a `TerminalShop::ProductAPI`
404
+ # product_api => {
405
+ # id: id,
406
+ # description: description,
407
+ # name: name
408
+ # }
394
409
  def deconstruct_keys(keys)
395
410
  (keys || self.class.known_fields.keys)
396
411
  .filter_map do |k|
@@ -10,6 +10,7 @@ module TerminalShop
10
10
  # Ruby has no Boolean class; this is something for models to refer to.
11
11
  class Boolean
12
12
  extend TerminalShop::Internal::Type::Converter
13
+ extend TerminalShop::Internal::Util::SorbetRuntimeSupport
13
14
 
14
15
  private_class_method :new
15
16
 
@@ -56,6 +57,13 @@ module TerminalShop
56
57
  # @option state [Boolean] :can_retry
57
58
  #
58
59
  # @return [Boolean, Object]
60
+
61
+ # @api private
62
+ #
63
+ # @return [Object]
64
+ def to_sorbet_type
65
+ T::Boolean
66
+ end
59
67
  end
60
68
  end
61
69
  end
@@ -112,6 +112,18 @@ module TerminalShop
112
112
  #
113
113
  # @return [Symbol, Object]
114
114
 
115
+ # @api private
116
+ #
117
+ # @return [Object]
118
+ def to_sorbet_type
119
+ case values
120
+ in []
121
+ T.noreturn
122
+ in [value, *_]
123
+ T.all(TerminalShop::Internal::Util::SorbetRuntimeSupport.to_sorbet_type(value), self)
124
+ end
125
+ end
126
+
115
127
  # @api private
116
128
  #
117
129
  # @param depth [Integer]
@@ -89,6 +89,13 @@ module TerminalShop
89
89
 
90
90
  value
91
91
  end
92
+
93
+ # @api private
94
+ #
95
+ # @return [Object]
96
+ def to_sorbet_type
97
+ T.any(Pathname, StringIO, IO, String, TerminalShop::FilePart)
98
+ end
92
99
  end
93
100
  end
94
101
  end
@@ -12,6 +12,7 @@ module TerminalShop
12
12
  # Hash of items of a given type.
13
13
  class HashOf
14
14
  include TerminalShop::Internal::Type::Converter
15
+ include TerminalShop::Internal::Util::SorbetRuntimeSupport
15
16
 
16
17
  private_class_method :new
17
18
 
@@ -130,6 +131,13 @@ module TerminalShop
130
131
  end
131
132
  end
132
133
 
134
+ # @api private
135
+ #
136
+ # @return [Object]
137
+ def to_sorbet_type
138
+ T::Hash[TerminalShop::Internal::Util::SorbetRuntimeSupport.to_sorbet_type(item_type)]
139
+ end
140
+
133
141
  # @api private
134
142
  #
135
143
  # @return [generic<Elem>]
@@ -197,6 +197,18 @@ module TerminalShop
197
197
  super
198
198
  end
199
199
 
200
+ # @api private
201
+ #
202
+ # @return [Object]
203
+ def to_sorbet_type
204
+ case (v = variants)
205
+ in []
206
+ T.noreturn
207
+ else
208
+ T.any(*v.map { TerminalShop::Internal::Util::SorbetRuntimeSupport.to_sorbet_type(_1) })
209
+ end
210
+ end
211
+
200
212
  # rubocop:enable Style/CaseEquality
201
213
  # rubocop:enable Style/HashEachMethods
202
214
 
@@ -10,6 +10,7 @@ module TerminalShop
10
10
  # When we don't know what to expect for the value.
11
11
  class Unknown
12
12
  extend TerminalShop::Internal::Type::Converter
13
+ extend TerminalShop::Internal::Util::SorbetRuntimeSupport
13
14
 
14
15
  # rubocop:disable Lint/UnusedMethodArgument
15
16
 
@@ -58,6 +59,13 @@ module TerminalShop
58
59
  # @option state [Boolean] :can_retry
59
60
  #
60
61
  # @return [Object]
62
+
63
+ # @api private
64
+ #
65
+ # @return [Object]
66
+ def to_sorbet_type
67
+ T.anything
68
+ end
61
69
  end
62
70
 
63
71
  # rubocop:enable Lint/UnusedMethodArgument
@@ -9,6 +9,23 @@ module TerminalShop
9
9
  # @return [Float]
10
10
  def self.monotonic_secs = Process.clock_gettime(Process::CLOCK_MONOTONIC)
11
11
 
12
+ # @api private
13
+ #
14
+ # @param ns [Module, Class]
15
+ #
16
+ # @return [Enumerable<Module, Class>]
17
+ def self.walk_namespaces(ns)
18
+ ns.constants(false).lazy.flat_map do
19
+ case (c = ns.const_get(_1, false))
20
+ in Module | Class
21
+ walk_namespaces(c)
22
+ else
23
+ []
24
+ end
25
+ end
26
+ .chain([ns])
27
+ end
28
+
12
29
  class << self
13
30
  # @api private
14
31
  #
@@ -583,11 +600,13 @@ module TerminalShop
583
600
  #
584
601
  # @return [Object]
585
602
  def encode_content(headers, body)
603
+ # rubocop:disable Style/CaseEquality
604
+ # rubocop:disable Layout/LineLength
586
605
  content_type = headers["content-type"]
587
606
  case [content_type, body]
588
607
  in [TerminalShop::Internal::Util::JSON_CONTENT, Hash | Array | -> { primitive?(_1) }]
589
608
  [headers, JSON.generate(body)]
590
- in [TerminalShop::Internal::Util::JSONL_CONTENT, Enumerable] unless body.is_a?(TerminalShop::Internal::Type::FileInput)
609
+ in [TerminalShop::Internal::Util::JSONL_CONTENT, Enumerable] unless TerminalShop::Internal::Type::FileInput === body
591
610
  [headers, body.lazy.map { JSON.generate(_1) }]
592
611
  in [%r{^multipart/form-data}, Hash | TerminalShop::Internal::Type::FileInput]
593
612
  boundary, strio = encode_multipart_streaming(body)
@@ -602,6 +621,8 @@ module TerminalShop
602
621
  else
603
622
  [headers, body]
604
623
  end
624
+ # rubocop:enable Layout/LineLength
625
+ # rubocop:enable Style/CaseEquality
605
626
  end
606
627
 
607
628
  # @api private
@@ -826,11 +847,39 @@ module TerminalShop
826
847
  sorbet_runtime_constants.fetch(name).call
827
848
  end
828
849
 
850
+ # @api private
851
+ #
852
+ # @param name [Symbol]
853
+ #
854
+ # @return [Boolean]
855
+ def sorbet_constant_defined?(name) = sorbet_runtime_constants.key?(name)
856
+
829
857
  # @api private
830
858
  #
831
859
  # @param name [Symbol]
832
860
  # @param blk [Proc]
833
861
  def define_sorbet_constant!(name, &blk) = sorbet_runtime_constants.store(name, blk)
862
+
863
+ # @api private
864
+ #
865
+ # @return [Object]
866
+ def to_sorbet_type = raise NotImplementedError
867
+
868
+ class << self
869
+ # @api private
870
+ #
871
+ # @param type [TerminalShop::Internal::Util::SorbetRuntimeSupport, Object]
872
+ #
873
+ # @return [Object]
874
+ def to_sorbet_type(type)
875
+ case type
876
+ in TerminalShop::Internal::Util::SorbetRuntimeSupport
877
+ type.to_sorbet_type
878
+ else
879
+ type
880
+ end
881
+ end
882
+ end
834
883
  end
835
884
 
836
885
  extend TerminalShop::Internal::Util::SorbetRuntimeSupport
@@ -13,5 +13,8 @@ module TerminalShop
13
13
  define_sorbet_constant!(:AnyHash) do
14
14
  T.type_alias { T::Hash[Symbol, T.anything] }
15
15
  end
16
+ define_sorbet_constant!(:FileInput) do
17
+ T.type_alias { T.any(Pathname, StringIO, IO, String, TerminalShop::FilePart) }
18
+ end
16
19
  end
17
20
  end
@@ -64,8 +64,8 @@ module TerminalShop
64
64
  optional :street2, String
65
65
 
66
66
  # @!method initialize(id:, city:, country:, created:, name:, street1:, zip:, phone: nil, province: nil, street2: nil)
67
- # Some parameter documentations has been truncated, see {TerminalShop::AddressAPI}
68
- # for more details.
67
+ # Some parameter documentations has been truncated, see
68
+ # {TerminalShop::Models::AddressAPI} for more details.
69
69
  #
70
70
  # Physical address associated with a Terminal shop user.
71
71
  #
@@ -7,11 +7,11 @@ module TerminalShop
7
7
  # @!attribute data
8
8
  # Physical address associated with a Terminal shop user.
9
9
  #
10
- # @return [TerminalShop::AddressAPI]
10
+ # @return [TerminalShop::Models::AddressAPI]
11
11
  required :data, -> { TerminalShop::AddressAPI }
12
12
 
13
13
  # @!method initialize(data:)
14
- # @param data [TerminalShop::AddressAPI] Physical address associated with a Terminal shop user.
14
+ # @param data [TerminalShop::Models::AddressAPI] Physical address associated with a Terminal shop user.
15
15
  end
16
16
  end
17
17
  end
@@ -7,11 +7,11 @@ module TerminalShop
7
7
  # @!attribute data
8
8
  # Shipping addresses.
9
9
  #
10
- # @return [Array<TerminalShop::AddressAPI>]
10
+ # @return [Array<TerminalShop::Models::AddressAPI>]
11
11
  required :data, -> { TerminalShop::Internal::Type::ArrayOf[TerminalShop::AddressAPI] }
12
12
 
13
13
  # @!method initialize(data:)
14
- # @param data [Array<TerminalShop::AddressAPI>] Shipping addresses.
14
+ # @param data [Array<TerminalShop::Models::AddressAPI>] Shipping addresses.
15
15
  end
16
16
  end
17
17
  end
@@ -28,8 +28,8 @@ module TerminalShop
28
28
  required :secret, String
29
29
 
30
30
  # @!method initialize(id:, name:, redirect_uri:, secret:)
31
- # Some parameter documentations has been truncated, see {TerminalShop::AppAPI} for
32
- # more details.
31
+ # Some parameter documentations has been truncated, see
32
+ # {TerminalShop::Models::AppAPI} for more details.
33
33
  #
34
34
  # A Terminal App used for configuring an OAuth 2.0 client.
35
35
  #