vectra-client 1.1.2 → 1.1.3

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: 6f59705f200c8a164cc9303e6761776af49e4a81a88f101eae2e371eccca8807
4
- data.tar.gz: 217dd74d00151f3ba6e94ed80718999656f9616b84e843dd937197cee612540a
3
+ metadata.gz: 83a312bb14b8f556d743e0072548a33ec0ac79c9d64768c78b18af3bc7ac6c6b
4
+ data.tar.gz: 0f0e859dd346e86f095a882e4cb7d47fd1ecf05aa968730b2b3e0d2ff7fa253b
5
5
  SHA512:
6
- metadata.gz: 8e62f19e82dfb88a14ae50f7cee6afdd8d058ece9972de8f447ba3cc881420d401cfd0d3a093d299e8273795958085349a8d3e6416ecd429f50ea2a05103dea3
7
- data.tar.gz: ace8ecc519dc588f917e6b29721ed9cfa3ff9b3f3fd7b3e82911233ed7d6e59a9f443e81ae9c0d20dd4891f904d8497cb506064964b00b3dc7587f12137e12bf
6
+ metadata.gz: ccbc0520ce83f7d2f039a50c0a4b16a9fb59ce21956eb00d5f28270bf61e3ae6c81ab133b02b3ffd1662d29864f5b0ae9c04f60b8e61715f8cbb513b71d48c72
7
+ data.tar.gz: 38a9b1bbfc4db14005b88d1f29957806f888dc80886c147925fe9dec1643ca67e992aae71258108130ba33b317b999658df5a7756fffe92f0f91bb39b3ba88d1
data/CHANGELOG.md CHANGED
@@ -1,25 +1,20 @@
1
1
  # Changelog
2
2
 
3
+ ## [v1.1.3](https://github.com/stokry/vectra/tree/v1.1.3) (2026-01-20)
4
+
5
+ [Full Changelog](https://github.com/stokry/vectra/compare/v1.1.2...v1.1.3)
6
+
7
+ - Add `Client#validate!` for configuration/capability checks
8
+ - Add `Client#with_defaults` block helper for temporary default index/namespace
9
+
10
+ ## [v1.1.2](https://github.com/stokry/vectra/tree/v1.1.2) (2026-01-19)
11
+
12
+ [Full Changelog](https://github.com/stokry/vectra/compare/v1.1.1...v1.1.2)
13
+
3
14
  ## [v1.1.1](https://github.com/stokry/vectra/tree/v1.1.1) (2026-01-15)
4
15
 
5
16
  [Full Changelog](https://github.com/stokry/vectra/compare/v1.1.0...v1.1.1)
6
17
 
7
- ### Added
8
- - **Text Search Support** - New `text_search` method for keyword-only search without requiring embeddings
9
- - Qdrant: BM25 text search
10
- - Weaviate: BM25 text search via GraphQL
11
- - pgvector: PostgreSQL full-text search (`to_tsvector`, `plainto_tsquery`, `ts_rank`)
12
- - Memory: Simple keyword matching (for testing)
13
- - Raises `UnsupportedFeatureError` for Pinecone (use sparse vectors instead)
14
- - **Documentation Search** - Added search functionality to documentation site with `simple-jekyll-search`
15
- - Client-side search with fuzzy matching
16
- - Search index auto-generated from all documentation pages
17
- - Responsive search UI in navigation
18
-
19
- ### Changed
20
- - Updated API documentation to include `text_search` method in overview and cheatsheet
21
- - Enhanced documentation with text search examples and use cases
22
-
23
18
  ## [v1.1.0](https://github.com/stokry/vectra/tree/v1.1.0) (2026-01-15)
24
19
 
25
20
  [Full Changelog](https://github.com/stokry/vectra/compare/v1.0.8...v1.1.0)
@@ -51,6 +51,23 @@ client.query(vector: query_embedding, top_k: 10)
51
51
 
52
52
  In a Rails app with `config/vectra.yml` generated by `rails generate vectra:index`, if that YAML file contains only one entry, `Vectra::Client.new` will automatically use that entry's `index` (and `namespace`, if present) as defaults.
53
53
 
54
+ ### Temporary defaults (block-scoped)
55
+
56
+ ```ruby
57
+ client.with_defaults(index: "products", namespace: "tenant-2") do |c|
58
+ c.upsert(vectors: [...])
59
+ c.query(vector: query_embedding, top_k: 10)
60
+ end
61
+ ```
62
+
63
+ ### Validate client config & capabilities
64
+
65
+ ```ruby
66
+ client.validate!
67
+ client.validate!(require_default_index: true)
68
+ client.validate!(features: [:text_search])
69
+ ```
70
+
54
71
  ### Upsert
55
72
 
56
73
  ```ruby
data/docs/api/methods.md CHANGED
@@ -426,6 +426,55 @@ After the block finishes (even if it raises), the previous `config.timeout` valu
426
426
 
427
427
  ---
428
428
 
429
+ ### `client.validate!(require_default_index: false, require_default_namespace: false, features: [])`
430
+
431
+ Validate the client configuration and (optionally) your defaults and provider feature support.
432
+
433
+ This is useful in boot-time checks (Rails initializers), health endpoints, and CI.
434
+
435
+ **Parameters:**
436
+ - `require_default_index` (Boolean) - Require `client.default_index` to be set
437
+ - `require_default_namespace` (Boolean) - Require `client.default_namespace` to be set
438
+ - `features` (Array<Symbol> or Symbol) - Provider features (methods) that must be supported (e.g. `:text_search`)
439
+
440
+ **Returns:** `Vectra::Client` (self)
441
+
442
+ **Raises:** `Vectra::ConfigurationError` when validation fails
443
+
444
+ **Example:**
445
+ ```ruby
446
+ # Ensure client is configured
447
+ client.validate!
448
+
449
+ # Ensure calls can omit index:
450
+ client.validate!(require_default_index: true)
451
+
452
+ # Ensure provider supports text_search:
453
+ client.validate!(features: [:text_search])
454
+ ```
455
+
456
+ ---
457
+
458
+ ### `client.with_defaults(index: ..., namespace: ...) { ... }`
459
+
460
+ Temporarily override the client's **default index and/or namespace** inside a block.
461
+
462
+ Unlike `with_index_and_namespace`, this helper accepts keyword arguments and only overrides what you pass.
463
+
464
+ **Returns:** Block result
465
+
466
+ **Example:**
467
+ ```ruby
468
+ client.with_defaults(index: "products", namespace: "tenant-2") do |c|
469
+ c.upsert(vectors: [...]) # uses products/tenant-2
470
+ c.query(vector: embedding, top_k: 10)
471
+ end
472
+
473
+ # Previous defaults are restored after the block.
474
+ ```
475
+
476
+ ---
477
+
429
478
  ### `client.health_check`
430
479
 
431
480
  Detailed health check with provider-specific information.
data/lib/vectra/client.rb CHANGED
@@ -44,6 +44,9 @@ module Vectra
44
44
 
45
45
  attr_reader :config, :provider, :default_index, :default_namespace
46
46
 
47
+ DEFAULT_UNSET = Object.new.freeze
48
+ private_constant :DEFAULT_UNSET
49
+
47
50
  class << self
48
51
  # Get the global middleware stack
49
52
  #
@@ -621,6 +624,43 @@ module Vectra
621
624
  result
622
625
  end
623
626
 
627
+ # Validate the client configuration and provider capabilities.
628
+ #
629
+ # This is a convenience wrapper around `config.validate!` that can also
630
+ # validate your defaults and provider feature support.
631
+ #
632
+ # @param require_default_index [Boolean] require default index to be set
633
+ # @param require_default_namespace [Boolean] require default namespace to be set
634
+ # @param features [Array<Symbol>, Symbol] provider features (methods) required, e.g. :text_search
635
+ # @return [true]
636
+ # @raise [ConfigurationError] when client is misconfigured
637
+ #
638
+ # @example Basic validation
639
+ # client.validate! # => client
640
+ #
641
+ # @example Ensure you can call methods without passing index:
642
+ # client.validate!(require_default_index: true)
643
+ #
644
+ # @example Ensure provider supports text search:
645
+ # client.validate!(features: [:text_search])
646
+ #
647
+ def validate!(require_default_index: false, require_default_namespace: false, features: [])
648
+ errors = []
649
+
650
+ append_client_config_errors(errors)
651
+ append_client_provider_errors(errors)
652
+ append_client_default_errors(
653
+ errors,
654
+ require_default_index: require_default_index,
655
+ require_default_namespace: require_default_namespace
656
+ )
657
+ append_client_feature_errors(errors, features: features)
658
+
659
+ raise ConfigurationError, client_validation_message(errors) if errors.any?
660
+
661
+ self
662
+ end
663
+
624
664
  # Chainable query builder
625
665
  #
626
666
  # @api public
@@ -786,6 +826,52 @@ module Vectra
786
826
  @default_namespace = namespace if @default_namespace.nil? && namespace.is_a?(String) && !namespace.empty?
787
827
  end
788
828
 
829
+ def append_client_config_errors(errors)
830
+ config.validate!
831
+ rescue ConfigurationError, UnsupportedProviderError => e
832
+ errors << e.message
833
+ end
834
+
835
+ def append_client_provider_errors(errors)
836
+ errors << "Provider is not initialized" if provider.nil?
837
+ end
838
+
839
+ def append_client_default_errors(errors, require_default_index:, require_default_namespace:)
840
+ append_default_index_error(errors) if require_default_index
841
+ append_default_namespace_error(errors) if require_default_namespace
842
+ end
843
+
844
+ def append_default_index_error(errors)
845
+ if default_index.nil? || (default_index.respond_to?(:empty?) && default_index.empty?)
846
+ errors << "Default index is not set (pass `index:` to Vectra::Client.new, or set it via config/vectra.yml in Rails)"
847
+ elsif !default_index.is_a?(String)
848
+ errors << "Default index must be a String"
849
+ end
850
+ end
851
+
852
+ def append_default_namespace_error(errors)
853
+ if default_namespace.nil? || (default_namespace.respond_to?(:empty?) && default_namespace.empty?)
854
+ errors << "Default namespace is not set (pass `namespace:` to Vectra::Client.new, or set it via config/vectra.yml in Rails)"
855
+ elsif !default_namespace.is_a?(String)
856
+ errors << "Default namespace must be a String"
857
+ end
858
+ end
859
+
860
+ def append_client_feature_errors(errors, features:)
861
+ return if provider.nil?
862
+
863
+ Array(features).compact.each do |feature|
864
+ method = feature.to_sym
865
+ next if provider.respond_to?(method)
866
+
867
+ errors << "Provider does not support `#{method}`"
868
+ end
869
+ end
870
+
871
+ def client_validation_message(errors)
872
+ "Client validation failed:\n- #{errors.join("\n- ")}"
873
+ end
874
+
789
875
  def validate_index!(index)
790
876
  raise ValidationError, "Index name cannot be nil" if index.nil?
791
877
  raise ValidationError, "Index name must be a string" unless index.is_a?(String)
@@ -908,7 +994,29 @@ module Vectra
908
994
  end
909
995
  end
910
996
 
911
- public :with_index, :with_namespace, :with_index_and_namespace, :with_timeout
997
+ # Temporarily override default index and/or namespace within a block.
998
+ #
999
+ # Unlike `with_index_and_namespace`, this method accepts keyword arguments
1000
+ # and only overrides the values you pass.
1001
+ #
1002
+ # @param index [String, nil] temporary index name (omit to keep current)
1003
+ # @param namespace [String, nil] temporary namespace (omit to keep current)
1004
+ # @yield [Client] yields self with overridden defaults
1005
+ # @return [Object] block result
1006
+ def with_defaults(index: DEFAULT_UNSET, namespace: DEFAULT_UNSET)
1007
+ previous_index = @default_index
1008
+ previous_namespace = @default_namespace
1009
+
1010
+ @default_index = index unless index.equal?(DEFAULT_UNSET)
1011
+ @default_namespace = namespace unless namespace.equal?(DEFAULT_UNSET)
1012
+
1013
+ yield self
1014
+ ensure
1015
+ @default_index = previous_index
1016
+ @default_namespace = previous_namespace
1017
+ end
1018
+
1019
+ public :with_index, :with_namespace, :with_index_and_namespace, :with_defaults, :with_timeout
912
1020
  end
913
1021
  # rubocop:enable Metrics/ClassLength
914
1022
  end
@@ -1,5 +1,5 @@
1
1
  # frozen_string_literal: true
2
2
 
3
3
  module Vectra
4
- VERSION = "1.1.2"
4
+ VERSION = "1.1.3"
5
5
  end
metadata CHANGED
@@ -1,7 +1,7 @@
1
1
  --- !ruby/object:Gem::Specification
2
2
  name: vectra-client
3
3
  version: !ruby/object:Gem::Version
4
- version: 1.1.2
4
+ version: 1.1.3
5
5
  platform: ruby
6
6
  authors:
7
7
  - Mijo Kristo