@seekora-ai/search-sdk 0.2.16 → 0.2.18

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, DataTypesFiltersResponse, DataTypesFacetValuesSearchResponse, DataTypesFiltersSchemaResponse, DataTypesFilterField, DataTypesFilterValue, DataTypesFilterStats, DataTypesFilterSchemaField, DataTypesExperimentAssignmentResponse } from './generated';
5
+ import type { DataTypesIndexConfig, DataTypesEventPayload, DataTypesFiltersResponse, DataTypesFacetValuesSearchResponse, DataTypesFiltersSchemaResponse, DataTypesFilterField, DataTypesFilterValue, DataTypesFilterStats, DataTypesFilterSchemaField } 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';
@@ -217,6 +217,40 @@ export interface SearchResponse {
217
217
  context: SearchContext;
218
218
  [key: string]: any;
219
219
  }
220
+ /**
221
+ * Options for a single query within a multi-search request.
222
+ * Mirrors SearchOptions but all fields are optional (q is required at call site).
223
+ */
224
+ export interface MultiSearchQuery {
225
+ /** Search query string */
226
+ q: string;
227
+ per_page?: number;
228
+ page?: number;
229
+ filter?: string;
230
+ filter_by?: string;
231
+ facet_by?: string;
232
+ sort?: string;
233
+ sort_by?: string;
234
+ analytics_tags?: string[];
235
+ widget_mode?: boolean;
236
+ search_fields?: string[];
237
+ field_weights?: number[];
238
+ return_fields?: string[];
239
+ omit_fields?: string[];
240
+ snippet_fields?: string[];
241
+ group_field?: string;
242
+ group_size?: number;
243
+ include_suggestions?: boolean;
244
+ suggestions_limit?: number;
245
+ max_facet_values?: number;
246
+ }
247
+ /**
248
+ * Response from multiSearch() — an array of per-query results,
249
+ * each with its own SearchContext for independent analytics tracking.
250
+ */
251
+ export interface MultiSearchResponse {
252
+ results: Array<SearchResponse>;
253
+ }
220
254
  /**
221
255
  * Full query suggestions API response when returnFullResponse is true.
222
256
  * Includes suggestion hits plus dropdown recommendations (trending_searches, top_searches,
@@ -325,7 +359,6 @@ export declare class SeekoraClient {
325
359
  private analyticsApi;
326
360
  private storeManagementApi;
327
361
  private filtersApi;
328
- private experimentsApi;
329
362
  private storeId;
330
363
  private readSecret;
331
364
  private writeSecret?;
@@ -356,6 +389,17 @@ export declare class SeekoraClient {
356
389
  * @returns SearchResponse with results and SearchContext
357
390
  */
358
391
  search(query: string, options?: Partial<SearchOptions>): Promise<SearchResponse>;
392
+ /**
393
+ * Execute multiple search queries in a single request.
394
+ *
395
+ * Batches up to 10 queries into one API call for efficiency.
396
+ * Each result gets its own SearchContext for independent analytics tracking
397
+ * (clicks, conversions, impressions are linked per sub-query).
398
+ *
399
+ * @param queries - Array of search queries (1-10)
400
+ * @returns MultiSearchResponse with per-query results and contexts
401
+ */
402
+ multiSearch(queries: MultiSearchQuery[]): Promise<MultiSearchResponse>;
359
403
  /**
360
404
  * Get query suggestions
361
405
  *
@@ -400,7 +444,7 @@ export declare class SeekoraClient {
400
444
  }): Promise<any[] | QuerySuggestionsFullResponse>;
401
445
  /**
402
446
  * Get query suggestions configuration (store-specific).
403
- * Uses GET /api/v1/stores/{storeId}/query-suggestions/config via SDKQuerySuggestionsConfigApi.
447
+ * Uses GET /api/v1/stores/{storeId}/query-suggestions/config via StoreManagementApi.
404
448
  */
405
449
  getSuggestionsConfig(): Promise<any>;
406
450
  /**
@@ -408,15 +452,6 @@ export declare class SeekoraClient {
408
452
  * Returns store search configuration and onboarding status
409
453
  */
410
454
  getConfig(): Promise<DataTypesIndexConfig>;
411
- /**
412
- * Get experiment assignments for the current user
413
- *
414
- * Returns variant assignments for all running experiments.
415
- * Uses hash-based consistent assignment on the backend.
416
- *
417
- * @returns ExperimentAssignmentResponse with assignments array
418
- */
419
- getExperimentAssignment(): Promise<DataTypesExperimentAssignmentResponse>;
420
455
  /**
421
456
  * Get store information
422
457
  * Returns store metadata including name, status, and configuration details
@@ -443,7 +478,7 @@ export declare class SeekoraClient {
443
478
  updateConfig(config: Partial<DataTypesIndexConfig>): Promise<DataTypesIndexConfig>;
444
479
  /**
445
480
  * Update query suggestions configuration (requires write secret).
446
- * Uses PUT /api/v1/stores/{xStoreID}/query-suggestions/config via SDKQuerySuggestionsConfigApi.
481
+ * Uses PUT /api/v1/stores/{xStoreID}/query-suggestions/config via StoreManagementApi.
447
482
  */
448
483
  updateQuerySuggestionsConfig(config: any): Promise<any>;
449
484
  /**
package/dist/client.js CHANGED
@@ -97,7 +97,6 @@ class SeekoraClient {
97
97
  this.analyticsApi = new generated_1.AnalyticsEventsApi(this.config);
98
98
  this.storeManagementApi = new generated_1.StoreManagementApi(this.config);
99
99
  this.filtersApi = new generated_1.FiltersApi(this.config);
100
- this.experimentsApi = new generated_1.SDKExperimentsApi(this.config);
101
100
  this.logger.info('SeekoraClient initialized successfully');
102
101
  }
103
102
  /**
@@ -172,7 +171,7 @@ class SeekoraClient {
172
171
  // Log API request start
173
172
  this.logger.verbose('Sending search API request', {
174
173
  endpoint: '/api/v1/search',
175
- method: 'POST',
174
+ method: 'GET',
176
175
  storeId: this.storeId
177
176
  });
178
177
  // Build headers with personalization support
@@ -190,9 +189,7 @@ class SeekoraClient {
190
189
  if (this.sessionId) {
191
190
  headers['x-session-id'] = this.sessionId;
192
191
  }
193
- const response = await this.searchApi.v1SearchPost(this.storeId, this.readSecret, searchRequest, this.userId, this.anonId, this.sessionId, {
194
- headers
195
- });
192
+ const response = await this.searchApi.v1SearchGet(this.storeId, this.readSecret, searchRequest.q, this.userId, this.anonId, this.sessionId, searchRequest.page, searchRequest.per_page, searchRequest.sort, searchRequest.filter, searchRequest.facet_by, searchRequest.max_facet_values, searchRequest.widget_mode, searchRequest.include_suggestions, searchRequest.suggestions_limit, Array.isArray(searchRequest.analytics_tags) ? searchRequest.analytics_tags.join(',') : searchRequest.analytics_tags, Array.isArray(searchRequest.stopword_sets) ? searchRequest.stopword_sets.join(',') : searchRequest.stopword_sets, Array.isArray(searchRequest.synonym_sets) ? searchRequest.synonym_sets.join(',') : searchRequest.synonym_sets, searchRequest.search_fields, searchRequest.return_fields, searchRequest.omit_fields, searchRequest.snippet_fields, searchRequest.full_snippet_fields, searchRequest.field_weights, searchRequest.group_field, searchRequest.group_size, searchRequest.snippet_prefix, searchRequest.snippet_suffix, searchRequest.snippet_token_limit, searchRequest.snippet_min_len, searchRequest.include_snippets, searchRequest.prefix_mode, searchRequest.infix_mode, searchRequest.typo_max, searchRequest.typo_min_len_1, searchRequest.typo_min_len_2, searchRequest.search_timeout_ms, searchRequest.require_all_terms, searchRequest.exact_match_boost, searchRequest.cache_results, searchRequest.apply_rules, searchRequest.preset_name, searchRequest.facet_search_text, { headers });
196
193
  // Log API response received
197
194
  this.logger.verbose('Search API response received', {
198
195
  status: response.status,
@@ -323,6 +320,131 @@ class SeekoraClient {
323
320
  throw this.handleError(error, 'search');
324
321
  }
325
322
  }
323
+ /**
324
+ * Execute multiple search queries in a single request.
325
+ *
326
+ * Batches up to 10 queries into one API call for efficiency.
327
+ * Each result gets its own SearchContext for independent analytics tracking
328
+ * (clicks, conversions, impressions are linked per sub-query).
329
+ *
330
+ * @param queries - Array of search queries (1-10)
331
+ * @returns MultiSearchResponse with per-query results and contexts
332
+ */
333
+ async multiSearch(queries) {
334
+ if (!queries || queries.length === 0) {
335
+ throw new Error('At least one search query is required');
336
+ }
337
+ if (queries.length > 10) {
338
+ throw new Error('Maximum 10 search queries per request');
339
+ }
340
+ this.logger.verbose('Executing multi-search', {
341
+ queryCount: queries.length,
342
+ queries: queries.map(q => q.q),
343
+ });
344
+ // Build request body matching DataTypes.MultiSearchRequest
345
+ const searches = queries.map(q => ({
346
+ q: q.q.trim() || '*',
347
+ per_page: q.per_page || 10,
348
+ page: q.page || 1,
349
+ filter: q.filter || q.filter_by,
350
+ facet_by: q.facet_by,
351
+ sort: q.sort || q.sort_by,
352
+ analytics_tags: q.analytics_tags,
353
+ widget_mode: q.widget_mode || false,
354
+ search_fields: q.search_fields,
355
+ field_weights: q.field_weights,
356
+ return_fields: q.return_fields,
357
+ omit_fields: q.omit_fields,
358
+ snippet_fields: q.snippet_fields,
359
+ group_field: q.group_field,
360
+ group_size: q.group_size,
361
+ include_suggestions: q.include_suggestions,
362
+ suggestions_limit: q.suggestions_limit,
363
+ max_facet_values: q.max_facet_values,
364
+ }));
365
+ const headers = {
366
+ 'x-storeid': this.storeId,
367
+ 'x-storesecret': this.readSecret,
368
+ };
369
+ if (this.userId)
370
+ headers['x-user-id'] = this.userId;
371
+ if (this.anonId)
372
+ headers['x-anon-id'] = this.anonId;
373
+ if (this.sessionId)
374
+ headers['x-session-id'] = this.sessionId;
375
+ try {
376
+ const response = await this.searchApi.v1MultiSearchPost(this.storeId, this.readSecret, { searches }, { headers });
377
+ const data = response.data;
378
+ const resultsList = [];
379
+ // Process each sub-result with its own SearchContext
380
+ const subResults = data?.data || [];
381
+ for (let i = 0; i < subResults.length; i++) {
382
+ const sub = subResults[i];
383
+ const correlationId = (0, utils_1.generateUUID)();
384
+ const searchId = sub?.search_id;
385
+ const context = {
386
+ correlationId,
387
+ searchId,
388
+ userId: this.userId,
389
+ anonId: this.anonId,
390
+ sessionId: this.sessionId,
391
+ };
392
+ // Process facets (same logic as single search)
393
+ const facets = sub?.facets || [];
394
+ const facetsMap = {};
395
+ if (Array.isArray(facets)) {
396
+ facets.forEach((facet, index) => {
397
+ const fieldName = facet?.field_name || facet?.fieldName || facet?.name || `facet_${index}`;
398
+ if (fieldName && (facet?.counts || facet?.values || Array.isArray(facet))) {
399
+ facetsMap[fieldName] = {
400
+ field_name: fieldName,
401
+ counts: facet.counts || facet.values || [],
402
+ stats: facet.stats || {},
403
+ };
404
+ }
405
+ });
406
+ }
407
+ const result = {
408
+ results: sub?.results || [],
409
+ totalResults: sub?.total_results || 0,
410
+ searchId,
411
+ context,
412
+ facets: facetsMap,
413
+ facet_counts: facetsMap,
414
+ };
415
+ resultsList.push(result);
416
+ // Auto-track search event per sub-query
417
+ if (this.autoTrackSearch) {
418
+ this.trackSearch({
419
+ query: queries[i]?.q || '*',
420
+ resultsCount: result.totalResults,
421
+ context,
422
+ }).catch((err) => {
423
+ this.logger.warn('Failed to auto-track multi-search event', { index: i, error: err.message });
424
+ });
425
+ }
426
+ // Auto-track impressions per sub-query
427
+ if (this.clientConfig.autoTrackImpressions !== false && result.results.length > 0) {
428
+ this.autoTrackSearchImpressions(result, context).catch((err) => {
429
+ this.logger.warn('Failed to auto-track multi-search impressions', { index: i, error: err.message });
430
+ });
431
+ }
432
+ }
433
+ this.logger.info('Multi-search completed', {
434
+ queryCount: queries.length,
435
+ totalResults: resultsList.map(r => r.totalResults),
436
+ });
437
+ return { results: resultsList };
438
+ }
439
+ catch (error) {
440
+ this.logger.error('Multi-search failed', {
441
+ queryCount: queries.length,
442
+ error: error.message,
443
+ status: error.response?.status,
444
+ });
445
+ throw this.handleError(error, 'multiSearch');
446
+ }
447
+ }
326
448
  /**
327
449
  * Get query suggestions
328
450
  *
@@ -352,72 +474,7 @@ class SeekoraClient {
352
474
  headers['x-anon-id'] = this.anonId;
353
475
  if (this.sessionId)
354
476
  headers['x-session-id'] = this.sessionId;
355
- // Use POST for:
356
- // - Complex filtered_tabs (5+ tabs or very long JSON would exceed URL limits)
357
- // - Explicit preference for POST (options.method === 'POST')
358
- // Use GET for everything else (including simple filtered_tabs)
359
- const hasComplexFilteredTabs = options?.filtered_tabs &&
360
- options.filtered_tabs.length > 5;
361
- const usePost = hasComplexFilteredTabs ||
362
- options?.method === 'POST'; // Allow explicit POST preference
363
477
  const defaults = this.clientConfig?.suggestionsDefaults;
364
- const buildRequestBody = () => {
365
- const body = {
366
- query,
367
- hitsPerPage: options?.hitsPerPage ?? defaults?.hitsPerPage ?? 5,
368
- page: options?.page,
369
- include_categories: options?.include_categories,
370
- include_facets: options?.include_facets,
371
- max_categories: options?.max_categories,
372
- max_facets: options?.max_facets,
373
- min_popularity: options?.min_popularity,
374
- time_range: options?.time_range ?? defaults?.time_range,
375
- disable_typo_tolerance: options?.disable_typo_tolerance,
376
- include_dropdown_recommendations: options?.include_dropdown_recommendations ?? defaults?.include_dropdown_recommendations,
377
- include_dropdown_product_list: options?.include_dropdown_product_list ?? defaults?.include_dropdown_product_list,
378
- include_filtered_tabs: options?.include_filtered_tabs ?? defaults?.include_filtered_tabs,
379
- filtered_tabs: options?.filtered_tabs,
380
- };
381
- if (options?.analytics_tags) {
382
- body.analytics_tags = Array.isArray(options.analytics_tags)
383
- ? options.analytics_tags
384
- : [options.analytics_tags];
385
- }
386
- if (options?.tags_match_mode)
387
- body.tags_match_mode = options.tags_match_mode;
388
- return body;
389
- };
390
- if (usePost) {
391
- this.logger.verbose('Using POST endpoint (filtered_tabs or include_dropdown_recommendations)', {
392
- endpoint: '/api/v1/suggestions/queries',
393
- query,
394
- });
395
- const requestBody = buildRequestBody();
396
- const response = await this.suggestionsApi.v1SuggestionsQueriesPost(this.storeId, this.readSecret, this.userId, this.anonId, this.sessionId, requestBody, { headers });
397
- const responseData = response.data?.data || response.data;
398
- const suggestions = responseData?.results?.[0]?.hits || responseData?.hits || [];
399
- const extensions = responseData?.results?.[1]?.extensions ?? responseData?.results?.[0]?.extensions;
400
- if (options?.returnFullResponse) {
401
- this.logger.info('Query suggestions retrieved (POST, full response)', {
402
- query,
403
- count: suggestions.length,
404
- status: response.status,
405
- });
406
- return {
407
- suggestions,
408
- results: responseData?.results,
409
- extensions: extensions ?? undefined,
410
- raw: responseData,
411
- };
412
- }
413
- this.logger.info('Query suggestions retrieved (POST)', {
414
- query,
415
- count: suggestions.length,
416
- status: response.status,
417
- });
418
- return suggestions;
419
- }
420
- // GET for simple requests and simple filtered_tabs (URL-encoded JSON)
421
478
  this.logger.verbose('Using GET endpoint', {
422
479
  endpoint: '/api/v1/suggestions/queries',
423
480
  query,
@@ -432,8 +489,8 @@ class SeekoraClient {
432
489
  : undefined;
433
490
  const response = await this.suggestionsApi.v1SuggestionsQueriesGet(this.storeId, this.readSecret, this.userId, this.anonId, this.sessionId, query, // query parameter
434
491
  undefined, // q parameter (alias for query)
435
- options?.hitsPerPage || 5, options?.page, analyticsTags, options?.tags_match_mode, options?.include_categories, options?.include_facets, options?.include_dropdown_recommendations, options?.include_dropdown_product_list, options?.include_filtered_tabs, undefined, // include_empty_query_recommendations
436
- options?.max_categories, options?.max_facets, options?.min_popularity, options?.time_range, options?.disable_typo_tolerance, filteredTabsParam, // filtered_tabs as JSON string
492
+ options?.hitsPerPage ?? defaults?.hitsPerPage ?? 5, options?.page, analyticsTags, options?.tags_match_mode, options?.include_categories, options?.include_facets, options?.include_dropdown_recommendations ?? defaults?.include_dropdown_recommendations, options?.include_dropdown_product_list ?? defaults?.include_dropdown_product_list, options?.include_filtered_tabs ?? defaults?.include_filtered_tabs, undefined, // include_empty_query_recommendations
493
+ options?.max_categories, options?.max_facets, options?.min_popularity, (options?.time_range ?? defaults?.time_range), options?.disable_typo_tolerance, filteredTabsParam, // filtered_tabs as JSON string
437
494
  undefined, // userId (using header instead)
438
495
  undefined, // anonId (using header instead)
439
496
  undefined, // sessionId (using header instead)
@@ -468,7 +525,7 @@ class SeekoraClient {
468
525
  }
469
526
  /**
470
527
  * Get query suggestions configuration (store-specific).
471
- * Uses GET /api/v1/stores/{storeId}/query-suggestions/config via SDKQuerySuggestionsConfigApi.
528
+ * Uses GET /api/v1/stores/{storeId}/query-suggestions/config via StoreManagementApi.
472
529
  */
473
530
  async getSuggestionsConfig() {
474
531
  this.logger.verbose('Getting suggestions configuration');
@@ -478,7 +535,7 @@ class SeekoraClient {
478
535
  'x-storesecret': this.readSecret,
479
536
  };
480
537
  try {
481
- const response = await this.storeManagementApi.apiV1StoresXStoreIDQuerySuggestionsConfigGet(this.storeId, this.readSecret, this.storeId, { headers });
538
+ const response = await this.storeManagementApi.apiV1StoresQuerySuggestionsConfigGet(this.storeId, this.readSecret, { headers });
482
539
  const data = response.data?.data;
483
540
  const config = data?.metadata?.config ?? data?.config ?? data;
484
541
  this.logger.info('Suggestions configuration retrieved', {
@@ -528,7 +585,7 @@ class SeekoraClient {
528
585
  if (this.sessionId) {
529
586
  headers['x-session-id'] = this.sessionId;
530
587
  }
531
- const response = await this.storeManagementApi.apiV1StoresXStoreIDConfigGet(this.storeId, this.readSecret, this.storeId, { headers });
588
+ const response = await this.storeManagementApi.apiV1StoresConfigGet(this.storeId, this.readSecret, { headers });
532
589
  const config = response.data?.data;
533
590
  this.logger.info('Store configuration retrieved', {
534
591
  status: response.status,
@@ -541,37 +598,6 @@ class SeekoraClient {
541
598
  throw this.handleError(error, 'getConfig');
542
599
  }
543
600
  }
544
- /**
545
- * Get experiment assignments for the current user
546
- *
547
- * Returns variant assignments for all running experiments.
548
- * Uses hash-based consistent assignment on the backend.
549
- *
550
- * @returns ExperimentAssignmentResponse with assignments array
551
- */
552
- async getExperimentAssignment() {
553
- this.logger.verbose('Getting experiment assignments');
554
- try {
555
- const headers = {
556
- 'x-storeid': this.storeId,
557
- 'x-storesecret': this.readSecret,
558
- };
559
- if (this.userId)
560
- headers['x-user-id'] = this.userId;
561
- if (this.anonId)
562
- headers['x-anon-id'] = this.anonId;
563
- const response = await this.experimentsApi.v1ExperimentsAssignmentGet(this.storeId, this.readSecret, this.userId, this.anonId, { headers });
564
- const data = response.data;
565
- this.logger.info('Experiment assignments retrieved', {
566
- count: data?.assignments?.length ?? 0,
567
- });
568
- return data;
569
- }
570
- catch (error) {
571
- this.logger.error('Failed to get experiment assignments', { error: error.message });
572
- throw this.handleError(error, 'getExperimentAssignment');
573
- }
574
- }
575
601
  /**
576
602
  * Get store information
577
603
  * Returns store metadata including name, status, and configuration details
@@ -658,7 +684,7 @@ class SeekoraClient {
658
684
  'x-storesecret': this.readSecret,
659
685
  'x-store-write-secret': this.writeSecret,
660
686
  };
661
- const response = await this.storeManagementApi.apiV1StoresXStoreIDConfigPut(this.storeId, this.writeSecret, this.storeId, config, { headers });
687
+ const response = await this.storeManagementApi.apiV1StoresConfigPut(this.storeId, this.writeSecret, config, { headers });
662
688
  const updatedConfig = response.data?.data;
663
689
  this.logger.info('Store configuration updated successfully', {
664
690
  status: response.status,
@@ -673,7 +699,7 @@ class SeekoraClient {
673
699
  }
674
700
  /**
675
701
  * Update query suggestions configuration (requires write secret).
676
- * Uses PUT /api/v1/stores/{xStoreID}/query-suggestions/config via SDKQuerySuggestionsConfigApi.
702
+ * Uses PUT /api/v1/stores/{xStoreID}/query-suggestions/config via StoreManagementApi.
677
703
  */
678
704
  async updateQuerySuggestionsConfig(config) {
679
705
  this.logger.verbose('Updating query suggestions configuration', { configKeys: Object.keys(config) });
@@ -691,7 +717,7 @@ class SeekoraClient {
691
717
  'Content-Type': 'application/json',
692
718
  };
693
719
  try {
694
- const response = await this.storeManagementApi.apiV1StoresXStoreIDQuerySuggestionsConfigPut(this.storeId, this.writeSecret, this.storeId, config, { headers });
720
+ const response = await this.storeManagementApi.apiV1StoresQuerySuggestionsConfigPut(this.storeId, this.writeSecret, config, { headers });
695
721
  const data = response.data?.data;
696
722
  const updatedConfig = data?.metadata?.config ?? data?.config ?? data;
697
723
  this.logger.info('Query suggestions configuration updated successfully', {
@@ -725,7 +751,7 @@ class SeekoraClient {
725
751
  async getConfigSchema() {
726
752
  this.logger.verbose('Getting configuration schema');
727
753
  try {
728
- const response = await this.storeManagementApi.apiV1StoresXStoreIDConfigSchemaGet(this.storeId, this.readSecret, this.storeId, {
754
+ const response = await this.storeManagementApi.apiV1StoresConfigSchemaGet(this.storeId, this.readSecret, {
729
755
  headers: {
730
756
  'x-storeid': this.storeId,
731
757
  'x-storesecret': this.readSecret,
@@ -766,7 +792,7 @@ class SeekoraClient {
766
792
  id: document.id,
767
793
  data: document.data,
768
794
  };
769
- const response = await this.storeManagementApi.apiV1StoresXStoreIDDocumentsPost(this.storeId, this.writeSecret, this.storeId, request);
795
+ const response = await this.storeManagementApi.apiV1StoresDocumentsPost(this.storeId, this.writeSecret, request);
770
796
  const responseData = response.data?.data;
771
797
  this.logger.info('Document indexed successfully', {
772
798
  id: responseData?.id || document.id,
@@ -810,7 +836,7 @@ class SeekoraClient {
810
836
  data: doc.data,
811
837
  })),
812
838
  };
813
- const response = await this.storeManagementApi.apiV1StoresXStoreIDDocumentsBulkPost(this.storeId, this.writeSecret, this.storeId, request);
839
+ const response = await this.storeManagementApi.apiV1StoresDocumentsBulkPost(this.storeId, this.writeSecret, request);
814
840
  const responseData = response.data?.data;
815
841
  this.logger.info('Bulk document indexing completed', {
816
842
  successCount: responseData?.successCount || 0,
@@ -854,7 +880,7 @@ class SeekoraClient {
854
880
  throw new Error('Write secret is required for deleteDocument');
855
881
  }
856
882
  try {
857
- const response = await this.storeManagementApi.apiV1StoresXStoreIDDocumentsDocumentIDDelete(this.storeId, this.writeSecret, this.storeId, documentId);
883
+ const response = await this.storeManagementApi.apiV1StoresDocumentsDocumentIDDelete(this.storeId, this.writeSecret, documentId);
858
884
  this.logger.info('Document deleted successfully', {
859
885
  documentId,
860
886
  status: response.status
@@ -932,7 +958,7 @@ class SeekoraClient {
932
958
  default_sorting_field: request.defaultSortingField,
933
959
  enable_nested_fields: request.enableNestedFields,
934
960
  };
935
- const response = await this.storeManagementApi.apiV1StoresXStoreIDSchemaPost(this.storeId, this.writeSecret, this.storeId, apiRequest);
961
+ const response = await this.storeManagementApi.apiV1StoresSchemaPost(this.storeId, this.writeSecret, apiRequest);
936
962
  const responseData = response.data;
937
963
  this.logger.info('Schema created/updated successfully', {
938
964
  name: responseData.data?.name,
@@ -973,7 +999,7 @@ class SeekoraClient {
973
999
  async getSchema() {
974
1000
  this.logger.verbose('Getting schema', { storeId: this.storeId });
975
1001
  try {
976
- const response = await this.storeManagementApi.apiV1StoresXStoreIDSchemaGet(this.storeId, this.readSecret, this.storeId);
1002
+ const response = await this.storeManagementApi.apiV1StoresSchemaGet(this.storeId, this.readSecret);
977
1003
  const responseData = response.data;
978
1004
  this.logger.info('Schema retrieved successfully', {
979
1005
  name: responseData.data?.name,
@@ -1024,7 +1050,7 @@ class SeekoraClient {
1024
1050
  throw new Error('Write secret is required for clearDocuments');
1025
1051
  }
1026
1052
  try {
1027
- const response = await this.storeManagementApi.apiV1StoresXStoreIDDocumentsDelete(this.storeId, this.writeSecret, this.storeId);
1053
+ const response = await this.storeManagementApi.apiV1StoresDocumentsDelete(this.storeId, this.writeSecret);
1028
1054
  const responseData = response.data;
1029
1055
  this.logger.info('Documents cleared successfully', {
1030
1056
  deletedCount: responseData.data?.deleted_count
@@ -1833,14 +1859,7 @@ class SeekoraClient {
1833
1859
  async getFilters(options) {
1834
1860
  this.logger.verbose('Getting filters', { options });
1835
1861
  try {
1836
- const req = {
1837
- q: options?.q,
1838
- filter: options?.filter,
1839
- facet_by: options?.facetBy,
1840
- max_facet_values: options?.maxFacetValues,
1841
- disjunctive_facets: options?.disjunctiveFacets,
1842
- };
1843
- const response = await this.filtersApi.v1FiltersPost(this.storeId, this.readSecret, req);
1862
+ const response = await this.filtersApi.v1FiltersGet(this.storeId, this.readSecret, options?.q, options?.filter, options?.facetBy, options?.maxFacetValues, options?.disjunctiveFacets?.join(','));
1844
1863
  const wrapper = response.data;
1845
1864
  const data = wrapper?.data || response.data;
1846
1865
  this.logger.info('Filters retrieved successfully', {
@@ -1865,13 +1884,7 @@ class SeekoraClient {
1865
1884
  async searchFacetValues(facetName, options) {
1866
1885
  this.logger.verbose('Searching facet values', { facetName, options });
1867
1886
  try {
1868
- const req = {
1869
- facet_query: options.facetQuery,
1870
- q: options?.q,
1871
- filter: options?.filter,
1872
- max_values: options?.maxValues,
1873
- };
1874
- const response = await this.filtersApi.v1FiltersFacetNameValuesPost(this.storeId, this.readSecret, facetName, req);
1887
+ const response = await this.filtersApi.v1FiltersFacetNameValuesGet(this.storeId, this.readSecret, facetName, options.facetQuery, options?.q, options?.filter, options?.maxValues);
1875
1888
  const wrapper = response.data;
1876
1889
  const data = wrapper?.data || response.data;
1877
1890
  this.logger.info('Facet values retrieved', {
package/dist/config.d.ts CHANGED
@@ -3,13 +3,13 @@
3
3
  *
4
4
  * Production API only. Use baseUrl for custom endpoints.
5
5
  */
6
- export type SeekoraEnvironment = 'production';
6
+ export type SeekoraEnvironment = 'production' | 'staging';
7
7
  export interface EnvironmentConfig {
8
8
  baseUrl: string;
9
9
  name: string;
10
10
  }
11
11
  /**
12
- * Environment configurations (production only in public SDK)
12
+ * Environment configurations
13
13
  */
14
14
  export declare const ENVIRONMENTS: Record<SeekoraEnvironment, EnvironmentConfig>;
15
15
  /**
@@ -17,6 +17,6 @@ export declare const ENVIRONMENTS: Record<SeekoraEnvironment, EnvironmentConfig>
17
17
  */
18
18
  export declare function getBaseUrl(environment?: SeekoraEnvironment, customBaseUrl?: string): string;
19
19
  /**
20
- * Get current environment (production only in public SDK)
20
+ * Get current environment
21
21
  */
22
22
  export declare function getEnvironment(environment?: SeekoraEnvironment): SeekoraEnvironment;
package/dist/config.js CHANGED
@@ -9,13 +9,17 @@ exports.ENVIRONMENTS = void 0;
9
9
  exports.getBaseUrl = getBaseUrl;
10
10
  exports.getEnvironment = getEnvironment;
11
11
  /**
12
- * Environment configurations (production only in public SDK)
12
+ * Environment configurations
13
13
  */
14
14
  exports.ENVIRONMENTS = {
15
15
  production: {
16
16
  baseUrl: 'https://api.seekora.com/api',
17
17
  name: 'Production',
18
18
  },
19
+ staging: {
20
+ baseUrl: 'https://stage-api.seekora.ai/api',
21
+ name: 'Staging',
22
+ },
19
23
  };
20
24
  /**
21
25
  * Get base URL. Use customBaseUrl for custom endpoints.
@@ -24,11 +28,12 @@ function getBaseUrl(environment, customBaseUrl) {
24
28
  if (customBaseUrl) {
25
29
  return customBaseUrl;
26
30
  }
27
- return exports.ENVIRONMENTS.production.baseUrl;
31
+ const env = environment || 'production';
32
+ return exports.ENVIRONMENTS[env]?.baseUrl || exports.ENVIRONMENTS.production.baseUrl;
28
33
  }
29
34
  /**
30
- * Get current environment (production only in public SDK)
35
+ * Get current environment
31
36
  */
32
37
  function getEnvironment(environment) {
33
- return 'production';
38
+ return environment || 'production';
34
39
  }