surge_api 0.1.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (212) hide show
  1. checksums.yaml +7 -0
  2. data/.ignore +2 -0
  3. data/CHANGELOG.md +28 -0
  4. data/README.md +286 -0
  5. data/SECURITY.md +27 -0
  6. data/lib/surge_api/client.rb +106 -0
  7. data/lib/surge_api/errors.rb +228 -0
  8. data/lib/surge_api/file_part.rb +55 -0
  9. data/lib/surge_api/internal/transport/base_client.rb +567 -0
  10. data/lib/surge_api/internal/transport/pooled_net_requester.rb +201 -0
  11. data/lib/surge_api/internal/type/array_of.rb +168 -0
  12. data/lib/surge_api/internal/type/base_model.rb +531 -0
  13. data/lib/surge_api/internal/type/base_page.rb +55 -0
  14. data/lib/surge_api/internal/type/boolean.rb +77 -0
  15. data/lib/surge_api/internal/type/converter.rb +327 -0
  16. data/lib/surge_api/internal/type/enum.rb +131 -0
  17. data/lib/surge_api/internal/type/file_input.rb +108 -0
  18. data/lib/surge_api/internal/type/hash_of.rb +188 -0
  19. data/lib/surge_api/internal/type/request_parameters.rb +42 -0
  20. data/lib/surge_api/internal/type/union.rb +250 -0
  21. data/lib/surge_api/internal/type/unknown.rb +81 -0
  22. data/lib/surge_api/internal/util.rb +915 -0
  23. data/lib/surge_api/internal.rb +20 -0
  24. data/lib/surge_api/models/account.rb +60 -0
  25. data/lib/surge_api/models/account_create_params.rb +481 -0
  26. data/lib/surge_api/models/account_retrieve_status_params.rb +32 -0
  27. data/lib/surge_api/models/account_status.rb +104 -0
  28. data/lib/surge_api/models/account_update_params.rb +480 -0
  29. data/lib/surge_api/models/blast.rb +61 -0
  30. data/lib/surge_api/models/blast_create_params.rb +90 -0
  31. data/lib/surge_api/models/call_ended_webhook_event.rb +106 -0
  32. data/lib/surge_api/models/campaign.rb +208 -0
  33. data/lib/surge_api/models/campaign_approved_webhook_event.rb +74 -0
  34. data/lib/surge_api/models/campaign_create_params.rb +202 -0
  35. data/lib/surge_api/models/contact.rb +59 -0
  36. data/lib/surge_api/models/contact_create_params.rb +54 -0
  37. data/lib/surge_api/models/contact_retrieve_params.rb +14 -0
  38. data/lib/surge_api/models/contact_update_params.rb +54 -0
  39. data/lib/surge_api/models/conversation_created_webhook_event.rb +70 -0
  40. data/lib/surge_api/models/error.rb +34 -0
  41. data/lib/surge_api/models/message.rb +146 -0
  42. data/lib/surge_api/models/message_create_params.rb +153 -0
  43. data/lib/surge_api/models/message_delivered_webhook_event.rb +159 -0
  44. data/lib/surge_api/models/message_failed_webhook_event.rb +167 -0
  45. data/lib/surge_api/models/message_received_webhook_event.rb +159 -0
  46. data/lib/surge_api/models/message_sent_webhook_event.rb +159 -0
  47. data/lib/surge_api/models/organization.rb +419 -0
  48. data/lib/surge_api/models/phone_number.rb +48 -0
  49. data/lib/surge_api/models/phone_number_purchase_params.rb +65 -0
  50. data/lib/surge_api/models/unwrap_webhook_event.rb +26 -0
  51. data/lib/surge_api/models/user.rb +51 -0
  52. data/lib/surge_api/models/user_create_params.rb +46 -0
  53. data/lib/surge_api/models/user_create_token_params.rb +22 -0
  54. data/lib/surge_api/models/user_retrieve_params.rb +14 -0
  55. data/lib/surge_api/models/user_token_response.rb +19 -0
  56. data/lib/surge_api/models/user_update_params.rb +46 -0
  57. data/lib/surge_api/models/verification.rb +58 -0
  58. data/lib/surge_api/models/verification_check.rb +43 -0
  59. data/lib/surge_api/models/verification_check_params.rb +22 -0
  60. data/lib/surge_api/models/verification_create_params.rb +22 -0
  61. data/lib/surge_api/models/webhook_unwrap_params.rb +14 -0
  62. data/lib/surge_api/models.rb +117 -0
  63. data/lib/surge_api/request_options.rb +77 -0
  64. data/lib/surge_api/resources/accounts.rb +102 -0
  65. data/lib/surge_api/resources/blasts.rb +53 -0
  66. data/lib/surge_api/resources/campaigns.rb +57 -0
  67. data/lib/surge_api/resources/contacts.rb +99 -0
  68. data/lib/surge_api/resources/messages.rb +75 -0
  69. data/lib/surge_api/resources/phone_numbers.rb +48 -0
  70. data/lib/surge_api/resources/users.rb +119 -0
  71. data/lib/surge_api/resources/verifications.rb +60 -0
  72. data/lib/surge_api/resources/webhooks.rb +22 -0
  73. data/lib/surge_api/version.rb +5 -0
  74. data/lib/surge_api.rb +100 -0
  75. data/manifest.yaml +15 -0
  76. data/rbi/surge_api/client.rbi +73 -0
  77. data/rbi/surge_api/errors.rbi +205 -0
  78. data/rbi/surge_api/file_part.rbi +37 -0
  79. data/rbi/surge_api/internal/transport/base_client.rbi +292 -0
  80. data/rbi/surge_api/internal/transport/pooled_net_requester.rbi +79 -0
  81. data/rbi/surge_api/internal/type/array_of.rbi +104 -0
  82. data/rbi/surge_api/internal/type/base_model.rbi +302 -0
  83. data/rbi/surge_api/internal/type/base_page.rbi +42 -0
  84. data/rbi/surge_api/internal/type/boolean.rbi +58 -0
  85. data/rbi/surge_api/internal/type/converter.rbi +216 -0
  86. data/rbi/surge_api/internal/type/enum.rbi +82 -0
  87. data/rbi/surge_api/internal/type/file_input.rbi +59 -0
  88. data/rbi/surge_api/internal/type/hash_of.rbi +104 -0
  89. data/rbi/surge_api/internal/type/request_parameters.rbi +29 -0
  90. data/rbi/surge_api/internal/type/union.rbi +128 -0
  91. data/rbi/surge_api/internal/type/unknown.rbi +58 -0
  92. data/rbi/surge_api/internal/util.rbi +487 -0
  93. data/rbi/surge_api/internal.rbi +16 -0
  94. data/rbi/surge_api/models/account.rbi +83 -0
  95. data/rbi/surge_api/models/account_create_params.rbi +1104 -0
  96. data/rbi/surge_api/models/account_retrieve_status_params.rbi +96 -0
  97. data/rbi/surge_api/models/account_status.rbi +185 -0
  98. data/rbi/surge_api/models/account_update_params.rbi +1105 -0
  99. data/rbi/surge_api/models/blast.rbi +108 -0
  100. data/rbi/surge_api/models/blast_create_params.rbi +145 -0
  101. data/rbi/surge_api/models/call_ended_webhook_event.rbi +205 -0
  102. data/rbi/surge_api/models/campaign.rbi +331 -0
  103. data/rbi/surge_api/models/campaign_approved_webhook_event.rbi +149 -0
  104. data/rbi/surge_api/models/campaign_create_params.rbi +386 -0
  105. data/rbi/surge_api/models/contact.rbi +88 -0
  106. data/rbi/surge_api/models/contact_create_params.rbi +87 -0
  107. data/rbi/surge_api/models/contact_retrieve_params.rbi +27 -0
  108. data/rbi/surge_api/models/contact_update_params.rbi +87 -0
  109. data/rbi/surge_api/models/conversation_created_webhook_event.rbi +129 -0
  110. data/rbi/surge_api/models/error.rbi +51 -0
  111. data/rbi/surge_api/models/message.rbi +283 -0
  112. data/rbi/surge_api/models/message_create_params.rbi +281 -0
  113. data/rbi/surge_api/models/message_delivered_webhook_event.rbi +331 -0
  114. data/rbi/surge_api/models/message_failed_webhook_event.rbi +335 -0
  115. data/rbi/surge_api/models/message_received_webhook_event.rbi +331 -0
  116. data/rbi/surge_api/models/message_sent_webhook_event.rbi +322 -0
  117. data/rbi/surge_api/models/organization.rbi +649 -0
  118. data/rbi/surge_api/models/phone_number.rbi +72 -0
  119. data/rbi/surge_api/models/phone_number_purchase_params.rbi +122 -0
  120. data/rbi/surge_api/models/unwrap_webhook_event.rbi +26 -0
  121. data/rbi/surge_api/models/user.rbi +80 -0
  122. data/rbi/surge_api/models/user_create_params.rbi +76 -0
  123. data/rbi/surge_api/models/user_create_token_params.rbi +46 -0
  124. data/rbi/surge_api/models/user_retrieve_params.rbi +27 -0
  125. data/rbi/surge_api/models/user_token_response.rbi +31 -0
  126. data/rbi/surge_api/models/user_update_params.rbi +76 -0
  127. data/rbi/surge_api/models/verification.rbi +86 -0
  128. data/rbi/surge_api/models/verification_check.rbi +84 -0
  129. data/rbi/surge_api/models/verification_check_params.rbi +40 -0
  130. data/rbi/surge_api/models/verification_create_params.rbi +40 -0
  131. data/rbi/surge_api/models/webhook_unwrap_params.rbi +27 -0
  132. data/rbi/surge_api/models.rbi +80 -0
  133. data/rbi/surge_api/request_options.rbi +59 -0
  134. data/rbi/surge_api/resources/accounts.rbi +94 -0
  135. data/rbi/surge_api/resources/blasts.rbi +48 -0
  136. data/rbi/surge_api/resources/campaigns.rbi +115 -0
  137. data/rbi/surge_api/resources/contacts.rbi +85 -0
  138. data/rbi/surge_api/resources/messages.rbi +72 -0
  139. data/rbi/surge_api/resources/phone_numbers.rbi +43 -0
  140. data/rbi/surge_api/resources/users.rbi +96 -0
  141. data/rbi/surge_api/resources/verifications.rbi +43 -0
  142. data/rbi/surge_api/resources/webhooks.rbi +31 -0
  143. data/rbi/surge_api/version.rbi +5 -0
  144. data/sig/surge_api/client.rbs +42 -0
  145. data/sig/surge_api/errors.rbs +117 -0
  146. data/sig/surge_api/file_part.rbs +21 -0
  147. data/sig/surge_api/internal/transport/base_client.rbs +131 -0
  148. data/sig/surge_api/internal/transport/pooled_net_requester.rbs +45 -0
  149. data/sig/surge_api/internal/type/array_of.rbs +48 -0
  150. data/sig/surge_api/internal/type/base_model.rbs +102 -0
  151. data/sig/surge_api/internal/type/base_page.rbs +24 -0
  152. data/sig/surge_api/internal/type/boolean.rbs +26 -0
  153. data/sig/surge_api/internal/type/converter.rbs +79 -0
  154. data/sig/surge_api/internal/type/enum.rbs +32 -0
  155. data/sig/surge_api/internal/type/file_input.rbs +25 -0
  156. data/sig/surge_api/internal/type/hash_of.rbs +48 -0
  157. data/sig/surge_api/internal/type/request_parameters.rbs +17 -0
  158. data/sig/surge_api/internal/type/union.rbs +52 -0
  159. data/sig/surge_api/internal/type/unknown.rbs +26 -0
  160. data/sig/surge_api/internal/util.rbs +185 -0
  161. data/sig/surge_api/internal.rbs +9 -0
  162. data/sig/surge_api/models/account.rbs +40 -0
  163. data/sig/surge_api/models/account_create_params.rbs +433 -0
  164. data/sig/surge_api/models/account_retrieve_status_params.rbs +40 -0
  165. data/sig/surge_api/models/account_status.rbs +71 -0
  166. data/sig/surge_api/models/account_update_params.rbs +435 -0
  167. data/sig/surge_api/models/blast.rbs +64 -0
  168. data/sig/surge_api/models/blast_create_params.rbs +82 -0
  169. data/sig/surge_api/models/call_ended_webhook_event.rbs +99 -0
  170. data/sig/surge_api/models/campaign.rbs +122 -0
  171. data/sig/surge_api/models/campaign_approved_webhook_event.rbs +67 -0
  172. data/sig/surge_api/models/campaign_create_params.rbs +127 -0
  173. data/sig/surge_api/models/contact.rbs +53 -0
  174. data/sig/surge_api/models/contact_create_params.rbs +54 -0
  175. data/sig/surge_api/models/contact_retrieve_params.rbs +15 -0
  176. data/sig/surge_api/models/contact_update_params.rbs +54 -0
  177. data/sig/surge_api/models/conversation_created_webhook_event.rbs +62 -0
  178. data/sig/surge_api/models/error.rbs +27 -0
  179. data/sig/surge_api/models/message.rbs +138 -0
  180. data/sig/surge_api/models/message_create_params.rbs +140 -0
  181. data/sig/surge_api/models/message_delivered_webhook_event.rbs +143 -0
  182. data/sig/surge_api/models/message_failed_webhook_event.rbs +148 -0
  183. data/sig/surge_api/models/message_received_webhook_event.rbs +143 -0
  184. data/sig/surge_api/models/message_sent_webhook_event.rbs +143 -0
  185. data/sig/surge_api/models/organization.rbs +385 -0
  186. data/sig/surge_api/models/phone_number.rbs +37 -0
  187. data/sig/surge_api/models/phone_number_purchase_params.rbs +62 -0
  188. data/sig/surge_api/models/unwrap_webhook_event.rbs +18 -0
  189. data/sig/surge_api/models/user.rbs +48 -0
  190. data/sig/surge_api/models/user_create_params.rbs +47 -0
  191. data/sig/surge_api/models/user_create_token_params.rbs +26 -0
  192. data/sig/surge_api/models/user_retrieve_params.rbs +15 -0
  193. data/sig/surge_api/models/user_token_response.rbs +15 -0
  194. data/sig/surge_api/models/user_update_params.rbs +47 -0
  195. data/sig/surge_api/models/verification.rbs +48 -0
  196. data/sig/surge_api/models/verification_check.rbs +45 -0
  197. data/sig/surge_api/models/verification_check_params.rbs +23 -0
  198. data/sig/surge_api/models/verification_create_params.rbs +23 -0
  199. data/sig/surge_api/models/webhook_unwrap_params.rbs +15 -0
  200. data/sig/surge_api/models.rbs +77 -0
  201. data/sig/surge_api/request_options.rbs +34 -0
  202. data/sig/surge_api/resources/accounts.rbs +30 -0
  203. data/sig/surge_api/resources/blasts.rbs +19 -0
  204. data/sig/surge_api/resources/campaigns.rbs +21 -0
  205. data/sig/surge_api/resources/contacts.rbs +32 -0
  206. data/sig/surge_api/resources/messages.rbs +18 -0
  207. data/sig/surge_api/resources/phone_numbers.rbs +16 -0
  208. data/sig/surge_api/resources/users.rbs +36 -0
  209. data/sig/surge_api/resources/verifications.rbs +18 -0
  210. data/sig/surge_api/resources/webhooks.rbs +17 -0
  211. data/sig/surge_api/version.rbs +3 -0
  212. metadata +269 -0
@@ -0,0 +1,188 @@
1
+ # frozen_string_literal: true
2
+
3
+ module SurgeAPI
4
+ module Internal
5
+ module Type
6
+ # @api private
7
+ #
8
+ # @abstract
9
+ #
10
+ # @generic Elem
11
+ #
12
+ # Hash of items of a given type.
13
+ class HashOf
14
+ include SurgeAPI::Internal::Type::Converter
15
+ include SurgeAPI::Internal::Util::SorbetRuntimeSupport
16
+
17
+ private_class_method :new
18
+
19
+ # @overload [](type_info, spec = {})
20
+ #
21
+ # @param type_info [Hash{Symbol=>Object}, Proc, SurgeAPI::Internal::Type::Converter, Class]
22
+ #
23
+ # @param spec [Hash{Symbol=>Object}] .
24
+ #
25
+ # @option spec [NilClass, TrueClass, FalseClass, Integer, Float, Symbol] :const
26
+ #
27
+ # @option spec [Proc] :enum
28
+ #
29
+ # @option spec [Proc] :union
30
+ #
31
+ # @option spec [Boolean] :"nil?"
32
+ #
33
+ # @return [self]
34
+ def self.[](...) = new(...)
35
+
36
+ # @api public
37
+ #
38
+ # @param other [Object]
39
+ #
40
+ # @return [Boolean]
41
+ def ===(other)
42
+ type = item_type
43
+ case other
44
+ in Hash
45
+ other.all? do |key, val|
46
+ case [key, val]
47
+ in [Symbol | String, ^type]
48
+ true
49
+ else
50
+ false
51
+ end
52
+ end
53
+ else
54
+ false
55
+ end
56
+ end
57
+
58
+ # @api public
59
+ #
60
+ # @param other [Object]
61
+ #
62
+ # @return [Boolean]
63
+ def ==(other)
64
+ # rubocop:disable Layout/LineLength
65
+ other.is_a?(SurgeAPI::Internal::Type::HashOf) && other.nilable? == nilable? && other.item_type == item_type
66
+ # rubocop:enable Layout/LineLength
67
+ end
68
+
69
+ # @api public
70
+ #
71
+ # @return [Integer]
72
+ def hash = [self.class, item_type].hash
73
+
74
+ # @api private
75
+ #
76
+ # @param value [Hash{Object=>Object}, Object]
77
+ #
78
+ # @param state [Hash{Symbol=>Object}] .
79
+ #
80
+ # @option state [Boolean] :translate_names
81
+ #
82
+ # @option state [Boolean] :strictness
83
+ #
84
+ # @option state [Hash{Symbol=>Object}] :exactness
85
+ #
86
+ # @option state [Class<StandardError>] :error
87
+ #
88
+ # @option state [Integer] :branched
89
+ #
90
+ # @return [Hash{Symbol=>Object}, Object]
91
+ def coerce(value, state:)
92
+ exactness = state.fetch(:exactness)
93
+
94
+ unless value.is_a?(Hash)
95
+ exactness[:no] += 1
96
+ state[:error] = TypeError.new("#{value.class} can't be coerced into #{Hash}")
97
+ return value
98
+ end
99
+
100
+ target = item_type
101
+ exactness[:yes] += 1
102
+ value
103
+ .to_h do |key, val|
104
+ k = key.is_a?(String) ? key.to_sym : key
105
+ v =
106
+ case [nilable?, val]
107
+ in [true, nil]
108
+ exactness[:yes] += 1
109
+ nil
110
+ else
111
+ SurgeAPI::Internal::Type::Converter.coerce(target, val, state: state)
112
+ end
113
+
114
+ exactness[:no] += 1 unless k.is_a?(Symbol)
115
+ [k, v]
116
+ end
117
+ end
118
+
119
+ # @api private
120
+ #
121
+ # @param value [Hash{Object=>Object}, Object]
122
+ #
123
+ # @param state [Hash{Symbol=>Object}] .
124
+ #
125
+ # @option state [Boolean] :can_retry
126
+ #
127
+ # @return [Hash{Symbol=>Object}, Object]
128
+ def dump(value, state:)
129
+ target = item_type
130
+ if value.is_a?(Hash)
131
+ value.transform_values do
132
+ SurgeAPI::Internal::Type::Converter.dump(target, _1, state: state)
133
+ end
134
+ else
135
+ super
136
+ end
137
+ end
138
+
139
+ # @api private
140
+ #
141
+ # @return [Object]
142
+ def to_sorbet_type
143
+ T::Hash[SurgeAPI::Internal::Util::SorbetRuntimeSupport.to_sorbet_type(item_type)]
144
+ end
145
+
146
+ # @api private
147
+ #
148
+ # @return [generic<Elem>]
149
+ protected def item_type = @item_type_fn.call
150
+
151
+ # @api private
152
+ #
153
+ # @return [Boolean]
154
+ protected def nilable? = @nilable
155
+
156
+ # @api private
157
+ #
158
+ # @param type_info [Hash{Symbol=>Object}, Proc, SurgeAPI::Internal::Type::Converter, Class]
159
+ #
160
+ # @param spec [Hash{Symbol=>Object}] .
161
+ #
162
+ # @option spec [NilClass, TrueClass, FalseClass, Integer, Float, Symbol] :const
163
+ #
164
+ # @option spec [Proc] :enum
165
+ #
166
+ # @option spec [Proc] :union
167
+ #
168
+ # @option spec [Boolean] :"nil?"
169
+ def initialize(type_info, spec = {})
170
+ @item_type_fn = SurgeAPI::Internal::Type::Converter.type_info(type_info || spec)
171
+ @meta = SurgeAPI::Internal::Type::Converter.meta_info(type_info, spec)
172
+ @nilable = spec.fetch(:nil?, false)
173
+ end
174
+
175
+ # @api private
176
+ #
177
+ # @param depth [Integer]
178
+ #
179
+ # @return [String]
180
+ def inspect(depth: 0)
181
+ items = SurgeAPI::Internal::Type::Converter.inspect(item_type, depth: depth.succ)
182
+
183
+ "#{self.class}[#{[items, nilable? ? 'nil' : nil].compact.join(' | ')}]"
184
+ end
185
+ end
186
+ end
187
+ end
188
+ end
@@ -0,0 +1,42 @@
1
+ # frozen_string_literal: true
2
+
3
+ module SurgeAPI
4
+ module Internal
5
+ module Type
6
+ # @api private
7
+ module RequestParameters
8
+ # @!attribute request_options
9
+ # Options to specify HTTP behaviour for this request.
10
+ #
11
+ # @return [SurgeAPI::RequestOptions, Hash{Symbol=>Object}]
12
+
13
+ # @param mod [Module]
14
+ def self.included(mod)
15
+ raise ArgumentError.new(mod) unless mod <= SurgeAPI::Internal::Type::BaseModel
16
+
17
+ mod.optional(:request_options, SurgeAPI::RequestOptions)
18
+ end
19
+
20
+ # @api private
21
+ module Converter
22
+ # @api private
23
+ #
24
+ # @param params [Object]
25
+ #
26
+ # @return [Array(Object, Hash{Symbol=>Object})]
27
+ def dump_request(params)
28
+ state = {can_retry: true}
29
+ case (dumped = dump(params, state: state))
30
+ in Hash
31
+ options = SurgeAPI::Internal::Util.coerce_hash!(dumped[:request_options]).to_h
32
+ request_options = state.fetch(:can_retry) ? options : {**options, max_retries: 0}
33
+ [dumped.except(:request_options), request_options]
34
+ else
35
+ [dumped, nil]
36
+ end
37
+ end
38
+ end
39
+ end
40
+ end
41
+ end
42
+ end
@@ -0,0 +1,250 @@
1
+ # frozen_string_literal: true
2
+
3
+ module SurgeAPI
4
+ module Internal
5
+ module Type
6
+ # @api private
7
+ #
8
+ # @example
9
+ # # `unwrap_webhook_event` is a `SurgeAPI::UnwrapWebhookEvent`
10
+ # case unwrap_webhook_event
11
+ # when SurgeAPI::CallEndedWebhookEvent
12
+ # puts(unwrap_webhook_event.account_id)
13
+ # when SurgeAPI::CampaignApprovedWebhookEvent
14
+ # puts(unwrap_webhook_event.data)
15
+ # when SurgeAPI::ConversationCreatedWebhookEvent
16
+ # puts(unwrap_webhook_event.timestamp)
17
+ # else
18
+ # puts(unwrap_webhook_event)
19
+ # end
20
+ module Union
21
+ include SurgeAPI::Internal::Type::Converter
22
+ include SurgeAPI::Internal::Util::SorbetRuntimeSupport
23
+
24
+ # @api private
25
+ #
26
+ # All of the specified variant info for this union.
27
+ #
28
+ # @return [Array<Array(Symbol, Proc, Hash{Symbol=>Object})>]
29
+ private def known_variants = (@known_variants ||= [])
30
+
31
+ # @api private
32
+ #
33
+ # @return [Array<Array(Symbol, Object, Hash{Symbol=>Object})>]
34
+ protected def derefed_variants
35
+ known_variants.map { |key, variant_fn, meta| [key, variant_fn.call, meta] }
36
+ end
37
+
38
+ # All of the specified variants for this union.
39
+ #
40
+ # @return [Array<Object>]
41
+ def variants = derefed_variants.map { _2 }
42
+
43
+ # @api private
44
+ #
45
+ # @param property [Symbol]
46
+ private def discriminator(property)
47
+ case property
48
+ in Symbol
49
+ @discriminator = property
50
+ end
51
+ end
52
+
53
+ # @api private
54
+ #
55
+ # @param key [Symbol, Hash{Symbol=>Object}, Proc, SurgeAPI::Internal::Type::Converter, Class]
56
+ #
57
+ # @param spec [Hash{Symbol=>Object}, Proc, SurgeAPI::Internal::Type::Converter, Class] .
58
+ #
59
+ # @option spec [NilClass, TrueClass, FalseClass, Integer, Float, Symbol] :const
60
+ #
61
+ # @option spec [Proc] :enum
62
+ #
63
+ # @option spec [Proc] :union
64
+ #
65
+ # @option spec [Boolean] :"nil?"
66
+ private def variant(key, spec = nil)
67
+ meta = SurgeAPI::Internal::Type::Converter.meta_info(nil, spec)
68
+ variant_info =
69
+ case key
70
+ in Symbol
71
+ [key, SurgeAPI::Internal::Type::Converter.type_info(spec), meta]
72
+ in Proc | SurgeAPI::Internal::Type::Converter | Class | Hash
73
+ [nil, SurgeAPI::Internal::Type::Converter.type_info(key), meta]
74
+ end
75
+
76
+ known_variants << variant_info
77
+ end
78
+
79
+ # @api private
80
+ #
81
+ # @param value [Object]
82
+ #
83
+ # @return [SurgeAPI::Internal::Type::Converter, Class, nil]
84
+ private def resolve_variant(value)
85
+ case [@discriminator, value]
86
+ in [_, SurgeAPI::Internal::Type::BaseModel]
87
+ value.class
88
+ in [Symbol, Hash]
89
+ key = value.fetch(@discriminator) do
90
+ value.fetch(@discriminator.to_s, SurgeAPI::Internal::OMIT)
91
+ end
92
+
93
+ return nil if key == SurgeAPI::Internal::OMIT
94
+
95
+ key = key.to_sym if key.is_a?(String)
96
+ _, found = known_variants.find { |k,| k == key }
97
+ found&.call
98
+ else
99
+ nil
100
+ end
101
+ end
102
+
103
+ # rubocop:disable Style/HashEachMethods
104
+ # rubocop:disable Style/CaseEquality
105
+
106
+ # @api public
107
+ #
108
+ # @param other [Object]
109
+ #
110
+ # @return [Boolean]
111
+ def ===(other)
112
+ known_variants.any? do |_, variant_fn|
113
+ variant_fn.call === other
114
+ end
115
+ end
116
+
117
+ # @api public
118
+ #
119
+ # @param other [Object]
120
+ #
121
+ # @return [Boolean]
122
+ def ==(other)
123
+ SurgeAPI::Internal::Type::Union === other && other.derefed_variants == derefed_variants
124
+ end
125
+
126
+ # @api public
127
+ #
128
+ # @return [Integer]
129
+ def hash = variants.hash
130
+
131
+ # @api private
132
+ #
133
+ # Tries to efficiently coerce the given value to one of the known variants.
134
+ #
135
+ # If the value cannot match any of the known variants, the coercion is considered
136
+ # non-viable and returns the original value.
137
+ #
138
+ # @param value [Object]
139
+ #
140
+ # @param state [Hash{Symbol=>Object}] .
141
+ #
142
+ # @option state [Boolean] :translate_names
143
+ #
144
+ # @option state [Boolean] :strictness
145
+ #
146
+ # @option state [Hash{Symbol=>Object}] :exactness
147
+ #
148
+ # @option state [Class<StandardError>] :error
149
+ #
150
+ # @option state [Integer] :branched
151
+ #
152
+ # @return [Object]
153
+ def coerce(value, state:)
154
+ if (target = resolve_variant(value))
155
+ return SurgeAPI::Internal::Type::Converter.coerce(target, value, state: state)
156
+ end
157
+
158
+ strictness = state.fetch(:strictness)
159
+ exactness = state.fetch(:exactness)
160
+
161
+ alternatives = []
162
+ known_variants.each do |_, variant_fn|
163
+ target = variant_fn.call
164
+ exact = state[:exactness] = {yes: 0, no: 0, maybe: 0}
165
+ state[:branched] += 1
166
+
167
+ coerced = SurgeAPI::Internal::Type::Converter.coerce(target, value, state: state)
168
+ yes, no, maybe = exact.values
169
+ if (no + maybe).zero? || (!strictness && yes.positive?)
170
+ exact.each { exactness[_1] += _2 }
171
+ state[:exactness] = exactness
172
+ return coerced
173
+ elsif maybe.positive?
174
+ alternatives << [[-yes, -maybe, no], exact, coerced]
175
+ end
176
+ end
177
+
178
+ case alternatives.sort_by!(&:first)
179
+ in []
180
+ exactness[:no] += 1
181
+ state[:error] = ArgumentError.new("no matching variant for #{value.inspect}")
182
+ value
183
+ in [[_, exact, coerced], *]
184
+ exact.each { exactness[_1] += _2 }
185
+ coerced
186
+ end
187
+ .tap { state[:exactness] = exactness }
188
+ ensure
189
+ state[:strictness] = strictness
190
+ end
191
+
192
+ # @api private
193
+ #
194
+ # @param value [Object]
195
+ #
196
+ # @param state [Hash{Symbol=>Object}] .
197
+ #
198
+ # @option state [Boolean] :can_retry
199
+ #
200
+ # @return [Object]
201
+ def dump(value, state:)
202
+ if (target = resolve_variant(value))
203
+ return SurgeAPI::Internal::Type::Converter.dump(target, value, state: state)
204
+ end
205
+
206
+ known_variants.each do
207
+ target = _2.call
208
+ return SurgeAPI::Internal::Type::Converter.dump(target, value, state: state) if target === value
209
+ end
210
+
211
+ super
212
+ end
213
+
214
+ # @api private
215
+ #
216
+ # @return [Object]
217
+ def to_sorbet_type
218
+ types = variants.map { SurgeAPI::Internal::Util::SorbetRuntimeSupport.to_sorbet_type(_1) }.uniq
219
+ case types
220
+ in []
221
+ T.noreturn
222
+ in [type]
223
+ type
224
+ else
225
+ T.any(*types)
226
+ end
227
+ end
228
+
229
+ # rubocop:enable Style/CaseEquality
230
+ # rubocop:enable Style/HashEachMethods
231
+
232
+ # @api private
233
+ #
234
+ # @param depth [Integer]
235
+ #
236
+ # @return [String]
237
+ def inspect(depth: 0)
238
+ if depth.positive?
239
+ return is_a?(Module) ? super() : self.class.name
240
+ end
241
+
242
+ members = variants.map { SurgeAPI::Internal::Type::Converter.inspect(_1, depth: depth.succ) }
243
+ prefix = is_a?(Module) ? name : self.class.name
244
+
245
+ "#{prefix}[#{members.join(' | ')}]"
246
+ end
247
+ end
248
+ end
249
+ end
250
+ end
@@ -0,0 +1,81 @@
1
+ # frozen_string_literal: true
2
+
3
+ module SurgeAPI
4
+ module Internal
5
+ module Type
6
+ # @api private
7
+ #
8
+ # @abstract
9
+ #
10
+ # When we don't know what to expect for the value.
11
+ class Unknown
12
+ extend SurgeAPI::Internal::Type::Converter
13
+ extend SurgeAPI::Internal::Util::SorbetRuntimeSupport
14
+
15
+ # rubocop:disable Lint/UnusedMethodArgument
16
+
17
+ private_class_method :new
18
+
19
+ # @api public
20
+ #
21
+ # @param other [Object]
22
+ #
23
+ # @return [Boolean]
24
+ def self.===(other) = true
25
+
26
+ # @api public
27
+ #
28
+ # @param other [Object]
29
+ #
30
+ # @return [Boolean]
31
+ def self.==(other) = other.is_a?(Class) && other <= SurgeAPI::Internal::Type::Unknown
32
+
33
+ class << self
34
+ # @api private
35
+ #
36
+ # No coercion needed for Unknown type.
37
+ #
38
+ # @param value [Object]
39
+ #
40
+ # @param state [Hash{Symbol=>Object}] .
41
+ #
42
+ # @option state [Boolean] :translate_names
43
+ #
44
+ # @option state [Boolean] :strictness
45
+ #
46
+ # @option state [Hash{Symbol=>Object}] :exactness
47
+ #
48
+ # @option state [Class<StandardError>] :error
49
+ #
50
+ # @option state [Integer] :branched
51
+ #
52
+ # @return [Object]
53
+ def coerce(value, state:)
54
+ state.fetch(:exactness)[:yes] += 1
55
+ value
56
+ end
57
+
58
+ # @!method dump(value, state:)
59
+ # @api private
60
+ #
61
+ # @param value [Object]
62
+ #
63
+ # @param state [Hash{Symbol=>Object}] .
64
+ #
65
+ # @option state [Boolean] :can_retry
66
+ #
67
+ # @return [Object]
68
+
69
+ # @api private
70
+ #
71
+ # @return [Object]
72
+ def to_sorbet_type
73
+ T.anything
74
+ end
75
+ end
76
+
77
+ # rubocop:enable Lint/UnusedMethodArgument
78
+ end
79
+ end
80
+ end
81
+ end