@seekora-ai/search-sdk 0.2.12 → 0.2.14
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 +98 -3
- package/dist/client.js +149 -2
- package/dist/generated/api.d.ts +1492 -562
- package/dist/generated/api.js +1002 -465
- 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 } 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
|
-
*
|
|
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
|
/**
|
|
@@ -78,6 +79,14 @@ export interface SeekoraClientConfig {
|
|
|
78
79
|
* @default 0
|
|
79
80
|
*/
|
|
80
81
|
impressionTrackingDelay?: number;
|
|
82
|
+
/**
|
|
83
|
+
* A/B test experiment ID to include in all analytics events
|
|
84
|
+
*/
|
|
85
|
+
abTestId?: string;
|
|
86
|
+
/**
|
|
87
|
+
* A/B test variant to include in all analytics events
|
|
88
|
+
*/
|
|
89
|
+
abVariant?: string;
|
|
81
90
|
/**
|
|
82
91
|
* Enable event deduplication (industry standard: Segment, Amplitude pattern)
|
|
83
92
|
* When enabled, generates insert_id for backend deduplication
|
|
@@ -147,6 +156,10 @@ export interface ExtendedEventPayload extends DataTypesEventPayload {
|
|
|
147
156
|
insert_id?: string;
|
|
148
157
|
/** Conversion type for conversion events (add_to_cart, wishlist, purchase, etc.) */
|
|
149
158
|
conversion_type?: string;
|
|
159
|
+
/** A/B test experiment ID */
|
|
160
|
+
ab_test_id?: string;
|
|
161
|
+
/** A/B test variant */
|
|
162
|
+
ab_variant?: string;
|
|
150
163
|
}
|
|
151
164
|
export interface SearchOptions {
|
|
152
165
|
q: string;
|
|
@@ -314,6 +327,8 @@ export declare class SeekoraClient {
|
|
|
314
327
|
private storesApi;
|
|
315
328
|
private documentsApi;
|
|
316
329
|
private schemaApi;
|
|
330
|
+
private filtersApi;
|
|
331
|
+
private experimentsApi;
|
|
317
332
|
private storeId;
|
|
318
333
|
private readSecret;
|
|
319
334
|
private writeSecret?;
|
|
@@ -330,6 +345,8 @@ export declare class SeekoraClient {
|
|
|
330
345
|
private clientConfig;
|
|
331
346
|
private enableDeduplication;
|
|
332
347
|
private deduplicationWindow;
|
|
348
|
+
private abTestId?;
|
|
349
|
+
private abVariant?;
|
|
333
350
|
constructor(config?: SeekoraClientConfig);
|
|
334
351
|
/**
|
|
335
352
|
* Search for documents
|
|
@@ -394,6 +411,15 @@ export declare class SeekoraClient {
|
|
|
394
411
|
* Returns store search configuration and onboarding status
|
|
395
412
|
*/
|
|
396
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>;
|
|
397
423
|
/**
|
|
398
424
|
* Get store information
|
|
399
425
|
* Returns store metadata including name, status, and configuration details
|
|
@@ -743,6 +769,18 @@ export declare class SeekoraClient {
|
|
|
743
769
|
anonId: string;
|
|
744
770
|
sessionId: string;
|
|
745
771
|
};
|
|
772
|
+
/**
|
|
773
|
+
* Set A/B test experiment ID and variant for all subsequent analytics events.
|
|
774
|
+
* Call this when experiment assignments are fetched.
|
|
775
|
+
*/
|
|
776
|
+
setAbTest(abTestId?: string, abVariant?: string): void;
|
|
777
|
+
/**
|
|
778
|
+
* Get current A/B test fields
|
|
779
|
+
*/
|
|
780
|
+
getAbTest(): {
|
|
781
|
+
abTestId?: string;
|
|
782
|
+
abVariant?: string;
|
|
783
|
+
};
|
|
746
784
|
/**
|
|
747
785
|
* Get the event queue instance (if enabled)
|
|
748
786
|
*/
|
|
@@ -787,5 +825,62 @@ export declare class SeekoraClient {
|
|
|
787
825
|
* Get the logger instance
|
|
788
826
|
*/
|
|
789
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;
|
|
790
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;
|
|
791
886
|
export default SeekoraClient;
|
package/dist/client.js
CHANGED
|
@@ -42,6 +42,8 @@ class SeekoraClient {
|
|
|
42
42
|
this.anonId = config.anonId || (0, utils_1.getOrCreateAnonId)();
|
|
43
43
|
this.sessionId = config.sessionId || (0, utils_1.getOrCreateSessionId)();
|
|
44
44
|
this.autoTrackSearch = config.autoTrackSearch || false;
|
|
45
|
+
this.abTestId = config.abTestId;
|
|
46
|
+
this.abVariant = config.abVariant;
|
|
45
47
|
// Initialize context collection
|
|
46
48
|
this.enableContextCollection = config.enableContextCollection !== false; // Default to true
|
|
47
49
|
this.contextCollector = new context_collector_1.ContextCollector(config.contextCollector);
|
|
@@ -49,8 +51,8 @@ class SeekoraClient {
|
|
|
49
51
|
if (this.enableContextCollection) {
|
|
50
52
|
this.collectContextAsync();
|
|
51
53
|
}
|
|
52
|
-
// Initialize event queue
|
|
53
|
-
this.enableEventQueue = config.enableEventQueue
|
|
54
|
+
// Initialize event queue (enabled by default for batching and offline support)
|
|
55
|
+
this.enableEventQueue = config.enableEventQueue ?? true;
|
|
54
56
|
if (this.enableEventQueue) {
|
|
55
57
|
this.eventQueue = new event_queue_1.EventQueue(config.eventQueue);
|
|
56
58
|
this.eventQueue.setLogger(this.logger);
|
|
@@ -97,6 +99,8 @@ class SeekoraClient {
|
|
|
97
99
|
this.storesApi = new generated_1.SDKStoreConfigApi(this.config);
|
|
98
100
|
this.documentsApi = new generated_1.SDKDocumentsApi(this.config);
|
|
99
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);
|
|
100
104
|
this.logger.info('SeekoraClient initialized successfully');
|
|
101
105
|
}
|
|
102
106
|
/**
|
|
@@ -540,6 +544,37 @@ class SeekoraClient {
|
|
|
540
544
|
throw this.handleError(error, 'getConfig');
|
|
541
545
|
}
|
|
542
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
|
+
}
|
|
543
578
|
/**
|
|
544
579
|
* Get store information
|
|
545
580
|
* Returns store metadata including name, status, and configuration details
|
|
@@ -1235,6 +1270,13 @@ class SeekoraClient {
|
|
|
1235
1270
|
payload.is_tablet = ctx.is_tablet ? 1 : 0;
|
|
1236
1271
|
payload.is_touch_device = ctx.is_touch_device;
|
|
1237
1272
|
}
|
|
1273
|
+
// Inject A/B test fields from client config (event-level values take precedence)
|
|
1274
|
+
if (this.abTestId && !payload.ab_test_id) {
|
|
1275
|
+
payload.ab_test_id = this.abTestId;
|
|
1276
|
+
}
|
|
1277
|
+
if (this.abVariant && !payload.ab_variant) {
|
|
1278
|
+
payload.ab_variant = this.abVariant;
|
|
1279
|
+
}
|
|
1238
1280
|
// Generate insert_id for deduplication (industry standard: Segment/Amplitude pattern)
|
|
1239
1281
|
// Always enable for purchase events (revenue must be accurate)
|
|
1240
1282
|
// Optional for other events based on config
|
|
@@ -1631,6 +1673,21 @@ class SeekoraClient {
|
|
|
1631
1673
|
sessionId: this.sessionId,
|
|
1632
1674
|
};
|
|
1633
1675
|
}
|
|
1676
|
+
/**
|
|
1677
|
+
* Set A/B test experiment ID and variant for all subsequent analytics events.
|
|
1678
|
+
* Call this when experiment assignments are fetched.
|
|
1679
|
+
*/
|
|
1680
|
+
setAbTest(abTestId, abVariant) {
|
|
1681
|
+
this.abTestId = abTestId;
|
|
1682
|
+
this.abVariant = abVariant;
|
|
1683
|
+
this.logger.verbose('A/B test fields updated', { abTestId, abVariant });
|
|
1684
|
+
}
|
|
1685
|
+
/**
|
|
1686
|
+
* Get current A/B test fields
|
|
1687
|
+
*/
|
|
1688
|
+
getAbTest() {
|
|
1689
|
+
return { abTestId: this.abTestId, abVariant: this.abVariant };
|
|
1690
|
+
}
|
|
1634
1691
|
/**
|
|
1635
1692
|
* Get the event queue instance (if enabled)
|
|
1636
1693
|
*/
|
|
@@ -1764,6 +1821,96 @@ class SeekoraClient {
|
|
|
1764
1821
|
getLogger() {
|
|
1765
1822
|
return this.logger;
|
|
1766
1823
|
}
|
|
1824
|
+
// =========================================================================
|
|
1825
|
+
// Filters API
|
|
1826
|
+
// =========================================================================
|
|
1827
|
+
/**
|
|
1828
|
+
* Get filter values and counts for configured facets.
|
|
1829
|
+
* Use this to build faceted navigation UIs without performing a full search.
|
|
1830
|
+
* Supports disjunctive faceting for OR-based filter combinations.
|
|
1831
|
+
*
|
|
1832
|
+
* @param options - Filter options (query, filters, facet_by, max_facet_values, disjunctive_facets)
|
|
1833
|
+
* @returns Filter values with counts grouped by field
|
|
1834
|
+
*/
|
|
1835
|
+
async getFilters(options) {
|
|
1836
|
+
this.logger.verbose('Getting filters', { options });
|
|
1837
|
+
try {
|
|
1838
|
+
const req = {
|
|
1839
|
+
q: options?.q,
|
|
1840
|
+
filter: options?.filter,
|
|
1841
|
+
facet_by: options?.facetBy,
|
|
1842
|
+
max_facet_values: options?.maxFacetValues,
|
|
1843
|
+
disjunctive_facets: options?.disjunctiveFacets,
|
|
1844
|
+
};
|
|
1845
|
+
const response = await this.filtersApi.v1FiltersPost(this.storeId, this.readSecret, req);
|
|
1846
|
+
const wrapper = response.data;
|
|
1847
|
+
const data = wrapper?.data || response.data;
|
|
1848
|
+
this.logger.info('Filters retrieved successfully', {
|
|
1849
|
+
filterCount: data?.filters?.length,
|
|
1850
|
+
totalResults: data?.total_results,
|
|
1851
|
+
});
|
|
1852
|
+
return data;
|
|
1853
|
+
}
|
|
1854
|
+
catch (error) {
|
|
1855
|
+
this.logger.error('Failed to get filters', { error: error.message });
|
|
1856
|
+
throw this.handleError(error, 'getFilters');
|
|
1857
|
+
}
|
|
1858
|
+
}
|
|
1859
|
+
/**
|
|
1860
|
+
* Search within a single facet's values.
|
|
1861
|
+
* Useful for facets with many values (e.g., brands) where you need typeahead/autocomplete.
|
|
1862
|
+
*
|
|
1863
|
+
* @param facetName - The facet field name to search within (e.g., "brand", "category")
|
|
1864
|
+
* @param options - Search options including facetQuery (required), optional q, filter, maxValues
|
|
1865
|
+
* @returns Matching facet values with counts
|
|
1866
|
+
*/
|
|
1867
|
+
async searchFacetValues(facetName, options) {
|
|
1868
|
+
this.logger.verbose('Searching facet values', { facetName, options });
|
|
1869
|
+
try {
|
|
1870
|
+
const req = {
|
|
1871
|
+
facet_query: options.facetQuery,
|
|
1872
|
+
q: options?.q,
|
|
1873
|
+
filter: options?.filter,
|
|
1874
|
+
max_values: options?.maxValues,
|
|
1875
|
+
};
|
|
1876
|
+
const response = await this.filtersApi.v1FiltersFacetNameValuesPost(this.storeId, this.readSecret, facetName, req);
|
|
1877
|
+
const wrapper = response.data;
|
|
1878
|
+
const data = wrapper?.data || response.data;
|
|
1879
|
+
this.logger.info('Facet values retrieved', {
|
|
1880
|
+
facetName,
|
|
1881
|
+
valueCount: data?.values?.length,
|
|
1882
|
+
});
|
|
1883
|
+
return data;
|
|
1884
|
+
}
|
|
1885
|
+
catch (error) {
|
|
1886
|
+
this.logger.error('Failed to search facet values', { facetName, error: error.message });
|
|
1887
|
+
throw this.handleError(error, 'searchFacetValues');
|
|
1888
|
+
}
|
|
1889
|
+
}
|
|
1890
|
+
/**
|
|
1891
|
+
* Get available filter field metadata (schema).
|
|
1892
|
+
* Returns information about all facetable fields including types, sortability, and configured ranges.
|
|
1893
|
+
* Useful for dynamically building filter UIs.
|
|
1894
|
+
*
|
|
1895
|
+
* @returns Filter field metadata with types, default facets, and max values
|
|
1896
|
+
*/
|
|
1897
|
+
async getFiltersSchema() {
|
|
1898
|
+
this.logger.verbose('Getting filters schema');
|
|
1899
|
+
try {
|
|
1900
|
+
const response = await this.filtersApi.v1FiltersSchemaGet(this.storeId, this.readSecret);
|
|
1901
|
+
const wrapper = response.data;
|
|
1902
|
+
const data = wrapper?.data || response.data;
|
|
1903
|
+
this.logger.info('Filters schema retrieved', {
|
|
1904
|
+
fieldCount: data?.fields?.length,
|
|
1905
|
+
defaultFacets: data?.default_facets?.length,
|
|
1906
|
+
});
|
|
1907
|
+
return data;
|
|
1908
|
+
}
|
|
1909
|
+
catch (error) {
|
|
1910
|
+
this.logger.error('Failed to get filters schema', { error: error.message });
|
|
1911
|
+
throw this.handleError(error, 'getFiltersSchema');
|
|
1912
|
+
}
|
|
1913
|
+
}
|
|
1767
1914
|
}
|
|
1768
1915
|
exports.SeekoraClient = SeekoraClient;
|
|
1769
1916
|
// Export default
|