@chatlychat/react-native 0.0.0-stage → 0.1.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.
Files changed (114) hide show
  1. package/README.md +208 -2
  2. package/dist/ChatlyProvider.d.ts +69 -0
  3. package/dist/ChatlyProvider.d.ts.map +1 -0
  4. package/dist/ChatlyProvider.js +146 -0
  5. package/dist/ChatlyProvider.js.map +1 -0
  6. package/dist/ChatlyWidget.d.ts +15 -0
  7. package/dist/ChatlyWidget.d.ts.map +1 -0
  8. package/dist/ChatlyWidget.js +122 -0
  9. package/dist/ChatlyWidget.js.map +1 -0
  10. package/dist/blocks/money.d.ts +56 -0
  11. package/dist/blocks/money.d.ts.map +1 -0
  12. package/dist/blocks/money.js +82 -0
  13. package/dist/blocks/money.js.map +1 -0
  14. package/dist/blocks/money.parity.spec.d.ts +2 -0
  15. package/dist/blocks/money.parity.spec.d.ts.map +1 -0
  16. package/dist/blocks/money.parity.spec.js +87 -0
  17. package/dist/blocks/money.parity.spec.js.map +1 -0
  18. package/dist/blocks/read-envelope.d.ts +15 -0
  19. package/dist/blocks/read-envelope.d.ts.map +1 -0
  20. package/dist/blocks/read-envelope.js +196 -0
  21. package/dist/blocks/read-envelope.js.map +1 -0
  22. package/dist/blocks/read-envelope.parity.spec.d.ts +2 -0
  23. package/dist/blocks/read-envelope.parity.spec.d.ts.map +1 -0
  24. package/dist/blocks/read-envelope.parity.spec.js +146 -0
  25. package/dist/blocks/read-envelope.parity.spec.js.map +1 -0
  26. package/dist/blocks/types.d.ts +171 -0
  27. package/dist/blocks/types.d.ts.map +1 -0
  28. package/dist/blocks/types.js +3 -0
  29. package/dist/blocks/types.js.map +1 -0
  30. package/dist/client/RealtimeClient.d.ts +29 -0
  31. package/dist/client/RealtimeClient.d.ts.map +1 -0
  32. package/dist/client/RealtimeClient.js +113 -0
  33. package/dist/client/RealtimeClient.js.map +1 -0
  34. package/dist/client/RealtimeClient.spec.d.ts +2 -0
  35. package/dist/client/RealtimeClient.spec.d.ts.map +1 -0
  36. package/dist/client/RealtimeClient.spec.js +123 -0
  37. package/dist/client/RealtimeClient.spec.js.map +1 -0
  38. package/dist/client/RestClient.d.ts +160 -0
  39. package/dist/client/RestClient.d.ts.map +1 -0
  40. package/dist/client/RestClient.js +395 -0
  41. package/dist/client/RestClient.js.map +1 -0
  42. package/dist/client/RestClient.spec.d.ts +2 -0
  43. package/dist/client/RestClient.spec.d.ts.map +1 -0
  44. package/dist/client/RestClient.spec.js +267 -0
  45. package/dist/client/RestClient.spec.js.map +1 -0
  46. package/dist/client/types.d.ts +148 -0
  47. package/dist/client/types.d.ts.map +1 -0
  48. package/dist/client/types.js +14 -0
  49. package/dist/client/types.js.map +1 -0
  50. package/dist/components/Composer.d.ts +35 -0
  51. package/dist/components/Composer.d.ts.map +1 -0
  52. package/dist/components/Composer.js +180 -0
  53. package/dist/components/Composer.js.map +1 -0
  54. package/dist/components/HelpCenter.d.ts +13 -0
  55. package/dist/components/HelpCenter.d.ts.map +1 -0
  56. package/dist/components/HelpCenter.js +96 -0
  57. package/dist/components/HelpCenter.js.map +1 -0
  58. package/dist/components/MessageBlocks.d.ts +41 -0
  59. package/dist/components/MessageBlocks.d.ts.map +1 -0
  60. package/dist/components/MessageBlocks.js +167 -0
  61. package/dist/components/MessageBlocks.js.map +1 -0
  62. package/dist/components/MessageBubble.d.ts +14 -0
  63. package/dist/components/MessageBubble.d.ts.map +1 -0
  64. package/dist/components/MessageBubble.js +87 -0
  65. package/dist/components/MessageBubble.js.map +1 -0
  66. package/dist/components/MessageBubble.spec.d.ts +2 -0
  67. package/dist/components/MessageBubble.spec.d.ts.map +1 -0
  68. package/dist/components/MessageBubble.spec.js +207 -0
  69. package/dist/components/MessageBubble.spec.js.map +1 -0
  70. package/dist/components/MessageCanvas.d.ts +39 -0
  71. package/dist/components/MessageCanvas.d.ts.map +1 -0
  72. package/dist/components/MessageCanvas.js +144 -0
  73. package/dist/components/MessageCanvas.js.map +1 -0
  74. package/dist/components/MessageCanvas.spec.d.ts +2 -0
  75. package/dist/components/MessageCanvas.spec.d.ts.map +1 -0
  76. package/dist/components/MessageCanvas.spec.js +142 -0
  77. package/dist/components/MessageCanvas.spec.js.map +1 -0
  78. package/dist/components/MessagesList.d.ts +8 -0
  79. package/dist/components/MessagesList.d.ts.map +1 -0
  80. package/dist/components/MessagesList.js +58 -0
  81. package/dist/components/MessagesList.js.map +1 -0
  82. package/dist/index.d.ts +48 -0
  83. package/dist/index.d.ts.map +1 -0
  84. package/dist/index.js +35 -0
  85. package/dist/index.js.map +1 -0
  86. package/dist/push/registerPushToken.d.ts +12 -0
  87. package/dist/push/registerPushToken.d.ts.map +1 -0
  88. package/dist/push/registerPushToken.js +32 -0
  89. package/dist/push/registerPushToken.js.map +1 -0
  90. package/dist/storage/TokenStore.d.ts +53 -0
  91. package/dist/storage/TokenStore.d.ts.map +1 -0
  92. package/dist/storage/TokenStore.js +89 -0
  93. package/dist/storage/TokenStore.js.map +1 -0
  94. package/dist/test/react-native-dom.d.ts +97 -0
  95. package/dist/test/react-native-dom.d.ts.map +1 -0
  96. package/dist/test/react-native-dom.js +155 -0
  97. package/dist/test/react-native-dom.js.map +1 -0
  98. package/dist/test/react-native-dom.spec.d.ts +2 -0
  99. package/dist/test/react-native-dom.spec.d.ts.map +1 -0
  100. package/dist/test/react-native-dom.spec.js +83 -0
  101. package/dist/test/react-native-dom.spec.js.map +1 -0
  102. package/dist/theme/ChatlyTheme.d.ts +37 -0
  103. package/dist/theme/ChatlyTheme.d.ts.map +1 -0
  104. package/dist/theme/ChatlyTheme.js +2 -0
  105. package/dist/theme/ChatlyTheme.js.map +1 -0
  106. package/dist/theme/defaultTheme.d.ts +7 -0
  107. package/dist/theme/defaultTheme.d.ts.map +1 -0
  108. package/dist/theme/defaultTheme.js +37 -0
  109. package/dist/theme/defaultTheme.js.map +1 -0
  110. package/dist/useChatly.d.ts +3 -0
  111. package/dist/useChatly.d.ts.map +1 -0
  112. package/dist/useChatly.js +10 -0
  113. package/dist/useChatly.js.map +1 -0
  114. package/package.json +50 -4
@@ -0,0 +1,171 @@
1
+ /**
2
+ * The rich-block vocabulary, restated for the published package.
3
+ *
4
+ * Mirrors `packages/shared/src/widget-blocks/schema.ts` (which is zod, and
5
+ * zod is not a dependency of this package) and `types.ts` beside it. The
6
+ * canonical definition is there; `read-envelope.parity.spec.ts` asserts this
7
+ * reader accepts and refuses exactly what the shared one does, and
8
+ * `check-block-renderer-parity.mjs` fails the build if a block type is added
9
+ * to the schema and not handled here.
10
+ *
11
+ * Why not import: `@livechat/shared` is `private: true` — see the note at the
12
+ * top of `blocks/money.ts`.
13
+ */
14
+ import type { Money } from './money';
15
+ /** Bumped only on a breaking change to the envelope itself. */
16
+ export declare const BLOCK_PROTOCOL_VERSION = 1;
17
+ /**
18
+ * What a button does.
19
+ *
20
+ * `host_event` is the one the native app exists for: it does nothing here and
21
+ * is handed to the app's own `onAction`, which is what runs Stripe, opens a
22
+ * native screen, or adds to a cart with the buyer's real session. See
23
+ * `ChatlyProviderProps.onAction`.
24
+ */
25
+ export type WidgetAction = {
26
+ readonly kind: 'url';
27
+ readonly label: string;
28
+ readonly href: string;
29
+ readonly style?: string;
30
+ } | {
31
+ readonly kind: 'postback';
32
+ readonly label: string;
33
+ readonly value: string;
34
+ readonly payload?: Record<string, unknown>;
35
+ readonly silent?: boolean;
36
+ readonly style?: string;
37
+ } | {
38
+ readonly kind: 'host_event';
39
+ readonly label: string;
40
+ readonly event: string;
41
+ readonly data?: Record<string, unknown>;
42
+ readonly id?: string;
43
+ readonly style?: string;
44
+ } | {
45
+ readonly kind: 'step';
46
+ readonly label: string;
47
+ readonly canvasId: string;
48
+ readonly params?: Record<string, unknown>;
49
+ readonly style?: string;
50
+ } | {
51
+ readonly kind: 'copy';
52
+ readonly label: string;
53
+ readonly text: string;
54
+ readonly style?: string;
55
+ };
56
+ export interface WidgetCard {
57
+ readonly id?: string;
58
+ readonly title: string;
59
+ readonly subtitle?: string;
60
+ readonly image?: string;
61
+ readonly badge?: string;
62
+ readonly price?: Money;
63
+ readonly fields?: ReadonlyArray<{
64
+ readonly label: string;
65
+ readonly value: string;
66
+ }>;
67
+ readonly actions?: readonly WidgetAction[];
68
+ }
69
+ export type WidgetBlock = {
70
+ readonly type: 'text';
71
+ readonly markdown: string;
72
+ readonly id?: string;
73
+ } | {
74
+ readonly type: 'media';
75
+ readonly kind: 'image' | 'video';
76
+ readonly url: string;
77
+ readonly alt: string;
78
+ readonly id?: string;
79
+ } | {
80
+ readonly type: 'fields';
81
+ readonly items: ReadonlyArray<{
82
+ readonly label: string;
83
+ readonly value: string;
84
+ }>;
85
+ readonly id?: string;
86
+ } | ({
87
+ readonly type: 'card';
88
+ } & WidgetCard) | {
89
+ readonly type: 'card_grid';
90
+ readonly cards: readonly WidgetCard[];
91
+ readonly layout?: 'grid' | 'carousel';
92
+ readonly id?: string;
93
+ } | {
94
+ readonly type: 'actions';
95
+ readonly actions: readonly WidgetAction[];
96
+ readonly id?: string;
97
+ } | {
98
+ readonly type: 'quick_replies';
99
+ readonly options: ReadonlyArray<{
100
+ readonly label: string;
101
+ readonly value: string;
102
+ }>;
103
+ readonly id?: string;
104
+ } | {
105
+ readonly type: 'status';
106
+ readonly id: string;
107
+ readonly text: string;
108
+ readonly state?: 'running' | 'done' | 'failed';
109
+ } | {
110
+ readonly type: 'divider';
111
+ readonly id?: string;
112
+ };
113
+ export interface WidgetBlocksEnvelope {
114
+ readonly v: 1;
115
+ readonly blocks: readonly WidgetBlock[];
116
+ }
117
+ export type CanvasField = {
118
+ readonly type: 'text' | 'email' | 'tel' | 'number';
119
+ readonly name: string;
120
+ readonly label: string;
121
+ readonly required?: boolean;
122
+ readonly placeholder?: string;
123
+ readonly value?: string;
124
+ } | {
125
+ readonly type: 'select';
126
+ readonly name: string;
127
+ readonly label: string;
128
+ readonly required?: boolean;
129
+ readonly options: ReadonlyArray<{
130
+ readonly label: string;
131
+ readonly value: string;
132
+ }>;
133
+ readonly value?: string;
134
+ } | {
135
+ readonly type: 'checkbox';
136
+ readonly name: string;
137
+ readonly label: string;
138
+ readonly required?: boolean;
139
+ readonly value?: boolean;
140
+ };
141
+ export interface CanvasAction {
142
+ readonly id: string;
143
+ readonly kind: 'submit' | 'cancel';
144
+ readonly label: string;
145
+ readonly style?: 'primary' | 'secondary' | 'danger';
146
+ }
147
+ export interface WidgetCanvas {
148
+ readonly v: 1;
149
+ readonly canvasId: string;
150
+ readonly title?: string;
151
+ readonly blocks?: readonly WidgetBlock[];
152
+ readonly fields?: readonly CanvasField[];
153
+ readonly actions?: readonly CanvasAction[];
154
+ readonly state?: string;
155
+ /**
156
+ * Tier 3 — an integrator's own page in a sandboxed frame.
157
+ *
158
+ * Deliberately NOT rendered by this package. A WebView inside a native chat
159
+ * is the thing the spec asked to avoid ("without a WebView"), and a sandbox
160
+ * attribute is a browser concept with no React Native equivalent — so an
161
+ * app frame here would be an iframe's security model re-implemented by
162
+ * hand. The renderer shows the app's `title` and a note instead, and the
163
+ * integrator handles it natively if they want it.
164
+ */
165
+ readonly app?: {
166
+ readonly url: string;
167
+ readonly title?: string;
168
+ readonly height?: number;
169
+ };
170
+ }
171
+ //# sourceMappingURL=types.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"types.d.ts","sourceRoot":"","sources":["../../src/blocks/types.ts"],"names":[],"mappings":"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"}
@@ -0,0 +1,3 @@
1
+ /** Bumped only on a breaking change to the envelope itself. */
2
+ export const BLOCK_PROTOCOL_VERSION = 1;
3
+ //# sourceMappingURL=types.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"types.js","sourceRoot":"","sources":["../../src/blocks/types.ts"],"names":[],"mappings":"AAeA,+DAA+D;AAC/D,MAAM,CAAC,MAAM,sBAAsB,GAAG,CAAC,CAAC"}
@@ -0,0 +1,29 @@
1
+ /**
2
+ * Socket.IO-based realtime client. Subscribes to the contact's conversation
3
+ * channels and re-emits typed `RealtimeEnvelope` events.
4
+ *
5
+ * Reconnection + replay is handled by socket.io's built-in backoff; we pass
6
+ * `lastEventId` on subscribe so the server can replay missed envelopes
7
+ * (durable-then-deliver, per CLAUDE.md realtime conventions).
8
+ */
9
+ import type { ChatlyConfig, MessageCreatedPayload, RealtimeEnvelope, RealtimeEventType, SessionState } from './types';
10
+ type Listener<P = unknown> = (envelope: RealtimeEnvelope<P>) => void;
11
+ export declare class RealtimeClient {
12
+ private socket;
13
+ private readonly url;
14
+ private readonly listeners;
15
+ private lastEventId;
16
+ private session;
17
+ private subscribedChannels;
18
+ constructor(config: ChatlyConfig);
19
+ connect(session: SessionState, token: string): void;
20
+ disconnect(): void;
21
+ subscribe(channels: string[]): void;
22
+ on<P = unknown>(type: RealtimeEventType, listener: Listener<P>): () => void;
23
+ onMessageCreated(listener: Listener<MessageCreatedPayload>): () => void;
24
+ private dispatch;
25
+ private resubscribe;
26
+ private sendSubscribe;
27
+ }
28
+ export {};
29
+ //# sourceMappingURL=RealtimeClient.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"RealtimeClient.d.ts","sourceRoot":"","sources":["../../src/client/RealtimeClient.ts"],"names":[],"mappings":"AAAA;;;;;;;GAOG;AAIH,OAAO,KAAK,EACV,YAAY,EACZ,qBAAqB,EACrB,gBAAgB,EAChB,iBAAiB,EACjB,YAAY,EACb,MAAM,SAAS,CAAC;AAEjB,KAAK,QAAQ,CAAC,CAAC,GAAG,OAAO,IAAI,CAAC,QAAQ,EAAE,gBAAgB,CAAC,CAAC,CAAC,KAAK,IAAI,CAAC;AAcrE,qBAAa,cAAc;IACzB,OAAO,CAAC,MAAM,CAAuB;IACrC,OAAO,CAAC,QAAQ,CAAC,GAAG,CAAS;IAC7B,OAAO,CAAC,QAAQ,CAAC,SAAS,CAA+C;IACzE,OAAO,CAAC,WAAW,CAAuB;IAC1C,OAAO,CAAC,OAAO,CAA6B;IAC5C,OAAO,CAAC,kBAAkB,CAAgB;gBAEvB,MAAM,EAAE,YAAY;IAMhC,OAAO,CAAC,OAAO,EAAE,YAAY,EAAE,KAAK,EAAE,MAAM,GAAG,IAAI;IAsBnD,UAAU,IAAI,IAAI;IAQlB,SAAS,CAAC,QAAQ,EAAE,MAAM,EAAE,GAAG,IAAI;IAOnC,EAAE,CAAC,CAAC,GAAG,OAAO,EAAE,IAAI,EAAE,iBAAiB,EAAE,QAAQ,EAAE,QAAQ,CAAC,CAAC,CAAC,GAAG,MAAM,IAAI;IAY3E,gBAAgB,CAAC,QAAQ,EAAE,QAAQ,CAAC,qBAAqB,CAAC,GAAG,MAAM,IAAI;IAI9E,OAAO,CAAC,QAAQ;IAgBhB,OAAO,CAAC,WAAW;IAMnB,OAAO,CAAC,aAAa;CAatB"}
@@ -0,0 +1,113 @@
1
+ /**
2
+ * Socket.IO-based realtime client. Subscribes to the contact's conversation
3
+ * channels and re-emits typed `RealtimeEnvelope` events.
4
+ *
5
+ * Reconnection + replay is handled by socket.io's built-in backoff; we pass
6
+ * `lastEventId` on subscribe so the server can replay missed envelopes
7
+ * (durable-then-deliver, per CLAUDE.md realtime conventions).
8
+ */
9
+ import { io } from 'socket.io-client';
10
+ /**
11
+ * Socket.IO channel names, as the gateway actually speaks them.
12
+ *
13
+ * Both of these were `'envelope'`, which matches nothing the server does:
14
+ * `apps/realtime/src/gateway.ts` EMITS on `'event'` and LISTENS on
15
+ * `'subscribe'`. So this client received nothing and its subscribe frame was
16
+ * never heard — the whole realtime surface of the React Native SDK was inert,
17
+ * silently, for every integrator.
18
+ */
19
+ const INBOUND_EVENT_CHANNEL = 'event';
20
+ const SUBSCRIBE_CHANNEL = 'subscribe';
21
+ export class RealtimeClient {
22
+ constructor(config) {
23
+ this.socket = null;
24
+ this.listeners = new Map();
25
+ this.lastEventId = null;
26
+ this.session = null;
27
+ this.subscribedChannels = [];
28
+ const host = config.realtimeHost ?? config.apiHost ?? 'api.chatly.com';
29
+ const scheme = config.secure === false ? 'ws' : 'wss';
30
+ this.url = `${scheme}://${host}`;
31
+ }
32
+ connect(session, token) {
33
+ if (this.socket !== null) {
34
+ return;
35
+ }
36
+ this.session = session;
37
+ this.socket = io(this.url, {
38
+ transports: ['websocket'],
39
+ auth: { token, workspaceId: session.workspaceId, contactId: session.contactId },
40
+ reconnection: true,
41
+ reconnectionDelay: 1000,
42
+ reconnectionDelayMax: 10000,
43
+ });
44
+ this.socket.on('connect', () => {
45
+ this.resubscribe();
46
+ });
47
+ this.socket.on(INBOUND_EVENT_CHANNEL, (raw) => {
48
+ this.dispatch(raw);
49
+ });
50
+ }
51
+ disconnect() {
52
+ if (this.socket !== null) {
53
+ this.socket.removeAllListeners();
54
+ this.socket.disconnect();
55
+ this.socket = null;
56
+ }
57
+ }
58
+ subscribe(channels) {
59
+ this.subscribedChannels = Array.from(new Set([...this.subscribedChannels, ...channels]));
60
+ if (this.socket?.connected === true) {
61
+ this.sendSubscribe(channels);
62
+ }
63
+ }
64
+ on(type, listener) {
65
+ let bucket = this.listeners.get(type);
66
+ if (bucket === undefined) {
67
+ bucket = new Set();
68
+ this.listeners.set(type, bucket);
69
+ }
70
+ bucket.add(listener);
71
+ return () => {
72
+ bucket?.delete(listener);
73
+ };
74
+ }
75
+ onMessageCreated(listener) {
76
+ return this.on('message.created', listener);
77
+ }
78
+ dispatch(envelope) {
79
+ if (envelope?.id !== undefined) {
80
+ this.lastEventId = envelope.id;
81
+ }
82
+ const bucket = this.listeners.get(envelope.type);
83
+ if (bucket !== undefined) {
84
+ for (const listener of bucket) {
85
+ try {
86
+ listener(envelope);
87
+ }
88
+ catch {
89
+ // Listener errors must not break the dispatch loop.
90
+ }
91
+ }
92
+ }
93
+ }
94
+ resubscribe() {
95
+ if (this.subscribedChannels.length > 0) {
96
+ this.sendSubscribe(this.subscribedChannels);
97
+ }
98
+ }
99
+ sendSubscribe(channels) {
100
+ if (this.socket === null || this.session === null) {
101
+ return;
102
+ }
103
+ // The gateway parses this with `subscribePayloadSchema`, which is the BARE
104
+ // payload — `{ channels, lastEventId? }`. It was being wrapped in a
105
+ // RealtimeEnvelope, so even on the right channel the parse would have
106
+ // failed and answered `validation_failed`.
107
+ this.socket.emit(SUBSCRIBE_CHANNEL, {
108
+ channels,
109
+ ...(this.lastEventId !== null ? { lastEventId: this.lastEventId } : {}),
110
+ });
111
+ }
112
+ }
113
+ //# sourceMappingURL=RealtimeClient.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"RealtimeClient.js","sourceRoot":"","sources":["../../src/client/RealtimeClient.ts"],"names":[],"mappings":"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"}
@@ -0,0 +1,2 @@
1
+ export {};
2
+ //# sourceMappingURL=RealtimeClient.spec.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"RealtimeClient.spec.d.ts","sourceRoot":"","sources":["../../src/client/RealtimeClient.spec.ts"],"names":[],"mappings":""}
@@ -0,0 +1,123 @@
1
+ /**
2
+ * The React Native SDK's realtime wire protocol.
3
+ *
4
+ * Every channel name here was wrong, so the whole surface was inert — for
5
+ * every integrator, silently:
6
+ *
7
+ * - it LISTENED on 'envelope'; the gateway EMITS on 'event', so nothing
8
+ * ever arrived;
9
+ * - it EMITTED subscribe on 'envelope'; the gateway LISTENS on 'subscribe',
10
+ * so no subscription was ever registered;
11
+ * - it wrapped the subscribe payload in a RealtimeEnvelope; the gateway
12
+ * parses the BARE `{ channels, lastEventId? }` with `subscribePayloadSchema`,
13
+ * so even on the right channel it would have answered validation_failed.
14
+ *
15
+ * Nothing failed loudly. The socket connected, the SDK reported itself
16
+ * healthy, and no message ever appeared.
17
+ *
18
+ * These pin the protocol against the server's own definitions.
19
+ */
20
+ import { describe, expect, it, vi } from 'vitest';
21
+ const emitted = [];
22
+ const handlers = new Map();
23
+ vi.mock('socket.io-client', () => ({
24
+ io: () => ({
25
+ // `subscribe()` gates on `socket.connected`, exactly as socket.io-client
26
+ // exposes it — a mock without this silently emits nothing.
27
+ connected: true,
28
+ on: (channel, fn) => {
29
+ handlers.set(channel, fn);
30
+ },
31
+ emit: (channel, payload) => {
32
+ emitted.push({ channel, payload });
33
+ },
34
+ disconnect: vi.fn(),
35
+ close: vi.fn(),
36
+ }),
37
+ }));
38
+ const { RealtimeClient } = await import('./RealtimeClient.js');
39
+ const SESSION = { workspaceId: 'ws-1', contactId: 'c-1' };
40
+ function connected() {
41
+ emitted.length = 0;
42
+ handlers.clear();
43
+ const c = new RealtimeClient({ apiHost: 'api.test' });
44
+ c.connect(SESSION, 'tok');
45
+ return c;
46
+ }
47
+ describe('inbound channel', () => {
48
+ it('listens on the channel the gateway emits — "event"', () => {
49
+ connected();
50
+ expect(handlers.has('event')).toBe(true);
51
+ });
52
+ it('no longer listens on "envelope", which the server never emits', () => {
53
+ connected();
54
+ expect(handlers.has('envelope')).toBe(false);
55
+ });
56
+ it('delivers a received envelope to a subscriber', () => {
57
+ const c = connected();
58
+ const seen = [];
59
+ c.on('message.created', (e) => void seen.push(e));
60
+ handlers.get('event')?.({
61
+ v: 1,
62
+ type: 'message.created',
63
+ id: '01000000-0000-7000-8000-000000000001',
64
+ ts: Date.now(),
65
+ workspace_id: 'ws-1',
66
+ payload: { body: 'hi' },
67
+ });
68
+ expect(seen).toHaveLength(1);
69
+ });
70
+ });
71
+ describe('subscribe frame', () => {
72
+ it('emits on "subscribe", the channel the gateway listens on', () => {
73
+ const c = connected();
74
+ c.subscribe(['conversation:1']);
75
+ expect(emitted.map((e) => e.channel)).toContain('subscribe');
76
+ });
77
+ it('never emits on "envelope"', () => {
78
+ const c = connected();
79
+ c.subscribe(['conversation:1']);
80
+ expect(emitted.map((e) => e.channel)).not.toContain('envelope');
81
+ });
82
+ it('sends the BARE payload the server parses, not an envelope', () => {
83
+ const c = connected();
84
+ c.subscribe(['conversation:1']);
85
+ const frame = emitted.find((e) => e.channel === 'subscribe')?.payload;
86
+ expect(frame['channels']).toEqual(['conversation:1']);
87
+ // An envelope would carry these; the schema rejects unknown top-level keys.
88
+ expect(frame['v']).toBeUndefined();
89
+ expect(frame['type']).toBeUndefined();
90
+ expect(frame['workspace_id']).toBeUndefined();
91
+ });
92
+ it('omits lastEventId until something has actually been received', () => {
93
+ const c = connected();
94
+ c.subscribe(['conversation:1']);
95
+ const frame = emitted.find((e) => e.channel === 'subscribe')?.payload;
96
+ expect('lastEventId' in frame).toBe(false);
97
+ });
98
+ it('replays from the last envelope id once one has arrived', () => {
99
+ // The cursor must be a real server-issued uuidv7 — the client used to
100
+ // mint its own id, which the server cannot resolve.
101
+ const c = connected();
102
+ const id = '01000000-0000-7000-8000-0000000000ab';
103
+ handlers.get('event')?.({
104
+ v: 1,
105
+ type: 'message.created',
106
+ id,
107
+ ts: Date.now(),
108
+ workspace_id: 'ws-1',
109
+ payload: {},
110
+ });
111
+ c.subscribe(['conversation:1']);
112
+ const frame = emitted.find((e) => e.channel === 'subscribe')?.payload;
113
+ expect(frame['lastEventId']).toBe(id);
114
+ });
115
+ it('re-subscribes on reconnect', () => {
116
+ const c = connected();
117
+ c.subscribe(['conversation:1']);
118
+ emitted.length = 0;
119
+ handlers.get('connect')?.(undefined);
120
+ expect(emitted.filter((e) => e.channel === 'subscribe')).toHaveLength(1);
121
+ });
122
+ });
123
+ //# sourceMappingURL=RealtimeClient.spec.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"RealtimeClient.spec.js","sourceRoot":"","sources":["../../src/client/RealtimeClient.spec.ts"],"names":[],"mappings":"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"}
@@ -0,0 +1,160 @@
1
+ /**
2
+ * Thin wrapper around the widget REST surface (see `apps/widget/src/client.ts`).
3
+ *
4
+ * All write endpoints accept the `publicId` + `visitorToken` in the JSON body.
5
+ * The visitor token is persisted via `TokenStore` and rotated whenever
6
+ * `/v1/widget/init` returns a fresh one.
7
+ */
8
+ import type { Attachment, ChatlyConfig, ChatlyIdentity, ConversationSummary, InitResponse, KbArticle, KbResult, MessageRow, StartResponse } from './types';
9
+ export declare class RestClient {
10
+ private readonly apiUrl;
11
+ private readonly publicId;
12
+ private readonly tokenStore;
13
+ private readonly identityStore;
14
+ private tokenCache;
15
+ /** `undefined` = not yet read from disk; `null` = read, nothing stored. */
16
+ private identityCache;
17
+ constructor(config: ChatlyConfig);
18
+ get baseUrl(): string;
19
+ getToken(): Promise<string | null>;
20
+ /**
21
+ * Forget this device's session entirely. Backs `logout()`.
22
+ *
23
+ * Drops the remembered identity too: after a logout, a stale-session
24
+ * recovery must NOT quietly re-identify as the person who just signed out.
25
+ */
26
+ clearToken(): Promise<void>;
27
+ /** Drop only the session credential, keeping the remembered identity so a
28
+ * recovery can replay it. */
29
+ private dropToken;
30
+ /**
31
+ * The identity to replay after the server refuses a stale session.
32
+ *
33
+ * Only offered when we hold BOTH an external id and its hash — mirroring
34
+ * `rememberedIdentity()` in `apps/widget/src/client.ts`. On a channel with
35
+ * identity verification enabled a claim without a hash is refused, and on a
36
+ * channel without it a legacy token is still accepted, so an unverifiable
37
+ * replay could only ever turn one refusal into two. Without both, the SDK
38
+ * re-inits anonymously and history returns as soon as the host app calls
39
+ * `identify()` again.
40
+ */
41
+ private rememberedIdentity;
42
+ init(identity?: ChatlyIdentity): Promise<InitResponse>;
43
+ start(body: string, attachments?: Attachment[]): Promise<StartResponse>;
44
+ reply(conversationId: string, body: string, attachments?: Attachment[]): Promise<unknown>;
45
+ /**
46
+ * A card's `postback` action: a reply the bot reads, optionally invisible.
47
+ *
48
+ * `silent` is what makes a filter chip work — the agent hears "under_50"
49
+ * and the shopper does not see their own tap echoed as a message bubble.
50
+ * It is a separate method rather than an option on `reply` because the two
51
+ * differ in whether anything renders.
52
+ */
53
+ postback(conversationId: string, input: {
54
+ value: string;
55
+ payload?: Record<string, unknown>;
56
+ silent?: boolean;
57
+ }): Promise<unknown>;
58
+ /**
59
+ * Report what the APP did about a `host_event` card action.
60
+ *
61
+ * This is the other half of the one feature a native SDK exists for. A card
62
+ * saying "Pay $48.20" cannot run Stripe from inside a chat library — the
63
+ * app does it, with the buyer's real session and a native payment sheet —
64
+ * and then has to say what happened, or the shopper is left looking at a
65
+ * card with nothing under it and the bot asks again.
66
+ *
67
+ * `text` appends a visible line under the card. `status: 'failed'` with no
68
+ * text is legitimate: the bot is told, and the shopper sees the card
69
+ * unchanged rather than an error they can do nothing about.
70
+ */
71
+ reportAction(conversationId: string, input: {
72
+ messageId: string;
73
+ actionId: string;
74
+ status: 'done' | 'failed';
75
+ text?: string;
76
+ data?: Record<string, unknown>;
77
+ }): Promise<{
78
+ blocks: unknown;
79
+ deliveredMessageId: string;
80
+ }>;
81
+ /** A `step` card action: ask for the first step of a flow and post it. */
82
+ requestCanvasStep(conversationId: string, canvasId: string, params?: Record<string, unknown>): Promise<{
83
+ messageId: string;
84
+ canvas: unknown;
85
+ hostEvent?: unknown;
86
+ }>;
87
+ /**
88
+ * Submit a canvas step.
89
+ *
90
+ * `errors` comes back keyed by field name when the server refuses, and the
91
+ * canvas comes back either way — a refused submission returns the SAME
92
+ * canvas with messages on it, which is why the renderer replaces what it
93
+ * holds rather than keeping its own copy.
94
+ */
95
+ submitCanvas(conversationId: string, input: {
96
+ messageId: string;
97
+ actionId: string;
98
+ values: Record<string, unknown>;
99
+ }): Promise<{
100
+ canvas: unknown;
101
+ errors: Record<string, string>;
102
+ hostEvent?: unknown;
103
+ }>;
104
+ /**
105
+ * Uploads raw bytes to the public widget upload endpoint and returns the
106
+ * persisted [Attachment] reference. The widget surface accepts only JSON,
107
+ * so the bytes are base64-encoded before transport. The server enforces
108
+ * the size cap — clients must not pre-check.
109
+ */
110
+ uploadAttachment(input: {
111
+ bytes: Uint8Array;
112
+ filename: string;
113
+ mimeType: string;
114
+ }): Promise<Attachment>;
115
+ listConversations(limit?: number): Promise<{
116
+ conversations: ConversationSummary[];
117
+ }>;
118
+ listMessages(conversationId: string, limit?: number): Promise<{
119
+ messages: MessageRow[];
120
+ }>;
121
+ searchKb(query: string, limit?: number): Promise<{
122
+ results: KbResult[];
123
+ }>;
124
+ getKbArticle(slug: string): Promise<{
125
+ article: KbArticle;
126
+ }>;
127
+ registerPushToken(input: {
128
+ platform: 'apns' | 'fcm' | 'web-push';
129
+ token: string;
130
+ appVersion?: string;
131
+ }): Promise<{
132
+ id: string;
133
+ created: boolean;
134
+ }>;
135
+ /**
136
+ * @param idempotencyKey minted once per logical call and REUSED on the
137
+ * stale-session replay below, so a replayed write coalesces server-side
138
+ * instead of double-sending.
139
+ * @param isRetry set only by `recoverSession`, to bound recovery to a
140
+ * single attempt. A second refusal is a real error and is thrown.
141
+ */
142
+ private post;
143
+ /**
144
+ * The server refused the token in this device's storage. Get a new one and
145
+ * replay the call, once.
146
+ *
147
+ * This is what a mid-session mobile visitor hits on the deploy that closes
148
+ * the identity-verification bypass: the token in the token store predates
149
+ * signed visitor sessions, and on a channel with verification enabled it is
150
+ * refused rather than honoured. Without this the app surfaces one failed
151
+ * send and only self-heals on the NEXT launch, because the dead token stays
152
+ * on disk. Handled here rather than surfaced, because from the visitor's
153
+ * side nothing has gone wrong.
154
+ *
155
+ * The dead token is cleared from the token store, not just the in-memory
156
+ * cache — otherwise the next launch repeats the failure.
157
+ */
158
+ private recoverSession;
159
+ }
160
+ //# sourceMappingURL=RestClient.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"RestClient.d.ts","sourceRoot":"","sources":["../../src/client/RestClient.ts"],"names":[],"mappings":"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"}