@seekora-ai/search-sdk 0.2.13 → 0.2.15

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.
package/dist/client.d.ts CHANGED
@@ -2,7 +2,7 @@
2
2
  * Seekora SDK Client
3
3
  * High-level wrapper around generated OpenAPI client
4
4
  */
5
- import type { DataTypesIndexConfig, DataTypesEventPayload } from './generated';
5
+ import type { DataTypesIndexConfig, DataTypesEventPayload, DataTypesFiltersResponse, DataTypesFacetValuesSearchResponse, DataTypesFiltersSchemaResponse, DataTypesFilterField, DataTypesFilterValue, DataTypesFilterStats, DataTypesFilterSchemaField, DataTypesExperimentAssignmentResponse } from './generated';
6
6
  import { type SeekoraEnvironment } from './config';
7
7
  import { Logger, type LogLevel, type LoggerConfig } from './logger';
8
8
  import { type ContextCollectorConfig, type BrowserContext } from './context-collector';
@@ -46,8 +46,9 @@ export interface SeekoraClientConfig {
46
46
  */
47
47
  contextCollector?: ContextCollectorConfig;
48
48
  /**
49
- * Enable event queue for offline buffering and retry
50
- * @default false
49
+ * Enable event queue for batching, offline buffering, and retry
50
+ * Batches events automatically (default: 10 events or 5s interval) for better performance
51
+ * @default true
51
52
  */
52
53
  enableEventQueue?: boolean;
53
54
  /**
@@ -326,6 +327,8 @@ export declare class SeekoraClient {
326
327
  private storesApi;
327
328
  private documentsApi;
328
329
  private schemaApi;
330
+ private filtersApi;
331
+ private experimentsApi;
329
332
  private storeId;
330
333
  private readSecret;
331
334
  private writeSecret?;
@@ -408,6 +411,15 @@ export declare class SeekoraClient {
408
411
  * Returns store search configuration and onboarding status
409
412
  */
410
413
  getConfig(): Promise<DataTypesIndexConfig>;
414
+ /**
415
+ * Get experiment assignments for the current user
416
+ *
417
+ * Returns variant assignments for all running experiments.
418
+ * Uses hash-based consistent assignment on the backend.
419
+ *
420
+ * @returns ExperimentAssignmentResponse with assignments array
421
+ */
422
+ getExperimentAssignment(): Promise<DataTypesExperimentAssignmentResponse>;
411
423
  /**
412
424
  * Get store information
413
425
  * Returns store metadata including name, status, and configuration details
@@ -813,5 +825,62 @@ export declare class SeekoraClient {
813
825
  * Get the logger instance
814
826
  */
815
827
  getLogger(): Logger;
828
+ /**
829
+ * Get filter values and counts for configured facets.
830
+ * Use this to build faceted navigation UIs without performing a full search.
831
+ * Supports disjunctive faceting for OR-based filter combinations.
832
+ *
833
+ * @param options - Filter options (query, filters, facet_by, max_facet_values, disjunctive_facets)
834
+ * @returns Filter values with counts grouped by field
835
+ */
836
+ getFilters(options?: FilterOptions): Promise<DataTypesFiltersResponse>;
837
+ /**
838
+ * Search within a single facet's values.
839
+ * Useful for facets with many values (e.g., brands) where you need typeahead/autocomplete.
840
+ *
841
+ * @param facetName - The facet field name to search within (e.g., "brand", "category")
842
+ * @param options - Search options including facetQuery (required), optional q, filter, maxValues
843
+ * @returns Matching facet values with counts
844
+ */
845
+ searchFacetValues(facetName: string, options: FacetSearchOptions): Promise<DataTypesFacetValuesSearchResponse>;
846
+ /**
847
+ * Get available filter field metadata (schema).
848
+ * Returns information about all facetable fields including types, sortability, and configured ranges.
849
+ * Useful for dynamically building filter UIs.
850
+ *
851
+ * @returns Filter field metadata with types, default facets, and max values
852
+ */
853
+ getFiltersSchema(): Promise<DataTypesFiltersSchemaResponse>;
854
+ }
855
+ /** Options for getFilters() — high-level wrapper with camelCase fields */
856
+ export interface FilterOptions {
857
+ /** Search query to scope filters */
858
+ q?: string;
859
+ /** Active filter string (Typesense filter_by syntax) */
860
+ filter?: string;
861
+ /** Comma-separated facet fields to return (defaults to store config) */
862
+ facetBy?: string;
863
+ /** Maximum number of values per facet */
864
+ maxFacetValues?: number;
865
+ /** Fields that should use disjunctive (OR) faceting */
866
+ disjunctiveFacets?: string[];
867
+ }
868
+ /** Options for searchFacetValues() — high-level wrapper with camelCase fields */
869
+ export interface FacetSearchOptions {
870
+ /** Search query to scope the facet values */
871
+ q?: string;
872
+ /** Active filter string */
873
+ filter?: string;
874
+ /** Query to search within facet values (required) */
875
+ facetQuery: string;
876
+ /** Maximum values to return */
877
+ maxValues?: number;
816
878
  }
879
+ export type FilterValue = DataTypesFilterValue;
880
+ export type FilterStats = DataTypesFilterStats;
881
+ export type FilterField = DataTypesFilterField;
882
+ export type FiltersResponse = DataTypesFiltersResponse;
883
+ export type FacetValuesSearchResponse = DataTypesFacetValuesSearchResponse;
884
+ export type FilterSchemaField = DataTypesFilterSchemaField;
885
+ export type FiltersSchemaResponse = DataTypesFiltersSchemaResponse;
817
886
  export default SeekoraClient;
package/dist/client.js CHANGED
@@ -51,8 +51,8 @@ class SeekoraClient {
51
51
  if (this.enableContextCollection) {
52
52
  this.collectContextAsync();
53
53
  }
54
- // Initialize event queue if enabled
55
- this.enableEventQueue = config.enableEventQueue || false;
54
+ // Initialize event queue (enabled by default for batching and offline support)
55
+ this.enableEventQueue = config.enableEventQueue ?? true;
56
56
  if (this.enableEventQueue) {
57
57
  this.eventQueue = new event_queue_1.EventQueue(config.eventQueue);
58
58
  this.eventQueue.setLogger(this.logger);
@@ -99,6 +99,8 @@ class SeekoraClient {
99
99
  this.storesApi = new generated_1.SDKStoreConfigApi(this.config);
100
100
  this.documentsApi = new generated_1.SDKDocumentsApi(this.config);
101
101
  this.schemaApi = new generated_1.SDKSchemaApi(this.config);
102
+ this.filtersApi = new generated_1.FiltersApi(this.config);
103
+ this.experimentsApi = new generated_1.SDKExperimentsApi(this.config);
102
104
  this.logger.info('SeekoraClient initialized successfully');
103
105
  }
104
106
  /**
@@ -542,6 +544,37 @@ class SeekoraClient {
542
544
  throw this.handleError(error, 'getConfig');
543
545
  }
544
546
  }
547
+ /**
548
+ * Get experiment assignments for the current user
549
+ *
550
+ * Returns variant assignments for all running experiments.
551
+ * Uses hash-based consistent assignment on the backend.
552
+ *
553
+ * @returns ExperimentAssignmentResponse with assignments array
554
+ */
555
+ async getExperimentAssignment() {
556
+ this.logger.verbose('Getting experiment assignments');
557
+ try {
558
+ const headers = {
559
+ 'x-storeid': this.storeId,
560
+ 'x-storesecret': this.readSecret,
561
+ };
562
+ if (this.userId)
563
+ headers['x-user-id'] = this.userId;
564
+ if (this.anonId)
565
+ headers['x-anon-id'] = this.anonId;
566
+ const response = await this.experimentsApi.v1ExperimentsAssignmentGet(this.storeId, this.readSecret, this.userId, this.anonId, { headers });
567
+ const data = response.data;
568
+ this.logger.info('Experiment assignments retrieved', {
569
+ count: data?.assignments?.length ?? 0,
570
+ });
571
+ return data;
572
+ }
573
+ catch (error) {
574
+ this.logger.error('Failed to get experiment assignments', { error: error.message });
575
+ throw this.handleError(error, 'getExperimentAssignment');
576
+ }
577
+ }
545
578
  /**
546
579
  * Get store information
547
580
  * Returns store metadata including name, status, and configuration details
@@ -1416,6 +1449,7 @@ class SeekoraClient {
1416
1449
  await this.trackEvent({
1417
1450
  event_name: 'product_click',
1418
1451
  clicked_item_id: itemId,
1452
+ position,
1419
1453
  metadata: {
1420
1454
  position,
1421
1455
  },
@@ -1788,6 +1822,96 @@ class SeekoraClient {
1788
1822
  getLogger() {
1789
1823
  return this.logger;
1790
1824
  }
1825
+ // =========================================================================
1826
+ // Filters API
1827
+ // =========================================================================
1828
+ /**
1829
+ * Get filter values and counts for configured facets.
1830
+ * Use this to build faceted navigation UIs without performing a full search.
1831
+ * Supports disjunctive faceting for OR-based filter combinations.
1832
+ *
1833
+ * @param options - Filter options (query, filters, facet_by, max_facet_values, disjunctive_facets)
1834
+ * @returns Filter values with counts grouped by field
1835
+ */
1836
+ async getFilters(options) {
1837
+ this.logger.verbose('Getting filters', { options });
1838
+ try {
1839
+ const req = {
1840
+ q: options?.q,
1841
+ filter: options?.filter,
1842
+ facet_by: options?.facetBy,
1843
+ max_facet_values: options?.maxFacetValues,
1844
+ disjunctive_facets: options?.disjunctiveFacets,
1845
+ };
1846
+ const response = await this.filtersApi.v1FiltersPost(this.storeId, this.readSecret, req);
1847
+ const wrapper = response.data;
1848
+ const data = wrapper?.data || response.data;
1849
+ this.logger.info('Filters retrieved successfully', {
1850
+ filterCount: data?.filters?.length,
1851
+ totalResults: data?.total_results,
1852
+ });
1853
+ return data;
1854
+ }
1855
+ catch (error) {
1856
+ this.logger.error('Failed to get filters', { error: error.message });
1857
+ throw this.handleError(error, 'getFilters');
1858
+ }
1859
+ }
1860
+ /**
1861
+ * Search within a single facet's values.
1862
+ * Useful for facets with many values (e.g., brands) where you need typeahead/autocomplete.
1863
+ *
1864
+ * @param facetName - The facet field name to search within (e.g., "brand", "category")
1865
+ * @param options - Search options including facetQuery (required), optional q, filter, maxValues
1866
+ * @returns Matching facet values with counts
1867
+ */
1868
+ async searchFacetValues(facetName, options) {
1869
+ this.logger.verbose('Searching facet values', { facetName, options });
1870
+ try {
1871
+ const req = {
1872
+ facet_query: options.facetQuery,
1873
+ q: options?.q,
1874
+ filter: options?.filter,
1875
+ max_values: options?.maxValues,
1876
+ };
1877
+ const response = await this.filtersApi.v1FiltersFacetNameValuesPost(this.storeId, this.readSecret, facetName, req);
1878
+ const wrapper = response.data;
1879
+ const data = wrapper?.data || response.data;
1880
+ this.logger.info('Facet values retrieved', {
1881
+ facetName,
1882
+ valueCount: data?.values?.length,
1883
+ });
1884
+ return data;
1885
+ }
1886
+ catch (error) {
1887
+ this.logger.error('Failed to search facet values', { facetName, error: error.message });
1888
+ throw this.handleError(error, 'searchFacetValues');
1889
+ }
1890
+ }
1891
+ /**
1892
+ * Get available filter field metadata (schema).
1893
+ * Returns information about all facetable fields including types, sortability, and configured ranges.
1894
+ * Useful for dynamically building filter UIs.
1895
+ *
1896
+ * @returns Filter field metadata with types, default facets, and max values
1897
+ */
1898
+ async getFiltersSchema() {
1899
+ this.logger.verbose('Getting filters schema');
1900
+ try {
1901
+ const response = await this.filtersApi.v1FiltersSchemaGet(this.storeId, this.readSecret);
1902
+ const wrapper = response.data;
1903
+ const data = wrapper?.data || response.data;
1904
+ this.logger.info('Filters schema retrieved', {
1905
+ fieldCount: data?.fields?.length,
1906
+ defaultFacets: data?.default_facets?.length,
1907
+ });
1908
+ return data;
1909
+ }
1910
+ catch (error) {
1911
+ this.logger.error('Failed to get filters schema', { error: error.message });
1912
+ throw this.handleError(error, 'getFiltersSchema');
1913
+ }
1914
+ }
1791
1915
  }
1792
1916
  exports.SeekoraClient = SeekoraClient;
1793
1917
  // Export default