@nuskin/react-search-sdk 1.0.0-comx-2233.1 → 1.0.0-comx-2233.2
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/index.d.mts +14 -9
- package/dist/index.d.ts +14 -9
- package/dist/index.js +82 -23
- package/dist/index.js.map +1 -1
- package/dist/index.mjs +82 -23
- package/dist/index.mjs.map +1 -1
- package/package.json +1 -1
package/dist/index.d.mts
CHANGED
|
@@ -292,10 +292,14 @@ interface ChatServiceOptions {
|
|
|
292
292
|
conversationsUrl?: string;
|
|
293
293
|
/** POST endpoint for sending a message (SSE response). */
|
|
294
294
|
messagesUrl?: string;
|
|
295
|
-
/** X-
|
|
296
|
-
|
|
297
|
-
/**
|
|
298
|
-
|
|
295
|
+
/** X-Sales-AI-App-Key header value (from CS configurations). */
|
|
296
|
+
salesAiAppKey?: string;
|
|
297
|
+
/** X-Sales-AI-Parent-Origin header value (from CS configurations). */
|
|
298
|
+
salesAiParentOrigin?: string;
|
|
299
|
+
/** Market code (e.g., "US", "JP") for scope_context in message requests. */
|
|
300
|
+
market?: string;
|
|
301
|
+
/** Language code (e.g., "en", "ja") for scope_context in message requests. */
|
|
302
|
+
language?: string;
|
|
299
303
|
/** Override fetch for testing. */
|
|
300
304
|
fetchImpl?: typeof fetch | null;
|
|
301
305
|
}
|
|
@@ -385,6 +389,7 @@ interface SpeechRecognitionErrorEventLike {
|
|
|
385
389
|
interface UseVoiceSearchOptions {
|
|
386
390
|
lang?: string;
|
|
387
391
|
onResult: (transcript: string) => void;
|
|
392
|
+
onInterimResult?: (transcript: string) => void;
|
|
388
393
|
onError?: (error: SpeechRecognitionErrorEventLike) => void;
|
|
389
394
|
}
|
|
390
395
|
interface UseVoiceSearchResult {
|
|
@@ -393,7 +398,7 @@ interface UseVoiceSearchResult {
|
|
|
393
398
|
start: () => void;
|
|
394
399
|
stop: () => void;
|
|
395
400
|
}
|
|
396
|
-
declare function useVoiceSearch({ lang, onResult, onError, }: UseVoiceSearchOptions): UseVoiceSearchResult;
|
|
401
|
+
declare function useVoiceSearch({ lang, onInterimResult, onResult, onError, }: UseVoiceSearchOptions): UseVoiceSearchResult;
|
|
397
402
|
|
|
398
403
|
/**
|
|
399
404
|
* Catalog-product normalisation helpers — Phase 0 lift-and-shift of the
|
|
@@ -502,12 +507,12 @@ declare const TRIGGER_PLACEHOLDER = "Product Search";
|
|
|
502
507
|
/**
|
|
503
508
|
* Full path segment for the AI commerce chat SSE endpoint.
|
|
504
509
|
* Appended to the consumer-provided `chatBaseUrl`.
|
|
505
|
-
* Source: https://admin.tst.nuskin.ai/api/analytics/v1/
|
|
510
|
+
* Source: https://admin.tst.nuskin.ai/api/analytics/v1/embed
|
|
506
511
|
*/
|
|
507
|
-
declare const DEFAULT_AI_CHAT_BASE_URL = "https://admin.tst.nuskin.ai/api/analytics/v1/
|
|
512
|
+
declare const DEFAULT_AI_CHAT_BASE_URL = "https://admin.tst.nuskin.ai/api/analytics/v1/embed";
|
|
508
513
|
/** Default POST endpoint for creating an AI chat conversation. */
|
|
509
|
-
declare const DEFAULT_AI_CHAT_CONVERSATIONS_URL = "https://admin.tst.nuskin.ai/api/analytics/v1/
|
|
514
|
+
declare const DEFAULT_AI_CHAT_CONVERSATIONS_URL = "https://admin.tst.nuskin.ai/api/analytics/v1/embed/conversations";
|
|
510
515
|
/** Default POST endpoint for sending AI chat messages. */
|
|
511
|
-
declare const DEFAULT_AI_CHAT_MESSAGES_URL = "https://admin.tst.nuskin.ai/api/analytics/v1/
|
|
516
|
+
declare const DEFAULT_AI_CHAT_MESSAGES_URL = "https://admin.tst.nuskin.ai/api/analytics/v1/embed/messages";
|
|
512
517
|
|
|
513
518
|
export { CATALOG_SUGGESTIONS_PATH, type CatalogSuggestionItem, type ChatMessageResult, type ChatProduct, type ChatService, type ChatServiceOptions, DEBOUNCE_MS, DEFAULT_AI_CHAT_BASE_URL, DEFAULT_AI_CHAT_CONVERSATIONS_URL, DEFAULT_AI_CHAT_MESSAGES_URL, DEFAULT_SEARCH_PATH, DEFAULT_SUGGESTION_PAGE, DEFAULT_SUGGESTION_SIZE, type DidYouMeanItem, type GetMarketConfig, type LocaleParts, type LocationLike, MAX_VISIBLE_SUGGESTIONS, type MarketConfig, type ProductType, RECENT_SEARCHES_DEFAULT_LIMIT, RECENT_SEARCHES_PREFIX, SEARCH_PLACEHOLDER, STOREFRONT_SHOPPING_CONTEXT, type SearchChromeCopy, type SearchHistoryEntry, type SearchHistoryState, type SearchHistoryEntry as SearchHistoryStoreEntry, type SearchService, type SearchServiceOptions, type SuggestionOption, type SuggestionsResponse, TRIGGER_PLACEHOLDER, type UseSearchHistoryResult, type UseSearchSuggestionsOptions, type UseSearchSuggestionsResult, type UseVoiceSearchOptions, type UseVoiceSearchResult, createChatService, createSearchService, getImageFromProperty, getIngredientTerms, getSeeMoreResultsPayload, getVisibleSuggestions, isCartActionDisabled, isSellableProductStatus, isSuggestionDisabled, mapCatalogProductToSuggestion, normalizeDidYouMean, resolveApiGatewayPath, resolveSuggestionImageSrc, useSearchHistory, useSearchHistoryStore, useSearchSuggestions, useVoiceSearch };
|
package/dist/index.d.ts
CHANGED
|
@@ -292,10 +292,14 @@ interface ChatServiceOptions {
|
|
|
292
292
|
conversationsUrl?: string;
|
|
293
293
|
/** POST endpoint for sending a message (SSE response). */
|
|
294
294
|
messagesUrl?: string;
|
|
295
|
-
/** X-
|
|
296
|
-
|
|
297
|
-
/**
|
|
298
|
-
|
|
295
|
+
/** X-Sales-AI-App-Key header value (from CS configurations). */
|
|
296
|
+
salesAiAppKey?: string;
|
|
297
|
+
/** X-Sales-AI-Parent-Origin header value (from CS configurations). */
|
|
298
|
+
salesAiParentOrigin?: string;
|
|
299
|
+
/** Market code (e.g., "US", "JP") for scope_context in message requests. */
|
|
300
|
+
market?: string;
|
|
301
|
+
/** Language code (e.g., "en", "ja") for scope_context in message requests. */
|
|
302
|
+
language?: string;
|
|
299
303
|
/** Override fetch for testing. */
|
|
300
304
|
fetchImpl?: typeof fetch | null;
|
|
301
305
|
}
|
|
@@ -385,6 +389,7 @@ interface SpeechRecognitionErrorEventLike {
|
|
|
385
389
|
interface UseVoiceSearchOptions {
|
|
386
390
|
lang?: string;
|
|
387
391
|
onResult: (transcript: string) => void;
|
|
392
|
+
onInterimResult?: (transcript: string) => void;
|
|
388
393
|
onError?: (error: SpeechRecognitionErrorEventLike) => void;
|
|
389
394
|
}
|
|
390
395
|
interface UseVoiceSearchResult {
|
|
@@ -393,7 +398,7 @@ interface UseVoiceSearchResult {
|
|
|
393
398
|
start: () => void;
|
|
394
399
|
stop: () => void;
|
|
395
400
|
}
|
|
396
|
-
declare function useVoiceSearch({ lang, onResult, onError, }: UseVoiceSearchOptions): UseVoiceSearchResult;
|
|
401
|
+
declare function useVoiceSearch({ lang, onInterimResult, onResult, onError, }: UseVoiceSearchOptions): UseVoiceSearchResult;
|
|
397
402
|
|
|
398
403
|
/**
|
|
399
404
|
* Catalog-product normalisation helpers — Phase 0 lift-and-shift of the
|
|
@@ -502,12 +507,12 @@ declare const TRIGGER_PLACEHOLDER = "Product Search";
|
|
|
502
507
|
/**
|
|
503
508
|
* Full path segment for the AI commerce chat SSE endpoint.
|
|
504
509
|
* Appended to the consumer-provided `chatBaseUrl`.
|
|
505
|
-
* Source: https://admin.tst.nuskin.ai/api/analytics/v1/
|
|
510
|
+
* Source: https://admin.tst.nuskin.ai/api/analytics/v1/embed
|
|
506
511
|
*/
|
|
507
|
-
declare const DEFAULT_AI_CHAT_BASE_URL = "https://admin.tst.nuskin.ai/api/analytics/v1/
|
|
512
|
+
declare const DEFAULT_AI_CHAT_BASE_URL = "https://admin.tst.nuskin.ai/api/analytics/v1/embed";
|
|
508
513
|
/** Default POST endpoint for creating an AI chat conversation. */
|
|
509
|
-
declare const DEFAULT_AI_CHAT_CONVERSATIONS_URL = "https://admin.tst.nuskin.ai/api/analytics/v1/
|
|
514
|
+
declare const DEFAULT_AI_CHAT_CONVERSATIONS_URL = "https://admin.tst.nuskin.ai/api/analytics/v1/embed/conversations";
|
|
510
515
|
/** Default POST endpoint for sending AI chat messages. */
|
|
511
|
-
declare const DEFAULT_AI_CHAT_MESSAGES_URL = "https://admin.tst.nuskin.ai/api/analytics/v1/
|
|
516
|
+
declare const DEFAULT_AI_CHAT_MESSAGES_URL = "https://admin.tst.nuskin.ai/api/analytics/v1/embed/messages";
|
|
512
517
|
|
|
513
518
|
export { CATALOG_SUGGESTIONS_PATH, type CatalogSuggestionItem, type ChatMessageResult, type ChatProduct, type ChatService, type ChatServiceOptions, DEBOUNCE_MS, DEFAULT_AI_CHAT_BASE_URL, DEFAULT_AI_CHAT_CONVERSATIONS_URL, DEFAULT_AI_CHAT_MESSAGES_URL, DEFAULT_SEARCH_PATH, DEFAULT_SUGGESTION_PAGE, DEFAULT_SUGGESTION_SIZE, type DidYouMeanItem, type GetMarketConfig, type LocaleParts, type LocationLike, MAX_VISIBLE_SUGGESTIONS, type MarketConfig, type ProductType, RECENT_SEARCHES_DEFAULT_LIMIT, RECENT_SEARCHES_PREFIX, SEARCH_PLACEHOLDER, STOREFRONT_SHOPPING_CONTEXT, type SearchChromeCopy, type SearchHistoryEntry, type SearchHistoryState, type SearchHistoryEntry as SearchHistoryStoreEntry, type SearchService, type SearchServiceOptions, type SuggestionOption, type SuggestionsResponse, TRIGGER_PLACEHOLDER, type UseSearchHistoryResult, type UseSearchSuggestionsOptions, type UseSearchSuggestionsResult, type UseVoiceSearchOptions, type UseVoiceSearchResult, createChatService, createSearchService, getImageFromProperty, getIngredientTerms, getSeeMoreResultsPayload, getVisibleSuggestions, isCartActionDisabled, isSellableProductStatus, isSuggestionDisabled, mapCatalogProductToSuggestion, normalizeDidYouMean, resolveApiGatewayPath, resolveSuggestionImageSrc, useSearchHistory, useSearchHistoryStore, useSearchSuggestions, useVoiceSearch };
|
package/dist/index.js
CHANGED
|
@@ -18,7 +18,7 @@ var DEBOUNCE_MS = 220;
|
|
|
18
18
|
var MAX_VISIBLE_SUGGESTIONS = 6;
|
|
19
19
|
var SEARCH_PLACEHOLDER = "Search by product name, ingredient, benefits, or SKU";
|
|
20
20
|
var TRIGGER_PLACEHOLDER = "Product Search";
|
|
21
|
-
var DEFAULT_AI_CHAT_BASE_URL = "https://admin.tst.nuskin.ai/api/analytics/v1/
|
|
21
|
+
var DEFAULT_AI_CHAT_BASE_URL = "https://admin.tst.nuskin.ai/api/analytics/v1/embed";
|
|
22
22
|
var DEFAULT_AI_CHAT_CONVERSATIONS_URL = `${DEFAULT_AI_CHAT_BASE_URL}/conversations`;
|
|
23
23
|
var DEFAULT_AI_CHAT_MESSAGES_URL = `${DEFAULT_AI_CHAT_BASE_URL}/messages`;
|
|
24
24
|
|
|
@@ -769,6 +769,19 @@ function findClosingFence(content, fromIndex) {
|
|
|
769
769
|
}
|
|
770
770
|
return -1;
|
|
771
771
|
}
|
|
772
|
+
function isRecord(value) {
|
|
773
|
+
return value !== null && typeof value === "object";
|
|
774
|
+
}
|
|
775
|
+
function getRenderProductListItems(event) {
|
|
776
|
+
if (event["type"] !== "render" || event["pattern"] !== "product_list") {
|
|
777
|
+
return [];
|
|
778
|
+
}
|
|
779
|
+
const data = event["data"];
|
|
780
|
+
if (!isRecord(data) || !Array.isArray(data["items"])) {
|
|
781
|
+
return [];
|
|
782
|
+
}
|
|
783
|
+
return data["items"].filter(isRecord);
|
|
784
|
+
}
|
|
772
785
|
function extractProductsFromMarkdown(content) {
|
|
773
786
|
const products = [];
|
|
774
787
|
const summaryParts = [];
|
|
@@ -797,7 +810,8 @@ function extractProductsFromMarkdown(content) {
|
|
|
797
810
|
if (Array.isArray(parsed)) {
|
|
798
811
|
products.push(...parsed);
|
|
799
812
|
}
|
|
800
|
-
} catch {
|
|
813
|
+
} catch (e) {
|
|
814
|
+
console.error("Failed to parse products block:", e);
|
|
801
815
|
}
|
|
802
816
|
summaryParts.push(content.slice(summaryCursor, start));
|
|
803
817
|
summaryCursor = end + MARKDOWN_CLOSING_FENCE.length;
|
|
@@ -810,8 +824,10 @@ function createChatService(options) {
|
|
|
810
824
|
const {
|
|
811
825
|
conversationsUrl = DEFAULT_AI_CHAT_CONVERSATIONS_URL,
|
|
812
826
|
messagesUrl = DEFAULT_AI_CHAT_MESSAGES_URL,
|
|
813
|
-
|
|
814
|
-
|
|
827
|
+
salesAiAppKey,
|
|
828
|
+
salesAiParentOrigin,
|
|
829
|
+
market,
|
|
830
|
+
language,
|
|
815
831
|
fetchImpl: fetchImplOption
|
|
816
832
|
} = options;
|
|
817
833
|
let fetchImpl;
|
|
@@ -824,22 +840,30 @@ function createChatService(options) {
|
|
|
824
840
|
throw new Error("ChatService: no fetch implementation available");
|
|
825
841
|
};
|
|
826
842
|
}
|
|
827
|
-
function buildHeaders(extra) {
|
|
843
|
+
function buildHeaders(extra, includeJsonContentType = true) {
|
|
828
844
|
const headers = {
|
|
829
|
-
"Content-Type": "application/json",
|
|
830
845
|
...extra
|
|
831
846
|
};
|
|
832
|
-
if (
|
|
833
|
-
|
|
834
|
-
|
|
847
|
+
if (includeJsonContentType) {
|
|
848
|
+
headers["Content-Type"] = "application/json";
|
|
849
|
+
}
|
|
850
|
+
const accessToken = typeof window !== "undefined" ? window.localStorage?.getItem("accessToken") : null;
|
|
851
|
+
if (accessToken) {
|
|
852
|
+
headers["Authorization"] = `Bearer ${accessToken}`;
|
|
853
|
+
}
|
|
854
|
+
if (salesAiAppKey) {
|
|
855
|
+
headers["X-Sales-AI-App-Key"] = salesAiAppKey;
|
|
856
|
+
}
|
|
857
|
+
if (salesAiParentOrigin) {
|
|
858
|
+
headers["X-Sales-AI-Parent-Origin"] = salesAiParentOrigin;
|
|
859
|
+
}
|
|
835
860
|
return headers;
|
|
836
861
|
}
|
|
837
862
|
return {
|
|
838
|
-
async createConversation(
|
|
863
|
+
async createConversation() {
|
|
839
864
|
const res = await fetchImpl(conversationsUrl, {
|
|
840
865
|
method: "POST",
|
|
841
|
-
headers: buildHeaders()
|
|
842
|
-
body: JSON.stringify({ title })
|
|
866
|
+
headers: buildHeaders(void 0, false)
|
|
843
867
|
});
|
|
844
868
|
if (!res.ok) {
|
|
845
869
|
throw new Error(
|
|
@@ -856,14 +880,26 @@ function createChatService(options) {
|
|
|
856
880
|
return id;
|
|
857
881
|
},
|
|
858
882
|
async sendMessage(conversationId, content, onChunk) {
|
|
883
|
+
const requestBody = {
|
|
884
|
+
conversation_id: conversationId,
|
|
885
|
+
content
|
|
886
|
+
};
|
|
887
|
+
if (market || language) {
|
|
888
|
+
requestBody.scope_context = {
|
|
889
|
+
market: market ?? "US",
|
|
890
|
+
language: language ?? "en"
|
|
891
|
+
};
|
|
892
|
+
}
|
|
893
|
+
requestBody.client_capabilities = {
|
|
894
|
+
patterns: {
|
|
895
|
+
product_list: [1],
|
|
896
|
+
follow_up: [1]
|
|
897
|
+
}
|
|
898
|
+
};
|
|
859
899
|
const res = await fetchImpl(messagesUrl, {
|
|
860
900
|
method: "POST",
|
|
861
|
-
headers: buildHeaders({ Accept: "
|
|
862
|
-
body: JSON.stringify(
|
|
863
|
-
conversation_id: conversationId,
|
|
864
|
-
content,
|
|
865
|
-
compact: false
|
|
866
|
-
})
|
|
901
|
+
headers: buildHeaders({ Accept: "text/event-stream" }),
|
|
902
|
+
body: JSON.stringify(requestBody)
|
|
867
903
|
});
|
|
868
904
|
if (!res.ok) {
|
|
869
905
|
throw new Error(
|
|
@@ -871,6 +907,7 @@ function createChatService(options) {
|
|
|
871
907
|
);
|
|
872
908
|
}
|
|
873
909
|
let accumulated = "";
|
|
910
|
+
const renderedProducts = [];
|
|
874
911
|
const parser = createParser({
|
|
875
912
|
onEvent(event) {
|
|
876
913
|
const data = event.data;
|
|
@@ -879,6 +916,9 @@ function createChatService(options) {
|
|
|
879
916
|
const parsed = JSON.parse(data);
|
|
880
917
|
const parsedType = parsed["type"];
|
|
881
918
|
const type = typeof parsedType === "string" ? parsedType : "";
|
|
919
|
+
renderedProducts.push(
|
|
920
|
+
...getRenderProductListItems(parsed)
|
|
921
|
+
);
|
|
882
922
|
if (type === "content" && typeof parsed["text"] === "string") {
|
|
883
923
|
const text = parsed["text"];
|
|
884
924
|
accumulated += text;
|
|
@@ -906,7 +946,12 @@ function createChatService(options) {
|
|
|
906
946
|
parser.feed(rawBody);
|
|
907
947
|
}
|
|
908
948
|
const { summary, products } = extractProductsFromMarkdown(accumulated);
|
|
909
|
-
|
|
949
|
+
const finalProducts = renderedProducts.length > 0 ? renderedProducts : products;
|
|
950
|
+
return {
|
|
951
|
+
summary,
|
|
952
|
+
products: finalProducts,
|
|
953
|
+
rawContent: accumulated
|
|
954
|
+
};
|
|
910
955
|
}
|
|
911
956
|
};
|
|
912
957
|
}
|
|
@@ -1653,6 +1698,7 @@ function getSpeechRecognition() {
|
|
|
1653
1698
|
}
|
|
1654
1699
|
function useVoiceSearch({
|
|
1655
1700
|
lang,
|
|
1701
|
+
onInterimResult,
|
|
1656
1702
|
onResult,
|
|
1657
1703
|
onError
|
|
1658
1704
|
}) {
|
|
@@ -1670,11 +1716,24 @@ function useVoiceSearch({
|
|
|
1670
1716
|
stop();
|
|
1671
1717
|
const rec = new SR();
|
|
1672
1718
|
rec.lang = lang ?? navigator.language ?? "en-US";
|
|
1673
|
-
rec.interimResults =
|
|
1719
|
+
rec.interimResults = true;
|
|
1674
1720
|
rec.maxAlternatives = 1;
|
|
1675
1721
|
rec.onresult = (event) => {
|
|
1676
|
-
|
|
1677
|
-
|
|
1722
|
+
let finalTranscript = "";
|
|
1723
|
+
let interimTranscript = "";
|
|
1724
|
+
const startIndex = event.resultIndex ?? 0;
|
|
1725
|
+
for (let index = startIndex; index < event.results.length; index += 1) {
|
|
1726
|
+
const result = event.results[index];
|
|
1727
|
+
const transcript = result?.[0]?.transcript ?? "";
|
|
1728
|
+
if (!transcript) continue;
|
|
1729
|
+
if (result?.isFinal) {
|
|
1730
|
+
finalTranscript += transcript;
|
|
1731
|
+
} else {
|
|
1732
|
+
interimTranscript += transcript;
|
|
1733
|
+
}
|
|
1734
|
+
}
|
|
1735
|
+
if (interimTranscript) onInterimResult?.(interimTranscript);
|
|
1736
|
+
if (finalTranscript) onResult(finalTranscript);
|
|
1678
1737
|
};
|
|
1679
1738
|
rec.onerror = (event) => {
|
|
1680
1739
|
onError?.(event);
|
|
@@ -1684,7 +1743,7 @@ function useVoiceSearch({
|
|
|
1684
1743
|
recognitionRef.current = rec;
|
|
1685
1744
|
rec.start();
|
|
1686
1745
|
setListening(true);
|
|
1687
|
-
}, [lang, onResult, onError, stop]);
|
|
1746
|
+
}, [lang, onInterimResult, onResult, onError, stop]);
|
|
1688
1747
|
return { listening, supported, start, stop };
|
|
1689
1748
|
}
|
|
1690
1749
|
|