@kitbase/messaging 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.
@@ -0,0 +1,320 @@
1
+ /**
2
+ * Configuration for the Messaging SDK
3
+ *
4
+ * @example CDN / Script tag
5
+ * ```html
6
+ * <script>
7
+ * window.KITBASE_MESSAGING = { sdkKey: 'your-api-key' };
8
+ * </script>
9
+ * <script src="https://unpkg.com/@kitbase/messaging/dist/cdn.js"></script>
10
+ * ```
11
+ *
12
+ * @example NPM
13
+ * ```typescript
14
+ * import { Messaging } from '@kitbase/messaging';
15
+ *
16
+ * const messaging = new Messaging({
17
+ * sdkKey: 'your-api-key',
18
+ * metadata: { plan: 'pro' },
19
+ * });
20
+ * ```
21
+ */
22
+ interface MessagingConfig {
23
+ /** Your Kitbase SDK key */
24
+ sdkKey: string;
25
+ /**
26
+ * Override the API base URL (for self-hosted instances).
27
+ * @default 'https://api.kitbase.dev'
28
+ */
29
+ baseUrl?: string;
30
+ /**
31
+ * Current user ID. When provided, show-once messages that the user
32
+ * has already viewed are excluded from results.
33
+ *
34
+ * @example
35
+ * ```typescript
36
+ * new Messaging({
37
+ * sdkKey: '...',
38
+ * userId: currentUser.id,
39
+ * });
40
+ * ```
41
+ */
42
+ userId?: string;
43
+ /**
44
+ * Metadata key-value pairs for targeting evaluation.
45
+ * Only messages whose targeting conditions match this metadata
46
+ * will be returned.
47
+ *
48
+ * @example
49
+ * ```typescript
50
+ * new Messaging({
51
+ * sdkKey: '...',
52
+ * metadata: { plan: 'free', country: 'US' },
53
+ * });
54
+ * ```
55
+ */
56
+ metadata?: Record<string, string>;
57
+ /**
58
+ * How often to poll for new messages (milliseconds).
59
+ * Set to `0` to disable polling (fetch once on init only).
60
+ * @default 60000
61
+ */
62
+ pollInterval?: number;
63
+ /**
64
+ * Automatically render messages in the page.
65
+ * Set to `false` to use data-only mode (fetch without rendering).
66
+ * @default true
67
+ */
68
+ autoShow?: boolean;
69
+ /** Called when a message is displayed to the user. */
70
+ onShow?: (message: InAppMessage) => void;
71
+ /** Called when a message is dismissed (close button or after action). */
72
+ onDismiss?: (message: InAppMessage) => void;
73
+ /**
74
+ * Called when an action button is clicked.
75
+ * By default, the URL is opened in a new tab.
76
+ * Return `false` to prevent the default navigation.
77
+ */
78
+ onAction?: (message: InAppMessage, button: MessageButton) => void | false;
79
+ }
80
+ /** Message display format */
81
+ type MessageType = 'modal' | 'banner' | 'card' | 'image';
82
+ /**
83
+ * A message action button with optional styling
84
+ */
85
+ interface MessageButton {
86
+ /** Button label */
87
+ text: string;
88
+ /** URL to navigate to when clicked */
89
+ url: string;
90
+ /** Button background color (hex, e.g. '#4F46E5') */
91
+ color?: string;
92
+ /** Button text color (hex, e.g. '#FFFFFF') */
93
+ textColor?: string;
94
+ }
95
+ /**
96
+ * An in-app message
97
+ */
98
+ interface InAppMessage {
99
+ /** Unique message ID */
100
+ id: string;
101
+ /** Message heading */
102
+ title: string;
103
+ /** Message body */
104
+ body: string;
105
+ /** If true, the message is hidden after the user views it once */
106
+ showOnce: boolean;
107
+ /** Display format */
108
+ type: MessageType;
109
+ /** Channel this message belongs to, or null */
110
+ channel: string | null;
111
+ /** Optional image URL */
112
+ imageUrl?: string;
113
+ /** Primary action button */
114
+ actionButton?: MessageButton;
115
+ /** Secondary action button (e.g. dismiss) */
116
+ secondaryButton?: MessageButton;
117
+ /** Background color (hex) */
118
+ backgroundColor?: string;
119
+ /** Scheduled start date (ISO-8601) */
120
+ startDate?: string;
121
+ /** Scheduled end date (ISO-8601) */
122
+ endDate?: string;
123
+ }
124
+ /**
125
+ * Options for fetching in-app messages
126
+ */
127
+ interface GetMessagesOptions {
128
+ /** User ID for filtering already-viewed show-once messages */
129
+ userId?: string;
130
+ /** Metadata for targeting evaluation */
131
+ metadata?: Record<string, string>;
132
+ }
133
+ /**
134
+ * Options for subscribing to messages with polling
135
+ */
136
+ interface SubscribeOptions extends GetMessagesOptions {
137
+ /**
138
+ * How often to poll for new messages (milliseconds).
139
+ * @default 60000
140
+ */
141
+ pollInterval?: number;
142
+ }
143
+
144
+ /**
145
+ * Initialize the Kitbase In-App Messaging SDK.
146
+ *
147
+ * Creates a singleton instance that is used for all messaging.
148
+ * Call this once at the top of your application entry point.
149
+ *
150
+ * @param config - SDK configuration
151
+ * @returns The Messaging instance
152
+ *
153
+ * @example
154
+ * ```typescript
155
+ * import { init } from '@kitbase/messaging';
156
+ *
157
+ * const messaging = init({
158
+ * sdkKey: 'your-api-key',
159
+ * userId: currentUser.id,
160
+ * metadata: { plan: 'pro' },
161
+ * });
162
+ * ```
163
+ */
164
+ declare function init(config: MessagingConfig): Messaging;
165
+ /**
166
+ * Get the current Messaging singleton instance.
167
+ *
168
+ * @returns The instance, or null if `init()` has not been called
169
+ */
170
+ declare function getInstance(): Messaging | null;
171
+ /**
172
+ * Kitbase In-App Messaging SDK
173
+ *
174
+ * Fetches targeted in-app messages and renders them directly in the page.
175
+ * Supports modals, banners, cards, and full-screen images with automatic
176
+ * stacking.
177
+ *
178
+ * @example Using init (recommended)
179
+ * ```typescript
180
+ * import { init } from '@kitbase/messaging';
181
+ *
182
+ * const messaging = init({
183
+ * sdkKey: 'your-api-key',
184
+ * metadata: { plan: 'pro' },
185
+ * onAction: (msg, btn) => {
186
+ * console.log('User clicked:', btn.text);
187
+ * },
188
+ * });
189
+ *
190
+ * // Later: clean up
191
+ * messaging.close();
192
+ * ```
193
+ *
194
+ * @example CDN (zero-config)
195
+ * ```html
196
+ * <script>
197
+ * window.KITBASE_MESSAGING = { sdkKey: 'your-api-key' };
198
+ * </script>
199
+ * <script src="https://unpkg.com/@kitbase/messaging/dist/cdn.js"></script>
200
+ * <!-- Messages appear automatically! -->
201
+ * ```
202
+ *
203
+ * @example Data-only (no rendering)
204
+ * ```typescript
205
+ * const messaging = init({
206
+ * sdkKey: 'your-api-key',
207
+ * autoShow: false,
208
+ * });
209
+ *
210
+ * const messages = await messaging.getMessages();
211
+ * // render messages yourself
212
+ * ```
213
+ */
214
+ declare class Messaging {
215
+ private api;
216
+ private renderer;
217
+ private config;
218
+ private pollTimer;
219
+ private dismissed;
220
+ private subscriptionTimers;
221
+ private pendingPoll;
222
+ private visibilityHandler;
223
+ private userId;
224
+ constructor(config: MessagingConfig);
225
+ /**
226
+ * Start fetching and rendering messages.
227
+ * Called automatically unless `autoShow: false`.
228
+ */
229
+ start(): void;
230
+ /**
231
+ * Stop polling and remove all rendered messages.
232
+ */
233
+ stop(): void;
234
+ /**
235
+ * Stop everything and remove all rendered UI.
236
+ */
237
+ close(): void;
238
+ /**
239
+ * Set the current user ID.
240
+ * Triggers an immediate re-fetch so show-once messages that the user
241
+ * has already viewed are filtered out.
242
+ */
243
+ identify(userId: string): void;
244
+ /**
245
+ * Clear the current user ID and reset dismissed messages.
246
+ * Call this on logout.
247
+ */
248
+ reset(): void;
249
+ /**
250
+ * Record that the current user has viewed a message.
251
+ * The message is optimistically removed from the UI.
252
+ *
253
+ * @throws {ValidationError} When no user ID has been set
254
+ * @throws {ApiError} When the API returns an error
255
+ */
256
+ markViewed(messageId: string): Promise<void>;
257
+ /**
258
+ * Fetch active messages without rendering.
259
+ * Use this when `autoShow: false` or for custom rendering.
260
+ *
261
+ * @param options - Metadata for targeting evaluation
262
+ * @throws {AuthenticationError} When the API key is invalid
263
+ * @throws {ApiError} When the API returns an error
264
+ * @throws {TimeoutError} When the request times out
265
+ */
266
+ getMessages(options?: GetMessagesOptions): Promise<InAppMessage[]>;
267
+ /**
268
+ * Subscribe to messages with polling (data-only, no rendering).
269
+ * Returns an unsubscribe function.
270
+ *
271
+ * @example
272
+ * ```typescript
273
+ * const unsub = messaging.subscribe(
274
+ * (messages) => renderMyUI(messages),
275
+ * { pollInterval: 30_000 },
276
+ * );
277
+ *
278
+ * // Later
279
+ * unsub();
280
+ * ```
281
+ */
282
+ subscribe(callback: (messages: InAppMessage[]) => void, options?: SubscribeOptions): () => void;
283
+ private poll;
284
+ }
285
+
286
+ /**
287
+ * Base error class for Messaging SDK errors
288
+ */
289
+ declare class MessagingError extends Error {
290
+ constructor(message: string);
291
+ }
292
+ /**
293
+ * Error thrown when API authentication fails
294
+ */
295
+ declare class AuthenticationError extends MessagingError {
296
+ constructor(message?: string);
297
+ }
298
+ /**
299
+ * Error thrown when the API request fails
300
+ */
301
+ declare class ApiError extends MessagingError {
302
+ readonly statusCode: number;
303
+ readonly response?: unknown;
304
+ constructor(message: string, statusCode: number, response?: unknown);
305
+ }
306
+ /**
307
+ * Error thrown when request validation fails
308
+ */
309
+ declare class ValidationError extends MessagingError {
310
+ readonly field?: string;
311
+ constructor(message: string, field?: string);
312
+ }
313
+ /**
314
+ * Error thrown when a request times out
315
+ */
316
+ declare class TimeoutError extends MessagingError {
317
+ constructor(message?: string);
318
+ }
319
+
320
+ export { ApiError, AuthenticationError, type GetMessagesOptions, type InAppMessage, type MessageButton, type MessageType, Messaging, type MessagingConfig, MessagingError, type SubscribeOptions, TimeoutError, ValidationError, getInstance, init };