algolia 3.34.3 → 3.35.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.
checksums.yaml CHANGED
@@ -1,7 +1,7 @@
1
1
  ---
2
2
  SHA256:
3
- metadata.gz: 1db63a1b903c40427512010e991ee81e6bf594486711c26a694d20a4d7f46a14
4
- data.tar.gz: ad4231553e54fd5a0b585e976d9cada33b6d0965066879aaacbc4bf34c6bb2cf
3
+ metadata.gz: ed9225f3ee712ee510d7e5ec50de5224f13c3c6ec128ab8ce321a2f37515000c
4
+ data.tar.gz: d5b7a0e0bc1f1fda4ec306f4ad83949b8e2235136463baeff81a6ac833d631f7
5
5
  SHA512:
6
- metadata.gz: d426e45713dd051dc7cc0f19a901971aa7d465fc8a4b2e5e1fdbd1f515c67dcfe40ea919e0b518123581560dfc2e69d677a52c4f86f46cbd1431fec322bd89e3
7
- data.tar.gz: dba20a8fd6f82fd0203081d818bba3ab664e5176c07f6f60a96583baefcc10024aa1b7fae79bff8ee61688258d0b7118fa908fba197dc0ccb25f677559eec1be
6
+ metadata.gz: 3f3f07f51bb0ef9f91c64b91f83756b6ef1be282568df60911c0e9bcef6fbc7a07c431fc72266b6ac557f46e372bfa1b34e91e1ccc168971c0588d8040a487af
7
+ data.tar.gz: 20e2455d1b6bf30b08b8aa048bf19bc1bb0c180bee3c235e4c8471364df289abe83c5c01b1dfd91b21a9468100ab75815be68f5821e3fc512cbf9d2a18ec2a1f
@@ -21,7 +21,7 @@ jobs:
21
21
  - name: Install Ruby
22
22
  uses: ruby/setup-ruby@v1
23
23
  with:
24
- ruby-version: 4.0.0
24
+ ruby-version: 4.0.1
25
25
  bundler-cache: true
26
26
 
27
27
  - uses: rubygems/release-gem@1c162a739e8b4cb21a676e97b087e8268d8fc40b
data/AGENTS.md ADDED
@@ -0,0 +1,182 @@
1
+ # RUBY CLIENT - AI AGENT INSTRUCTIONS
2
+
3
+ ## ⚠️ CRITICAL: CHECK YOUR REPOSITORY FIRST
4
+
5
+ Before making ANY changes, verify you're in the correct repository:
6
+
7
+ ```bash
8
+ git remote -v
9
+ ```
10
+
11
+ - ✅ **CORRECT**: `origin .../algolia/api-clients-automation.git` → You may proceed
12
+ - ❌ **WRONG**: `origin .../algolia/algoliasearch-client-ruby.git` → STOP! This is the PUBLIC repository
13
+
14
+ **If you're in `algoliasearch-client-ruby`**: Do NOT make changes here. All changes must go through `api-clients-automation`. PRs and commits made directly to the public repo will be discarded on next release.
15
+
16
+ ## ⚠️ BEFORE ANY EDIT: Check If File Is Generated
17
+
18
+ Before editing ANY file, verify it's hand-written by checking `config/generation.config.mjs`:
19
+
20
+ ```javascript
21
+ // In generation.config.mjs - patterns WITHOUT '!' are GENERATED (do not edit)
22
+ 'clients/algoliasearch-client-ruby/lib/algolia/**', // Generated
23
+ '!clients/algoliasearch-client-ruby/lib/algolia/transport/**', // Hand-written ✓
24
+ '!clients/algoliasearch-client-ruby/lib/algolia/error.rb', // Hand-written ✓
25
+ ```
26
+
27
+ **Hand-written (safe to edit):**
28
+
29
+ - `lib/algolia/transport/**` - Transport, retry strategy, HTTP handling
30
+ - `lib/algolia/api_client.rb` - Core API client
31
+ - `lib/algolia/api_error.rb` - API error class
32
+ - `lib/algolia/configuration.rb` - Configuration
33
+ - `lib/algolia/error.rb` - Error base class
34
+ - `lib/algolia/logger_helper.rb` - Logging utilities
35
+ - `lib/algolia/user_agent.rb` - User agent handling
36
+
37
+ **Generated (DO NOT EDIT):**
38
+
39
+ - `lib/algolia/api/**` - API client classes
40
+ - `lib/algolia/models/**` - API models
41
+ - `Gemfile.lock`, `version.rb`
42
+
43
+ ## Language Conventions
44
+
45
+ ### Naming
46
+
47
+ - **Files**: `snake_case.rb`
48
+ - **Classes/Modules**: `PascalCase`
49
+ - **Methods/Variables**: `snake_case`
50
+ - **Constants**: `UPPER_SNAKE_CASE`
51
+ - **Predicates**: `method_name?` (returns boolean)
52
+ - **Dangerous methods**: `method_name!` (mutates or raises)
53
+
54
+ ### Formatting
55
+
56
+ - RubyFmt for formatting
57
+ - Run: `yarn cli format ruby clients/algoliasearch-client-ruby`
58
+
59
+ ### Ruby Idioms
60
+
61
+ - Use `attr_reader`, `attr_accessor` for accessors
62
+ - Prefer `||=` for memoization
63
+ - Use `&.` safe navigation operator
64
+ - Blocks over lambdas for callbacks
65
+
66
+ ### Dependencies
67
+
68
+ - **HTTP**: Faraday (with Net::HTTP adapter)
69
+ - **Build**: Bundler + gemspec
70
+ - **Versions**: Ruby 3.4+
71
+
72
+ ## Client Patterns
73
+
74
+ ### Transport Architecture
75
+
76
+ ```ruby
77
+ # lib/algolia/transport/
78
+ class Transport
79
+ def initialize(config)
80
+ @http_requester = HttpRequester.new(config.app_id, config.api_key)
81
+ @retry_strategy = RetryStrategy.new(config.hosts)
82
+ end
83
+
84
+ def request(method, path, body, opts)
85
+ # Retry with host failover
86
+ end
87
+ end
88
+ ```
89
+
90
+ ### Retry Strategy
91
+
92
+ ```ruby
93
+ # lib/algolia/transport/retry_strategy.rb
94
+ class RetryStrategy
95
+ # Host states: :up, :down, :timed_out
96
+ # Retries on network errors
97
+ # 4xx errors not retried
98
+ end
99
+ ```
100
+
101
+ ### Configuration
102
+
103
+ ```ruby
104
+ # Configuration object pattern
105
+ config = Algolia::Configuration.new(
106
+ app_id: 'APP_ID',
107
+ api_key: 'API_KEY',
108
+ hosts: [...],
109
+ read_timeout: 5,
110
+ write_timeout: 30
111
+ )
112
+ ```
113
+
114
+ ## Common Gotchas
115
+
116
+ ### Symbol vs String Keys
117
+
118
+ ```ruby
119
+ # API returns string keys, use with_indifferent_access or symbols
120
+ response[:hits] # May not work
121
+ response['hits'] # Works
122
+ response.hits # Works if using model objects
123
+ ```
124
+
125
+ ### Block Syntax
126
+
127
+ ```ruby
128
+ # Use do..end for multi-line, braces for single-line
129
+ client.search { |r| r.query = 'test' }
130
+
131
+ client.search do |params|
132
+ params.query = 'test'
133
+ params.hits_per_page = 10
134
+ end
135
+ ```
136
+
137
+ ### Error Handling
138
+
139
+ ```ruby
140
+ begin
141
+ response = client.search(params)
142
+ rescue Algolia::AlgoliaError => e
143
+ # Base error class
144
+ rescue Algolia::ApiError => e
145
+ # API returned error
146
+ puts e.status_code
147
+ puts e.message
148
+ end
149
+ ```
150
+
151
+ ### Nil Safety
152
+
153
+ ```ruby
154
+ # Use safe navigation
155
+ result&.hits&.first&.object_id
156
+
157
+ # Or explicit checks
158
+ if result && result.hits && result.hits.any?
159
+ result.hits.first.object_id
160
+ end
161
+ ```
162
+
163
+ ### Deprecated Operations
164
+
165
+ Some operations in `ingestion_client.rb` and `search_client.rb` are deprecated. Check method documentation before use.
166
+
167
+ ## Build & Test Commands
168
+
169
+ ```bash
170
+ # From repo root (api-clients-automation)
171
+ yarn cli build clients ruby # Build Ruby client
172
+ yarn cli cts generate ruby # Generate CTS tests
173
+ yarn cli cts run ruby # Run CTS tests
174
+ yarn cli playground ruby search # Interactive playground
175
+ yarn cli format ruby clients/algoliasearch-client-ruby
176
+
177
+ # From client directory
178
+ cd clients/algoliasearch-client-ruby
179
+ bundle install # Install dependencies
180
+ bundle exec rake test # Run tests
181
+ bundle exec rubocop # Run linter
182
+ ```
data/CHANGELOG.md CHANGED
@@ -1,3 +1,23 @@
1
+ ## [3.35.0](https://github.com/algolia/algoliasearch-client-ruby/compare/3.34.4...3.35.0)
2
+
3
+ BREAKING CHANGES: this minor version includes multiple breaking changes related to fixes on different APIs. See below for more details.
4
+
5
+ - [b39e3e013](https://github.com/algolia/api-clients-automation/commit/b39e3e013) feat(specs): `conditions` is not required anymore in composition rules ([#5853](https://github.com/algolia/api-clients-automation/pull/5853)) by [@ClaraMuller](https://github.com/ClaraMuller/)
6
+ - [9ef126ccd](https://github.com/algolia/api-clients-automation/commit/9ef126ccd) docs(SearchParams): Document that filter scores are supported in virtual replicas ([#5716](https://github.com/algolia/api-clients-automation/pull/5716)) by [@NixFrog](https://github.com/NixFrog/)
7
+ - [6a3e60802](https://github.com/algolia/api-clients-automation/commit/6a3e60802) fix(specs): BREAKING CHANGE – remove baseRecommendRequest from trendingFacets [CR-10264] ([#5858](https://github.com/algolia/api-clients-automation/pull/5858)) by [@raed667](https://github.com/raed667/)
8
+ - The `TrendingFacets` model has been updated to reflect the API response.
9
+ - [f9453e693](https://github.com/algolia/api-clients-automation/commit/f9453e693) docs: BREAKING CHANGE – authentication type can't be updated ([#5824](https://github.com/algolia/api-clients-automation/pull/5824)) by [@sbellone](https://github.com/sbellone/)
10
+ - The `AuthenticationUpdate` model has been updated to reflect that the `type` field can't be updated.
11
+ - [52aed5b35](https://github.com/algolia/api-clients-automation/commit/52aed5b35) fix(specs): allow additionalProperties on insights-api events ([#5885](https://github.com/algolia/api-clients-automation/pull/5885)) by [@sirockin](https://github.com/sirockin/)
12
+ - [2925f56d1](https://github.com/algolia/api-clients-automation/commit/2925f56d1) fix(specs): BREAKING CHANGE – more accurate composition behavior typing ([#5892](https://github.com/algolia/api-clients-automation/pull/5892)) by [@gavinwade12](https://github.com/gavinwade12/)
13
+ - The `CompositionBehavior` model is now a union type for better accuracy.
14
+ - [63b0c5464](https://github.com/algolia/api-clients-automation/commit/63b0c5464) feat(specs): BREAKING CHANGE – Ingestion API: new `code` property in oauth authentication ([#5897](https://github.com/algolia/api-clients-automation/pull/5897)) by [@sbellone](https://github.com/sbellone/)
15
+ - The `AuthOAuth` and `AuthOAuthPartial` models have been updated to reflect that the `clientId` field is now optional, and the `code` field can be set.
16
+
17
+ ## [3.34.4](https://github.com/algolia/algoliasearch-client-ruby/compare/3.34.3...3.34.4)
18
+
19
+ - [f02ab6fa0](https://github.com/algolia/api-clients-automation/commit/f02ab6fa0) chore: agentic config prep ([#5825](https://github.com/algolia/api-clients-automation/pull/5825)) by [@Fluf22](https://github.com/Fluf22/)
20
+
1
21
  ## [3.34.3](https://github.com/algolia/algoliasearch-client-ruby/compare/3.34.2...3.34.3)
2
22
 
3
23
  - [cd7a174b4](https://github.com/algolia/api-clients-automation/commit/cd7a174b4) fix(specs): BREAKING CHANGE — remove fields requirement from run response in CompAPI client ([#5809](https://github.com/algolia/api-clients-automation/pull/5809)) by [@ClaraMuller](https://github.com/ClaraMuller/)\
data/Gemfile.lock CHANGED
@@ -1,7 +1,7 @@
1
1
  PATH
2
2
  remote: .
3
3
  specs:
4
- algolia (3.34.3)
4
+ algolia (3.35.0)
5
5
  base64 (>= 0.2.0, < 1)
6
6
  faraday (>= 1.0.1, < 3.0)
7
7
  faraday-net_http_persistent (>= 0.15, < 3)
@@ -7,200 +7,101 @@ require "time"
7
7
 
8
8
  module Algolia
9
9
  module Composition
10
- class CompositionBehavior
11
- attr_accessor :injection
12
-
13
- # Attribute mapping from ruby-style variable name to JSON key.
14
- def self.attribute_map
15
- {
16
- :injection => :injection
17
- }
18
- end
19
-
20
- # Attribute type mapping.
21
- def self.types_mapping
22
- {
23
- :injection => :"Injection"
24
- }
25
- end
26
-
27
- # List of attributes with nullable: true
28
- def self.openapi_nullable
29
- Set.new(
30
- []
31
- )
32
- end
33
-
34
- # Initializes the object
35
- # @param [Hash] attributes Model attributes in the form of hash
36
- def initialize(attributes = {})
37
- if (!attributes.is_a?(Hash))
38
- raise(
39
- ArgumentError,
40
- "The input argument (attributes) must be a hash in `Algolia::CompositionBehavior` initialize method"
41
- )
10
+ # An object containing either an `injection` or `multifeed` behavior schema, but not both.
11
+ module CompositionBehavior
12
+ class << self
13
+ # List of class defined in oneOf (OpenAPI v3)
14
+ def openapi_one_of
15
+ [
16
+ :"CompositionInjectionBehavior",
17
+ :"CompositionMultifeedBehavior"
18
+ ]
42
19
  end
43
20
 
44
- # check to see if the attribute exists and convert string to symbol for hash key
45
- attributes = attributes.each_with_object({}) { |(k, v), h|
46
- if (!self.class.attribute_map.key?(k.to_sym))
47
- raise(
48
- ArgumentError,
49
- "`#{k}` is not a valid attribute in `Algolia::CompositionBehavior`. Please check the name to make sure it's valid. List of attributes: " +
50
- self.class.attribute_map.keys.inspect
51
- )
21
+ # Builds the object
22
+ # @param [Mixed] Data to be matched against the list of oneOf items
23
+ # @return [Object] Returns the model or the data itself
24
+ def build(data)
25
+ # Go through the list of oneOf items and attempt to identify the appropriate one.
26
+ # Note:
27
+ # - We do not attempt to check whether exactly one item matches.
28
+ # - No advanced validation of types in some cases (e.g. "x: { type: string }" will happily match { x: 123 })
29
+ # due to the way the deserialization is made in the base_object template (it just casts without verifying).
30
+ # - TODO: scalar values are de facto behaving as if they were nullable.
31
+ # - TODO: logging when debugging is set.
32
+ openapi_one_of.each do |klass|
33
+ begin
34
+ # "nullable: true"
35
+ next if klass == :AnyType
36
+ typed_data = find_and_cast_into_type(klass, data)
37
+ return typed_data if typed_data
38
+ # rescue all errors so we keep iterating even if the current item lookup raises
39
+ rescue
40
+ end
52
41
  end
53
42
 
54
- h[k.to_sym] = v
55
- }
56
-
57
- if attributes.key?(:injection)
58
- self.injection = attributes[:injection]
59
- else
60
- self.injection = nil
43
+ openapi_one_of.include?(:AnyType) ? data : nil
61
44
  end
62
- end
63
45
 
64
- # Checks equality by comparing each attribute.
65
- # @param [Object] Object to be compared
66
- def ==(other)
67
- return true if self.equal?(other)
68
- self.class == other.class &&
69
- injection == other.injection
70
- end
71
-
72
- # @see the `==` method
73
- # @param [Object] Object to be compared
74
- def eql?(other)
75
- self == other
76
- end
77
-
78
- # Calculates hash code according to all attributes.
79
- # @return [Integer] Hash code
80
- def hash
81
- [injection].hash
82
- end
83
-
84
- # Builds the object from hash
85
- # @param [Hash] attributes Model attributes in the form of hash
86
- # @return [Object] Returns the model itself
87
- def self.build_from_hash(attributes)
88
- return nil unless attributes.is_a?(Hash)
89
- attributes = attributes.transform_keys(&:to_sym)
90
- transformed_hash = {}
91
- types_mapping.each_pair do |key, type|
92
- if attributes.key?(attribute_map[key]) && attributes[attribute_map[key]].nil?
93
- transformed_hash[key.to_sym] = nil
94
- elsif type =~ /\AArray<(.*)>/i
95
- # check to ensure the input is an array given that the attribute
96
- # is documented as an array but the input is not
97
- if attributes[attribute_map[key]].is_a?(Array)
98
- transformed_hash[key.to_sym] = attributes[attribute_map[key]].map { |v|
99
- _deserialize(::Regexp.last_match(1), v)
100
- }
46
+ private
47
+
48
+ SchemaMismatchError = Class.new(StandardError)
49
+
50
+ def find_and_cast_into_type(klass, data)
51
+ return if data.nil?
52
+
53
+ case klass.to_s
54
+ when "Boolean"
55
+ return data if data.instance_of?(TrueClass) || data.instance_of?(FalseClass)
56
+ when "Float"
57
+ return data if data.instance_of?(Float)
58
+ when "Integer"
59
+ return data if data.instance_of?(Integer)
60
+ when "Time"
61
+ return Time.parse(data)
62
+ when "Date"
63
+ return Date.parse(data)
64
+ when "String"
65
+ return data if data.instance_of?(String)
66
+ # "type: object"
67
+ when "Object"
68
+ return data if data.instance_of?(Hash)
69
+ # "type: array"
70
+ when /\AArray<(?<sub_type>.+)>\z/
71
+ if data.instance_of?(Array)
72
+ sub_type = Regexp.last_match[:sub_type]
73
+ return data.map { |item| find_and_cast_into_type(sub_type, item) }
101
74
  end
102
- elsif !attributes[attribute_map[key]].nil?
103
- transformed_hash[key.to_sym] = _deserialize(type, attributes[attribute_map[key]])
104
- end
105
- end
106
-
107
- new(transformed_hash)
108
- end
109
-
110
- # Deserializes the data based on type
111
- # @param string type Data type
112
- # @param string value Value to be deserialized
113
- # @return [Object] Deserialized data
114
- def self._deserialize(type, value)
115
- case type.to_sym
116
- when :Time
117
- Time.parse(value)
118
- when :Date
119
- Date.parse(value)
120
- when :String
121
- value.to_s
122
- when :Integer
123
- value.to_i
124
- when :Float
125
- value.to_f
126
- when :Boolean
127
- if value.to_s =~ /\A(true|t|yes|y|1)\z/i
128
- true
75
+ # "type: object" with "additionalProperties: { ... }"
76
+ when /\AHash<String, (?<sub_type>.+)>\z/
77
+ if data.instance_of?(Hash) && data.keys.all? { |k| k.instance_of?(Symbol) || k.instance_of?(String) }
78
+ sub_type = Regexp.last_match[:sub_type]
79
+ return data.each_with_object({}) { |(k, v), hsh| hsh[k] = find_and_cast_into_type(sub_type, v) }
80
+ end
81
+ # model
129
82
  else
130
- false
131
- end
132
-
133
- when :Object
134
- # generic object (usually a Hash), return directly
135
- value
136
- when /\AArray<(?<inner_type>.+)>\z/
137
- inner_type = Regexp.last_match[:inner_type]
138
- value.map { |v| _deserialize(inner_type, v) }
139
- when /\AHash<(?<k_type>.+?), (?<v_type>.+)>\z/
140
- k_type = Regexp.last_match[:k_type]
141
- v_type = Regexp.last_match[:v_type]
142
- {}.tap do |hash|
143
- value.each do |k, v|
144
- hash[_deserialize(k_type, k)] = _deserialize(v_type, v)
83
+ const = Algolia::Composition.const_get(klass)
84
+ if const
85
+ if const.respond_to?(:openapi_one_of)
86
+ # nested oneOf model
87
+ model = const.build(data)
88
+ elsif const.respond_to?(:discriminator_attributes)
89
+ if const.discriminator_attributes.all? { |attr| data.key?(attr) }
90
+ model = const.build_from_hash(data)
91
+ end
92
+ else
93
+ # maybe it's an enum, or doens't have discriminators
94
+ model = const.build_from_hash(data)
95
+ end
96
+
97
+ return model if model
145
98
  end
146
99
  end
147
- # model
148
- else
149
- # models (e.g. Pet) or oneOf
150
- klass = Algolia::Composition.const_get(type)
151
- klass.respond_to?(:openapi_any_of) || klass.respond_to?(:openapi_one_of) ? klass.build(value) : klass
152
- .build_from_hash(value)
153
- end
154
- end
155
-
156
- # Returns the string representation of the object
157
- # @return [String] String presentation of the object
158
- def to_s
159
- to_hash.to_s
160
- end
161
-
162
- # to_body is an alias to to_hash (backward compatibility)
163
- # @return [Hash] Returns the object in the form of hash
164
- def to_body
165
- to_hash
166
- end
167
100
 
168
- def to_json(*_args)
169
- to_hash.to_json
170
- end
171
-
172
- # Returns the object in the form of hash
173
- # @return [Hash] Returns the object in the form of hash
174
- def to_hash
175
- hash = {}
176
- self.class.attribute_map.each_pair do |attr, param|
177
- value = send(attr)
178
- if value.nil?
179
- is_nullable = self.class.openapi_nullable.include?(attr)
180
- next if !is_nullable || (is_nullable && !instance_variable_defined?(:"@#{attr}"))
181
- end
182
-
183
- hash[param] = _to_hash(value)
184
- end
185
-
186
- hash
187
- end
188
-
189
- # Outputs non-array value in the form of hash
190
- # For object, use to_hash. Otherwise, just return the value
191
- # @param [Object] value Any valid value
192
- # @return [Hash] Returns the value in the form of hash
193
- def _to_hash(value)
194
- if value.is_a?(Array)
195
- value.compact.map { |v| _to_hash(v) }
196
- elsif value.is_a?(Hash)
197
- {}.tap do |hash|
198
- value.each { |k, v| hash[k] = _to_hash(v) }
199
- end
200
- elsif value.respond_to?(:to_hash)
201
- value.to_hash
202
- else
203
- value
101
+ # if no match by now, raise
102
+ raise
103
+ rescue
104
+ raise SchemaMismatchError, "#{data} doesn't match the #{klass} type"
204
105
  end
205
106
  end
206
107
  end