terminal-shop 3.6.2 → 3.8.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 (137) hide show
  1. checksums.yaml +4 -4
  2. data/CHANGELOG.md +48 -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/errors.rb +1 -1
  7. data/lib/terminal_shop/internal/transport/base_client.rb +77 -5
  8. data/lib/terminal_shop/internal/transport/pooled_net_requester.rb +17 -1
  9. data/lib/terminal_shop/internal/type/array_of.rb +9 -1
  10. data/lib/terminal_shop/internal/type/base_model.rb +77 -30
  11. data/lib/terminal_shop/internal/type/boolean.rb +8 -0
  12. data/lib/terminal_shop/internal/type/converter.rb +18 -0
  13. data/lib/terminal_shop/internal/type/enum.rb +13 -0
  14. data/lib/terminal_shop/internal/type/file_input.rb +7 -0
  15. data/lib/terminal_shop/internal/type/hash_of.rb +9 -1
  16. data/lib/terminal_shop/internal/type/union.rb +13 -0
  17. data/lib/terminal_shop/internal/type/unknown.rb +8 -0
  18. data/lib/terminal_shop/internal/util.rb +101 -0
  19. data/lib/terminal_shop/internal.rb +9 -0
  20. data/lib/terminal_shop/models.rb +38 -0
  21. data/lib/terminal_shop/request_options.rb +4 -0
  22. data/lib/terminal_shop/version.rb +1 -1
  23. data/lib/terminal_shop.rb +2 -0
  24. data/rbi/terminal_shop/internal/transport/base_client.rbi +31 -8
  25. data/rbi/terminal_shop/internal/transport/pooled_net_requester.rbi +10 -4
  26. data/rbi/terminal_shop/internal/type/array_of.rbi +6 -0
  27. data/rbi/terminal_shop/internal/type/base_model.rbi +38 -15
  28. data/rbi/terminal_shop/internal/type/base_page.rbi +1 -1
  29. data/rbi/terminal_shop/internal/type/boolean.rbi +6 -0
  30. data/rbi/terminal_shop/internal/type/converter.rbi +2 -0
  31. data/rbi/terminal_shop/internal/type/enum.rbi +6 -0
  32. data/rbi/terminal_shop/internal/type/file_input.rbi +5 -0
  33. data/rbi/terminal_shop/internal/type/hash_of.rbi +6 -0
  34. data/rbi/terminal_shop/internal/type/union.rbi +6 -0
  35. data/rbi/terminal_shop/internal/type/unknown.rbi +6 -0
  36. data/rbi/terminal_shop/internal/util.rbi +62 -5
  37. data/rbi/terminal_shop/internal.rbi +7 -0
  38. data/rbi/terminal_shop/models/address.rbi +3 -1
  39. data/rbi/terminal_shop/models/address_create_params.rbi +6 -1
  40. data/rbi/terminal_shop/models/address_create_response.rbi +6 -1
  41. data/rbi/terminal_shop/models/address_delete_params.rbi +6 -1
  42. data/rbi/terminal_shop/models/address_delete_response.rbi +6 -1
  43. data/rbi/terminal_shop/models/address_get_params.rbi +3 -1
  44. data/rbi/terminal_shop/models/address_get_response.rbi +6 -1
  45. data/rbi/terminal_shop/models/address_list_params.rbi +6 -1
  46. data/rbi/terminal_shop/models/address_list_response.rbi +6 -1
  47. data/rbi/terminal_shop/models/app.rbi +3 -1
  48. data/rbi/terminal_shop/models/app_create_params.rbi +3 -1
  49. data/rbi/terminal_shop/models/app_create_response.rbi +12 -2
  50. data/rbi/terminal_shop/models/app_delete_params.rbi +3 -1
  51. data/rbi/terminal_shop/models/app_delete_response.rbi +6 -1
  52. data/rbi/terminal_shop/models/app_get_params.rbi +3 -1
  53. data/rbi/terminal_shop/models/app_get_response.rbi +6 -1
  54. data/rbi/terminal_shop/models/app_list_params.rbi +3 -1
  55. data/rbi/terminal_shop/models/app_list_response.rbi +6 -1
  56. data/rbi/terminal_shop/models/card.rbi +9 -2
  57. data/rbi/terminal_shop/models/card_collect_params.rbi +6 -1
  58. data/rbi/terminal_shop/models/card_collect_response.rbi +12 -2
  59. data/rbi/terminal_shop/models/card_create_params.rbi +3 -1
  60. data/rbi/terminal_shop/models/card_create_response.rbi +6 -1
  61. data/rbi/terminal_shop/models/card_delete_params.rbi +3 -1
  62. data/rbi/terminal_shop/models/card_delete_response.rbi +6 -1
  63. data/rbi/terminal_shop/models/card_get_params.rbi +3 -1
  64. data/rbi/terminal_shop/models/card_get_response.rbi +6 -1
  65. data/rbi/terminal_shop/models/card_list_params.rbi +3 -1
  66. data/rbi/terminal_shop/models/card_list_response.rbi +6 -1
  67. data/rbi/terminal_shop/models/cart.rbi +18 -4
  68. data/rbi/terminal_shop/models/cart_clear_params.rbi +3 -1
  69. data/rbi/terminal_shop/models/cart_clear_response.rbi +6 -1
  70. data/rbi/terminal_shop/models/cart_convert_params.rbi +6 -1
  71. data/rbi/terminal_shop/models/cart_convert_response.rbi +6 -1
  72. data/rbi/terminal_shop/models/cart_get_params.rbi +3 -1
  73. data/rbi/terminal_shop/models/cart_get_response.rbi +6 -1
  74. data/rbi/terminal_shop/models/cart_set_address_params.rbi +6 -1
  75. data/rbi/terminal_shop/models/cart_set_address_response.rbi +6 -1
  76. data/rbi/terminal_shop/models/cart_set_card_params.rbi +6 -1
  77. data/rbi/terminal_shop/models/cart_set_card_response.rbi +6 -1
  78. data/rbi/terminal_shop/models/cart_set_item_params.rbi +6 -1
  79. data/rbi/terminal_shop/models/cart_set_item_response.rbi +6 -1
  80. data/rbi/terminal_shop/models/email_create_params.rbi +6 -1
  81. data/rbi/terminal_shop/models/email_create_response.rbi +6 -1
  82. data/rbi/terminal_shop/models/order.rbi +24 -5
  83. data/rbi/terminal_shop/models/order_create_params.rbi +6 -1
  84. data/rbi/terminal_shop/models/order_create_response.rbi +6 -1
  85. data/rbi/terminal_shop/models/order_get_params.rbi +3 -1
  86. data/rbi/terminal_shop/models/order_get_response.rbi +6 -1
  87. data/rbi/terminal_shop/models/order_list_params.rbi +3 -1
  88. data/rbi/terminal_shop/models/order_list_response.rbi +6 -1
  89. data/rbi/terminal_shop/models/product.rbi +9 -2
  90. data/rbi/terminal_shop/models/product_get_params.rbi +3 -1
  91. data/rbi/terminal_shop/models/product_get_response.rbi +6 -1
  92. data/rbi/terminal_shop/models/product_list_params.rbi +6 -1
  93. data/rbi/terminal_shop/models/product_list_response.rbi +6 -1
  94. data/rbi/terminal_shop/models/product_variant.rbi +9 -2
  95. data/rbi/terminal_shop/models/profile.rbi +9 -2
  96. data/rbi/terminal_shop/models/profile_me_params.rbi +3 -1
  97. data/rbi/terminal_shop/models/profile_me_response.rbi +6 -1
  98. data/rbi/terminal_shop/models/profile_update_params.rbi +6 -1
  99. data/rbi/terminal_shop/models/profile_update_response.rbi +6 -1
  100. data/rbi/terminal_shop/models/subscription.rbi +17 -16
  101. data/rbi/terminal_shop/models/subscription_create_params.rbi +6 -1
  102. data/rbi/terminal_shop/models/subscription_create_response.rbi +6 -1
  103. data/rbi/terminal_shop/models/subscription_delete_params.rbi +6 -1
  104. data/rbi/terminal_shop/models/subscription_delete_response.rbi +6 -1
  105. data/rbi/terminal_shop/models/subscription_get_params.rbi +6 -1
  106. data/rbi/terminal_shop/models/subscription_get_response.rbi +6 -1
  107. data/rbi/terminal_shop/models/subscription_list_params.rbi +6 -1
  108. data/rbi/terminal_shop/models/subscription_list_response.rbi +6 -1
  109. data/rbi/terminal_shop/models/subscription_update_params.rbi +18 -3
  110. data/rbi/terminal_shop/models/subscription_update_response.rbi +6 -1
  111. data/rbi/terminal_shop/models/token.rbi +3 -1
  112. data/rbi/terminal_shop/models/token_create_params.rbi +6 -1
  113. data/rbi/terminal_shop/models/token_create_response.rbi +12 -2
  114. data/rbi/terminal_shop/models/token_delete_params.rbi +6 -1
  115. data/rbi/terminal_shop/models/token_delete_response.rbi +6 -1
  116. data/rbi/terminal_shop/models/token_get_params.rbi +3 -1
  117. data/rbi/terminal_shop/models/token_get_response.rbi +6 -1
  118. data/rbi/terminal_shop/models/token_list_params.rbi +3 -1
  119. data/rbi/terminal_shop/models/token_list_response.rbi +6 -1
  120. data/rbi/terminal_shop/models/view_init_params.rbi +3 -1
  121. data/rbi/terminal_shop/models/view_init_response.rbi +12 -2
  122. data/rbi/terminal_shop/request_options.rbi +3 -1
  123. data/sig/terminal_shop/internal/transport/base_client.rbs +16 -1
  124. data/sig/terminal_shop/internal/transport/pooled_net_requester.rbs +4 -0
  125. data/sig/terminal_shop/internal/type/array_of.rbs +3 -0
  126. data/sig/terminal_shop/internal/type/base_model.rbs +13 -5
  127. data/sig/terminal_shop/internal/type/base_page.rbs +1 -1
  128. data/sig/terminal_shop/internal/type/boolean.rbs +3 -0
  129. data/sig/terminal_shop/internal/type/converter.rbs +2 -0
  130. data/sig/terminal_shop/internal/type/enum.rbs +3 -0
  131. data/sig/terminal_shop/internal/type/file_input.rbs +2 -0
  132. data/sig/terminal_shop/internal/type/hash_of.rbs +3 -0
  133. data/sig/terminal_shop/internal/type/union.rbs +3 -0
  134. data/sig/terminal_shop/internal/type/unknown.rbs +3 -0
  135. data/sig/terminal_shop/internal/util.rbs +25 -0
  136. data/sig/terminal_shop/internal.rbs +4 -0
  137. metadata +2 -2
checksums.yaml CHANGED
@@ -1,7 +1,7 @@
1
1
  ---
2
2
  SHA256:
3
- metadata.gz: df81693d60a13914c0ca1d8f9b9b9f5691e846931716167132d2133c29471043
4
- data.tar.gz: c8c644764b8b414bec54167ab89a1d3cc7b87b19611c9092fff4cc0209463194
3
+ metadata.gz: '01845ef0b10623ae25a1778177a60981b0edf186dc844b730f99d7cf76b91b99'
4
+ data.tar.gz: 59e7ee0af19ab4dd6ef9d95b54edad958cf89de4fb2e5ce9ba11b23e87509818
5
5
  SHA512:
6
- metadata.gz: 532a6a6630d948cbd312576bcfa4e1f173b8b8229bc9974e05bed17bb5740b6b944342c0cdcd590fdb1932323278a7189f9e9a047791ced7fbdd8cd557404b8e
7
- data.tar.gz: f5741d50ec9f61d5e14a13161d9d13f89b4641b1aa88264681425545e281f1a2a4ef09459ef141971345cbf82560ae87ac71e751ad4dd7f98f458914a79933ed
6
+ metadata.gz: 9f1503d288a6b28bce4920c36d9fdd71bf703985b7c7cba6eaeb117d27729cb9ce527b95ed3c8a8705cf5484015026e01a2532f690af7ac74f594f9adf044410
7
+ data.tar.gz: 7af9706e59ebac0b27c713f7d9e93b45867a865423139d7841b0eb655988ff7ced99f3cb6d2dd8bb75f8b15c6057f70ec86f20c2f76f4d73c9bbf67403de20d4
data/CHANGELOG.md CHANGED
@@ -1,5 +1,53 @@
1
1
  # Changelog
2
2
 
3
+ ## 3.8.0 (2025-05-22)
4
+
5
+ Full Changelog: [v3.7.0...v3.8.0](https://github.com/terminaldotshop/terminal-sdk-ruby/compare/v3.7.0...v3.8.0)
6
+
7
+ ### Features
8
+
9
+ * bump default connection pool size limit to minimum of 99 ([81feb3e](https://github.com/terminaldotshop/terminal-sdk-ruby/commit/81feb3eb7e2d0c5b1df983647c436ebf966ece2c))
10
+
11
+
12
+ ### Bug Fixes
13
+
14
+ * correctly instantiate sorbet type aliases for enums and unions ([2698489](https://github.com/terminaldotshop/terminal-sdk-ruby/commit/2698489f9f63ced3353196009dc2329e20f8cff5))
15
+
16
+
17
+ ### Chores
18
+
19
+ * **docs:** grammar improvements ([841d9a7](https://github.com/terminaldotshop/terminal-sdk-ruby/commit/841d9a7d18776a55e947cee60233d0756579b22c))
20
+ * **internal:** codegen related update ([68a3efa](https://github.com/terminaldotshop/terminal-sdk-ruby/commit/68a3efaf40e8944faf60b604b5aa33b46c1aedf0))
21
+ * refine Yard and Sorbet types and ensure linting is turned on for examples ([41916e7](https://github.com/terminaldotshop/terminal-sdk-ruby/commit/41916e7b6c195ae8085ac89393b0893b42bf72bc))
22
+ * use sorbet union aliases where available ([046dd18](https://github.com/terminaldotshop/terminal-sdk-ruby/commit/046dd183ff9c9826d45fdcf73a6512effd343ca5))
23
+ * whitespaces ([88c3862](https://github.com/terminaldotshop/terminal-sdk-ruby/commit/88c38620dbdceefd1eb268b457a464a0b59daa6c))
24
+
25
+
26
+ ### Documentation
27
+
28
+ * rewrite much of README.md for readability ([564f4f7](https://github.com/terminaldotshop/terminal-sdk-ruby/commit/564f4f7b65f67c1f4f17f6a06c952a570263d4d1))
29
+
30
+ ## 3.7.0 (2025-05-14)
31
+
32
+ Full Changelog: [v3.6.2...v3.7.0](https://github.com/terminaldotshop/terminal-sdk-ruby/compare/v3.6.2...v3.7.0)
33
+
34
+ ### Features
35
+
36
+ * expose base client options as read only attributes ([5ed1891](https://github.com/terminaldotshop/terminal-sdk-ruby/commit/5ed18915050ee0f2db755deaa6655e93e0e3b766))
37
+ * expose recursive `#to_h` conversion ([ca0cc5f](https://github.com/terminaldotshop/terminal-sdk-ruby/commit/ca0cc5f0001bbb2f5b9c5edd7e4e7a017f268956))
38
+ * support sorbet aliases at the runtime ([9e210bb](https://github.com/terminaldotshop/terminal-sdk-ruby/commit/9e210bb7cb568a0c4b7a10e87e69772d56a0306b))
39
+
40
+
41
+ ### Bug Fixes
42
+
43
+ * **internal:** update gemspec name ([47cc74b](https://github.com/terminaldotshop/terminal-sdk-ruby/commit/47cc74b18b522e6caa46b014977c035b144e8faf))
44
+
45
+
46
+ ### Chores
47
+
48
+ * fix misc linting / minor issues ([536f483](https://github.com/terminaldotshop/terminal-sdk-ruby/commit/536f483f7916651ae0ae11f663315c8b379dc619))
49
+ * **internal:** version bump ([cbba1d7](https://github.com/terminaldotshop/terminal-sdk-ruby/commit/cbba1d7501215bf6a55a54d1fcbdaea01da212d6))
50
+
3
51
  ## 3.6.2 (2025-05-08)
4
52
 
5
53
  Full Changelog: [v3.6.1...v3.6.2](https://github.com/terminaldotshop/terminal-sdk-ruby/compare/v3.6.1...v3.6.2)
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.6.2"
20
+ gem "terminal-shop", "~> 3.8.0"
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}"
@@ -99,7 +99,7 @@ module TerminalShop
99
99
  # @param response [nil]
100
100
  # @param message [String, nil]
101
101
  #
102
- # @return [TerminalShop::Errors::APIStatusError]
102
+ # @return [self]
103
103
  def self.for(url:, status:, body:, request:, response:, message: nil)
104
104
  kwargs = {
105
105
  url: url,
@@ -7,6 +7,8 @@ module TerminalShop
7
7
  #
8
8
  # @abstract
9
9
  class BaseClient
10
+ extend TerminalShop::Internal::Util::SorbetRuntimeSupport
11
+
10
12
  # from whatwg fetch spec
11
13
  MAX_REDIRECTS = 20
12
14
 
@@ -151,6 +153,27 @@ module TerminalShop
151
153
  end
152
154
  end
153
155
 
156
+ # @return [URI::Generic]
157
+ attr_reader :base_url
158
+
159
+ # @return [Float]
160
+ attr_reader :timeout
161
+
162
+ # @return [Integer]
163
+ attr_reader :max_retries
164
+
165
+ # @return [Float]
166
+ attr_reader :initial_retry_delay
167
+
168
+ # @return [Float]
169
+ attr_reader :max_retry_delay
170
+
171
+ # @return [Hash{String=>String}]
172
+ attr_reader :headers
173
+
174
+ # @return [String, nil]
175
+ attr_reader :idempotency_header
176
+
154
177
  # @api private
155
178
  # @return [TerminalShop::Internal::Transport::PooledNetRequester]
156
179
  attr_reader :requester
@@ -182,10 +205,11 @@ module TerminalShop
182
205
  },
183
206
  headers
184
207
  )
185
- @base_url = TerminalShop::Internal::Util.parse_uri(base_url)
208
+ @base_url_components = TerminalShop::Internal::Util.parse_uri(base_url)
209
+ @base_url = TerminalShop::Internal::Util.unparse_uri(@base_url_components)
186
210
  @idempotency_header = idempotency_header&.to_s&.downcase
187
- @max_retries = max_retries
188
211
  @timeout = timeout
212
+ @max_retries = max_retries
189
213
  @initial_retry_delay = initial_retry_delay
190
214
  @max_retry_delay = max_retry_delay
191
215
  end
@@ -276,10 +300,14 @@ module TerminalShop
276
300
  TerminalShop::Internal::Util.deep_merge(*[req[:body], opts[:extra_body]].compact)
277
301
  end
278
302
 
303
+ url = TerminalShop::Internal::Util.join_parsed_uri(
304
+ @base_url_components,
305
+ {**req, path: path, query: query}
306
+ )
279
307
  headers, encoded = TerminalShop::Internal::Util.encode_content(headers, body)
280
308
  {
281
309
  method: method,
282
- url: TerminalShop::Internal::Util.join_parsed_uri(@base_url, {**req, path: path, query: query}),
310
+ url: url,
283
311
  headers: headers,
284
312
  body: encoded,
285
313
  max_retries: opts.fetch(:max_retries, @max_retries),
@@ -476,10 +504,54 @@ module TerminalShop
476
504
  # @return [String]
477
505
  def inspect
478
506
  # rubocop:disable Layout/LineLength
479
- base_url = TerminalShop::Internal::Util.unparse_uri(@base_url)
480
- "#<#{self.class.name}:0x#{object_id.to_s(16)} base_url=#{base_url} max_retries=#{@max_retries} timeout=#{@timeout}>"
507
+ "#<#{self.class.name}:0x#{object_id.to_s(16)} base_url=#{@base_url} max_retries=#{@max_retries} timeout=#{@timeout}>"
481
508
  # rubocop:enable Layout/LineLength
482
509
  end
510
+
511
+ define_sorbet_constant!(:RequestComponents) do
512
+ T.type_alias do
513
+ {
514
+ method: Symbol,
515
+ path: T.any(String, T::Array[String]),
516
+ query: T.nilable(T::Hash[String, T.nilable(T.any(T::Array[String], String))]),
517
+ headers: T.nilable(
518
+ T::Hash[String,
519
+ T.nilable(
520
+ T.any(
521
+ String,
522
+ Integer,
523
+ T::Array[T.nilable(T.any(String, Integer))]
524
+ )
525
+ )]
526
+ ),
527
+ body: T.nilable(T.anything),
528
+ unwrap: T.nilable(
529
+ T.any(
530
+ Symbol,
531
+ Integer,
532
+ T::Array[T.any(Symbol, Integer)],
533
+ T.proc.params(arg0: T.anything).returns(T.anything)
534
+ )
535
+ ),
536
+ page: T.nilable(T::Class[TerminalShop::Internal::Type::BasePage[TerminalShop::Internal::Type::BaseModel]]),
537
+ stream: T.nilable(T::Class[T.anything]),
538
+ model: T.nilable(TerminalShop::Internal::Type::Converter::Input),
539
+ options: T.nilable(TerminalShop::RequestOptions::OrHash)
540
+ }
541
+ end
542
+ end
543
+ define_sorbet_constant!(:RequestInput) do
544
+ T.type_alias do
545
+ {
546
+ method: Symbol,
547
+ url: URI::Generic,
548
+ headers: T::Hash[String, String],
549
+ body: T.anything,
550
+ max_retries: Integer,
551
+ timeout: Float
552
+ }
553
+ end
554
+ end
483
555
  end
484
556
  end
485
557
  end
@@ -5,10 +5,14 @@ module TerminalShop
5
5
  module Transport
6
6
  # @api private
7
7
  class PooledNetRequester
8
+ extend TerminalShop::Internal::Util::SorbetRuntimeSupport
9
+
8
10
  # from the golang stdlib
9
11
  # https://github.com/golang/go/blob/c8eced8580028328fde7c03cbfcb720ce15b2358/src/net/http/transport.go#L49
10
12
  KEEP_ALIVE_TIMEOUT = 30
11
13
 
14
+ DEFAULT_MAX_CONNECTIONS = [Etc.nprocessors, 99].max
15
+
12
16
  class << self
13
17
  # @api private
14
18
  #
@@ -182,11 +186,23 @@ module TerminalShop
182
186
  # @api private
183
187
  #
184
188
  # @param size [Integer]
185
- def initialize(size: Etc.nprocessors)
189
+ def initialize(size: self.class::DEFAULT_MAX_CONNECTIONS)
186
190
  @mutex = Mutex.new
187
191
  @size = size
188
192
  @pools = {}
189
193
  end
194
+
195
+ define_sorbet_constant!(:Request) do
196
+ T.type_alias do
197
+ {
198
+ method: Symbol,
199
+ url: URI::Generic,
200
+ headers: T::Hash[String, String],
201
+ body: T.anything,
202
+ deadline: Float
203
+ }
204
+ end
205
+ end
190
206
  end
191
207
  end
192
208
  end
@@ -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
 
@@ -29,7 +30,7 @@ module TerminalShop
29
30
  #
30
31
  # @option spec [Boolean] :"nil?"
31
32
  #
32
- # @return [TerminalShop::Internal::Type::ArrayOf]
33
+ # @return [self]
33
34
  def self.[](...) = new(...)
34
35
 
35
36
  # @api public
@@ -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>]