@developer.notchatbot/webchat 1.5.2 → 1.6.0

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/types.d.ts CHANGED
@@ -142,6 +142,15 @@ export interface ChatWindowProps {
142
142
  isRated?: boolean;
143
143
  onRatingChange?: (isRated: boolean) => void;
144
144
  conversationId?: string;
145
+ /** Configurable auto-survey threshold from the backend; undefined = legacy default (2). */
146
+ surveyAfterUserMessages?: number;
147
+ /** Timestamp of the last manual survey request from Livechat; undefined = never requested. */
148
+ webchatSurveyRequestedAt?: number;
149
+ }
150
+ /** Survey-related conversation state forwarded from the Convex realtime subscription. */
151
+ export interface ConversationSurveyState {
152
+ surveyAfterUserMessages?: number;
153
+ webchatSurveyRequestedAt?: number;
145
154
  }
146
155
  export interface ChatHeaderProps {
147
156
  title: string;
@@ -1,5 +1,5 @@
1
1
  import { ConvexReactClient } from 'convex/react';
2
- import { Message } from '../types';
2
+ import { ConversationSurveyState, Message } from '../types';
3
3
  export interface ConvexConnectionData {
4
4
  client: ConvexReactClient;
5
5
  unsubscribe: (() => void) | null;
@@ -11,9 +11,10 @@ export interface ConvexConnectionData {
11
11
  * @param conversationId Conversation ID
12
12
  * @param onMessage Callback for new messages
13
13
  * @param onChatbotToggle Callback for chatbot activation changes
14
+ * @param onSurveyStateChange Callback for survey state changes (threshold + manual trigger)
14
15
  * @returns Promise that resolves to Convex connection data
15
16
  */
16
- export declare const initializeConvexConnection: (realtimeEndpoint: string, _chatbotUid: string, conversationId: string, onMessage: (message: Message) => void, onChatbotToggle?: (chatbotActivated: boolean) => void) => Promise<ConvexConnectionData>;
17
+ export declare const initializeConvexConnection: (realtimeEndpoint: string, _chatbotUid: string, conversationId: string, onMessage: (message: Message) => void, onChatbotToggle?: (chatbotActivated: boolean) => void, onSurveyStateChange?: (surveyState: ConversationSurveyState) => void) => Promise<ConvexConnectionData>;
17
18
  /**
18
19
  * Fetches initial conversation data with messages from Convex
19
20
  * @param realtimeEndpoint Realtime service deployment URL
@@ -0,0 +1,40 @@
1
+ /**
2
+ * Self-initialization from the bundle's own <script> URL.
3
+ *
4
+ * Used by the Tiendanube 1-click install (Scripts API): Tiendanube injects
5
+ * <script src="https://unpkg.com/...bundle.min.umd.cjs?apiKey=<uid>&s=<base64url>">
6
+ * and the bundle configures itself from those params — zero requests to the
7
+ * NotChatbot backend on page view. The `s` payload is built SERVER-SIDE when
8
+ * the script is (re)associated to the store, so this module only decodes it;
9
+ * it never derives styles on its own.
10
+ *
11
+ * ⚠️ CRITICAL BACKWARD COMPATIBILITY ⚠️
12
+ * Every existing GTM/manual customer loads this same bundle from @latest
13
+ * WITHOUT query params. For any src without `apiKey` this module MUST return
14
+ * null and MUST NOT throw — the bundle then behaves exactly as before
15
+ * (waiting for a manual WebChat.initialize). Keep every code path here
16
+ * defensive: a broken payload degrades to apiKey-only defaults, never to an
17
+ * error that could interfere with the bundle load.
18
+ */
19
+ /** Versioned payload carried in the `s` query param (base64url of its JSON). */
20
+ export interface StylesParamV1 {
21
+ v: 1;
22
+ /** Fully-resolved WebChatConfig (minus apiKey), built server-side. */
23
+ c: Record<string, unknown>;
24
+ /** CSS for window.injectWebChatCSS (button resize), or null. */
25
+ css: string | null;
26
+ }
27
+ export interface SelfInitPayload {
28
+ apiKey: string;
29
+ /** Resolved config from `s`, or null to initialize with defaults. */
30
+ config: Record<string, unknown> | null;
31
+ injectCss: string | null;
32
+ }
33
+ /** Encodes a styles payload to base64url. Exported for tests and tooling; production encoding lives server-side. */
34
+ export declare function encodeStylesParam(payload: StylesParamV1 | Record<string, unknown>): string;
35
+ /**
36
+ * Parses the bundle's own script src. Returns null unless the URL carries an
37
+ * `apiKey` query param (the self-init opt-in marker). A present-but-broken
38
+ * `s` param degrades to apiKey-only (default appearance) instead of failing.
39
+ */
40
+ export declare function parseSelfInitFromSrc(src: string): SelfInitPayload | null;
@@ -0,0 +1,30 @@
1
+ import { Message } from '../types';
2
+ /** Legacy hardcoded threshold, used when the backend does not send one. */
3
+ export declare const DEFAULT_SURVEY_AFTER_USER_MESSAGES = 2;
4
+ /**
5
+ * Resolves the configured auto-survey threshold.
6
+ * Falls back to the default when the backend does not expose the field yet
7
+ * or sends something unusable (non-number, NaN, zero/negative).
8
+ */
9
+ export declare const resolveSurveyThreshold: (value: unknown) => number;
10
+ /** Counts only messages sent by the end user (bot/employee ones don't count). */
11
+ export declare const countUserMessages: (messages: Message[]) => number;
12
+ /**
13
+ * Whether the survey should auto-open because the user reached the
14
+ * configured message threshold. Never true for already rated conversations.
15
+ */
16
+ export declare const shouldAutoShowSurvey: (messages: Message[], surveyAfterUserMessages: number | undefined, isRated: boolean) => boolean;
17
+ /**
18
+ * Whether a manual survey request (`webchatSurveyRequestedAt`, a timestamp
19
+ * written by an agent from Livechat) is a new, still unhandled trigger.
20
+ * Comparing against the last handled value — not just presence — keeps
21
+ * re-renders and Convex reconnections from re-opening the survey for the
22
+ * same request, while a fresh timestamp triggers it again.
23
+ *
24
+ * Deliberately NOT gated on `isRated`: a manual request fired after a rating
25
+ * re-opens the survey so the agent can re-validate the experience (the new
26
+ * rating overwrites the previous one server-side). Stale requests can't leak
27
+ * across reloads because the backend clears `webchatSurveyRequestedAt` when a
28
+ * rating is submitted — a present timestamp is always a pending ask.
29
+ */
30
+ export declare const isNewSurveyRequest: (requestedAt: number | undefined, lastHandledRequestedAt: number | undefined) => boolean;