@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 +48 -13
- package/dist/client.js +144 -131
- package/dist/config.d.ts +3 -3
- package/dist/config.js +9 -4
- package/dist/generated/api.d.ts +420 -367
- package/dist/generated/api.js +353 -508
- package/dist/generated/base.d.ts +1 -1
- package/dist/generated/base.js +1 -1
- package/dist/generated/common.d.ts +1 -1
- package/dist/generated/common.js +1 -1
- package/dist/generated/configuration.d.ts +1 -1
- package/dist/generated/configuration.js +1 -1
- package/dist/generated/index.d.ts +1 -1
- package/dist/generated/index.js +1 -1
- package/dist/index.d.ts +1 -1
- package/package.json +1 -1
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
|
|
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
|
|
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
|
|
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: '
|
|
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.
|
|
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
|
|
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
|
|
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.
|
|
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.
|
|
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.
|
|
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
|
|
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.
|
|
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.
|
|
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.
|
|
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.
|
|
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.
|
|
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.
|
|
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.
|
|
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.
|
|
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
|
|
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
|
|
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
|
|
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
|
|
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
|
|
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
|
-
|
|
31
|
+
const env = environment || 'production';
|
|
32
|
+
return exports.ENVIRONMENTS[env]?.baseUrl || exports.ENVIRONMENTS.production.baseUrl;
|
|
28
33
|
}
|
|
29
34
|
/**
|
|
30
|
-
* Get current environment
|
|
35
|
+
* Get current environment
|
|
31
36
|
*/
|
|
32
37
|
function getEnvironment(environment) {
|
|
33
|
-
return 'production';
|
|
38
|
+
return environment || 'production';
|
|
34
39
|
}
|