galaxy-ruby 0.2.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 (145) hide show
  1. checksums.yaml +7 -0
  2. data/CHANGELOG.md +8 -0
  3. data/LICENSE +201 -0
  4. data/README.md +169 -0
  5. data/SECURITY.md +19 -0
  6. data/SKILL.md +83 -0
  7. data/api.md +188 -0
  8. data/lib/galaxy-ruby/client.rb +254 -0
  9. data/lib/galaxy-ruby/errors.rb +227 -0
  10. data/lib/galaxy-ruby/file_part.rb +58 -0
  11. data/lib/galaxy-ruby/internal/transport/base_client.rb +576 -0
  12. data/lib/galaxy-ruby/internal/transport/pooled_net_requester.rb +224 -0
  13. data/lib/galaxy-ruby/internal/type/array_of.rb +164 -0
  14. data/lib/galaxy-ruby/internal/type/base_model.rb +529 -0
  15. data/lib/galaxy-ruby/internal/type/base_page.rb +55 -0
  16. data/lib/galaxy-ruby/internal/type/boolean.rb +77 -0
  17. data/lib/galaxy-ruby/internal/type/converter.rb +333 -0
  18. data/lib/galaxy-ruby/internal/type/enum.rb +130 -0
  19. data/lib/galaxy-ruby/internal/type/file_input.rb +111 -0
  20. data/lib/galaxy-ruby/internal/type/hash_of.rb +184 -0
  21. data/lib/galaxy-ruby/internal/type/request_parameters.rb +42 -0
  22. data/lib/galaxy-ruby/internal/type/union.rb +234 -0
  23. data/lib/galaxy-ruby/internal/type/unknown.rb +81 -0
  24. data/lib/galaxy-ruby/internal/util.rb +960 -0
  25. data/lib/galaxy-ruby/internal.rb +15 -0
  26. data/lib/galaxy-ruby/models/authentication_create_token_params.rb +14 -0
  27. data/lib/galaxy-ruby/models/authentication_create_token_response.rb +16 -0
  28. data/lib/galaxy-ruby/models/authentication_create_user_params.rb +32 -0
  29. data/lib/galaxy-ruby/models/authentication_list_me_params.rb +14 -0
  30. data/lib/galaxy-ruby/models/celestial_body.rb +81 -0
  31. data/lib/galaxy-ruby/models/celestial_body_create_params.rb +20 -0
  32. data/lib/galaxy-ruby/models/credentials.rb +25 -0
  33. data/lib/galaxy-ruby/models/new_planet_webhook_event.rb +216 -0
  34. data/lib/galaxy-ruby/models/planet.rb +218 -0
  35. data/lib/galaxy-ruby/models/planet_create_params.rb +14 -0
  36. data/lib/galaxy-ruby/models/planet_delete_params.rb +20 -0
  37. data/lib/galaxy-ruby/models/planet_delte_image_params.rb +29 -0
  38. data/lib/galaxy-ruby/models/planet_delte_image_response.rb +48 -0
  39. data/lib/galaxy-ruby/models/planet_list_all_data_params.rb +30 -0
  40. data/lib/galaxy-ruby/models/planet_list_all_data_response.rb +51 -0
  41. data/lib/galaxy-ruby/models/planet_retrieve_params.rb +20 -0
  42. data/lib/galaxy-ruby/models/planet_update_params.rb +20 -0
  43. data/lib/galaxy-ruby/models/unwrap_webhook_event.rb +14 -0
  44. data/lib/galaxy-ruby/models/user.rb +26 -0
  45. data/lib/galaxy-ruby/models/webhook_unwrap_params.rb +14 -0
  46. data/lib/galaxy-ruby/models.rb +78 -0
  47. data/lib/galaxy-ruby/request_options.rb +77 -0
  48. data/lib/galaxy-ruby/resources/authentication.rb +80 -0
  49. data/lib/galaxy-ruby/resources/celestial_bodies.rb +37 -0
  50. data/lib/galaxy-ruby/resources/planets.rb +215 -0
  51. data/lib/galaxy-ruby/resources/webhooks.rb +34 -0
  52. data/lib/galaxy-ruby/version.rb +5 -0
  53. data/lib/galaxy-ruby.rb +78 -0
  54. data/rbi/galaxy-ruby/client.rbi +128 -0
  55. data/rbi/galaxy-ruby/errors.rbi +205 -0
  56. data/rbi/galaxy-ruby/file_part.rbi +37 -0
  57. data/rbi/galaxy-ruby/internal/transport/base_client.rbi +305 -0
  58. data/rbi/galaxy-ruby/internal/transport/pooled_net_requester.rbi +84 -0
  59. data/rbi/galaxy-ruby/internal/type/array_of.rbi +104 -0
  60. data/rbi/galaxy-ruby/internal/type/base_model.rbi +314 -0
  61. data/rbi/galaxy-ruby/internal/type/base_page.rbi +43 -0
  62. data/rbi/galaxy-ruby/internal/type/boolean.rbi +58 -0
  63. data/rbi/galaxy-ruby/internal/type/converter.rbi +222 -0
  64. data/rbi/galaxy-ruby/internal/type/enum.rbi +82 -0
  65. data/rbi/galaxy-ruby/internal/type/file_input.rbi +59 -0
  66. data/rbi/galaxy-ruby/internal/type/hash_of.rbi +104 -0
  67. data/rbi/galaxy-ruby/internal/type/request_parameters.rbi +31 -0
  68. data/rbi/galaxy-ruby/internal/type/union.rbi +128 -0
  69. data/rbi/galaxy-ruby/internal/type/unknown.rbi +58 -0
  70. data/rbi/galaxy-ruby/internal/util.rbi +515 -0
  71. data/rbi/galaxy-ruby/internal.rbi +18 -0
  72. data/rbi/galaxy-ruby/models/authentication_create_token_params.rbi +32 -0
  73. data/rbi/galaxy-ruby/models/authentication_create_token_response.rbi +29 -0
  74. data/rbi/galaxy-ruby/models/authentication_create_user_params.rbi +54 -0
  75. data/rbi/galaxy-ruby/models/authentication_list_me_params.rbi +32 -0
  76. data/rbi/galaxy-ruby/models/celestial_body.rbi +140 -0
  77. data/rbi/galaxy-ruby/models/celestial_body_create_params.rbi +53 -0
  78. data/rbi/galaxy-ruby/models/credentials.rbi +27 -0
  79. data/rbi/galaxy-ruby/models/new_planet_webhook_event.rbi +396 -0
  80. data/rbi/galaxy-ruby/models/planet.rbi +350 -0
  81. data/rbi/galaxy-ruby/models/planet_create_params.rbi +32 -0
  82. data/rbi/galaxy-ruby/models/planet_delete_params.rbi +38 -0
  83. data/rbi/galaxy-ruby/models/planet_delte_image_params.rbi +55 -0
  84. data/rbi/galaxy-ruby/models/planet_delte_image_response.rbi +85 -0
  85. data/rbi/galaxy-ruby/models/planet_list_all_data_params.rbi +60 -0
  86. data/rbi/galaxy-ruby/models/planet_list_all_data_response.rbi +110 -0
  87. data/rbi/galaxy-ruby/models/planet_retrieve_params.rbi +38 -0
  88. data/rbi/galaxy-ruby/models/planet_update_params.rbi +38 -0
  89. data/rbi/galaxy-ruby/models/unwrap_webhook_event.rbi +17 -0
  90. data/rbi/galaxy-ruby/models/user.rbi +33 -0
  91. data/rbi/galaxy-ruby/models/webhook_unwrap_params.rbi +32 -0
  92. data/rbi/galaxy-ruby/models.rbi +39 -0
  93. data/rbi/galaxy-ruby/request_options.rbi +59 -0
  94. data/rbi/galaxy-ruby/resources/authentication.rbi +47 -0
  95. data/rbi/galaxy-ruby/resources/celestial_bodies.rbi +28 -0
  96. data/rbi/galaxy-ruby/resources/planets.rbi +176 -0
  97. data/rbi/galaxy-ruby/resources/webhooks.rbi +29 -0
  98. data/rbi/galaxy-ruby/version.rbi +5 -0
  99. data/sig/galaxy-ruby/client.rbs +62 -0
  100. data/sig/galaxy-ruby/errors.rbs +117 -0
  101. data/sig/galaxy-ruby/file_part.rbs +21 -0
  102. data/sig/galaxy-ruby/internal/transport/base_client.rbs +133 -0
  103. data/sig/galaxy-ruby/internal/transport/pooled_net_requester.rbs +48 -0
  104. data/sig/galaxy-ruby/internal/type/array_of.rbs +48 -0
  105. data/sig/galaxy-ruby/internal/type/base_model.rbs +102 -0
  106. data/sig/galaxy-ruby/internal/type/base_page.rbs +24 -0
  107. data/sig/galaxy-ruby/internal/type/boolean.rbs +26 -0
  108. data/sig/galaxy-ruby/internal/type/converter.rbs +79 -0
  109. data/sig/galaxy-ruby/internal/type/enum.rbs +32 -0
  110. data/sig/galaxy-ruby/internal/type/file_input.rbs +25 -0
  111. data/sig/galaxy-ruby/internal/type/hash_of.rbs +48 -0
  112. data/sig/galaxy-ruby/internal/type/request_parameters.rbs +17 -0
  113. data/sig/galaxy-ruby/internal/type/union.rbs +52 -0
  114. data/sig/galaxy-ruby/internal/type/unknown.rbs +26 -0
  115. data/sig/galaxy-ruby/internal/util.rbs +199 -0
  116. data/sig/galaxy-ruby/internal.rbs +9 -0
  117. data/sig/galaxy-ruby/models/authentication_create_token_params.rbs +15 -0
  118. data/sig/galaxy-ruby/models/authentication_create_token_response.rbs +15 -0
  119. data/sig/galaxy-ruby/models/authentication_create_user_params.rbs +34 -0
  120. data/sig/galaxy-ruby/models/authentication_list_me_params.rbs +15 -0
  121. data/sig/galaxy-ruby/models/celestial_body.rbs +76 -0
  122. data/sig/galaxy-ruby/models/celestial_body_create_params.rbs +24 -0
  123. data/sig/galaxy-ruby/models/credentials.rbs +15 -0
  124. data/sig/galaxy-ruby/models/new_planet_webhook_event.rbs +211 -0
  125. data/sig/galaxy-ruby/models/planet.rbs +211 -0
  126. data/sig/galaxy-ruby/models/planet_create_params.rbs +15 -0
  127. data/sig/galaxy-ruby/models/planet_delete_params.rbs +23 -0
  128. data/sig/galaxy-ruby/models/planet_delte_image_params.rbs +32 -0
  129. data/sig/galaxy-ruby/models/planet_delte_image_response.rbs +50 -0
  130. data/sig/galaxy-ruby/models/planet_list_all_data_params.rbs +32 -0
  131. data/sig/galaxy-ruby/models/planet_list_all_data_response.rbs +64 -0
  132. data/sig/galaxy-ruby/models/planet_retrieve_params.rbs +23 -0
  133. data/sig/galaxy-ruby/models/planet_update_params.rbs +25 -0
  134. data/sig/galaxy-ruby/models/unwrap_webhook_event.rbs +11 -0
  135. data/sig/galaxy-ruby/models/user.rbs +19 -0
  136. data/sig/galaxy-ruby/models/webhook_unwrap_params.rbs +15 -0
  137. data/sig/galaxy-ruby/models.rbs +35 -0
  138. data/sig/galaxy-ruby/request_options.rbs +34 -0
  139. data/sig/galaxy-ruby/resources/authentication.rbs +24 -0
  140. data/sig/galaxy-ruby/resources/celestial_bodies.rbs +12 -0
  141. data/sig/galaxy-ruby/resources/planets.rbs +68 -0
  142. data/sig/galaxy-ruby/resources/webhooks.rbs +13 -0
  143. data/sig/galaxy-ruby/version.rbs +3 -0
  144. data/sig/manifest.yaml +6 -0
  145. metadata +245 -0
@@ -0,0 +1,529 @@
1
+ # frozen_string_literal: true
2
+
3
+ module ScalarGalaxy
4
+ module Internal
5
+ module Type
6
+ # @abstract
7
+ class BaseModel
8
+ extend ScalarGalaxy::Internal::Type::Converter
9
+ extend ScalarGalaxy::Internal::Util::SorbetRuntimeSupport
10
+
11
+ class << self
12
+ # @api private
13
+ #
14
+ # Assumes superclass fields are totally defined before fields are accessed /
15
+ # defined on subclasses.
16
+ #
17
+ # @param child [Class<ScalarGalaxy::Internal::Type::BaseModel>]
18
+ def inherited(child)
19
+ super
20
+ child.known_fields.replace(known_fields.dup)
21
+ end
22
+
23
+ # @api private
24
+ #
25
+ # @return [Hash{Symbol=>Hash{Symbol=>Object}}]
26
+ def known_fields = @known_fields ||= {}
27
+
28
+ # @api private
29
+ #
30
+ # @return [Hash{Symbol=>Hash{Symbol=>Object}}]
31
+ def fields
32
+ known_fields.transform_values do |field|
33
+ {**field.except(:type_fn), type: field.fetch(:type_fn).call}
34
+ end
35
+ end
36
+
37
+ # @api private
38
+ #
39
+ # @param name_sym [Symbol]
40
+ #
41
+ # @param required [Boolean]
42
+ #
43
+ # @param type_info [Hash{Symbol=>Object}, Proc, ScalarGalaxy::Internal::Type::Converter, Class]
44
+ #
45
+ # @param spec [Hash{Symbol=>Object}] .
46
+ #
47
+ # @option spec [NilClass, TrueClass, FalseClass, Integer, Float, Symbol] :const
48
+ #
49
+ # @option spec [Proc] :enum
50
+ #
51
+ # @option spec [Proc] :union
52
+ #
53
+ # @option spec [Boolean] :"nil?"
54
+ private def add_field(name_sym, required:, type_info:, spec:)
55
+ meta = ScalarGalaxy::Internal::Type::Converter.meta_info(type_info, spec)
56
+ type_fn, info =
57
+ case type_info
58
+ in Proc | ScalarGalaxy::Internal::Type::Converter | Class
59
+ [ScalarGalaxy::Internal::Type::Converter.type_info({**spec, union: type_info}), spec]
60
+ in Hash
61
+ [ScalarGalaxy::Internal::Type::Converter.type_info(type_info), type_info]
62
+ end
63
+
64
+ setter = :"#{name_sym}="
65
+ api_name = info.fetch(:api_name, name_sym)
66
+ nilable = info.fetch(:nil?, false)
67
+ const =
68
+ (
69
+ if required && !nilable
70
+ info.fetch(:const, ScalarGalaxy::Internal::OMIT)
71
+ else
72
+ ScalarGalaxy::Internal::OMIT
73
+ end
74
+ )
75
+
76
+ [name_sym, setter].each { undef_method(_1) } if known_fields.key?(name_sym)
77
+
78
+ known_fields[name_sym] = {
79
+ mode: @mode,
80
+ api_name: api_name,
81
+ required: required,
82
+ nilable: nilable,
83
+ const: const,
84
+ type_fn: type_fn,
85
+ meta: meta
86
+ }
87
+
88
+ define_method(setter) do |value|
89
+ target = type_fn.call
90
+ state = ScalarGalaxy::Internal::Type::Converter.new_coerce_state(translate_names: false)
91
+ coerced = ScalarGalaxy::Internal::Type::Converter.coerce(target, value, state: state)
92
+ status = @coerced.store(name_sym, state.fetch(:error) || true)
93
+ stored =
94
+ case [target, status]
95
+ in [ScalarGalaxy::Internal::Type::Converter | Symbol, true]
96
+ coerced
97
+ else
98
+ value
99
+ end
100
+ @data.store(name_sym, stored)
101
+ end
102
+
103
+ # rubocop:disable Style/CaseEquality
104
+ # rubocop:disable Metrics/BlockLength
105
+ define_method(name_sym) do
106
+ target = type_fn.call
107
+
108
+ case @coerced[name_sym]
109
+ in true | false if ScalarGalaxy::Internal::Type::Converter === target
110
+ @data.fetch(name_sym)
111
+ in ::StandardError => e
112
+ raise ScalarGalaxy::Errors::ConversionError.new(
113
+ on: self.class,
114
+ method: __method__,
115
+ target: target,
116
+ value: @data.fetch(name_sym),
117
+ cause: e
118
+ )
119
+ else
120
+ Kernel.then do
121
+ value = @data.fetch(name_sym) { const == ScalarGalaxy::Internal::OMIT ? nil : const }
122
+ state = ScalarGalaxy::Internal::Type::Converter.new_coerce_state(translate_names: false)
123
+ if (nilable || !required) && value.nil?
124
+ nil
125
+ else
126
+ ScalarGalaxy::Internal::Type::Converter.coerce(target, value, state: state)
127
+ end
128
+ rescue StandardError => e
129
+ raise ScalarGalaxy::Errors::ConversionError.new(
130
+ on: self.class,
131
+ method: __method__,
132
+ target: target,
133
+ value: value,
134
+ cause: e
135
+ )
136
+ end
137
+ end
138
+ end
139
+ # rubocop:enable Metrics/BlockLength
140
+ # rubocop:enable Style/CaseEquality
141
+ end
142
+
143
+ # @api private
144
+ #
145
+ # @param name_sym [Symbol]
146
+ #
147
+ # @param type_info [Hash{Symbol=>Object}, Proc, ScalarGalaxy::Internal::Type::Converter, Class]
148
+ #
149
+ # @param spec [Hash{Symbol=>Object}] .
150
+ #
151
+ # @option spec [NilClass, TrueClass, FalseClass, Integer, Float, Symbol] :const
152
+ #
153
+ # @option spec [Proc] :enum
154
+ #
155
+ # @option spec [Proc] :union
156
+ #
157
+ # @option spec [Boolean] :"nil?"
158
+ def required(name_sym, type_info, spec = {})
159
+ add_field(name_sym, required: true, type_info: type_info, spec: spec)
160
+ end
161
+
162
+ # @api private
163
+ #
164
+ # @param name_sym [Symbol]
165
+ #
166
+ # @param type_info [Hash{Symbol=>Object}, Proc, ScalarGalaxy::Internal::Type::Converter, Class]
167
+ #
168
+ # @param spec [Hash{Symbol=>Object}] .
169
+ #
170
+ # @option spec [NilClass, TrueClass, FalseClass, Integer, Float, Symbol] :const
171
+ #
172
+ # @option spec [Proc] :enum
173
+ #
174
+ # @option spec [Proc] :union
175
+ #
176
+ # @option spec [Boolean] :"nil?"
177
+ def optional(name_sym, type_info, spec = {})
178
+ add_field(name_sym, required: false, type_info: type_info, spec: spec)
179
+ end
180
+
181
+ # @api private
182
+ #
183
+ # `request_only` attributes not excluded from `.#coerce` when receiving responses
184
+ # even if well behaved servers should not send them
185
+ #
186
+ # @param blk [Proc]
187
+ private def request_only(&blk)
188
+ @mode = :dump
189
+ blk.call
190
+ ensure
191
+ @mode = nil
192
+ end
193
+
194
+ # @api private
195
+ #
196
+ # `response_only` attributes are omitted from `.#dump` when making requests
197
+ #
198
+ # @param blk [Proc]
199
+ private def response_only(&blk)
200
+ @mode = :coerce
201
+ blk.call
202
+ ensure
203
+ @mode = nil
204
+ end
205
+
206
+ # @api public
207
+ #
208
+ # @param other [Object]
209
+ #
210
+ # @return [Boolean]
211
+ def ==(other)
212
+ other.is_a?(Class) && other <= ScalarGalaxy::Internal::Type::BaseModel && other.fields == fields
213
+ end
214
+
215
+ # @api public
216
+ #
217
+ # @return [Integer]
218
+ def hash = fields.hash
219
+ end
220
+
221
+ # @api public
222
+ #
223
+ # @param other [Object]
224
+ #
225
+ # @return [Boolean]
226
+ def ==(other) = self.class == other.class && @data == other.to_h
227
+
228
+ # @api public
229
+ #
230
+ # @return [Integer]
231
+ def hash = [self.class, @data].hash
232
+
233
+ class << self
234
+ # @api private
235
+ #
236
+ # @param value [ScalarGalaxy::Internal::Type::BaseModel, Hash{Object=>Object}, Object]
237
+ #
238
+ # @param state [Hash{Symbol=>Object}] .
239
+ #
240
+ # @option state [Boolean] :translate_names
241
+ #
242
+ # @option state [Boolean] :strictness
243
+ #
244
+ # @option state [Hash{Symbol=>Object}] :exactness
245
+ #
246
+ # @option state [Class<StandardError>] :error
247
+ #
248
+ # @option state [Integer] :branched
249
+ #
250
+ # @return [self, Object]
251
+ def coerce(value, state:)
252
+ exactness = state.fetch(:exactness)
253
+
254
+ if value.is_a?(self)
255
+ exactness[:yes] += 1
256
+ return value
257
+ end
258
+
259
+ unless (val = ScalarGalaxy::Internal::Util.coerce_hash(value)).is_a?(Hash)
260
+ exactness[:no] += 1
261
+ state[:error] = TypeError.new("#{value.class} can't be coerced into #{Hash}")
262
+ return value
263
+ end
264
+ exactness[:yes] += 1
265
+
266
+ keys = val.keys.to_set
267
+ instance = new
268
+ data = instance.to_h
269
+ status = instance.instance_variable_get(:@coerced)
270
+
271
+ # rubocop:disable Metrics/BlockLength
272
+ fields.each do |name, field|
273
+ mode, required, target = field.fetch_values(:mode, :required, :type)
274
+ api_name, nilable, const = field.fetch_values(:api_name, :nilable, :const)
275
+ src_name = state.fetch(:translate_names) ? api_name : name
276
+
277
+ unless val.key?(src_name)
278
+ if required && mode != :dump && const == ScalarGalaxy::Internal::OMIT
279
+ exactness[nilable ? :maybe : :no] += 1
280
+ else
281
+ exactness[:yes] += 1
282
+ end
283
+ next
284
+ end
285
+
286
+ item = val.fetch(src_name)
287
+ keys.delete(src_name)
288
+
289
+ state[:error] = nil
290
+ converted =
291
+ if item.nil? && (nilable || !required)
292
+ exactness[nilable ? :yes : :maybe] += 1
293
+ nil
294
+ else
295
+ coerced = ScalarGalaxy::Internal::Type::Converter.coerce(target, item, state: state)
296
+ case target
297
+ in ScalarGalaxy::Internal::Type::Converter | Symbol
298
+ coerced
299
+ else
300
+ item
301
+ end
302
+ end
303
+
304
+ status.store(name, state.fetch(:error) || true)
305
+ data.store(name, converted)
306
+ end
307
+ # rubocop:enable Metrics/BlockLength
308
+
309
+ keys.each { data.store(_1, val.fetch(_1)) }
310
+ instance
311
+ end
312
+
313
+ # @api private
314
+ #
315
+ # @param value [self, Object]
316
+ #
317
+ # @param state [Hash{Symbol=>Object}] .
318
+ #
319
+ # @option state [Boolean] :can_retry
320
+ #
321
+ # @return [Hash{Object=>Object}, Object]
322
+ def dump(value, state:)
323
+ unless (coerced = ScalarGalaxy::Internal::Util.coerce_hash(value)).is_a?(Hash)
324
+ return super
325
+ end
326
+
327
+ acc = {}
328
+
329
+ coerced.each do |key, val|
330
+ name = key.is_a?(String) ? key.to_sym : key
331
+ case (field = known_fields[name])
332
+ in nil
333
+ acc.store(name, super(val, state: state))
334
+ else
335
+ api_name, mode, type_fn = field.fetch_values(:api_name, :mode, :type_fn)
336
+ case mode
337
+ in :coerce
338
+ next
339
+ else
340
+ target = type_fn.call
341
+ acc.store(api_name, ScalarGalaxy::Internal::Type::Converter.dump(target, val, state: state))
342
+ end
343
+ end
344
+ end
345
+
346
+ known_fields.each_value do |field|
347
+ api_name, mode, const = field.fetch_values(:api_name, :mode, :const)
348
+ next if mode == :coerce || acc.key?(api_name) || const == ScalarGalaxy::Internal::OMIT
349
+ acc.store(api_name, const)
350
+ end
351
+
352
+ acc
353
+ end
354
+
355
+ # @api private
356
+ #
357
+ # @return [Object]
358
+ def to_sorbet_type
359
+ self
360
+ end
361
+ end
362
+
363
+ class << self
364
+ # @api private
365
+ #
366
+ # @param model [ScalarGalaxy::Internal::Type::BaseModel]
367
+ # @param convert [Boolean]
368
+ #
369
+ # @return [Hash{Symbol=>Object}]
370
+ def recursively_to_h(model, convert:)
371
+ rec = ->(x) do
372
+ case x
373
+ in ScalarGalaxy::Internal::Type::BaseModel
374
+ if convert
375
+ fields = x.class.known_fields
376
+ x.to_h.to_h do |key, val|
377
+ [key, rec.call(fields.key?(key) ? x.public_send(key) : val)]
378
+ rescue ScalarGalaxy::Errors::ConversionError
379
+ [key, rec.call(val)]
380
+ end
381
+ else
382
+ rec.call(x.to_h)
383
+ end
384
+ in Hash
385
+ x.transform_values(&rec)
386
+ in Array
387
+ x.map(&rec)
388
+ else
389
+ x
390
+ end
391
+ end
392
+ rec.call(model)
393
+ end
394
+ end
395
+
396
+ # @api public
397
+ #
398
+ # Returns the raw value associated with the given key, if found. Otherwise, nil is
399
+ # returned.
400
+ #
401
+ # It is valid to lookup keys that are not in the API spec, for example to access
402
+ # undocumented features. This method does not parse response data into
403
+ # higher-level types. Lookup by anything other than a Symbol is an ArgumentError.
404
+ #
405
+ # @param key [Symbol]
406
+ #
407
+ # @return [Object, nil]
408
+ def [](key)
409
+ unless key.instance_of?(Symbol)
410
+ raise ArgumentError.new("Expected symbol key for lookup, got #{key.inspect}")
411
+ end
412
+
413
+ @data[key]
414
+ end
415
+
416
+ # @api public
417
+ #
418
+ # Returns a Hash of the data underlying this object. O(1)
419
+ #
420
+ # Keys are Symbols and values are the raw values from the response. The return
421
+ # value indicates which values were ever set on the object. i.e. there will be a
422
+ # key in this hash if they ever were, even if the set value was nil.
423
+ #
424
+ # This method is not recursive. The returned value is shared by the object, so it
425
+ # should not be mutated.
426
+ #
427
+ # @return [Hash{Symbol=>Object}]
428
+ def to_h = @data
429
+
430
+ alias_method :to_hash, :to_h
431
+
432
+ # @api public
433
+ #
434
+ # In addition to the behaviour of `#to_h`, this method will recursively call
435
+ # `#to_h` on nested models.
436
+ #
437
+ # @return [Hash{Symbol=>Object}]
438
+ def deep_to_h = self.class.recursively_to_h(@data, convert: false)
439
+
440
+ # @param keys [Array<Symbol>, nil]
441
+ #
442
+ # @return [Hash{Symbol=>Object}]
443
+ #
444
+ def deconstruct_keys(keys)
445
+ (keys || self.class.known_fields.keys)
446
+ .filter_map do |k|
447
+ next unless self.class.known_fields.key?(k)
448
+
449
+ [k, public_send(k)]
450
+ end
451
+ .to_h
452
+ end
453
+
454
+ # @api public
455
+ #
456
+ # @param a [Object]
457
+ #
458
+ # @return [String]
459
+ def to_json(*a) = ScalarGalaxy::Internal::Type::Converter.dump(self.class, self).to_json(*a)
460
+
461
+ # @api public
462
+ #
463
+ # @param a [Object]
464
+ #
465
+ # @return [String]
466
+ def to_yaml(*a) = ScalarGalaxy::Internal::Type::Converter.dump(self.class, self).to_yaml(*a)
467
+
468
+ # Create a new instance of a model.
469
+ #
470
+ # @param data [Hash{Symbol=>Object}, self]
471
+ def initialize(data = {})
472
+ @data = {}
473
+ @coerced = {}
474
+ ScalarGalaxy::Internal::Util
475
+ .coerce_hash!(data)
476
+ .each do
477
+ if self.class.known_fields.key?(_1)
478
+ public_send(:"#{_1}=", _2)
479
+ else
480
+ @data.store(_1, _2)
481
+ @coerced.store(_1, false)
482
+ end
483
+ end
484
+ end
485
+
486
+ class << self
487
+ # @api private
488
+ #
489
+ # @param depth [Integer]
490
+ #
491
+ # @return [String]
492
+ def inspect(depth: 0)
493
+ return super() if depth.positive?
494
+
495
+ depth = depth.succ
496
+ deferred =
497
+ fields.transform_values do |field|
498
+ type, required, nilable = field.fetch_values(:type, :required, :nilable)
499
+ inspected = [
500
+ ScalarGalaxy::Internal::Type::Converter.inspect(type, depth: depth),
501
+ !required || nilable ? "nil" : nil
502
+ ].compact.join(" | ")
503
+ -> { inspected }.tap { _1.define_singleton_method(:inspect) { call } }
504
+ end
505
+
506
+ "#{name}[#{deferred.inspect}]"
507
+ end
508
+ end
509
+
510
+ # @api public
511
+ #
512
+ # @return [String]
513
+ def to_s = deep_to_h.to_s
514
+
515
+ # @api private
516
+ #
517
+ # @return [String]
518
+ def inspect
519
+ converted = self.class.recursively_to_h(self, convert: true)
520
+ "#<#{self.class}:0x#{object_id.to_s(16)} #{converted}>"
521
+ end
522
+
523
+ define_sorbet_constant!(:KnownField) do
524
+ T.type_alias { {mode: T.nilable(Symbol), required: T::Boolean, nilable: T::Boolean} }
525
+ end
526
+ end
527
+ end
528
+ end
529
+ end
@@ -0,0 +1,55 @@
1
+ # frozen_string_literal: true
2
+
3
+ module ScalarGalaxy
4
+ module Internal
5
+ module Type
6
+ # @api private
7
+ #
8
+ # @generic Elem
9
+ #
10
+ # This module provides a base implementation for paginated responses in the SDK.
11
+ module BasePage
12
+ # rubocop:disable Lint/UnusedMethodArgument
13
+
14
+ # @api public
15
+ #
16
+ # @return [Boolean]
17
+ def next_page? = (raise NotImplementedError)
18
+
19
+ # @api public
20
+ #
21
+ # @raise [ScalarGalaxy::Errors::APIError]
22
+ # @return [self]
23
+ def next_page = (raise NotImplementedError)
24
+
25
+ # @api public
26
+ #
27
+ # @param blk [Proc]
28
+ #
29
+ # @yieldparam [generic<Elem>]
30
+ # @return [void]
31
+ def auto_paging_each(&blk) = (raise NotImplementedError)
32
+
33
+ # @return [Enumerable<generic<Elem>>]
34
+ def to_enum = super(:auto_paging_each)
35
+
36
+ alias_method :enum_for, :to_enum
37
+
38
+ # @api private
39
+ #
40
+ # @param client [ScalarGalaxy::Internal::Transport::BaseClient]
41
+ # @param req [Hash{Symbol=>Object}]
42
+ # @param headers [Hash{String=>String}]
43
+ # @param page_data [Object]
44
+ def initialize(client:, req:, headers:, page_data:)
45
+ @client = client
46
+ @req = req
47
+ @model = req.fetch(:model)
48
+ super()
49
+ end
50
+
51
+ # rubocop:enable Lint/UnusedMethodArgument
52
+ end
53
+ end
54
+ end
55
+ end
@@ -0,0 +1,77 @@
1
+ # frozen_string_literal: true
2
+
3
+ module ScalarGalaxy
4
+ module Internal
5
+ module Type
6
+ # @api private
7
+ #
8
+ # @abstract
9
+ #
10
+ # Ruby has no Boolean class; this is something for models to refer to.
11
+ class Boolean
12
+ extend ScalarGalaxy::Internal::Type::Converter
13
+ extend ScalarGalaxy::Internal::Util::SorbetRuntimeSupport
14
+
15
+ private_class_method :new
16
+
17
+ # @api public
18
+ #
19
+ # @param other [Object]
20
+ #
21
+ # @return [Boolean]
22
+ def self.===(other) = other == true || other == false
23
+
24
+ # @api public
25
+ #
26
+ # @param other [Object]
27
+ #
28
+ # @return [Boolean]
29
+ def self.==(other) = other.is_a?(Class) && other <= ScalarGalaxy::Internal::Type::Boolean
30
+
31
+ class << self
32
+ # @api private
33
+ #
34
+ # Coerce value to Boolean if possible, otherwise return the original value.
35
+ #
36
+ # @param value [Boolean, Object]
37
+ #
38
+ # @param state [Hash{Symbol=>Object}] .
39
+ #
40
+ # @option state [Boolean] :translate_names
41
+ #
42
+ # @option state [Boolean] :strictness
43
+ #
44
+ # @option state [Hash{Symbol=>Object}] :exactness
45
+ #
46
+ # @option state [Class<StandardError>] :error
47
+ #
48
+ # @option state [Integer] :branched
49
+ #
50
+ # @return [Boolean, Object]
51
+ def coerce(value, state:)
52
+ state.fetch(:exactness)[value == true || value == false ? :yes : :no] += 1
53
+ value
54
+ end
55
+
56
+ # @!method dump(value, state:)
57
+ # @api private
58
+ #
59
+ # @param value [Boolean, Object]
60
+ #
61
+ # @param state [Hash{Symbol=>Object}] .
62
+ #
63
+ # @option state [Boolean] :can_retry
64
+ #
65
+ # @return [Boolean, Object]
66
+
67
+ # @api private
68
+ #
69
+ # @return [Object]
70
+ def to_sorbet_type
71
+ T::Boolean
72
+ end
73
+ end
74
+ end
75
+ end
76
+ end
77
+ end