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