signalbird 2.6.0 → 2.9.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/README.md +200 -69
- package/dist/angular.js +23 -8
- package/dist/angular.js.map +1 -1
- package/dist/angular.mjs +23 -8
- package/dist/angular.mjs.map +1 -1
- package/dist/app.d.mts +41 -6
- package/dist/app.d.ts +41 -6
- package/dist/app.js +23 -8
- package/dist/app.js.map +1 -1
- package/dist/app.mjs +23 -8
- package/dist/app.mjs.map +1 -1
- package/dist/browser.d.mts +17 -0
- package/dist/browser.d.ts +17 -0
- package/dist/browser.js +92 -3
- package/dist/browser.js.map +1 -1
- package/dist/browser.mjs +92 -3
- package/dist/browser.mjs.map +1 -1
- package/dist/index.d.mts +114 -19
- package/dist/index.d.ts +114 -19
- package/dist/index.js +98 -9
- package/dist/index.js.map +1 -1
- package/dist/index.mjs +99 -10
- package/dist/index.mjs.map +1 -1
- package/dist/react-native.js +23 -8
- package/dist/react-native.js.map +1 -1
- package/dist/react-native.mjs +23 -8
- package/dist/react-native.mjs.map +1 -1
- package/dist/react.js +23 -8
- package/dist/react.js.map +1 -1
- package/dist/react.mjs +23 -8
- package/dist/react.mjs.map +1 -1
- package/dist/signalbird.js +3 -3
- package/dist/vue.js +23 -8
- package/dist/vue.js.map +1 -1
- package/dist/vue.mjs +23 -8
- package/dist/vue.mjs.map +1 -1
- package/package.json +2 -1
package/dist/browser.js.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"sources":["../src/shared/version.ts","../src/browser/index.ts"],"names":[],"mappings":"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","file":"browser.js","sourcesContent":["/**\n * SDK sürüm bildirimi - CONTRACT §14.\n *\n * Her istek `X-Signalbird-Sdk: <platform>/<sürüm>` taşır; API bunu kaydeder\n * ve yanıtta `Signalbird-Sdk-Status` (current | outdated | unsupported) ile\n * `Signalbird-Sdk-Latest` döner. SDK eski olduğunu öğrenince geliştiriciye\n * süreç başına BİR KEZ uyarı yazar. Uyarı hata değildir: istek sonucu\n * değişmez, istisna fırlatılmaz.\n *\n * Sürüm numarası derlemede `VERSION` dosyasından gömülür (tsup `define`).\n */\n\ndeclare const __SB_VERSION__: string;\n\nexport const SDK_VERSION: string = typeof __SB_VERSION__ === 'string' ? __SB_VERSION__ : '0.0.0';\n\nexport const SDK_HEADER = 'X-Signalbird-Sdk';\n\n/** `node/2.6.0` - platform adları CONTRACT §14.1'deki listededir. */\nexport function sdkHeaderValue(platform: string): string {\n return `${platform}/${SDK_VERSION}`;\n}\n\n/** Başlık okuyabilen her şey: fetch `Headers`, ya da sahte bir yanıt. */\ninterface HeaderSource {\n get(name: string): string | null;\n}\n\nlet warned = false;\n\n/**\n * Yanıttaki sürüm durumuna bakar; eskiyse bir kez `console.warn` yazar.\n * Hiçbir koşulda hata fırlatmaz: sürüm uyarısı yüzünden müşterinin isteği\n * bozulmamalı.\n */\nexport function noteSdkStatus(headers: HeaderSource | null | undefined): void {\n if (warned || !headers) return;\n\n try {\n const status = headers.get('Signalbird-Sdk-Status');\n\n if (status !== 'outdated' && status !== 'unsupported') return;\n\n warned = true;\n\n const latest = headers.get('Signalbird-Sdk-Latest') ?? '?';\n const message = status === 'unsupported'\n ? `[signalbird] Bu SDK sürümü (${SDK_VERSION}) artık desteklenmiyor. Son sürüm: ${latest}. Paketi güncelleyin.`\n : `[signalbird] Yeni SDK sürümü var: ${latest} (kurulu: ${SDK_VERSION}).`;\n\n if (typeof console !== 'undefined') console.warn(message);\n } catch {\n // uyarı yazılamadıysa sessiz kal\n }\n}\n\n/** Yalnız testler için: uyarıyı yeniden kurar. */\nexport function resetSdkStatusWarning(): void {\n warned = false;\n}\n","/**\n * signalbird/browser - tarayıcı istemcisi.\n *\n * Ayrı bir giriş noktası olmasının sebebi teknik değil, GÜVENLİKTİR: sunucu\n * anahtarı istemciye gömülemez ve sunucu `Origin` başlığı taşıyan bir istekte\n * onu zaten reddeder. Tarayıcı, açık anahtarı (`sb_public_live_…`) kullanır ve\n * güvenliği gizlilikten değil kısıttan gelir: yalnız izinli alan adlarından\n * çalışır ve Origin taşımayan istekte reddedilir (`ORIGIN_REQUIRED`).\n *\n * React, Vue, Angular ve düz JS aynı istemciyi kullanır; çatıya özel sarmalayıcı\n * yoktur çünkü gereken tek şey bir fonksiyon çağrısıdır.\n */\nimport { SDK_HEADER, noteSdkStatus, sdkHeaderValue } from '../shared/version';\n\nexport type Level = 'debug' | 'info' | 'warn' | 'error' | 'critical';\n\nexport interface BrowserConfig {\n /** Açık anahtar (`sb_public_live_…`). Gizli anahtar BURAYA YAZILMAZ. */\n publicKey: string;\n baseUrl?: string;\n source?: string;\n /**\n * Kayıtlar tek tek değil, toplu gider. Kullanıcının tarayıcısından saniyede\n * onlarca istek çıkarmak hem yavaş hem pahalıdır.\n */\n flushIntervalMs?: number;\n maxQueue?: number;\n debug?: boolean;\n}\n\ninterface QueuedEvent {\n key: string;\n message: string;\n level?: Level;\n context?: Record<string, unknown>;\n source?: string;\n}\n\nconst DEFAULT_BASE_URL = 'https://live.signalbird.io/api';\n\nexport class SignalbirdBrowser {\n private queue: QueuedEvent[] = [];\n private timer: ReturnType<typeof setInterval> | null = null;\n private readonly baseUrl: string;\n private readonly maxQueue: number;\n\n constructor(private readonly config: BrowserConfig) {\n if (!config.publicKey?.startsWith('sb_public_live_')) {\n throw new Error(\n 'Signalbird: tarayıcı istemcisi açık anahtar ister (sb_public_live_…). ' +\n 'Gizli anahtarı (sb_secret_live_…) istemci koduna KOYMAYIN.'\n );\n }\n\n this.baseUrl = (config.baseUrl ?? DEFAULT_BASE_URL).replace(/\\/$/, '');\n this.maxQueue = config.maxQueue ?? 50;\n\n if (typeof window !== 'undefined') {\n this.timer = setInterval(() => void this.flush(), config.flushIntervalMs ?? 3000);\n\n // Sekme kapanırken kuyruk boşaltılır. `sendBeacon` sayfa ölürken bile\n // gider; normal fetch yarıda kesilirdi.\n window.addEventListener('pagehide', () => this.flushBeacon());\n }\n }\n\n log(key: string, message: string, level?: Level, context?: Record<string, unknown>): void {\n this.queue.push({ key, message, level, context, source: this.config.source });\n\n // Kuyruk dolduysa beklemeden gönder: bellekte sonsuza kadar biriktirmek,\n // logu hiç göndermemekten kötüdür.\n if (this.queue.length >= this.maxQueue) {\n void this.flush();\n }\n }\n\n info(key: string, message: string, context?: Record<string, unknown>) {\n this.log(key, message, 'info', context);\n }\n\n warn(key: string, message: string, context?: Record<string, unknown>) {\n this.log(key, message, 'warn', context);\n }\n\n error(key: string, message: string, context?: Record<string, unknown>) {\n this.log(key, message, 'error', context);\n }\n\n /**\n * Tarayıcıdaki yakalanmamış hataları bağlar.\n *\n * Varsayılan anahtar `browser`dır ve KRİTİK DEĞİLDİR: istemci tarafı kod\n * herkesin elindedir, oradan kritik alarm tetiklemek kötü niyetli birine\n * ekibin telefonunu çaldırma imkânı verirdi. Hangi kanalın kime bildirim\n * göndereceği panelde durur; oradan sessiz bırakılabilir.\n */\n captureErrors(key = 'browser'): () => void {\n const onError = (event: ErrorEvent) => {\n this.error(key, event.message, {\n file: event.filename,\n line: event.lineno,\n column: event.colno,\n url: window.location.href,\n });\n };\n\n const onRejection = (event: PromiseRejectionEvent) => {\n this.error(key, String(event.reason), { url: window.location.href });\n };\n\n window.addEventListener('error', onError);\n window.addEventListener('unhandledrejection', onRejection);\n\n return () => {\n window.removeEventListener('error', onError);\n window.removeEventListener('unhandledrejection', onRejection);\n };\n }\n\n async flush(): Promise<void> {\n if (this.queue.length === 0) return;\n\n const batch = this.queue.splice(0, 100);\n\n try {\n const response = await fetch(`${this.baseUrl}/v1/radio/log/batch`, {\n method: 'POST',\n headers: {\n 'Content-Type': 'application/json',\n 'X-Signalbird-Key': this.config.publicKey,\n [SDK_HEADER]: sdkHeaderValue('browser'),\n },\n body: JSON.stringify({ events: batch }),\n keepalive: true,\n });\n noteSdkStatus(response.headers);\n } catch (error) {\n if (this.config.debug) {\n console.warn('[signalbird] gönderilemedi', error);\n }\n // Kayıtlar geri konur ama kuyruk sınırı aşılmaz: ağ uzun süre kapalıysa\n // sekme belleği şişmemeli.\n this.queue = [...batch, ...this.queue].slice(0, this.maxQueue);\n }\n }\n\n /** Sayfa kapanırken son gönderim. */\n private flushBeacon(): void {\n if (this.queue.length === 0 || typeof navigator === 'undefined') return;\n\n const blob = new Blob(\n [JSON.stringify({ events: this.queue.splice(0, 100) })],\n { type: 'application/json' }\n );\n\n // sendBeacon özel başlık taşıyamaz; anahtar ve SDK sürümü sorgu dizesinden gider.\n navigator.sendBeacon?.(\n `${this.baseUrl}/v1/radio/log/batch?k=${encodeURIComponent(this.config.publicKey)}` +\n `&sdk=${encodeURIComponent(sdkHeaderValue('browser'))}`,\n blob\n );\n }\n\n destroy(): void {\n if (this.timer) clearInterval(this.timer);\n void this.flush();\n }\n}\n\nlet singleton: SignalbirdBrowser | null = null;\n\n/** Uygulama başlangıcında bir kez çağrılır. */\nexport function initSignalbird(config: BrowserConfig): SignalbirdBrowser {\n singleton = new SignalbirdBrowser(config);\n return singleton;\n}\n\n/** Kurulmamışsa sessizce yok sayar - log çağrısı uygulamayı çökertmemeli. */\nexport function signalbird(): SignalbirdBrowser | null {\n return singleton;\n}\n"]}
|
|
1
|
+
{"version":3,"sources":["../src/shared/version.ts","../src/shared/serialize.ts","../src/browser/index.ts"],"names":[],"mappings":"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","file":"browser.js","sourcesContent":["/**\n * SDK sürüm bildirimi - CONTRACT §14.\n *\n * Her istek `X-Signalbird-Sdk: <platform>/<sürüm>` taşır; API bunu kaydeder\n * ve yanıtta `Signalbird-Sdk-Status` (current | outdated | unsupported) ile\n * `Signalbird-Sdk-Latest` döner. SDK eski olduğunu öğrenince geliştiriciye\n * süreç başına BİR KEZ uyarı yazar. Uyarı hata değildir: istek sonucu\n * değişmez, istisna fırlatılmaz.\n *\n * Sürüm numarası derlemede `VERSION` dosyasından gömülür (tsup `define`).\n */\n\ndeclare const __SB_VERSION__: string;\n\nexport const SDK_VERSION: string = typeof __SB_VERSION__ === 'string' ? __SB_VERSION__ : '0.0.0';\n\nexport const SDK_HEADER = 'X-Signalbird-Sdk';\n\n/** `node/2.6.0` - platform adları CONTRACT §14.1'deki listededir. */\nexport function sdkHeaderValue(platform: string): string {\n return `${platform}/${SDK_VERSION}`;\n}\n\n/** Başlık okuyabilen her şey: fetch `Headers`, ya da sahte bir yanıt. */\ninterface HeaderSource {\n get(name: string): string | null;\n}\n\nlet warned = false;\n\n/**\n * Yanıttaki sürüm durumuna bakar; eskiyse bir kez `console.warn` yazar.\n * Hiçbir koşulda hata fırlatmaz: sürüm uyarısı yüzünden müşterinin isteği\n * bozulmamalı.\n */\nexport function noteSdkStatus(headers: HeaderSource | null | undefined): void {\n if (warned || !headers) return;\n\n try {\n const status = headers.get('Signalbird-Sdk-Status');\n\n if (status !== 'outdated' && status !== 'unsupported') return;\n\n warned = true;\n\n const latest = headers.get('Signalbird-Sdk-Latest') ?? '?';\n const message = status === 'unsupported'\n ? `[signalbird] Bu SDK sürümü (${SDK_VERSION}) artık desteklenmiyor. Son sürüm: ${latest}. Paketi güncelleyin.`\n : `[signalbird] Yeni SDK sürümü var: ${latest} (kurulu: ${SDK_VERSION}).`;\n\n if (typeof console !== 'undefined') console.warn(message);\n } catch {\n // uyarı yazılamadıysa sessiz kal\n }\n}\n\n/** Yalnız testler için: uyarıyı yeniden kurar. */\nexport function resetSdkStatusWarning(): void {\n warned = false;\n}\n","/**\n * Telsiz gövdesini sunucunun kabul edeceği biçime getiren yardımcılar.\n *\n * Node ve tarayıcı istemcisi ortak kullanır. Sınıf metodu DEĞİL, modül\n * fonksiyonudur: `check-parity.mjs` istemci sınıfının girintili metotlarını\n * sayar ve buraya eklenen bir yardımcı Telsiz paritesini bozardı.\n */\n\n/**\n * API `message` alanını `max:4000` ile doğrular (Laravel → `mb_strlen`, yani\n * KOD NOKTASI). Sınırı aşan tek satır 422 alır ve toplu gönderimde bütün\n * paketi düşürür - 99 sağlam log bir uzun yığın izi yüzünden kaybolurdu.\n */\nexport const MAX_MESSAGE_LENGTH = 4000;\n\n/**\n * Mesajı 4000 kod noktasına kırpar.\n *\n * `.slice(0, 4000)` UTF-16 birimi sayar ve bir emoji'nin (vekil çift) ortasından\n * kesebilir; tek kalan vekil `\\ud83d` olarak gider ve PHP `json_decode` bütün\n * gövdeyi reddeder - düzeltmeye çalıştığımız hatanın aynısı. `Array.from` kod\n * noktası üzerinden yürür; pahalıdır, bu yüzden yalnız sınır aşıldığında çalışır.\n */\nexport function truncateMessage(message: string): string {\n const text = typeof message === 'string' ? message : String(message);\n\n if (text.length <= MAX_MESSAGE_LENGTH) {\n return text;\n }\n\n return Array.from(text).slice(0, MAX_MESSAGE_LENGTH).join('');\n}\n\n/**\n * `context`'i JSON'a güvenle çevrilebilir bir kopyaya dönüştürür.\n *\n * `JSON.stringify` döngüsel nesnede (ör. `req`, Mongoose belgesi) ve\n * `BigInt`'te İSTİSNA fırlatır. Node'da bu istisna isteğin içinde\n * yakalanıp `NETWORK_ERROR` diye raporlanıyordu - asıl sebep görünmüyordu.\n * Tarayıcıda daha kötüsü: başarısız toplu gönderim kuyruğa geri konur, aynı\n * satır her 3 saniyede tekrar patlar ve arkasındaki bütün loglar takılı kalırdı.\n *\n * - döngüsel başvuru → `\"[Circular]\"` (yalnız ATA zinciri sayılır: aynı nesneye\n * iki kardeş alandan başvurmak döngü değildir ve korunur)\n * - `Error` → `{name, message, stack}` (JSON'da `{}` olurdu, yani bilgi kaybı)\n * - `BigInt` → string\n * - `toJSON` taşıyan nesne (Date vb.) → onun çıktısı\n * - erişimde fırlatan getter → `\"[Unserializable]\"`\n */\nexport function toJsonSafe(value: unknown): unknown {\n const ancestors: object[] = [];\n\n const walk = (current: unknown): unknown => {\n if (typeof current === 'bigint') {\n return current.toString();\n }\n\n // Fonksiyon, symbol ve undefined olduğu gibi kalır: JSON.stringify onları\n // zaten atar (dizide null yapar); burada ayrıca karar vermeye gerek yok.\n if (current === null || typeof current !== 'object') {\n return current;\n }\n\n if (ancestors.includes(current)) {\n return '[Circular]';\n }\n\n if (current instanceof Error) {\n return { name: current.name, message: current.message, stack: current.stack };\n }\n\n const withToJson = current as { toJSON?: () => unknown };\n\n if (typeof withToJson.toJSON === 'function') {\n try {\n ancestors.push(current);\n return walk(withToJson.toJSON());\n } catch {\n return '[Unserializable]';\n } finally {\n ancestors.pop();\n }\n }\n\n ancestors.push(current);\n\n try {\n if (Array.isArray(current)) {\n return current.map((item) => walk(item));\n }\n\n const out: Record<string, unknown> = {};\n\n for (const key of Object.keys(current)) {\n let item: unknown;\n\n try {\n item = (current as Record<string, unknown>)[key];\n } catch {\n item = '[Unserializable]';\n }\n\n out[key] = walk(item);\n }\n\n return out;\n } finally {\n ancestors.pop();\n }\n };\n\n return walk(value);\n}\n\n/** `context` verilmediyse `undefined` kalır (gövdeye hiç girmez). */\nexport function safeContext(context?: Record<string, unknown>): Record<string, unknown> | undefined {\n if (context === undefined || context === null) {\n return undefined;\n }\n\n return toJsonSafe(context) as Record<string, unknown>;\n}\n","/**\n * signalbird/browser - tarayıcı istemcisi.\n *\n * Ayrı bir giriş noktası olmasının sebebi teknik değil, GÜVENLİKTİR: sunucu\n * anahtarı istemciye gömülemez ve sunucu `Origin` başlığı taşıyan bir istekte\n * onu zaten reddeder. Tarayıcı, açık anahtarı (`sb_public_live_…`) kullanır ve\n * güvenliği gizlilikten değil kısıttan gelir: yalnız izinli alan adlarından\n * çalışır ve Origin taşımayan istekte reddedilir (`ORIGIN_REQUIRED`).\n *\n * React, Vue, Angular ve düz JS aynı istemciyi kullanır; çatıya özel sarmalayıcı\n * yoktur çünkü gereken tek şey bir fonksiyon çağrısıdır.\n */\nimport { SDK_HEADER, noteSdkStatus, sdkHeaderValue } from '../shared/version';\nimport { safeContext, truncateMessage } from '../shared/serialize';\n\nexport type Level = 'debug' | 'info' | 'warn' | 'error' | 'critical';\n\nexport interface BrowserConfig {\n /** Açık anahtar (`sb_public_live_…`). Gizli anahtar BURAYA YAZILMAZ. */\n publicKey: string;\n baseUrl?: string;\n source?: string;\n /**\n * Kayıtlar tek tek değil, toplu gider. Kullanıcının tarayıcısından saniyede\n * onlarca istek çıkarmak hem yavaş hem pahalıdır.\n */\n flushIntervalMs?: number;\n maxQueue?: number;\n debug?: boolean;\n}\n\ninterface QueuedEvent {\n key: string;\n message: string;\n level?: Level;\n context?: Record<string, unknown>;\n source?: string;\n}\n\nconst DEFAULT_BASE_URL = 'https://live.signalbird.io/api';\n\nexport class SignalbirdBrowser {\n private queue: QueuedEvent[] = [];\n private timer: ReturnType<typeof setInterval> | null = null;\n private readonly baseUrl: string;\n private readonly maxQueue: number;\n\n constructor(private readonly config: BrowserConfig) {\n if (!config.publicKey?.startsWith('sb_public_live_')) {\n throw new Error(\n 'Signalbird: tarayıcı istemcisi açık anahtar ister (sb_public_live_…). ' +\n 'Gizli anahtarı (sb_secret_live_…) istemci koduna KOYMAYIN.'\n );\n }\n\n this.baseUrl = (config.baseUrl ?? DEFAULT_BASE_URL).replace(/\\/$/, '');\n this.maxQueue = config.maxQueue ?? 50;\n\n if (typeof window !== 'undefined') {\n this.timer = setInterval(() => void this.flush(), config.flushIntervalMs ?? 3000);\n\n // Sekme kapanırken kuyruk boşaltılır. `sendBeacon` sayfa ölürken bile\n // gider; normal fetch yarıda kesilirdi.\n window.addEventListener('pagehide', () => this.flushBeacon());\n }\n }\n\n /**\n * Kanalı bağlar ve yazacı döner - sunucu istemcisindeki `radio()` ile aynı\n * deyim (CONTRACT §1.1):\n *\n * sb.radio('sepet').error('sepet güncellenemedi', { cartId })\n *\n * `critical` BİLEREK yoktur: istemci kodu herkesin elindedir ve oradan\n * kritik alarm (sessiz saatleri delen bildirim) tetiklemek, kötü niyetli\n * birine ekibin telefonunu çaldırma imkânı verirdi. Gerekirse\n * `log(key, msg, 'critical')` hâlâ yazılabilir; kanal ayarı panelde durur.\n */\n radio(key: string) {\n return {\n debug: (message: string, context?: Record<string, unknown>) => this.log(key, message, 'debug', context),\n info: (message: string, context?: Record<string, unknown>) => this.log(key, message, 'info', context),\n warn: (message: string, context?: Record<string, unknown>) => this.log(key, message, 'warn', context),\n error: (message: string, context?: Record<string, unknown>) => this.log(key, message, 'error', context),\n };\n }\n\n log(key: string, message: string, level?: Level, context?: Record<string, unknown>): void {\n /*\n * Kırpma ve güvenli kopya KUYRUĞA GİRERKEN yapılır, gönderirken değil:\n * - 4000'i aşan tek mesaj bütün toplu paketi 422 ile düşürürdü;\n * - döngüsel `context` `JSON.stringify`'da patlar, `flush()` paketi geri\n * kuyruğa koyar ve aynı satır her turda tekrar patlayıp arkasındaki\n * bütün logları sonsuza dek bekletirdi;\n * - kopya o anki durumu saklar; nesne gönderime kadar değişse bile log,\n * yazıldığı andaki değeri taşır.\n */\n this.queue.push({\n key,\n message: truncateMessage(message),\n level,\n context: safeContext(context),\n source: this.config.source,\n });\n\n // Kuyruk dolduysa beklemeden gönder: bellekte sonsuza kadar biriktirmek,\n // logu hiç göndermemekten kötüdür.\n if (this.queue.length >= this.maxQueue) {\n void this.flush();\n }\n }\n\n info(key: string, message: string, context?: Record<string, unknown>) {\n this.log(key, message, 'info', context);\n }\n\n warn(key: string, message: string, context?: Record<string, unknown>) {\n this.log(key, message, 'warn', context);\n }\n\n error(key: string, message: string, context?: Record<string, unknown>) {\n this.log(key, message, 'error', context);\n }\n\n /**\n * Tarayıcıdaki yakalanmamış hataları bağlar.\n *\n * Varsayılan anahtar `browser`dır ve KRİTİK DEĞİLDİR: istemci tarafı kod\n * herkesin elindedir, oradan kritik alarm tetiklemek kötü niyetli birine\n * ekibin telefonunu çaldırma imkânı verirdi. Hangi kanalın kime bildirim\n * göndereceği panelde durur; oradan sessiz bırakılabilir.\n */\n captureErrors(key = 'browser'): () => void {\n const onError = (event: ErrorEvent) => {\n this.error(key, event.message, {\n file: event.filename,\n line: event.lineno,\n column: event.colno,\n url: window.location.href,\n });\n };\n\n const onRejection = (event: PromiseRejectionEvent) => {\n this.error(key, String(event.reason), { url: window.location.href });\n };\n\n window.addEventListener('error', onError);\n window.addEventListener('unhandledrejection', onRejection);\n\n return () => {\n window.removeEventListener('error', onError);\n window.removeEventListener('unhandledrejection', onRejection);\n };\n }\n\n async flush(): Promise<void> {\n if (this.queue.length === 0) return;\n\n const batch = this.queue.splice(0, 100);\n\n try {\n const response = await fetch(`${this.baseUrl}/v1/radio/log/batch`, {\n method: 'POST',\n headers: {\n 'Content-Type': 'application/json',\n 'X-Signalbird-Key': this.config.publicKey,\n [SDK_HEADER]: sdkHeaderValue('browser'),\n },\n body: JSON.stringify({ events: batch }),\n keepalive: true,\n });\n noteSdkStatus(response.headers);\n } catch (error) {\n if (this.config.debug) {\n console.warn('[signalbird] gönderilemedi', error);\n }\n // Kayıtlar geri konur ama kuyruk sınırı aşılmaz: ağ uzun süre kapalıysa\n // sekme belleği şişmemeli.\n this.queue = [...batch, ...this.queue].slice(0, this.maxQueue);\n }\n }\n\n /** Sayfa kapanırken son gönderim. */\n private flushBeacon(): void {\n if (this.queue.length === 0 || typeof navigator === 'undefined') return;\n\n /*\n * `text/plain`, `application/json` DEĞİL: `sendBeacon` CORS ön kontrolü\n * (preflight) yapamaz; \"basit\" olmayan içerik türü taşıyan cross-origin\n * beacon'ı tarayıcı hiç göndermez ve sayfa kapanırken son loglar sessizce\n * kaybolurdu. Gövde yine JSON'dur; API Telsiz log uçlarında text/plain\n * gövdeyi JSON olarak ayrıştırır. `fetch` yolu `application/json` kalır.\n */\n const blob = new Blob(\n [JSON.stringify({ events: this.queue.splice(0, 100) })],\n { type: 'text/plain;charset=UTF-8' }\n );\n\n // sendBeacon özel başlık taşıyamaz; anahtar ve SDK sürümü sorgu dizesinden gider.\n navigator.sendBeacon?.(\n `${this.baseUrl}/v1/radio/log/batch?k=${encodeURIComponent(this.config.publicKey)}` +\n `&sdk=${encodeURIComponent(sdkHeaderValue('browser'))}`,\n blob\n );\n }\n\n destroy(): void {\n if (this.timer) clearInterval(this.timer);\n void this.flush();\n }\n}\n\nlet singleton: SignalbirdBrowser | null = null;\n\n/** Uygulama başlangıcında bir kez çağrılır. */\nexport function initSignalbird(config: BrowserConfig): SignalbirdBrowser {\n singleton = new SignalbirdBrowser(config);\n return singleton;\n}\n\n/** Kurulmamışsa sessizce yok sayar - log çağrısı uygulamayı çökertmemeli. */\nexport function signalbird(): SignalbirdBrowser | null {\n return singleton;\n}\n"]}
|
package/dist/browser.mjs
CHANGED
|
@@ -1,5 +1,5 @@
|
|
|
1
1
|
// src/shared/version.ts
|
|
2
|
-
var SDK_VERSION = "2.
|
|
2
|
+
var SDK_VERSION = "2.9.0" ;
|
|
3
3
|
var SDK_HEADER = "X-Signalbird-Sdk";
|
|
4
4
|
function sdkHeaderValue(platform) {
|
|
5
5
|
return `${platform}/${SDK_VERSION}`;
|
|
@@ -18,6 +18,70 @@ function noteSdkStatus(headers) {
|
|
|
18
18
|
}
|
|
19
19
|
}
|
|
20
20
|
|
|
21
|
+
// src/shared/serialize.ts
|
|
22
|
+
var MAX_MESSAGE_LENGTH = 4e3;
|
|
23
|
+
function truncateMessage(message) {
|
|
24
|
+
const text = typeof message === "string" ? message : String(message);
|
|
25
|
+
if (text.length <= MAX_MESSAGE_LENGTH) {
|
|
26
|
+
return text;
|
|
27
|
+
}
|
|
28
|
+
return Array.from(text).slice(0, MAX_MESSAGE_LENGTH).join("");
|
|
29
|
+
}
|
|
30
|
+
function toJsonSafe(value) {
|
|
31
|
+
const ancestors = [];
|
|
32
|
+
const walk = (current) => {
|
|
33
|
+
if (typeof current === "bigint") {
|
|
34
|
+
return current.toString();
|
|
35
|
+
}
|
|
36
|
+
if (current === null || typeof current !== "object") {
|
|
37
|
+
return current;
|
|
38
|
+
}
|
|
39
|
+
if (ancestors.includes(current)) {
|
|
40
|
+
return "[Circular]";
|
|
41
|
+
}
|
|
42
|
+
if (current instanceof Error) {
|
|
43
|
+
return { name: current.name, message: current.message, stack: current.stack };
|
|
44
|
+
}
|
|
45
|
+
const withToJson = current;
|
|
46
|
+
if (typeof withToJson.toJSON === "function") {
|
|
47
|
+
try {
|
|
48
|
+
ancestors.push(current);
|
|
49
|
+
return walk(withToJson.toJSON());
|
|
50
|
+
} catch {
|
|
51
|
+
return "[Unserializable]";
|
|
52
|
+
} finally {
|
|
53
|
+
ancestors.pop();
|
|
54
|
+
}
|
|
55
|
+
}
|
|
56
|
+
ancestors.push(current);
|
|
57
|
+
try {
|
|
58
|
+
if (Array.isArray(current)) {
|
|
59
|
+
return current.map((item) => walk(item));
|
|
60
|
+
}
|
|
61
|
+
const out = {};
|
|
62
|
+
for (const key of Object.keys(current)) {
|
|
63
|
+
let item;
|
|
64
|
+
try {
|
|
65
|
+
item = current[key];
|
|
66
|
+
} catch {
|
|
67
|
+
item = "[Unserializable]";
|
|
68
|
+
}
|
|
69
|
+
out[key] = walk(item);
|
|
70
|
+
}
|
|
71
|
+
return out;
|
|
72
|
+
} finally {
|
|
73
|
+
ancestors.pop();
|
|
74
|
+
}
|
|
75
|
+
};
|
|
76
|
+
return walk(value);
|
|
77
|
+
}
|
|
78
|
+
function safeContext(context) {
|
|
79
|
+
if (context === void 0 || context === null) {
|
|
80
|
+
return void 0;
|
|
81
|
+
}
|
|
82
|
+
return toJsonSafe(context);
|
|
83
|
+
}
|
|
84
|
+
|
|
21
85
|
// src/browser/index.ts
|
|
22
86
|
var DEFAULT_BASE_URL = "https://live.signalbird.io/api";
|
|
23
87
|
var SignalbirdBrowser = class {
|
|
@@ -37,8 +101,33 @@ var SignalbirdBrowser = class {
|
|
|
37
101
|
window.addEventListener("pagehide", () => this.flushBeacon());
|
|
38
102
|
}
|
|
39
103
|
}
|
|
104
|
+
/**
|
|
105
|
+
* Kanalı bağlar ve yazacı döner - sunucu istemcisindeki `radio()` ile aynı
|
|
106
|
+
* deyim (CONTRACT §1.1):
|
|
107
|
+
*
|
|
108
|
+
* sb.radio('sepet').error('sepet güncellenemedi', { cartId })
|
|
109
|
+
*
|
|
110
|
+
* `critical` BİLEREK yoktur: istemci kodu herkesin elindedir ve oradan
|
|
111
|
+
* kritik alarm (sessiz saatleri delen bildirim) tetiklemek, kötü niyetli
|
|
112
|
+
* birine ekibin telefonunu çaldırma imkânı verirdi. Gerekirse
|
|
113
|
+
* `log(key, msg, 'critical')` hâlâ yazılabilir; kanal ayarı panelde durur.
|
|
114
|
+
*/
|
|
115
|
+
radio(key) {
|
|
116
|
+
return {
|
|
117
|
+
debug: (message, context) => this.log(key, message, "debug", context),
|
|
118
|
+
info: (message, context) => this.log(key, message, "info", context),
|
|
119
|
+
warn: (message, context) => this.log(key, message, "warn", context),
|
|
120
|
+
error: (message, context) => this.log(key, message, "error", context)
|
|
121
|
+
};
|
|
122
|
+
}
|
|
40
123
|
log(key, message, level, context) {
|
|
41
|
-
this.queue.push({
|
|
124
|
+
this.queue.push({
|
|
125
|
+
key,
|
|
126
|
+
message: truncateMessage(message),
|
|
127
|
+
level,
|
|
128
|
+
context: safeContext(context),
|
|
129
|
+
source: this.config.source
|
|
130
|
+
});
|
|
42
131
|
if (this.queue.length >= this.maxQueue) {
|
|
43
132
|
void this.flush();
|
|
44
133
|
}
|
|
@@ -106,7 +195,7 @@ var SignalbirdBrowser = class {
|
|
|
106
195
|
if (this.queue.length === 0 || typeof navigator === "undefined") return;
|
|
107
196
|
const blob = new Blob(
|
|
108
197
|
[JSON.stringify({ events: this.queue.splice(0, 100) })],
|
|
109
|
-
{ type: "
|
|
198
|
+
{ type: "text/plain;charset=UTF-8" }
|
|
110
199
|
);
|
|
111
200
|
navigator.sendBeacon?.(
|
|
112
201
|
`${this.baseUrl}/v1/radio/log/batch?k=${encodeURIComponent(this.config.publicKey)}&sdk=${encodeURIComponent(sdkHeaderValue("browser"))}`,
|
package/dist/browser.mjs.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"sources":["../src/shared/version.ts","../src/browser/index.ts"],"names":[],"mappings":"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","file":"browser.mjs","sourcesContent":["/**\n * SDK sürüm bildirimi - CONTRACT §14.\n *\n * Her istek `X-Signalbird-Sdk: <platform>/<sürüm>` taşır; API bunu kaydeder\n * ve yanıtta `Signalbird-Sdk-Status` (current | outdated | unsupported) ile\n * `Signalbird-Sdk-Latest` döner. SDK eski olduğunu öğrenince geliştiriciye\n * süreç başına BİR KEZ uyarı yazar. Uyarı hata değildir: istek sonucu\n * değişmez, istisna fırlatılmaz.\n *\n * Sürüm numarası derlemede `VERSION` dosyasından gömülür (tsup `define`).\n */\n\ndeclare const __SB_VERSION__: string;\n\nexport const SDK_VERSION: string = typeof __SB_VERSION__ === 'string' ? __SB_VERSION__ : '0.0.0';\n\nexport const SDK_HEADER = 'X-Signalbird-Sdk';\n\n/** `node/2.6.0` - platform adları CONTRACT §14.1'deki listededir. */\nexport function sdkHeaderValue(platform: string): string {\n return `${platform}/${SDK_VERSION}`;\n}\n\n/** Başlık okuyabilen her şey: fetch `Headers`, ya da sahte bir yanıt. */\ninterface HeaderSource {\n get(name: string): string | null;\n}\n\nlet warned = false;\n\n/**\n * Yanıttaki sürüm durumuna bakar; eskiyse bir kez `console.warn` yazar.\n * Hiçbir koşulda hata fırlatmaz: sürüm uyarısı yüzünden müşterinin isteği\n * bozulmamalı.\n */\nexport function noteSdkStatus(headers: HeaderSource | null | undefined): void {\n if (warned || !headers) return;\n\n try {\n const status = headers.get('Signalbird-Sdk-Status');\n\n if (status !== 'outdated' && status !== 'unsupported') return;\n\n warned = true;\n\n const latest = headers.get('Signalbird-Sdk-Latest') ?? '?';\n const message = status === 'unsupported'\n ? `[signalbird] Bu SDK sürümü (${SDK_VERSION}) artık desteklenmiyor. Son sürüm: ${latest}. Paketi güncelleyin.`\n : `[signalbird] Yeni SDK sürümü var: ${latest} (kurulu: ${SDK_VERSION}).`;\n\n if (typeof console !== 'undefined') console.warn(message);\n } catch {\n // uyarı yazılamadıysa sessiz kal\n }\n}\n\n/** Yalnız testler için: uyarıyı yeniden kurar. */\nexport function resetSdkStatusWarning(): void {\n warned = false;\n}\n","/**\n * signalbird/browser - tarayıcı istemcisi.\n *\n * Ayrı bir giriş noktası olmasının sebebi teknik değil, GÜVENLİKTİR: sunucu\n * anahtarı istemciye gömülemez ve sunucu `Origin` başlığı taşıyan bir istekte\n * onu zaten reddeder. Tarayıcı, açık anahtarı (`sb_public_live_…`) kullanır ve\n * güvenliği gizlilikten değil kısıttan gelir: yalnız izinli alan adlarından\n * çalışır ve Origin taşımayan istekte reddedilir (`ORIGIN_REQUIRED`).\n *\n * React, Vue, Angular ve düz JS aynı istemciyi kullanır; çatıya özel sarmalayıcı\n * yoktur çünkü gereken tek şey bir fonksiyon çağrısıdır.\n */\nimport { SDK_HEADER, noteSdkStatus, sdkHeaderValue } from '../shared/version';\n\nexport type Level = 'debug' | 'info' | 'warn' | 'error' | 'critical';\n\nexport interface BrowserConfig {\n /** Açık anahtar (`sb_public_live_…`). Gizli anahtar BURAYA YAZILMAZ. */\n publicKey: string;\n baseUrl?: string;\n source?: string;\n /**\n * Kayıtlar tek tek değil, toplu gider. Kullanıcının tarayıcısından saniyede\n * onlarca istek çıkarmak hem yavaş hem pahalıdır.\n */\n flushIntervalMs?: number;\n maxQueue?: number;\n debug?: boolean;\n}\n\ninterface QueuedEvent {\n key: string;\n message: string;\n level?: Level;\n context?: Record<string, unknown>;\n source?: string;\n}\n\nconst DEFAULT_BASE_URL = 'https://live.signalbird.io/api';\n\nexport class SignalbirdBrowser {\n private queue: QueuedEvent[] = [];\n private timer: ReturnType<typeof setInterval> | null = null;\n private readonly baseUrl: string;\n private readonly maxQueue: number;\n\n constructor(private readonly config: BrowserConfig) {\n if (!config.publicKey?.startsWith('sb_public_live_')) {\n throw new Error(\n 'Signalbird: tarayıcı istemcisi açık anahtar ister (sb_public_live_…). ' +\n 'Gizli anahtarı (sb_secret_live_…) istemci koduna KOYMAYIN.'\n );\n }\n\n this.baseUrl = (config.baseUrl ?? DEFAULT_BASE_URL).replace(/\\/$/, '');\n this.maxQueue = config.maxQueue ?? 50;\n\n if (typeof window !== 'undefined') {\n this.timer = setInterval(() => void this.flush(), config.flushIntervalMs ?? 3000);\n\n // Sekme kapanırken kuyruk boşaltılır. `sendBeacon` sayfa ölürken bile\n // gider; normal fetch yarıda kesilirdi.\n window.addEventListener('pagehide', () => this.flushBeacon());\n }\n }\n\n log(key: string, message: string, level?: Level, context?: Record<string, unknown>): void {\n this.queue.push({ key, message, level, context, source: this.config.source });\n\n // Kuyruk dolduysa beklemeden gönder: bellekte sonsuza kadar biriktirmek,\n // logu hiç göndermemekten kötüdür.\n if (this.queue.length >= this.maxQueue) {\n void this.flush();\n }\n }\n\n info(key: string, message: string, context?: Record<string, unknown>) {\n this.log(key, message, 'info', context);\n }\n\n warn(key: string, message: string, context?: Record<string, unknown>) {\n this.log(key, message, 'warn', context);\n }\n\n error(key: string, message: string, context?: Record<string, unknown>) {\n this.log(key, message, 'error', context);\n }\n\n /**\n * Tarayıcıdaki yakalanmamış hataları bağlar.\n *\n * Varsayılan anahtar `browser`dır ve KRİTİK DEĞİLDİR: istemci tarafı kod\n * herkesin elindedir, oradan kritik alarm tetiklemek kötü niyetli birine\n * ekibin telefonunu çaldırma imkânı verirdi. Hangi kanalın kime bildirim\n * göndereceği panelde durur; oradan sessiz bırakılabilir.\n */\n captureErrors(key = 'browser'): () => void {\n const onError = (event: ErrorEvent) => {\n this.error(key, event.message, {\n file: event.filename,\n line: event.lineno,\n column: event.colno,\n url: window.location.href,\n });\n };\n\n const onRejection = (event: PromiseRejectionEvent) => {\n this.error(key, String(event.reason), { url: window.location.href });\n };\n\n window.addEventListener('error', onError);\n window.addEventListener('unhandledrejection', onRejection);\n\n return () => {\n window.removeEventListener('error', onError);\n window.removeEventListener('unhandledrejection', onRejection);\n };\n }\n\n async flush(): Promise<void> {\n if (this.queue.length === 0) return;\n\n const batch = this.queue.splice(0, 100);\n\n try {\n const response = await fetch(`${this.baseUrl}/v1/radio/log/batch`, {\n method: 'POST',\n headers: {\n 'Content-Type': 'application/json',\n 'X-Signalbird-Key': this.config.publicKey,\n [SDK_HEADER]: sdkHeaderValue('browser'),\n },\n body: JSON.stringify({ events: batch }),\n keepalive: true,\n });\n noteSdkStatus(response.headers);\n } catch (error) {\n if (this.config.debug) {\n console.warn('[signalbird] gönderilemedi', error);\n }\n // Kayıtlar geri konur ama kuyruk sınırı aşılmaz: ağ uzun süre kapalıysa\n // sekme belleği şişmemeli.\n this.queue = [...batch, ...this.queue].slice(0, this.maxQueue);\n }\n }\n\n /** Sayfa kapanırken son gönderim. */\n private flushBeacon(): void {\n if (this.queue.length === 0 || typeof navigator === 'undefined') return;\n\n const blob = new Blob(\n [JSON.stringify({ events: this.queue.splice(0, 100) })],\n { type: 'application/json' }\n );\n\n // sendBeacon özel başlık taşıyamaz; anahtar ve SDK sürümü sorgu dizesinden gider.\n navigator.sendBeacon?.(\n `${this.baseUrl}/v1/radio/log/batch?k=${encodeURIComponent(this.config.publicKey)}` +\n `&sdk=${encodeURIComponent(sdkHeaderValue('browser'))}`,\n blob\n );\n }\n\n destroy(): void {\n if (this.timer) clearInterval(this.timer);\n void this.flush();\n }\n}\n\nlet singleton: SignalbirdBrowser | null = null;\n\n/** Uygulama başlangıcında bir kez çağrılır. */\nexport function initSignalbird(config: BrowserConfig): SignalbirdBrowser {\n singleton = new SignalbirdBrowser(config);\n return singleton;\n}\n\n/** Kurulmamışsa sessizce yok sayar - log çağrısı uygulamayı çökertmemeli. */\nexport function signalbird(): SignalbirdBrowser | null {\n return singleton;\n}\n"]}
|
|
1
|
+
{"version":3,"sources":["../src/shared/version.ts","../src/shared/serialize.ts","../src/browser/index.ts"],"names":[],"mappings":"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","file":"browser.mjs","sourcesContent":["/**\n * SDK sürüm bildirimi - CONTRACT §14.\n *\n * Her istek `X-Signalbird-Sdk: <platform>/<sürüm>` taşır; API bunu kaydeder\n * ve yanıtta `Signalbird-Sdk-Status` (current | outdated | unsupported) ile\n * `Signalbird-Sdk-Latest` döner. SDK eski olduğunu öğrenince geliştiriciye\n * süreç başına BİR KEZ uyarı yazar. Uyarı hata değildir: istek sonucu\n * değişmez, istisna fırlatılmaz.\n *\n * Sürüm numarası derlemede `VERSION` dosyasından gömülür (tsup `define`).\n */\n\ndeclare const __SB_VERSION__: string;\n\nexport const SDK_VERSION: string = typeof __SB_VERSION__ === 'string' ? __SB_VERSION__ : '0.0.0';\n\nexport const SDK_HEADER = 'X-Signalbird-Sdk';\n\n/** `node/2.6.0` - platform adları CONTRACT §14.1'deki listededir. */\nexport function sdkHeaderValue(platform: string): string {\n return `${platform}/${SDK_VERSION}`;\n}\n\n/** Başlık okuyabilen her şey: fetch `Headers`, ya da sahte bir yanıt. */\ninterface HeaderSource {\n get(name: string): string | null;\n}\n\nlet warned = false;\n\n/**\n * Yanıttaki sürüm durumuna bakar; eskiyse bir kez `console.warn` yazar.\n * Hiçbir koşulda hata fırlatmaz: sürüm uyarısı yüzünden müşterinin isteği\n * bozulmamalı.\n */\nexport function noteSdkStatus(headers: HeaderSource | null | undefined): void {\n if (warned || !headers) return;\n\n try {\n const status = headers.get('Signalbird-Sdk-Status');\n\n if (status !== 'outdated' && status !== 'unsupported') return;\n\n warned = true;\n\n const latest = headers.get('Signalbird-Sdk-Latest') ?? '?';\n const message = status === 'unsupported'\n ? `[signalbird] Bu SDK sürümü (${SDK_VERSION}) artık desteklenmiyor. Son sürüm: ${latest}. Paketi güncelleyin.`\n : `[signalbird] Yeni SDK sürümü var: ${latest} (kurulu: ${SDK_VERSION}).`;\n\n if (typeof console !== 'undefined') console.warn(message);\n } catch {\n // uyarı yazılamadıysa sessiz kal\n }\n}\n\n/** Yalnız testler için: uyarıyı yeniden kurar. */\nexport function resetSdkStatusWarning(): void {\n warned = false;\n}\n","/**\n * Telsiz gövdesini sunucunun kabul edeceği biçime getiren yardımcılar.\n *\n * Node ve tarayıcı istemcisi ortak kullanır. Sınıf metodu DEĞİL, modül\n * fonksiyonudur: `check-parity.mjs` istemci sınıfının girintili metotlarını\n * sayar ve buraya eklenen bir yardımcı Telsiz paritesini bozardı.\n */\n\n/**\n * API `message` alanını `max:4000` ile doğrular (Laravel → `mb_strlen`, yani\n * KOD NOKTASI). Sınırı aşan tek satır 422 alır ve toplu gönderimde bütün\n * paketi düşürür - 99 sağlam log bir uzun yığın izi yüzünden kaybolurdu.\n */\nexport const MAX_MESSAGE_LENGTH = 4000;\n\n/**\n * Mesajı 4000 kod noktasına kırpar.\n *\n * `.slice(0, 4000)` UTF-16 birimi sayar ve bir emoji'nin (vekil çift) ortasından\n * kesebilir; tek kalan vekil `\\ud83d` olarak gider ve PHP `json_decode` bütün\n * gövdeyi reddeder - düzeltmeye çalıştığımız hatanın aynısı. `Array.from` kod\n * noktası üzerinden yürür; pahalıdır, bu yüzden yalnız sınır aşıldığında çalışır.\n */\nexport function truncateMessage(message: string): string {\n const text = typeof message === 'string' ? message : String(message);\n\n if (text.length <= MAX_MESSAGE_LENGTH) {\n return text;\n }\n\n return Array.from(text).slice(0, MAX_MESSAGE_LENGTH).join('');\n}\n\n/**\n * `context`'i JSON'a güvenle çevrilebilir bir kopyaya dönüştürür.\n *\n * `JSON.stringify` döngüsel nesnede (ör. `req`, Mongoose belgesi) ve\n * `BigInt`'te İSTİSNA fırlatır. Node'da bu istisna isteğin içinde\n * yakalanıp `NETWORK_ERROR` diye raporlanıyordu - asıl sebep görünmüyordu.\n * Tarayıcıda daha kötüsü: başarısız toplu gönderim kuyruğa geri konur, aynı\n * satır her 3 saniyede tekrar patlar ve arkasındaki bütün loglar takılı kalırdı.\n *\n * - döngüsel başvuru → `\"[Circular]\"` (yalnız ATA zinciri sayılır: aynı nesneye\n * iki kardeş alandan başvurmak döngü değildir ve korunur)\n * - `Error` → `{name, message, stack}` (JSON'da `{}` olurdu, yani bilgi kaybı)\n * - `BigInt` → string\n * - `toJSON` taşıyan nesne (Date vb.) → onun çıktısı\n * - erişimde fırlatan getter → `\"[Unserializable]\"`\n */\nexport function toJsonSafe(value: unknown): unknown {\n const ancestors: object[] = [];\n\n const walk = (current: unknown): unknown => {\n if (typeof current === 'bigint') {\n return current.toString();\n }\n\n // Fonksiyon, symbol ve undefined olduğu gibi kalır: JSON.stringify onları\n // zaten atar (dizide null yapar); burada ayrıca karar vermeye gerek yok.\n if (current === null || typeof current !== 'object') {\n return current;\n }\n\n if (ancestors.includes(current)) {\n return '[Circular]';\n }\n\n if (current instanceof Error) {\n return { name: current.name, message: current.message, stack: current.stack };\n }\n\n const withToJson = current as { toJSON?: () => unknown };\n\n if (typeof withToJson.toJSON === 'function') {\n try {\n ancestors.push(current);\n return walk(withToJson.toJSON());\n } catch {\n return '[Unserializable]';\n } finally {\n ancestors.pop();\n }\n }\n\n ancestors.push(current);\n\n try {\n if (Array.isArray(current)) {\n return current.map((item) => walk(item));\n }\n\n const out: Record<string, unknown> = {};\n\n for (const key of Object.keys(current)) {\n let item: unknown;\n\n try {\n item = (current as Record<string, unknown>)[key];\n } catch {\n item = '[Unserializable]';\n }\n\n out[key] = walk(item);\n }\n\n return out;\n } finally {\n ancestors.pop();\n }\n };\n\n return walk(value);\n}\n\n/** `context` verilmediyse `undefined` kalır (gövdeye hiç girmez). */\nexport function safeContext(context?: Record<string, unknown>): Record<string, unknown> | undefined {\n if (context === undefined || context === null) {\n return undefined;\n }\n\n return toJsonSafe(context) as Record<string, unknown>;\n}\n","/**\n * signalbird/browser - tarayıcı istemcisi.\n *\n * Ayrı bir giriş noktası olmasının sebebi teknik değil, GÜVENLİKTİR: sunucu\n * anahtarı istemciye gömülemez ve sunucu `Origin` başlığı taşıyan bir istekte\n * onu zaten reddeder. Tarayıcı, açık anahtarı (`sb_public_live_…`) kullanır ve\n * güvenliği gizlilikten değil kısıttan gelir: yalnız izinli alan adlarından\n * çalışır ve Origin taşımayan istekte reddedilir (`ORIGIN_REQUIRED`).\n *\n * React, Vue, Angular ve düz JS aynı istemciyi kullanır; çatıya özel sarmalayıcı\n * yoktur çünkü gereken tek şey bir fonksiyon çağrısıdır.\n */\nimport { SDK_HEADER, noteSdkStatus, sdkHeaderValue } from '../shared/version';\nimport { safeContext, truncateMessage } from '../shared/serialize';\n\nexport type Level = 'debug' | 'info' | 'warn' | 'error' | 'critical';\n\nexport interface BrowserConfig {\n /** Açık anahtar (`sb_public_live_…`). Gizli anahtar BURAYA YAZILMAZ. */\n publicKey: string;\n baseUrl?: string;\n source?: string;\n /**\n * Kayıtlar tek tek değil, toplu gider. Kullanıcının tarayıcısından saniyede\n * onlarca istek çıkarmak hem yavaş hem pahalıdır.\n */\n flushIntervalMs?: number;\n maxQueue?: number;\n debug?: boolean;\n}\n\ninterface QueuedEvent {\n key: string;\n message: string;\n level?: Level;\n context?: Record<string, unknown>;\n source?: string;\n}\n\nconst DEFAULT_BASE_URL = 'https://live.signalbird.io/api';\n\nexport class SignalbirdBrowser {\n private queue: QueuedEvent[] = [];\n private timer: ReturnType<typeof setInterval> | null = null;\n private readonly baseUrl: string;\n private readonly maxQueue: number;\n\n constructor(private readonly config: BrowserConfig) {\n if (!config.publicKey?.startsWith('sb_public_live_')) {\n throw new Error(\n 'Signalbird: tarayıcı istemcisi açık anahtar ister (sb_public_live_…). ' +\n 'Gizli anahtarı (sb_secret_live_…) istemci koduna KOYMAYIN.'\n );\n }\n\n this.baseUrl = (config.baseUrl ?? DEFAULT_BASE_URL).replace(/\\/$/, '');\n this.maxQueue = config.maxQueue ?? 50;\n\n if (typeof window !== 'undefined') {\n this.timer = setInterval(() => void this.flush(), config.flushIntervalMs ?? 3000);\n\n // Sekme kapanırken kuyruk boşaltılır. `sendBeacon` sayfa ölürken bile\n // gider; normal fetch yarıda kesilirdi.\n window.addEventListener('pagehide', () => this.flushBeacon());\n }\n }\n\n /**\n * Kanalı bağlar ve yazacı döner - sunucu istemcisindeki `radio()` ile aynı\n * deyim (CONTRACT §1.1):\n *\n * sb.radio('sepet').error('sepet güncellenemedi', { cartId })\n *\n * `critical` BİLEREK yoktur: istemci kodu herkesin elindedir ve oradan\n * kritik alarm (sessiz saatleri delen bildirim) tetiklemek, kötü niyetli\n * birine ekibin telefonunu çaldırma imkânı verirdi. Gerekirse\n * `log(key, msg, 'critical')` hâlâ yazılabilir; kanal ayarı panelde durur.\n */\n radio(key: string) {\n return {\n debug: (message: string, context?: Record<string, unknown>) => this.log(key, message, 'debug', context),\n info: (message: string, context?: Record<string, unknown>) => this.log(key, message, 'info', context),\n warn: (message: string, context?: Record<string, unknown>) => this.log(key, message, 'warn', context),\n error: (message: string, context?: Record<string, unknown>) => this.log(key, message, 'error', context),\n };\n }\n\n log(key: string, message: string, level?: Level, context?: Record<string, unknown>): void {\n /*\n * Kırpma ve güvenli kopya KUYRUĞA GİRERKEN yapılır, gönderirken değil:\n * - 4000'i aşan tek mesaj bütün toplu paketi 422 ile düşürürdü;\n * - döngüsel `context` `JSON.stringify`'da patlar, `flush()` paketi geri\n * kuyruğa koyar ve aynı satır her turda tekrar patlayıp arkasındaki\n * bütün logları sonsuza dek bekletirdi;\n * - kopya o anki durumu saklar; nesne gönderime kadar değişse bile log,\n * yazıldığı andaki değeri taşır.\n */\n this.queue.push({\n key,\n message: truncateMessage(message),\n level,\n context: safeContext(context),\n source: this.config.source,\n });\n\n // Kuyruk dolduysa beklemeden gönder: bellekte sonsuza kadar biriktirmek,\n // logu hiç göndermemekten kötüdür.\n if (this.queue.length >= this.maxQueue) {\n void this.flush();\n }\n }\n\n info(key: string, message: string, context?: Record<string, unknown>) {\n this.log(key, message, 'info', context);\n }\n\n warn(key: string, message: string, context?: Record<string, unknown>) {\n this.log(key, message, 'warn', context);\n }\n\n error(key: string, message: string, context?: Record<string, unknown>) {\n this.log(key, message, 'error', context);\n }\n\n /**\n * Tarayıcıdaki yakalanmamış hataları bağlar.\n *\n * Varsayılan anahtar `browser`dır ve KRİTİK DEĞİLDİR: istemci tarafı kod\n * herkesin elindedir, oradan kritik alarm tetiklemek kötü niyetli birine\n * ekibin telefonunu çaldırma imkânı verirdi. Hangi kanalın kime bildirim\n * göndereceği panelde durur; oradan sessiz bırakılabilir.\n */\n captureErrors(key = 'browser'): () => void {\n const onError = (event: ErrorEvent) => {\n this.error(key, event.message, {\n file: event.filename,\n line: event.lineno,\n column: event.colno,\n url: window.location.href,\n });\n };\n\n const onRejection = (event: PromiseRejectionEvent) => {\n this.error(key, String(event.reason), { url: window.location.href });\n };\n\n window.addEventListener('error', onError);\n window.addEventListener('unhandledrejection', onRejection);\n\n return () => {\n window.removeEventListener('error', onError);\n window.removeEventListener('unhandledrejection', onRejection);\n };\n }\n\n async flush(): Promise<void> {\n if (this.queue.length === 0) return;\n\n const batch = this.queue.splice(0, 100);\n\n try {\n const response = await fetch(`${this.baseUrl}/v1/radio/log/batch`, {\n method: 'POST',\n headers: {\n 'Content-Type': 'application/json',\n 'X-Signalbird-Key': this.config.publicKey,\n [SDK_HEADER]: sdkHeaderValue('browser'),\n },\n body: JSON.stringify({ events: batch }),\n keepalive: true,\n });\n noteSdkStatus(response.headers);\n } catch (error) {\n if (this.config.debug) {\n console.warn('[signalbird] gönderilemedi', error);\n }\n // Kayıtlar geri konur ama kuyruk sınırı aşılmaz: ağ uzun süre kapalıysa\n // sekme belleği şişmemeli.\n this.queue = [...batch, ...this.queue].slice(0, this.maxQueue);\n }\n }\n\n /** Sayfa kapanırken son gönderim. */\n private flushBeacon(): void {\n if (this.queue.length === 0 || typeof navigator === 'undefined') return;\n\n /*\n * `text/plain`, `application/json` DEĞİL: `sendBeacon` CORS ön kontrolü\n * (preflight) yapamaz; \"basit\" olmayan içerik türü taşıyan cross-origin\n * beacon'ı tarayıcı hiç göndermez ve sayfa kapanırken son loglar sessizce\n * kaybolurdu. Gövde yine JSON'dur; API Telsiz log uçlarında text/plain\n * gövdeyi JSON olarak ayrıştırır. `fetch` yolu `application/json` kalır.\n */\n const blob = new Blob(\n [JSON.stringify({ events: this.queue.splice(0, 100) })],\n { type: 'text/plain;charset=UTF-8' }\n );\n\n // sendBeacon özel başlık taşıyamaz; anahtar ve SDK sürümü sorgu dizesinden gider.\n navigator.sendBeacon?.(\n `${this.baseUrl}/v1/radio/log/batch?k=${encodeURIComponent(this.config.publicKey)}` +\n `&sdk=${encodeURIComponent(sdkHeaderValue('browser'))}`,\n blob\n );\n }\n\n destroy(): void {\n if (this.timer) clearInterval(this.timer);\n void this.flush();\n }\n}\n\nlet singleton: SignalbirdBrowser | null = null;\n\n/** Uygulama başlangıcında bir kez çağrılır. */\nexport function initSignalbird(config: BrowserConfig): SignalbirdBrowser {\n singleton = new SignalbirdBrowser(config);\n return singleton;\n}\n\n/** Kurulmamışsa sessizce yok sayar - log çağrısı uygulamayı çökertmemeli. */\nexport function signalbird(): SignalbirdBrowser | null {\n return singleton;\n}\n"]}
|
package/dist/index.d.mts
CHANGED
|
@@ -57,7 +57,7 @@ interface LogResult {
|
|
|
57
57
|
ok: boolean;
|
|
58
58
|
/** Sunucunun döndüğü olay kimliği (rev_…). */
|
|
59
59
|
eventId?: string;
|
|
60
|
-
/** Reddedildiyse sebep:
|
|
60
|
+
/** Reddedildiyse sebep: DOMAIN_KEY_INVALID, MODULE_DISABLED, MODULE_KEY_DISABLED, LIMIT_REACHED… */
|
|
61
61
|
code?: string;
|
|
62
62
|
status?: number;
|
|
63
63
|
}
|
|
@@ -114,13 +114,22 @@ declare class SignalbirdClient {
|
|
|
114
114
|
error: (message: string, context?: Record<string, unknown>) => Promise<LogResult>;
|
|
115
115
|
critical: (message: string, context?: Record<string, unknown>) => Promise<LogResult>;
|
|
116
116
|
};
|
|
117
|
-
/**
|
|
117
|
+
/**
|
|
118
|
+
* Tek kayıt gönderir.
|
|
119
|
+
*
|
|
120
|
+
* `message` 4000 kod noktasına kırpılır (API sınırı; aşan satır 422 alırdı)
|
|
121
|
+
* ve `context` güvenli kopyaya çevrilir: döngüsel nesne ya da BigInt artık
|
|
122
|
+
* `NETWORK_ERROR` gibi görünen bir istisnaya dönüşmez.
|
|
123
|
+
*/
|
|
118
124
|
log(input: LogInput): Promise<LogResult>;
|
|
119
125
|
/**
|
|
120
126
|
* Toplu gönderim - 100 kayda kadar.
|
|
121
127
|
*
|
|
122
128
|
* Kısmi başarı normaldir (kota tam ortada dolabilir), o yüzden sonuç tek bir
|
|
123
129
|
* durum değil satır satır döner.
|
|
130
|
+
*
|
|
131
|
+
* Doğrulama ise satır satır DEĞİLDİR: tek bir geçersiz satır (4000'i aşan
|
|
132
|
+
* mesaj) bütün paketi 422 ile düşürür. Bu yüzden kırpma burada da yapılır.
|
|
124
133
|
*/
|
|
125
134
|
batch(events: LogInput[]): Promise<BatchResult>;
|
|
126
135
|
debugLog(key: string, message: string, context?: Record<string, unknown>): Promise<LogResult>;
|
|
@@ -128,6 +137,17 @@ declare class SignalbirdClient {
|
|
|
128
137
|
warn(key: string, message: string, context?: Record<string, unknown>): Promise<LogResult>;
|
|
129
138
|
error(key: string, message: string, context?: Record<string, unknown>): Promise<LogResult>;
|
|
130
139
|
critical(key: string, message: string, context?: Record<string, unknown>): Promise<LogResult>;
|
|
140
|
+
/**
|
|
141
|
+
* Kimlik doğrulama hash'i (CONTRACT §15.2) - sohbet/push ziyaretçisinin
|
|
142
|
+
* `external_id`'sini GÜVENİLİR kılar.
|
|
143
|
+
*
|
|
144
|
+
* identity_hash = hex(HMAC-SHA256(hex(SHA-256(secretKey)), externalId))
|
|
145
|
+
*
|
|
146
|
+
* Anahtar gizli anahtarın kendisi değil SHA-256 özetidir: sunucu anahtarı
|
|
147
|
+
* düz saklamaz. Hash sunucuda üretilir, sayfaya `external_id` ile birlikte
|
|
148
|
+
* yazılır; gizli anahtar istemciye İNMEZ.
|
|
149
|
+
*/
|
|
150
|
+
identityHash(externalId: string): string;
|
|
131
151
|
/**
|
|
132
152
|
* Yakalanmamış hataları Telsiz'e bağlar.
|
|
133
153
|
*
|
|
@@ -148,7 +168,7 @@ declare class SignalbirdClient {
|
|
|
148
168
|
* bulunur ve iki doküman arasında çeviri tablosu gerekmez.
|
|
149
169
|
*/
|
|
150
170
|
interface MessagingConfig {
|
|
151
|
-
/**
|
|
171
|
+
/** Gizli domain anahtarı (`sb_secret_live_…`). Yalnız sunucuda kullanılır. */
|
|
152
172
|
domainKey: string;
|
|
153
173
|
/** Varsayılan: https://live.signalbird.io/api */
|
|
154
174
|
baseUrl?: string;
|
|
@@ -174,22 +194,96 @@ type SbResult$1<T> = {
|
|
|
174
194
|
/** İleti sınıfı - API'de zorunludur ve varsayılanı YOKTUR (hukuki kapı). */
|
|
175
195
|
type MessageClass = 'transactional' | 'commercial';
|
|
176
196
|
type Channel = 'email' | 'sms' | 'push';
|
|
197
|
+
/** E-posta eki - içerik base64; toplam çözülmüş boyut sınırı sunucudadır (7 MB). */
|
|
198
|
+
interface EmailAttachment {
|
|
199
|
+
filename: string;
|
|
200
|
+
mime?: string;
|
|
201
|
+
/** Dosya içeriği, base64. */
|
|
202
|
+
content_b64: string;
|
|
203
|
+
}
|
|
204
|
+
/**
|
|
205
|
+
* `POST /v1/email/send` gövdesi - alanlar API doğrulamasıyla birebir
|
|
206
|
+
* (signalbird.api `Api\V1\MessagingController::sendEmail`).
|
|
207
|
+
*
|
|
208
|
+
* İçerik iki yoldan gelir: ya `subject` + `body`, ya panelde tanımlı bir
|
|
209
|
+
* şablon (`template` adıyla ya da `template_id` ile). Şablon verilmediyse
|
|
210
|
+
* `subject` ve `body` ZORUNLUDUR (API: `required_without_all:template_id,template`);
|
|
211
|
+
* verildiyse ikisi de şablondan gelir ve istenirse ezilebilir.
|
|
212
|
+
*
|
|
213
|
+
* Tip bilerek arayüz olarak kaldı (birleşim tipi değil): kullanıcı kodunda
|
|
214
|
+
* `extends SendEmailInput` yazan herkes kırılırdı.
|
|
215
|
+
*/
|
|
177
216
|
interface SendEmailInput {
|
|
217
|
+
/** Alıcı e-posta adresi. */
|
|
178
218
|
to: string;
|
|
219
|
+
/** Zorunlu, varsayılanı yok: işlemsel ile ticari arasındaki fark hukukidir. */
|
|
179
220
|
class: MessageClass;
|
|
180
|
-
|
|
221
|
+
/** Konu (en fazla 255). Şablon yoksa zorunlu. */
|
|
222
|
+
subject?: string;
|
|
223
|
+
/** Gövde - HTML ya da düz metin. Şablon yoksa zorunlu. */
|
|
181
224
|
body?: string;
|
|
182
|
-
|
|
225
|
+
/** Panelde tanımlı şablonun ADI (en fazla 190). Ad tercih edilir: şablon yeniden yaratılsa da kod değişmez. */
|
|
226
|
+
template?: string;
|
|
227
|
+
/** Panelde tanımlı şablonun kimliği. */
|
|
228
|
+
template_id?: number;
|
|
229
|
+
/** Şablon/gövde değişkenleri - `{{ad}}` yerine geçer. */
|
|
183
230
|
vars?: Record<string, unknown>;
|
|
231
|
+
/**
|
|
232
|
+
* GÖNDERİCİ KANALI: panelde adresle birlikte açılan `email` modül anahtarı
|
|
233
|
+
* (`noReply`). From adresini kanal seçer - PHP'deki
|
|
234
|
+
* `Signalbird::sendMail('noReply')` karşılığı. Kanala adres bağlanmamışsa
|
|
235
|
+
* 422 `SENDER_NOT_CONFIGURED`; tanımsız kanal `MODULE_KEY_NOT_FOUND`.
|
|
236
|
+
*/
|
|
237
|
+
module_key?: string;
|
|
238
|
+
/** Belirli bir doğrulanmış gönderen alan adından çıksın. */
|
|
184
239
|
sending_domain_id?: number;
|
|
240
|
+
/** Gönderen ADRES seçimi (destek@…); alan adını da belirler. `module_key` verilirse kanalınki geçerlidir. */
|
|
241
|
+
sending_address_id?: number;
|
|
242
|
+
/** Signalbird'deki kişi kaydı - açılma/tıklama geçmişi ona yazılsın. */
|
|
185
243
|
contact_id?: number;
|
|
244
|
+
/** Görünen gönderen adı (en fazla 120). Zarf adresi değil. */
|
|
245
|
+
from_name?: string;
|
|
246
|
+
/** "Yanıtla" adresi. */
|
|
247
|
+
reply_to?: string;
|
|
248
|
+
/** En fazla 5 ek. */
|
|
249
|
+
attachments?: EmailAttachment[];
|
|
250
|
+
/**
|
|
251
|
+
* @deprecated API bu alanı hiç okumaz ve SDK onu GÖNDERMEZ (2.9.0). Şablon
|
|
252
|
+
* için `template` (ad) ya da `template_id` kullanın. Yalnız eski kodun tip
|
|
253
|
+
* denetiminde kırılmaması için tanımlı; başka bir alana eşlenmez.
|
|
254
|
+
*/
|
|
255
|
+
template_hash?: string;
|
|
186
256
|
}
|
|
257
|
+
/**
|
|
258
|
+
* `POST /v1/sms/send` gövdesi - alanlar API doğrulamasıyla birebir
|
|
259
|
+
* (signalbird.api `Api\V1\MessagingController::sendSms`).
|
|
260
|
+
*
|
|
261
|
+
* İçerik ya `body` ya da panelde tanımlı bir şablondur (`template` adıyla ya
|
|
262
|
+
* da `template_id` ile). Şablon verilmediyse `body` ZORUNLUDUR (API:
|
|
263
|
+
* `required_without_all:template_id,template`).
|
|
264
|
+
*
|
|
265
|
+
* E-postanın aksine SMS ucunda gönderici KANALI (`module_key`) yoktur;
|
|
266
|
+
* gönderen adı `sender` ile seçilir.
|
|
267
|
+
*/
|
|
187
268
|
interface SendSmsInput {
|
|
269
|
+
/** Alıcı telefon (en fazla 20). Sunucu normalize eder; geçersizse 422 `INVALID_PHONE`. */
|
|
188
270
|
to: string;
|
|
271
|
+
/** Zorunlu, varsayılanı yok: işlemsel ile ticari arasındaki fark hukukidir. */
|
|
189
272
|
class: MessageClass;
|
|
190
|
-
|
|
273
|
+
/** Mesaj metni (en fazla 1600). Şablon yoksa zorunlu. */
|
|
274
|
+
body?: string;
|
|
275
|
+
/** Panelde tanımlı şablonun ADI (en fazla 190). */
|
|
276
|
+
template?: string;
|
|
277
|
+
/** Panelde tanımlı şablonun kimliği. */
|
|
278
|
+
template_id?: number;
|
|
279
|
+
/** Şablon/gövde değişkenleri - `{{ad}}` yerine geçer. */
|
|
280
|
+
vars?: Record<string, unknown>;
|
|
281
|
+
/** Marka (SMS başlığı/kotası bu markadan). */
|
|
191
282
|
brand_id?: number;
|
|
283
|
+
/** Signalbird'deki kişi kaydı. */
|
|
192
284
|
contact_id?: number;
|
|
285
|
+
/** Onaylı SMS gönderici adı (en fazla 11). Verilmezse şirketin varsayılanı. */
|
|
286
|
+
sender?: string;
|
|
193
287
|
}
|
|
194
288
|
interface SendPushInput {
|
|
195
289
|
/** Cihaz token'ı, `contact:<id>` ya da `external:<external_id>`. */
|
|
@@ -599,7 +693,7 @@ interface EmbedToken {
|
|
|
599
693
|
}
|
|
600
694
|
|
|
601
695
|
interface ManagementConfig {
|
|
602
|
-
/**
|
|
696
|
+
/** Gizli domain anahtarı (`sb_secret_live_…`). Scope yoktur (v2); yalnız gömme jetonu ayrı onay ister. */
|
|
603
697
|
domainKey: string;
|
|
604
698
|
/** Varsayılan: https://live.signalbird.io/api */
|
|
605
699
|
baseUrl?: string;
|
|
@@ -913,9 +1007,9 @@ interface TeamEmbedTokenInput {
|
|
|
913
1007
|
* kayıtlarına dokunur; başka takımın kaydı 404 döner.
|
|
914
1008
|
*
|
|
915
1009
|
* Neden ayrı sınıf: Gönderim (`SignalbirdMessaging`) ileti gönderir ve kota
|
|
916
|
-
* harcar; bu istemci yapılandırma değiştirir. Aynı
|
|
917
|
-
* (`
|
|
918
|
-
*
|
|
1010
|
+
* harcar; bu istemci yapılandırma değiştirir. Aynı gizli domain anahtarını
|
|
1011
|
+
* (`sb_secret_live_…`) kullanırlar ama hata kümeleri farklıdır - tek sınıfta
|
|
1012
|
+
* birleşseydi her metotta "bu kod hangi yüzeyin" sorusu sorulurdu.
|
|
919
1013
|
*
|
|
920
1014
|
* Sözleşme: docs/CONTRACT.md § 10
|
|
921
1015
|
*/
|
|
@@ -1055,7 +1149,7 @@ declare class SignalbirdManagement {
|
|
|
1055
1149
|
*
|
|
1056
1150
|
* **Bu, CLAUDE.md'deki "Admin yüzeyi OLMAYACAK" kuralının bilinçli
|
|
1057
1151
|
* istisnasıdır** ve istisna olduğu için ayrı anahtar türü taşır. Kural,
|
|
1058
|
-
* müşterinin kendi anahtarıyla
|
|
1152
|
+
* müşterinin kendi anahtarıyla şirket açamaması içindi; o kural aynen
|
|
1059
1153
|
* duruyor. Sözleşmeli partner farklı bir taraftır.
|
|
1060
1154
|
*
|
|
1061
1155
|
* Gizli anahtar **asla tarayıcıya inmez**: gömme jetonunu partner'ın
|
|
@@ -1162,11 +1256,12 @@ declare function verifyWebhook(rawBody: string | Uint8Array, signatureHeader: st
|
|
|
1162
1256
|
* Node betikleri buradan alır. TARAYICI için `signalbird/browser`
|
|
1163
1257
|
* kullanılır - gizli anahtar istemciye inmez.
|
|
1164
1258
|
*
|
|
1165
|
-
*
|
|
1166
|
-
*
|
|
1167
|
-
* - `
|
|
1168
|
-
* - `
|
|
1169
|
-
*
|
|
1259
|
+
* Sunucu istemcilerinin HEPSİ aynı gizli domain anahtarını (`sb_secret_live_…`)
|
|
1260
|
+
* kullanır; ayrım anahtarda değil, kapıdadır:
|
|
1261
|
+
* - `SignalbirdClient` → Telsiz (log yazma)
|
|
1262
|
+
* - `SignalbirdMessaging` → Gönderim (e-posta/SMS/push/kişi/kampanya)
|
|
1263
|
+
* - `SignalbirdManagement` → Yönetim (olay akışı, modül anahtarları, sohbet
|
|
1264
|
+
* gelen kutusu)
|
|
1170
1265
|
* - `SignalbirdPartner` → Partner (müşteri sağlama, modül yetkisi, gömme),
|
|
1171
1266
|
* gizli anahtar - yalnız sözleşmeli platformlar
|
|
1172
1267
|
*
|
|
@@ -1190,8 +1285,8 @@ declare function resetSignalbird(): void;
|
|
|
1190
1285
|
/**
|
|
1191
1286
|
* Ortam değişkeninden kurulan paylaşımlı yönetim istemcisi.
|
|
1192
1287
|
*
|
|
1193
|
-
* `SIGNALBIRD_DOMAIN_KEY` okunur
|
|
1194
|
-
*
|
|
1288
|
+
* `SIGNALBIRD_DOMAIN_KEY` okunur - Telsiz ve Gönderim ile aynı gizli domain
|
|
1289
|
+
* anahtarı (`sb_secret_live_…`).
|
|
1195
1290
|
*
|
|
1196
1291
|
* import { management } from 'signalbird'
|
|
1197
1292
|
* await management().createModuleKey('logger', { title: 'Kritik API hatası' })
|
|
@@ -1200,4 +1295,4 @@ declare function management(config?: Partial<ManagementConfig>): SignalbirdManag
|
|
|
1200
1295
|
/** Test ve sıcak yeniden yükleme için yönetim istemcisini sıfırlar. */
|
|
1201
1296
|
declare function resetManagement(): void;
|
|
1202
1297
|
|
|
1203
|
-
export { type AddDomainInput, type AddDomainResult, type AppDevice, type AppPlatform, type Batch, type BatchResult, type BulkContactsInput, type BulkContactsResult, type CampaignCreateResult, type CampaignDetail, type CannedReply, type CannedReplyInput, type Channel, type ChatConversation, type ChatMessage, type ChatVisitor, type Contact, type ContactInput, type ContactList, type ConversationStatus, type CreateCampaignInput, type CreateCompanyInput, type CreateCompanyResult, type CreateContactListInput, DEFAULT_BASE_URL, type DnsRecord, type EmbedModule, type EmbedToken, type EmbedTokenInput, type GrantModuleInput, type Level, type ListAppDevicesQuery, type ListCampaignMessagesQuery, type ListCampaignsQuery, type ListChatMessagesQuery, type ListContactsQuery, type ListConversationsQuery, type ListMessagesQuery, type ListRadioEventsQuery, type LogInput, type LogResult, type ManagementConfig, type Message, type MessageClass, type MessagingConfig, type MessagingErrorCode, type ModuleEntitlement, type Paginated$1 as Paginated, type PartnerCompany, type PartnerConfig, type PartnerDomain, type PartnerOwnerInput, type PartnerUser, type PartnerUserInput, type RadioEvent, type RadioLevel, type ReplyInput, type SbResult$1 as SbResult, type SendEmailInput, type SendPushInput, type SendResult, type SendSmsInput, SignalbirdClient, type SignalbirdConfig, SignalbirdError, SignalbirdManagement, SignalbirdMessaging, SignalbirdPartner, type SmsPreview, type StartConversationInput, type TeamEmbedTokenInput, type UpdateConversationInput, type UpdateVisitorInput, type UptimeIncident, type UptimeRange, type UptimeReport, type VerifyDomainResult, management, resetManagement, resetSignalbird, signalbird, verifyWebhook };
|
|
1298
|
+
export { type AddDomainInput, type AddDomainResult, type AppDevice, type AppPlatform, type Batch, type BatchResult, type BulkContactsInput, type BulkContactsResult, type CampaignCreateResult, type CampaignDetail, type CannedReply, type CannedReplyInput, type Channel, type ChatConversation, type ChatMessage, type ChatVisitor, type Contact, type ContactInput, type ContactList, type ConversationStatus, type CreateCampaignInput, type CreateCompanyInput, type CreateCompanyResult, type CreateContactListInput, DEFAULT_BASE_URL, type DnsRecord, type EmailAttachment, type EmbedModule, type EmbedToken, type EmbedTokenInput, type GrantModuleInput, type Level, type ListAppDevicesQuery, type ListCampaignMessagesQuery, type ListCampaignsQuery, type ListChatMessagesQuery, type ListContactsQuery, type ListConversationsQuery, type ListMessagesQuery, type ListRadioEventsQuery, type LogInput, type LogResult, type ManagementConfig, type Message, type MessageClass, type MessagingConfig, type MessagingErrorCode, type ModuleEntitlement, type Paginated$1 as Paginated, type PartnerCompany, type PartnerConfig, type PartnerDomain, type PartnerOwnerInput, type PartnerUser, type PartnerUserInput, type RadioEvent, type RadioLevel, type ReplyInput, type SbResult$1 as SbResult, type SendEmailInput, type SendPushInput, type SendResult, type SendSmsInput, SignalbirdClient, type SignalbirdConfig, SignalbirdError, SignalbirdManagement, SignalbirdMessaging, SignalbirdPartner, type SmsPreview, type StartConversationInput, type TeamEmbedTokenInput, type UpdateConversationInput, type UpdateVisitorInput, type UptimeIncident, type UptimeRange, type UptimeReport, type VerifyDomainResult, management, resetManagement, resetSignalbird, signalbird, verifyWebhook };
|