@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 @@
1
+ {"version":3,"sources":["../src/errors.ts","../src/api.ts","../src/styles.ts","../src/renderer.ts","../src/client.ts"],"sourcesContent":["/**\n * Base error class for Messaging SDK errors\n */\nexport class MessagingError extends Error {\n constructor(message: string) {\n super(message);\n this.name = 'MessagingError';\n Object.setPrototypeOf(this, MessagingError.prototype);\n }\n}\n\n/**\n * Error thrown when API authentication fails\n */\nexport class AuthenticationError extends MessagingError {\n constructor(message = 'Invalid API key') {\n super(message);\n this.name = 'AuthenticationError';\n Object.setPrototypeOf(this, AuthenticationError.prototype);\n }\n}\n\n/**\n * Error thrown when the API request fails\n */\nexport class ApiError extends MessagingError {\n public readonly statusCode: number;\n public readonly response?: unknown;\n\n constructor(message: string, statusCode: number, response?: unknown) {\n super(message);\n this.name = 'ApiError';\n this.statusCode = statusCode;\n this.response = response;\n Object.setPrototypeOf(this, ApiError.prototype);\n }\n}\n\n/**\n * Error thrown when request validation fails\n */\nexport class ValidationError extends MessagingError {\n public readonly field?: string;\n\n constructor(message: string, field?: string) {\n super(message);\n this.name = 'ValidationError';\n this.field = field;\n Object.setPrototypeOf(this, ValidationError.prototype);\n }\n}\n\n/**\n * Error thrown when a request times out\n */\nexport class TimeoutError extends MessagingError {\n constructor(message = 'Request timed out') {\n super(message);\n this.name = 'TimeoutError';\n Object.setPrototypeOf(this, TimeoutError.prototype);\n }\n}\n","import type { InAppMessage, MessageType, GetMessagesOptions } from './types.js';\nimport {\n ApiError,\n AuthenticationError,\n TimeoutError,\n} from './errors.js';\n\nconst DEFAULT_BASE_URL = 'https://api.kitbase.dev';\nconst TIMEOUT = 30000;\n\n/** Raw API response shape (internal) */\ninterface SdkInAppMessageResponse {\n id: string;\n title: string;\n message: string;\n showOnce: boolean;\n messageType: string;\n channelName: string;\n imageUrl?: string;\n actionButtonText?: string;\n actionButtonUrl?: string;\n actionButtonColor?: string;\n actionButtonTextColor?: string;\n secondaryButtonText?: string;\n secondaryButtonUrl?: string;\n secondaryButtonColor?: string;\n secondaryButtonTextColor?: string;\n backgroundColor?: string;\n startDate?: string;\n endDate?: string;\n}\n\n/**\n * Low-level HTTP client for the in-app messages API.\n * @internal\n */\nexport class MessagingApi {\n private readonly baseUrl: string;\n\n constructor(private readonly sdkKey: string, baseUrl?: string) {\n this.baseUrl = (baseUrl ?? DEFAULT_BASE_URL).replace(/\\/+$/, '');\n }\n\n async getMessages(options?: GetMessagesOptions): Promise<InAppMessage[]> {\n const params: Record<string, string> = {};\n if (options?.userId) params.userId = options.userId;\n if (options?.metadata) params.metadata = JSON.stringify(options.metadata);\n\n const response = await this.get<{ messages: SdkInAppMessageResponse[] }>(\n '/sdk/v1/in-app-messages',\n params,\n );\n\n return response.messages.map(toInAppMessage);\n }\n\n async markViewed(messageId: string, userId: string): Promise<void> {\n await this.post('/sdk/v1/in-app-messages/views', { messageId, userId });\n }\n\n // ── HTTP ──────────────────────────────────────────────────────\n\n private async get<T>(endpoint: string, params?: Record<string, string>): Promise<T> {\n let url = `${this.baseUrl}${endpoint}`;\n if (params && Object.keys(params).length > 0) {\n const qs = Object.entries(params)\n .map(([k, v]) => `${encodeURIComponent(k)}=${encodeURIComponent(v)}`)\n .join('&');\n url += `?${qs}`;\n }\n\n const controller = new AbortController();\n const tid = setTimeout(() => controller.abort(), TIMEOUT);\n\n try {\n const res = await fetch(url, {\n method: 'GET',\n headers: { 'Content-Type': 'application/json', 'x-sdk-key': this.sdkKey },\n signal: controller.signal,\n });\n clearTimeout(tid);\n if (!res.ok) this.throwError(res, await this.parseBody(res));\n return (await res.json()) as T;\n } catch (err) {\n clearTimeout(tid);\n if (err instanceof Error && err.name === 'AbortError') throw new TimeoutError();\n throw err;\n }\n }\n\n private async post(endpoint: string, body: unknown): Promise<void> {\n const controller = new AbortController();\n const tid = setTimeout(() => controller.abort(), TIMEOUT);\n\n try {\n const res = await fetch(`${this.baseUrl}${endpoint}`, {\n method: 'POST',\n headers: { 'Content-Type': 'application/json', 'x-sdk-key': this.sdkKey },\n body: JSON.stringify(body),\n signal: controller.signal,\n });\n clearTimeout(tid);\n if (!res.ok) this.throwError(res, await this.parseBody(res));\n } catch (err) {\n clearTimeout(tid);\n if (err instanceof Error && err.name === 'AbortError') throw new TimeoutError();\n throw err;\n }\n }\n\n private throwError(res: Response, body: unknown): never {\n if (res.status === 401) throw new AuthenticationError();\n let msg = res.statusText;\n if (body && typeof body === 'object') {\n if ('message' in body) msg = String((body as any).message);\n else if ('error' in body) msg = String((body as any).error);\n }\n throw new ApiError(msg, res.status, body);\n }\n\n private async parseBody(res: Response): Promise<unknown> {\n try { return await res.json(); } catch { return null; }\n }\n}\n\n// ── Response mapping ────────────────────────────────────────────\n\nfunction toInAppMessage(raw: SdkInAppMessageResponse): InAppMessage {\n const msg: InAppMessage = {\n id: raw.id,\n title: raw.title,\n body: raw.message,\n showOnce: raw.showOnce,\n type: raw.messageType as MessageType,\n channel: raw.channelName || null,\n imageUrl: raw.imageUrl,\n backgroundColor: raw.backgroundColor,\n startDate: raw.startDate,\n endDate: raw.endDate,\n };\n\n if (raw.actionButtonText) {\n msg.actionButton = {\n text: raw.actionButtonText,\n url: raw.actionButtonUrl!,\n color: raw.actionButtonColor,\n textColor: raw.actionButtonTextColor,\n };\n }\n\n if (raw.secondaryButtonText) {\n msg.secondaryButton = {\n text: raw.secondaryButtonText,\n url: raw.secondaryButtonUrl!,\n color: raw.secondaryButtonColor,\n textColor: raw.secondaryButtonTextColor,\n };\n }\n\n return msg;\n}\n","/** Scoped CSS injected into the shadow DOM */\nexport const STYLES = /* css */ `\n:host {\n all: initial;\n font-family: -apple-system, BlinkMacSystemFont, 'Segoe UI', Roboto, 'Helvetica Neue', sans-serif;\n font-size: 14px;\n line-height: 1.5;\n color: #1a1a1a;\n -webkit-font-smoothing: antialiased;\n -moz-osx-font-smoothing: grayscale;\n}\n\n*, *::before, *::after {\n box-sizing: border-box;\n margin: 0;\n padding: 0;\n}\n\n/* ============================== Overlay ============================== */\n\n.kb-overlay {\n position: fixed;\n inset: 0;\n z-index: 999999;\n background: rgba(0, 0, 0, 0.5);\n display: flex;\n align-items: center;\n justify-content: center;\n padding: 16px;\n animation: kb-fade-in 200ms ease-out;\n}\n.kb-overlay.kb-exit {\n animation: kb-fade-out 150ms ease-in forwards;\n}\n\n/* ============================== Modal ============================== */\n\n.kb-modal {\n position: relative;\n background: #fff;\n border-radius: 16px;\n box-shadow: 0 25px 50px -12px rgba(0, 0, 0, 0.25);\n max-width: 480px;\n width: 100%;\n overflow: hidden;\n animation: kb-scale-in 200ms ease-out;\n}\n.kb-overlay.kb-exit .kb-modal {\n animation: kb-scale-out 150ms ease-in forwards;\n}\n\n/* ============================== Banner ============================== */\n\n.kb-banner-container {\n position: fixed;\n top: 0;\n left: 0;\n right: 0;\n z-index: 999998;\n display: flex;\n flex-direction: column;\n pointer-events: none;\n}\n\n.kb-banner {\n display: flex;\n align-items: center;\n gap: 16px;\n padding: 12px 20px;\n background: #4F46E5;\n color: #fff;\n pointer-events: auto;\n animation: kb-slide-down 250ms ease-out;\n}\n.kb-banner.kb-exit {\n animation: kb-slide-up-exit 150ms ease-in forwards;\n}\n.kb-banner .kb-content {\n flex: 1;\n min-width: 0;\n}\n.kb-banner .kb-title {\n font-weight: 600;\n font-size: 14px;\n}\n.kb-banner .kb-body {\n font-size: 13px;\n opacity: 0.9;\n color: inherit;\n margin: 0;\n}\n.kb-banner .kb-actions {\n display: flex;\n align-items: center;\n gap: 8px;\n flex-shrink: 0;\n}\n.kb-banner .kb-btn-action {\n background: rgba(255,255,255,0.2);\n color: #fff;\n}\n.kb-banner .kb-btn-secondary {\n background: transparent;\n color: rgba(255,255,255,0.8);\n}\n.kb-banner .kb-close {\n position: static;\n background: rgba(255,255,255,0.15);\n color: #fff;\n}\n.kb-banner .kb-close:hover {\n background: rgba(255,255,255,0.25);\n}\n\n/* ============================== Card ============================== */\n\n.kb-card-container {\n position: fixed;\n bottom: 24px;\n right: 24px;\n z-index: 999997;\n display: flex;\n flex-direction: column;\n gap: 12px;\n max-width: 360px;\n pointer-events: none;\n}\n\n.kb-card {\n position: relative;\n background: #fff;\n border-radius: 16px;\n box-shadow: 0 10px 25px -5px rgba(0,0,0,0.1), 0 8px 10px -6px rgba(0,0,0,0.1);\n overflow: hidden;\n pointer-events: auto;\n animation: kb-slide-up 250ms ease-out;\n}\n.kb-card.kb-exit {\n animation: kb-slide-down-exit 150ms ease-in forwards;\n}\n\n/* ============================== Image (fullscreen) ============================== */\n\n.kb-image-msg {\n position: relative;\n max-width: 600px;\n width: 100%;\n animation: kb-scale-in 200ms ease-out;\n}\n.kb-overlay.kb-exit .kb-image-msg {\n animation: kb-scale-out 150ms ease-in forwards;\n}\n.kb-image-msg > img {\n display: block;\n width: 100%;\n border-radius: 16px;\n}\n.kb-image-msg .kb-buttons {\n margin-top: 12px;\n justify-content: center;\n}\n\n/* ============================== Shared ============================== */\n\n.kb-close {\n position: absolute;\n top: 8px;\n right: 8px;\n width: 28px;\n height: 28px;\n display: flex;\n align-items: center;\n justify-content: center;\n background: rgba(0,0,0,0.06);\n border: none;\n border-radius: 50%;\n cursor: pointer;\n font-size: 18px;\n line-height: 1;\n color: #666;\n transition: background 150ms, color 150ms;\n z-index: 1;\n}\n.kb-close:hover {\n background: rgba(0,0,0,0.12);\n color: #333;\n}\n.kb-overlay .kb-close {\n background: rgba(255,255,255,0.15);\n color: #fff;\n}\n.kb-overlay .kb-close:hover {\n background: rgba(255,255,255,0.25);\n}\n\n.kb-msg-image {\n display: block;\n width: 100%;\n}\n\n.kb-content {\n padding: 20px;\n}\n\n.kb-title {\n font-size: 18px;\n font-weight: 600;\n line-height: 1.3;\n margin-bottom: 6px;\n}\n\n.kb-body {\n font-size: 14px;\n color: #555;\n line-height: 1.6;\n margin-bottom: 16px;\n white-space: pre-wrap;\n}\n\n.kb-buttons {\n display: flex;\n gap: 8px;\n}\n\n.kb-btn {\n display: inline-flex;\n align-items: center;\n justify-content: center;\n padding: 10px 20px;\n border: none;\n border-radius: 10px;\n font-size: 14px;\n font-weight: 500;\n cursor: pointer;\n text-decoration: none;\n transition: opacity 150ms;\n font-family: inherit;\n line-height: 1;\n}\n.kb-btn:hover {\n opacity: 0.88;\n}\n\n.kb-btn-action {\n background: #4F46E5;\n color: #fff;\n}\n\n.kb-btn-secondary {\n background: #f3f4f6;\n color: #374151;\n}\n\n/* ============================== Animations ============================== */\n\n@keyframes kb-fade-in {\n from { opacity: 0 } to { opacity: 1 }\n}\n@keyframes kb-fade-out {\n from { opacity: 1 } to { opacity: 0 }\n}\n@keyframes kb-scale-in {\n from { transform: scale(0.95); opacity: 0 }\n to { transform: scale(1); opacity: 1 }\n}\n@keyframes kb-scale-out {\n from { transform: scale(1); opacity: 1 }\n to { transform: scale(0.95); opacity: 0 }\n}\n@keyframes kb-slide-down {\n from { transform: translateY(-100%) }\n to { transform: translateY(0) }\n}\n@keyframes kb-slide-up-exit {\n from { transform: translateY(0) }\n to { transform: translateY(-100%) }\n}\n@keyframes kb-slide-up {\n from { transform: translateY(20px); opacity: 0 }\n to { transform: translateY(0); opacity: 1 }\n}\n@keyframes kb-slide-down-exit {\n from { transform: translateY(0); opacity: 1 }\n to { transform: translateY(20px); opacity: 0 }\n}\n\n/* ============================== Responsive ============================== */\n\n@media (max-width: 480px) {\n .kb-card-container {\n left: 12px;\n right: 12px;\n bottom: 12px;\n max-width: none;\n }\n .kb-modal {\n max-width: none;\n }\n}\n`;\n","import type { InAppMessage, MessageButton } from './types.js';\nimport { STYLES } from './styles.js';\n\nexport interface RendererCallbacks {\n onShow: (message: InAppMessage) => void;\n onDismiss: (message: InAppMessage) => void;\n onAction: (message: InAppMessage, button: MessageButton) => void | false;\n}\n\n/**\n * Renders in-app messages into a shadow DOM container.\n * Handles stacking for banners (top) and cards (bottom-right),\n * and overlays for modals and images.\n * @internal\n */\nexport class MessageRenderer {\n private host: HTMLElement;\n private shadow: ShadowRoot;\n private bannerContainer: HTMLElement;\n private cardContainer: HTMLElement;\n private displayed = new Map<string, { element: HTMLElement; message: InAppMessage }>();\n\n constructor(private callbacks: RendererCallbacks) {\n this.host = document.createElement('div');\n this.host.id = 'kitbase-messaging';\n document.body.appendChild(this.host);\n\n this.shadow = this.host.attachShadow({ mode: 'open' });\n\n // Inject styles\n const style = document.createElement('style');\n style.textContent = STYLES;\n this.shadow.appendChild(style);\n\n // Persistent containers for stackable types\n this.bannerContainer = document.createElement('div');\n this.bannerContainer.className = 'kb-banner-container';\n this.shadow.appendChild(this.bannerContainer);\n\n this.cardContainer = document.createElement('div');\n this.cardContainer.className = 'kb-card-container';\n this.shadow.appendChild(this.cardContainer);\n }\n\n /**\n * Reconcile: add new messages, remove stale ones.\n * Idempotent — calling with the same list is a no-op.\n */\n update(messages: InAppMessage[]): void {\n const incoming = new Set(messages.map((m) => m.id));\n\n // Remove messages no longer in the response\n for (const [id] of this.displayed) {\n if (!incoming.has(id)) {\n this.removeMessage(id);\n }\n }\n\n // Add new messages\n for (const msg of messages) {\n if (!this.displayed.has(msg.id)) {\n this.renderMessage(msg);\n }\n }\n }\n\n /** Programmatically dismiss a message (with exit animation). */\n dismiss(messageId: string): void {\n this.removeMessage(messageId);\n }\n\n /** Remove all rendered messages immediately. */\n clear(): void {\n for (const [id] of this.displayed) {\n const entry = this.displayed.get(id);\n if (entry) entry.element.remove();\n }\n this.displayed.clear();\n }\n\n /** Remove the shadow host from the DOM entirely. */\n destroy(): void {\n this.clear();\n this.host.remove();\n }\n\n // ── Rendering ─────────────────────────────────────────────────\n\n private renderMessage(msg: InAppMessage): void {\n let element: HTMLElement;\n\n switch (msg.type) {\n case 'banner':\n element = this.renderBanner(msg);\n this.bannerContainer.appendChild(element);\n break;\n case 'card':\n element = this.renderCard(msg);\n this.cardContainer.appendChild(element);\n break;\n case 'image':\n element = this.renderImageOverlay(msg);\n this.shadow.appendChild(element);\n break;\n case 'modal':\n default:\n element = this.renderModal(msg);\n this.shadow.appendChild(element);\n break;\n }\n\n this.displayed.set(msg.id, { element, message: msg });\n this.callbacks.onShow(msg);\n }\n\n private renderModal(msg: InAppMessage): HTMLElement {\n const overlay = this.el('div', 'kb-overlay');\n\n const modal = this.el('div', 'kb-modal');\n if (msg.backgroundColor) modal.style.background = msg.backgroundColor;\n\n modal.appendChild(this.closeButton(msg));\n\n if (msg.imageUrl) {\n const img = document.createElement('img');\n img.className = 'kb-msg-image';\n img.src = msg.imageUrl;\n img.alt = '';\n modal.appendChild(img);\n }\n\n const content = this.el('div', 'kb-content');\n content.appendChild(this.titleEl(msg.title));\n if (msg.body) content.appendChild(this.bodyEl(msg.body));\n content.appendChild(this.buttonsEl(msg));\n modal.appendChild(content);\n\n // Click overlay backdrop to dismiss\n overlay.addEventListener('click', (e) => {\n if (e.target === overlay) this.handleDismiss(msg);\n });\n\n overlay.appendChild(modal);\n return overlay;\n }\n\n private renderBanner(msg: InAppMessage): HTMLElement {\n const banner = this.el('div', 'kb-banner');\n if (msg.backgroundColor) {\n banner.style.background = msg.backgroundColor;\n }\n\n const content = this.el('div', 'kb-content');\n content.appendChild(this.titleEl(msg.title));\n if (msg.body) content.appendChild(this.bodyEl(msg.body));\n banner.appendChild(content);\n\n const actions = this.el('div', 'kb-actions');\n if (msg.actionButton) {\n actions.appendChild(this.btnEl(msg, msg.actionButton, 'kb-btn-action'));\n }\n if (msg.secondaryButton) {\n actions.appendChild(this.btnEl(msg, msg.secondaryButton, 'kb-btn-secondary'));\n }\n actions.appendChild(this.closeButton(msg));\n banner.appendChild(actions);\n\n return banner;\n }\n\n private renderCard(msg: InAppMessage): HTMLElement {\n const card = this.el('div', 'kb-card');\n if (msg.backgroundColor) card.style.background = msg.backgroundColor;\n\n card.appendChild(this.closeButton(msg));\n\n if (msg.imageUrl) {\n const img = document.createElement('img');\n img.className = 'kb-msg-image';\n img.src = msg.imageUrl;\n img.alt = '';\n card.appendChild(img);\n }\n\n const content = this.el('div', 'kb-content');\n content.appendChild(this.titleEl(msg.title));\n if (msg.body) content.appendChild(this.bodyEl(msg.body));\n content.appendChild(this.buttonsEl(msg));\n card.appendChild(content);\n\n return card;\n }\n\n private renderImageOverlay(msg: InAppMessage): HTMLElement {\n const overlay = this.el('div', 'kb-overlay');\n\n const container = this.el('div', 'kb-image-msg');\n container.appendChild(this.closeButton(msg));\n\n if (msg.imageUrl) {\n const img = document.createElement('img');\n img.src = msg.imageUrl;\n img.alt = msg.title;\n container.appendChild(img);\n }\n\n const buttons = this.buttonsEl(msg);\n if (buttons.childElementCount > 0) {\n container.appendChild(buttons);\n }\n\n overlay.addEventListener('click', (e) => {\n if (e.target === overlay) this.handleDismiss(msg);\n });\n\n overlay.appendChild(container);\n return overlay;\n }\n\n // ── Shared elements ───────────────────────────────────────────\n\n private titleEl(text: string): HTMLElement {\n const el = this.el('div', 'kb-title');\n el.textContent = text;\n return el;\n }\n\n private bodyEl(text: string): HTMLElement {\n const el = this.el('div', 'kb-body');\n el.textContent = text;\n return el;\n }\n\n private buttonsEl(msg: InAppMessage): HTMLElement {\n const wrap = this.el('div', 'kb-buttons');\n if (msg.actionButton) {\n wrap.appendChild(this.btnEl(msg, msg.actionButton, 'kb-btn-action'));\n }\n if (msg.secondaryButton) {\n wrap.appendChild(this.btnEl(msg, msg.secondaryButton, 'kb-btn-secondary'));\n }\n return wrap;\n }\n\n private btnEl(\n msg: InAppMessage,\n button: MessageButton,\n className: string,\n ): HTMLElement {\n const btn = document.createElement('button');\n btn.className = `kb-btn ${className}`;\n btn.textContent = button.text;\n if (button.color) btn.style.background = button.color;\n if (button.textColor) btn.style.color = button.textColor;\n\n btn.addEventListener('click', (e) => {\n e.stopPropagation();\n this.handleAction(msg, button);\n });\n\n return btn;\n }\n\n private closeButton(msg: InAppMessage): HTMLElement {\n const btn = document.createElement('button');\n btn.className = 'kb-close';\n btn.innerHTML = '&#x2715;';\n btn.setAttribute('aria-label', 'Close');\n\n btn.addEventListener('click', (e) => {\n e.stopPropagation();\n this.handleDismiss(msg);\n });\n\n return btn;\n }\n\n // ── Event handling ────────────────────────────────────────────\n\n private handleDismiss(msg: InAppMessage): void {\n const entry = this.displayed.get(msg.id);\n if (!entry) return;\n this.animateOut(entry.element, msg);\n }\n\n private handleAction(msg: InAppMessage, button: MessageButton): void {\n const result = this.callbacks.onAction(msg, button);\n\n // Navigate unless prevented\n if (result !== false && button.url) {\n window.open(button.url, '_blank', 'noopener');\n }\n\n // Dismiss after action\n const entry = this.displayed.get(msg.id);\n if (entry) {\n this.animateOut(entry.element, msg);\n }\n }\n\n // ── Animation + cleanup ───────────────────────────────────────\n\n private removeMessage(id: string): void {\n const entry = this.displayed.get(id);\n if (!entry) return;\n this.animateOut(entry.element, entry.message);\n }\n\n private animateOut(element: HTMLElement, msg: InAppMessage): void {\n if (element.classList.contains('kb-exit')) return; // already exiting\n element.classList.add('kb-exit');\n\n const cleanup = () => {\n element.remove();\n this.displayed.delete(msg.id);\n this.callbacks.onDismiss(msg);\n };\n\n element.addEventListener('animationend', cleanup, { once: true });\n // Fallback if animation doesn't fire (e.g. prefers-reduced-motion)\n setTimeout(cleanup, 300);\n }\n\n // ── Helpers ───────────────────────────────────────────────────\n\n private el(tag: string, className: string): HTMLElement {\n const el = document.createElement(tag);\n el.className = className;\n return el;\n }\n}\n","import type {\n MessagingConfig,\n InAppMessage,\n GetMessagesOptions,\n SubscribeOptions,\n} from './types.js';\nimport { ValidationError } from './errors.js';\nimport { MessagingApi } from './api.js';\nimport { MessageRenderer } from './renderer.js';\n\nconst DEFAULT_POLL_INTERVAL = 60000;\n\n/**\n * Singleton instance managed by `init()` / `getInstance()`.\n */\nlet _instance: Messaging | null = null;\n\n/**\n * Initialize the Kitbase In-App Messaging SDK.\n *\n * Creates a singleton instance that is used for all messaging.\n * Call this once at the top of your application entry point.\n *\n * @param config - SDK configuration\n * @returns The Messaging instance\n *\n * @example\n * ```typescript\n * import { init } from '@kitbase/messaging';\n *\n * const messaging = init({\n * sdkKey: 'your-api-key',\n * userId: currentUser.id,\n * metadata: { plan: 'pro' },\n * });\n * ```\n */\nexport function init(config: MessagingConfig): Messaging {\n if (_instance) {\n _instance.close();\n }\n _instance = new Messaging(config);\n return _instance;\n}\n\n/**\n * Get the current Messaging singleton instance.\n *\n * @returns The instance, or null if `init()` has not been called\n */\nexport function getInstance(): Messaging | null {\n return _instance;\n}\n\n/**\n * Kitbase In-App Messaging SDK\n *\n * Fetches targeted in-app messages and renders them directly in the page.\n * Supports modals, banners, cards, and full-screen images with automatic\n * stacking.\n *\n * @example Using init (recommended)\n * ```typescript\n * import { init } from '@kitbase/messaging';\n *\n * const messaging = init({\n * sdkKey: 'your-api-key',\n * metadata: { plan: 'pro' },\n * onAction: (msg, btn) => {\n * console.log('User clicked:', btn.text);\n * },\n * });\n *\n * // Later: clean up\n * messaging.close();\n * ```\n *\n * @example CDN (zero-config)\n * ```html\n * <script>\n * window.KITBASE_MESSAGING = { sdkKey: 'your-api-key' };\n * </script>\n * <script src=\"https://unpkg.com/@kitbase/messaging/dist/cdn.js\"></script>\n * <!-- Messages appear automatically! -->\n * ```\n *\n * @example Data-only (no rendering)\n * ```typescript\n * const messaging = init({\n * sdkKey: 'your-api-key',\n * autoShow: false,\n * });\n *\n * const messages = await messaging.getMessages();\n * // render messages yourself\n * ```\n */\nexport class Messaging {\n private api: MessagingApi;\n private renderer: MessageRenderer | null = null;\n private config: MessagingConfig;\n private pollTimer: ReturnType<typeof setInterval> | null = null;\n private dismissed = new Set<string>();\n private subscriptionTimers = new Set<ReturnType<typeof setInterval>>();\n private pendingPoll = false;\n private visibilityHandler: (() => void) | null = null;\n\n private userId: string | undefined;\n\n constructor(config: MessagingConfig) {\n if (!config.sdkKey) {\n throw new ValidationError('SDK key is required', 'sdkKey');\n }\n\n this.config = config;\n this.userId = config.userId;\n this.api = new MessagingApi(config.sdkKey, config.baseUrl);\n\n if (config.autoShow !== false && typeof window !== 'undefined') {\n this.start();\n }\n }\n\n // ── Lifecycle ─────────────────────────────────────────────────\n\n /**\n * Start fetching and rendering messages.\n * Called automatically unless `autoShow: false`.\n */\n start(): void {\n if (typeof window === 'undefined') return;\n if (this.renderer) return; // already started\n\n this.renderer = new MessageRenderer({\n onShow: (msg) => {\n this.config.onShow?.(msg);\n },\n onDismiss: (msg) => {\n this.dismissed.add(msg.id);\n this.config.onDismiss?.(msg);\n },\n onAction: (msg, btn) => {\n return this.config.onAction?.(msg, btn);\n },\n });\n\n // Fetch immediately\n this.poll();\n\n // Set up polling\n const interval = this.config.pollInterval ?? DEFAULT_POLL_INTERVAL;\n if (interval > 0) {\n this.pollTimer = setInterval(() => this.poll(), interval);\n }\n\n // Pause polling when tab is hidden, resume when visible\n this.visibilityHandler = () => {\n if (document.visibilityState === 'visible' && this.pendingPoll) {\n this.pendingPoll = false;\n this.poll();\n }\n };\n document.addEventListener('visibilitychange', this.visibilityHandler);\n }\n\n /**\n * Stop polling and remove all rendered messages.\n */\n stop(): void {\n if (this.pollTimer) {\n clearInterval(this.pollTimer);\n this.pollTimer = null;\n }\n if (this.visibilityHandler) {\n document.removeEventListener('visibilitychange', this.visibilityHandler);\n this.visibilityHandler = null;\n }\n this.pendingPoll = false;\n this.renderer?.destroy();\n this.renderer = null;\n }\n\n /**\n * Stop everything and remove all rendered UI.\n */\n close(): void {\n this.stop();\n for (const tid of this.subscriptionTimers) {\n clearInterval(tid);\n }\n this.subscriptionTimers.clear();\n this.dismissed.clear();\n }\n\n // ── User identity ────────────────────────────────────────────\n\n /**\n * Set the current user ID.\n * Triggers an immediate re-fetch so show-once messages that the user\n * has already viewed are filtered out.\n */\n identify(userId: string): void {\n this.userId = userId;\n this.poll();\n }\n\n /**\n * Clear the current user ID and reset dismissed messages.\n * Call this on logout.\n */\n reset(): void {\n this.userId = undefined;\n this.dismissed.clear();\n this.poll();\n }\n\n /**\n * Record that the current user has viewed a message.\n * The message is optimistically removed from the UI.\n *\n * @throws {ValidationError} When no user ID has been set\n * @throws {ApiError} When the API returns an error\n */\n async markViewed(messageId: string): Promise<void> {\n if (!this.userId) {\n throw new ValidationError(\n 'User ID is required to mark a message as viewed. Call identify() first.',\n 'userId',\n );\n }\n this.dismissed.add(messageId);\n this.renderer?.dismiss(messageId);\n await this.api.markViewed(messageId, this.userId);\n }\n\n // ── Data-only methods ─────────────────────────────────────────\n\n /**\n * Fetch active messages without rendering.\n * Use this when `autoShow: false` or for custom rendering.\n *\n * @param options - Metadata for targeting evaluation\n * @throws {AuthenticationError} When the API key is invalid\n * @throws {ApiError} When the API returns an error\n * @throws {TimeoutError} When the request times out\n */\n async getMessages(options?: GetMessagesOptions): Promise<InAppMessage[]> {\n return this.api.getMessages(options);\n }\n\n /**\n * Subscribe to messages with polling (data-only, no rendering).\n * Returns an unsubscribe function.\n *\n * @example\n * ```typescript\n * const unsub = messaging.subscribe(\n * (messages) => renderMyUI(messages),\n * { pollInterval: 30_000 },\n * );\n *\n * // Later\n * unsub();\n * ```\n */\n subscribe(\n callback: (messages: InAppMessage[]) => void,\n options?: SubscribeOptions,\n ): () => void {\n const interval = options?.pollInterval ?? DEFAULT_POLL_INTERVAL;\n let active = true;\n\n const run = async () => {\n if (!active) return;\n try {\n const msgs = await this.api.getMessages(options);\n if (active) callback(msgs);\n } catch {\n /* skip failed polls */\n }\n };\n\n run();\n const tid = setInterval(run, interval);\n this.subscriptionTimers.add(tid);\n\n return () => {\n active = false;\n clearInterval(tid);\n this.subscriptionTimers.delete(tid);\n };\n }\n\n // ── Internal ──────────────────────────────────────────────────\n\n private async poll(): Promise<void> {\n if (typeof document !== 'undefined' && document.visibilityState === 'hidden') {\n this.pendingPoll = true;\n return;\n }\n\n try {\n const messages = await this.api.getMessages({\n userId: this.userId,\n metadata: this.config.metadata,\n });\n\n // Filter out messages dismissed in this session\n const visible = messages.filter((m) => !this.dismissed.has(m.id));\n\n this.renderer?.update(visible);\n } catch {\n /* silently skip failed polls */\n }\n }\n}\n"],"mappings":"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A;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAA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","names":[]}
package/package.json ADDED
@@ -0,0 +1,52 @@
1
+ {
2
+ "name": "@kitbase/messaging",
3
+ "version": "0.1.0",
4
+ "description": "Kitbase In-App Messaging SDK for TypeScript and JavaScript",
5
+ "type": "module",
6
+ "main": "./dist/index.cjs",
7
+ "module": "./dist/index.js",
8
+ "types": "./dist/index.d.ts",
9
+ "exports": {
10
+ ".": {
11
+ "import": {
12
+ "types": "./dist/index.d.ts",
13
+ "default": "./dist/index.js"
14
+ },
15
+ "require": {
16
+ "types": "./dist/index.d.cts",
17
+ "default": "./dist/index.cjs"
18
+ }
19
+ }
20
+ },
21
+ "files": [
22
+ "dist"
23
+ ],
24
+ "sideEffects": false,
25
+ "keywords": [
26
+ "kitbase",
27
+ "messaging",
28
+ "in-app-messages"
29
+ ],
30
+ "license": "MIT",
31
+ "repository": {
32
+ "type": "git",
33
+ "url": "https://github.com/scr2em/kitbase-sdk.git",
34
+ "directory": "messaging/typescript"
35
+ },
36
+ "devDependencies": {
37
+ "@types/node": "^20.11.0",
38
+ "tsup": "^8.0.1",
39
+ "typescript": "^5.3.3",
40
+ "vitest": "^1.2.0"
41
+ },
42
+ "engines": {
43
+ "node": ">=18"
44
+ },
45
+ "scripts": {
46
+ "build": "tsup",
47
+ "dev": "tsup --watch",
48
+ "test": "vitest run",
49
+ "test:watch": "vitest",
50
+ "clean": "rm -rf dist"
51
+ }
52
+ }