signalbird 1.4.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 +576 -0
- package/dist/angular.d.mts +53 -0
- package/dist/angular.d.ts +53 -0
- package/dist/angular.js +578 -0
- package/dist/angular.js.map +1 -0
- package/dist/angular.mjs +574 -0
- package/dist/angular.mjs.map +1 -0
- package/dist/app.d.mts +343 -0
- package/dist/app.d.ts +343 -0
- package/dist/app.js +518 -0
- package/dist/app.js.map +1 -0
- package/dist/app.mjs +514 -0
- package/dist/app.mjs.map +1 -0
- package/dist/browser.d.mts +56 -0
- package/dist/browser.d.ts +56 -0
- package/dist/browser.js +113 -0
- package/dist/browser.js.map +1 -0
- package/dist/browser.mjs +109 -0
- package/dist/browser.mjs.map +1 -0
- package/dist/index.d.mts +1170 -0
- package/dist/index.d.ts +1170 -0
- package/dist/index.js +853 -0
- package/dist/index.js.map +1 -0
- package/dist/index.mjs +841 -0
- package/dist/index.mjs.map +1 -0
- package/dist/react-native.d.mts +46 -0
- package/dist/react-native.d.ts +46 -0
- package/dist/react-native.js +576 -0
- package/dist/react-native.js.map +1 -0
- package/dist/react-native.mjs +569 -0
- package/dist/react-native.mjs.map +1 -0
- package/dist/react.d.mts +43 -0
- package/dist/react.d.ts +43 -0
- package/dist/react.js +587 -0
- package/dist/react.js.map +1 -0
- package/dist/react.mjs +580 -0
- package/dist/react.mjs.map +1 -0
- package/dist/signalbird.js +141 -0
- package/dist/vue.d.mts +46 -0
- package/dist/vue.d.ts +46 -0
- package/dist/vue.js +575 -0
- package/dist/vue.js.map +1 -0
- package/dist/vue.mjs +568 -0
- package/dist/vue.mjs.map +1 -0
- package/package.json +125 -0
package/dist/index.js
ADDED
|
@@ -0,0 +1,853 @@
|
|
|
1
|
+
'use strict';
|
|
2
|
+
|
|
3
|
+
var crypto = require('crypto');
|
|
4
|
+
|
|
5
|
+
// src/node/types.ts
|
|
6
|
+
var SignalbirdError = class extends Error {
|
|
7
|
+
constructor(message, status, code, body) {
|
|
8
|
+
super(message);
|
|
9
|
+
this.status = status;
|
|
10
|
+
this.code = code;
|
|
11
|
+
this.body = body;
|
|
12
|
+
this.name = "SignalbirdError";
|
|
13
|
+
}
|
|
14
|
+
};
|
|
15
|
+
var DEFAULT_BASE_URL = "https://signalbird.io/api";
|
|
16
|
+
|
|
17
|
+
// src/node/client.ts
|
|
18
|
+
var SignalbirdClient = class {
|
|
19
|
+
constructor(config) {
|
|
20
|
+
this.config = config;
|
|
21
|
+
if (!config.apiKey) {
|
|
22
|
+
throw new SignalbirdError("Signalbird: apiKey zorunlu.", 0, "NO_KEY");
|
|
23
|
+
}
|
|
24
|
+
if (config.apiKey.startsWith("sbr_pub_")) {
|
|
25
|
+
throw new SignalbirdError(
|
|
26
|
+
"Signalbird: sunucu istemcisine taray\u0131c\u0131 anahtar\u0131 (sbr_pub_\u2026) verildi. Sunucu anahtar\u0131 (sbr_live_\u2026) kullan\u0131n.",
|
|
27
|
+
0,
|
|
28
|
+
"WRONG_KEY_TYPE"
|
|
29
|
+
);
|
|
30
|
+
}
|
|
31
|
+
this.baseUrl = (config.baseUrl ?? DEFAULT_BASE_URL).replace(/\/$/, "");
|
|
32
|
+
this.timeout = config.timeout ?? 5e3;
|
|
33
|
+
this.throwOnError = config.throwOnError ?? false;
|
|
34
|
+
this.debug = config.debug ?? process.env.NODE_ENV !== "production";
|
|
35
|
+
this.source = config.source;
|
|
36
|
+
}
|
|
37
|
+
/** Tek kayıt gönderir. */
|
|
38
|
+
async log(input) {
|
|
39
|
+
return this.send("/v1/radio/log", {
|
|
40
|
+
channel: input.channel,
|
|
41
|
+
message: input.message,
|
|
42
|
+
level: input.level,
|
|
43
|
+
context: input.context,
|
|
44
|
+
source: input.source ?? this.source
|
|
45
|
+
});
|
|
46
|
+
}
|
|
47
|
+
/**
|
|
48
|
+
* Toplu gönderim — 100 kayda kadar.
|
|
49
|
+
*
|
|
50
|
+
* Kısmi başarı normaldir (kota tam ortada dolabilir), o yüzden sonuç tek bir
|
|
51
|
+
* durum değil satır satır döner.
|
|
52
|
+
*/
|
|
53
|
+
async batch(events) {
|
|
54
|
+
const payload = {
|
|
55
|
+
events: events.slice(0, 100).map((event) => ({
|
|
56
|
+
channel: event.channel,
|
|
57
|
+
message: event.message,
|
|
58
|
+
level: event.level,
|
|
59
|
+
context: event.context,
|
|
60
|
+
source: event.source ?? this.source
|
|
61
|
+
}))
|
|
62
|
+
};
|
|
63
|
+
const response = await this.request("/v1/radio/log/batch", payload);
|
|
64
|
+
if (!response) {
|
|
65
|
+
return { accepted: 0, total: events.length, results: {} };
|
|
66
|
+
}
|
|
67
|
+
const results = {};
|
|
68
|
+
for (const [index, row] of Object.entries(response.body?.results ?? {})) {
|
|
69
|
+
const value = row;
|
|
70
|
+
results[Number(index)] = { ok: value.ok, eventId: value.event_id, code: value.code };
|
|
71
|
+
}
|
|
72
|
+
return {
|
|
73
|
+
accepted: Number(response.body?.accepted ?? 0),
|
|
74
|
+
total: Number(response.body?.total ?? events.length),
|
|
75
|
+
results
|
|
76
|
+
};
|
|
77
|
+
}
|
|
78
|
+
// ── Seviye kısayolları ────────────────────────────────────────────────
|
|
79
|
+
// `log('critical', …)` yerine `critical(…)`: kanal adı ile seviye çoğu
|
|
80
|
+
// projede aynıdır, ikisini ayrı ayrı yazdırmak gereksiz tekrar olurdu.
|
|
81
|
+
debugLog(channel, message, context) {
|
|
82
|
+
return this.log({ channel, message, level: "debug", context });
|
|
83
|
+
}
|
|
84
|
+
info(channel, message, context) {
|
|
85
|
+
return this.log({ channel, message, level: "info", context });
|
|
86
|
+
}
|
|
87
|
+
warn(channel, message, context) {
|
|
88
|
+
return this.log({ channel, message, level: "warn", context });
|
|
89
|
+
}
|
|
90
|
+
error(channel, message, context) {
|
|
91
|
+
return this.log({ channel, message, level: "error", context });
|
|
92
|
+
}
|
|
93
|
+
critical(channel, message, context) {
|
|
94
|
+
return this.log({ channel, message, level: "critical", context });
|
|
95
|
+
}
|
|
96
|
+
/**
|
|
97
|
+
* Yakalanmamış hataları Telsiz'e bağlar.
|
|
98
|
+
*
|
|
99
|
+
* Kancayı takıp süreci ÖLDÜRMEYE devam eder: `uncaughtException` sonrası
|
|
100
|
+
* süreci ayakta tutmak, bozuk durumdaki bir uygulamayı çalıştırmaya devam
|
|
101
|
+
* etmek demektir — log göndermek bunu meşrulaştırmaz.
|
|
102
|
+
*/
|
|
103
|
+
captureUncaught(channel = "critical") {
|
|
104
|
+
const onError = (error) => {
|
|
105
|
+
void this.log({
|
|
106
|
+
channel,
|
|
107
|
+
message: error.message,
|
|
108
|
+
level: "critical",
|
|
109
|
+
context: { stack: error.stack?.split("\n").slice(0, 20).join("\n") }
|
|
110
|
+
});
|
|
111
|
+
};
|
|
112
|
+
const onRejection = (reason) => {
|
|
113
|
+
void this.log({
|
|
114
|
+
channel,
|
|
115
|
+
message: reason instanceof Error ? reason.message : String(reason),
|
|
116
|
+
level: "error",
|
|
117
|
+
context: reason instanceof Error ? { stack: reason.stack } : void 0
|
|
118
|
+
});
|
|
119
|
+
};
|
|
120
|
+
process.on("uncaughtException", onError);
|
|
121
|
+
process.on("unhandledRejection", onRejection);
|
|
122
|
+
return () => {
|
|
123
|
+
process.off("uncaughtException", onError);
|
|
124
|
+
process.off("unhandledRejection", onRejection);
|
|
125
|
+
};
|
|
126
|
+
}
|
|
127
|
+
async send(path, payload) {
|
|
128
|
+
const response = await this.request(path, payload);
|
|
129
|
+
if (!response) {
|
|
130
|
+
return { ok: false, code: "NETWORK_ERROR" };
|
|
131
|
+
}
|
|
132
|
+
if (!response.ok) {
|
|
133
|
+
const code = response.body?.code ?? "UNKNOWN";
|
|
134
|
+
if (this.throwOnError) {
|
|
135
|
+
throw new SignalbirdError(`Signalbird: ${code}`, response.status, code);
|
|
136
|
+
}
|
|
137
|
+
if (this.debug) {
|
|
138
|
+
console.warn(`[signalbird] g\xF6nderilemedi: ${code} (HTTP ${response.status})`);
|
|
139
|
+
}
|
|
140
|
+
return { ok: false, code, status: response.status };
|
|
141
|
+
}
|
|
142
|
+
return { ok: true, eventId: response.body?.event_id, status: response.status };
|
|
143
|
+
}
|
|
144
|
+
async request(path, payload) {
|
|
145
|
+
const controller = new AbortController();
|
|
146
|
+
const timer = setTimeout(() => controller.abort(), this.timeout);
|
|
147
|
+
try {
|
|
148
|
+
const response = await fetch(this.baseUrl + path, {
|
|
149
|
+
method: "POST",
|
|
150
|
+
headers: {
|
|
151
|
+
"Content-Type": "application/json",
|
|
152
|
+
Accept: "application/json",
|
|
153
|
+
Authorization: `Bearer ${this.config.apiKey}`
|
|
154
|
+
},
|
|
155
|
+
body: JSON.stringify(payload),
|
|
156
|
+
signal: controller.signal
|
|
157
|
+
});
|
|
158
|
+
const body = await response.json().catch(() => ({}));
|
|
159
|
+
return { ok: response.ok, status: response.status, body };
|
|
160
|
+
} catch (error) {
|
|
161
|
+
if (this.throwOnError) {
|
|
162
|
+
throw new SignalbirdError(
|
|
163
|
+
error instanceof Error ? error.message : "network error",
|
|
164
|
+
0,
|
|
165
|
+
"NETWORK_ERROR"
|
|
166
|
+
);
|
|
167
|
+
}
|
|
168
|
+
if (this.debug) {
|
|
169
|
+
console.warn("[signalbird] ula\u015F\u0131lamad\u0131:", error);
|
|
170
|
+
}
|
|
171
|
+
return null;
|
|
172
|
+
} finally {
|
|
173
|
+
clearTimeout(timer);
|
|
174
|
+
}
|
|
175
|
+
}
|
|
176
|
+
};
|
|
177
|
+
|
|
178
|
+
// src/node/messaging.ts
|
|
179
|
+
var BULK_CHUNK = 1e3;
|
|
180
|
+
var SignalbirdMessaging = class {
|
|
181
|
+
constructor(config) {
|
|
182
|
+
if (!config.apiKey) {
|
|
183
|
+
throw new SignalbirdError("Signalbird: apiKey zorunlu.", 0, "NO_KEY");
|
|
184
|
+
}
|
|
185
|
+
if (!config.apiKey.startsWith("sb_")) {
|
|
186
|
+
throw new SignalbirdError(
|
|
187
|
+
"Signalbird: g\xF6nderim istemcisi tak\u0131m API anahtar\u0131 ister (sb_\u2026). Telsiz (sbr_\u2026) ve uygulama (sbw_pub_\u2026) anahtarlar\u0131 burada \xE7al\u0131\u015Fmaz.",
|
|
188
|
+
0,
|
|
189
|
+
"WRONG_KEY_TYPE"
|
|
190
|
+
);
|
|
191
|
+
}
|
|
192
|
+
this.apiKey = config.apiKey;
|
|
193
|
+
this.baseUrl = (config.baseUrl ?? DEFAULT_BASE_URL).replace(/\/$/, "");
|
|
194
|
+
this.timeout = config.timeout ?? 15e3;
|
|
195
|
+
this.throwOnError = config.throwOnError ?? false;
|
|
196
|
+
this.debug = config.debug ?? false;
|
|
197
|
+
}
|
|
198
|
+
// ── Gönderim ──────────────────────────────────────────────────────────
|
|
199
|
+
sendEmail(input) {
|
|
200
|
+
return this.request("POST", "/v1/email/send", input);
|
|
201
|
+
}
|
|
202
|
+
sendSms(input) {
|
|
203
|
+
return this.request("POST", "/v1/sms/send", input);
|
|
204
|
+
}
|
|
205
|
+
/** SMS parça/karakter hesabı — kota harcamaz. */
|
|
206
|
+
previewSms(body) {
|
|
207
|
+
return this.request("POST", "/v1/sms/preview", { body });
|
|
208
|
+
}
|
|
209
|
+
sendPush(input) {
|
|
210
|
+
return this.request("POST", "/v1/push/send", input);
|
|
211
|
+
}
|
|
212
|
+
// ── Kişiler ───────────────────────────────────────────────────────────
|
|
213
|
+
listContacts(query) {
|
|
214
|
+
return this.request("GET", "/v1/contacts", void 0, query);
|
|
215
|
+
}
|
|
216
|
+
createContact(contact) {
|
|
217
|
+
return this.request("POST", "/v1/contacts", contact);
|
|
218
|
+
}
|
|
219
|
+
updateContact(id, contact) {
|
|
220
|
+
return this.request("PATCH", `/v1/contacts/${encodeURIComponent(id)}`, contact);
|
|
221
|
+
}
|
|
222
|
+
deleteContact(id) {
|
|
223
|
+
return this.request("DELETE", `/v1/contacts/${encodeURIComponent(id)}`);
|
|
224
|
+
}
|
|
225
|
+
/**
|
|
226
|
+
* Toplu kişi yükleme.
|
|
227
|
+
*
|
|
228
|
+
* 1000'lik parçalara bölünür ve SIRAYLA gönderilir (paralel değil: aynı
|
|
229
|
+
* e-posta iki parçada da varsa yarış olmasın). Sonuçlar tek yanıtta
|
|
230
|
+
* birleştirilir. Bir parça başarısız olursa o noktada durulur ve o ana kadar
|
|
231
|
+
* biriken sayımlar `data` içinde döner — çağıran kaç kişinin işlendiğini görür.
|
|
232
|
+
*/
|
|
233
|
+
async bulkContacts(input) {
|
|
234
|
+
const merged = { imported: 0, updated: 0, skipped: [] };
|
|
235
|
+
const { contacts, ...rest } = input;
|
|
236
|
+
let status = 200;
|
|
237
|
+
if (contacts.length === 0) {
|
|
238
|
+
return { ok: true, status, data: merged };
|
|
239
|
+
}
|
|
240
|
+
for (let offset = 0; offset < contacts.length; offset += BULK_CHUNK) {
|
|
241
|
+
const chunk = contacts.slice(offset, offset + BULK_CHUNK);
|
|
242
|
+
const result = await this.request("POST", "/v1/contacts/bulk", {
|
|
243
|
+
...rest,
|
|
244
|
+
contacts: chunk
|
|
245
|
+
});
|
|
246
|
+
if (!result.ok) {
|
|
247
|
+
return { ...result, data: merged };
|
|
248
|
+
}
|
|
249
|
+
status = result.status;
|
|
250
|
+
merged.imported += Number(result.data?.imported ?? 0);
|
|
251
|
+
merged.updated += Number(result.data?.updated ?? 0);
|
|
252
|
+
if (Array.isArray(result.data?.skipped)) {
|
|
253
|
+
merged.skipped.push(...result.data.skipped);
|
|
254
|
+
}
|
|
255
|
+
}
|
|
256
|
+
return { ok: true, status, data: merged };
|
|
257
|
+
}
|
|
258
|
+
// ── Listeler ──────────────────────────────────────────────────────────
|
|
259
|
+
listContactLists() {
|
|
260
|
+
return this.request("GET", "/v1/contact-lists");
|
|
261
|
+
}
|
|
262
|
+
createContactList(input) {
|
|
263
|
+
return this.request("POST", "/v1/contact-lists", input);
|
|
264
|
+
}
|
|
265
|
+
deleteContactList(id) {
|
|
266
|
+
return this.request("DELETE", `/v1/contact-lists/${encodeURIComponent(id)}`);
|
|
267
|
+
}
|
|
268
|
+
// ── Kampanyalar ───────────────────────────────────────────────────────
|
|
269
|
+
listCampaigns(query) {
|
|
270
|
+
return this.request("GET", "/v1/campaigns", void 0, query);
|
|
271
|
+
}
|
|
272
|
+
createCampaign(input) {
|
|
273
|
+
return this.request("POST", "/v1/campaigns", input);
|
|
274
|
+
}
|
|
275
|
+
getCampaign(id) {
|
|
276
|
+
return this.request("GET", `/v1/campaigns/${encodeURIComponent(id)}`);
|
|
277
|
+
}
|
|
278
|
+
cancelCampaign(id) {
|
|
279
|
+
return this.request("POST", `/v1/campaigns/${encodeURIComponent(id)}/cancel`);
|
|
280
|
+
}
|
|
281
|
+
listCampaignMessages(id, query) {
|
|
282
|
+
return this.request("GET", `/v1/campaigns/${encodeURIComponent(id)}/messages`, void 0, query);
|
|
283
|
+
}
|
|
284
|
+
/**
|
|
285
|
+
* Bir kampanyanın tüm mesajlarını sayfa sayfa gezer.
|
|
286
|
+
*
|
|
287
|
+
* for await (const m of sdk.iterateCampaignMessages(42)) { … }
|
|
288
|
+
*
|
|
289
|
+
* Bir sayfa alınamazsa `SignalbirdError` fırlatır (sessiz yarım liste,
|
|
290
|
+
* "hepsi bu" sanılır — o daha tehlikeli).
|
|
291
|
+
*/
|
|
292
|
+
async *iterateCampaignMessages(id, query = {}) {
|
|
293
|
+
let page = 1;
|
|
294
|
+
while (true) {
|
|
295
|
+
const result = await this.listCampaignMessages(id, { per_page: 100, ...query, page });
|
|
296
|
+
if (!result.ok) {
|
|
297
|
+
throw new SignalbirdError(`Signalbird: ${result.code}`, result.status, result.code, result.data);
|
|
298
|
+
}
|
|
299
|
+
for (const message of result.data.data ?? []) {
|
|
300
|
+
yield message;
|
|
301
|
+
}
|
|
302
|
+
if (page >= (result.data.last_page ?? 1) || (result.data.data ?? []).length === 0) {
|
|
303
|
+
return;
|
|
304
|
+
}
|
|
305
|
+
page++;
|
|
306
|
+
}
|
|
307
|
+
}
|
|
308
|
+
// ── Mesajlar ──────────────────────────────────────────────────────────
|
|
309
|
+
listMessages(query) {
|
|
310
|
+
return this.request("GET", "/v1/messages", void 0, query);
|
|
311
|
+
}
|
|
312
|
+
getMessage(id) {
|
|
313
|
+
return this.request("GET", `/v1/messages/${encodeURIComponent(id)}`);
|
|
314
|
+
}
|
|
315
|
+
// ── HTTP ──────────────────────────────────────────────────────────────
|
|
316
|
+
async request(method, path, body, query) {
|
|
317
|
+
const controller = new AbortController();
|
|
318
|
+
const timer = setTimeout(() => controller.abort(), this.timeout);
|
|
319
|
+
const url = this.baseUrl + path + buildQuery(query);
|
|
320
|
+
let status = 0;
|
|
321
|
+
let data;
|
|
322
|
+
try {
|
|
323
|
+
const response = await fetch(url, {
|
|
324
|
+
method,
|
|
325
|
+
headers: {
|
|
326
|
+
Accept: "application/json",
|
|
327
|
+
Authorization: `Bearer ${this.apiKey}`,
|
|
328
|
+
...body !== void 0 ? { "Content-Type": "application/json" } : {}
|
|
329
|
+
},
|
|
330
|
+
body: body !== void 0 ? JSON.stringify(body) : void 0,
|
|
331
|
+
signal: controller.signal
|
|
332
|
+
});
|
|
333
|
+
status = response.status;
|
|
334
|
+
const text = await response.text();
|
|
335
|
+
try {
|
|
336
|
+
data = text ? JSON.parse(text) : null;
|
|
337
|
+
} catch {
|
|
338
|
+
data = text;
|
|
339
|
+
}
|
|
340
|
+
if (response.ok) {
|
|
341
|
+
return { ok: true, status, data };
|
|
342
|
+
}
|
|
343
|
+
} catch (error) {
|
|
344
|
+
const timedOut = error instanceof Error && error.name === "AbortError";
|
|
345
|
+
const code2 = timedOut ? "TIMEOUT" : "NETWORK_ERROR";
|
|
346
|
+
const message2 = error instanceof Error ? error.message : "network error";
|
|
347
|
+
return this.fail(0, code2, message2, void 0);
|
|
348
|
+
} finally {
|
|
349
|
+
clearTimeout(timer);
|
|
350
|
+
}
|
|
351
|
+
const code = data && typeof data === "object" && typeof data.code === "string" && data.code || (status === 422 ? "VALIDATION_ERROR" : status === 401 ? "API_KEY_INVALID" : `HTTP_${status}`);
|
|
352
|
+
const message = data && typeof data === "object" && typeof data.message === "string" && data.message || `HTTP ${status}`;
|
|
353
|
+
return this.fail(status, code, message, data);
|
|
354
|
+
}
|
|
355
|
+
fail(status, code, message, data) {
|
|
356
|
+
if (this.throwOnError) {
|
|
357
|
+
throw new SignalbirdError(`Signalbird: ${code} \u2014 ${message}`, status, code, data);
|
|
358
|
+
}
|
|
359
|
+
if (this.debug) {
|
|
360
|
+
console.warn(`[signalbird] ${code} (HTTP ${status}): ${message}`);
|
|
361
|
+
}
|
|
362
|
+
return { ok: false, status, code, message, data };
|
|
363
|
+
}
|
|
364
|
+
};
|
|
365
|
+
function buildQuery(query) {
|
|
366
|
+
if (!query) return "";
|
|
367
|
+
const params = new URLSearchParams();
|
|
368
|
+
for (const [key, value] of Object.entries(query)) {
|
|
369
|
+
if (value === void 0 || value === null) continue;
|
|
370
|
+
if (Array.isArray(value)) {
|
|
371
|
+
for (const item of value) params.append(`${key}[]`, String(item));
|
|
372
|
+
} else {
|
|
373
|
+
params.append(key, String(value));
|
|
374
|
+
}
|
|
375
|
+
}
|
|
376
|
+
const encoded = params.toString();
|
|
377
|
+
return encoded ? `?${encoded}` : "";
|
|
378
|
+
}
|
|
379
|
+
|
|
380
|
+
// src/node/http.ts
|
|
381
|
+
var SbTransport = class {
|
|
382
|
+
constructor(config) {
|
|
383
|
+
this.config = config;
|
|
384
|
+
}
|
|
385
|
+
async request(method, path, body, query) {
|
|
386
|
+
const controller = new AbortController();
|
|
387
|
+
const timer = setTimeout(() => controller.abort(), this.config.timeout);
|
|
388
|
+
const url = this.config.baseUrl + path + buildQuery2(query);
|
|
389
|
+
let status = 0;
|
|
390
|
+
let data;
|
|
391
|
+
try {
|
|
392
|
+
const response = await fetch(url, {
|
|
393
|
+
method,
|
|
394
|
+
headers: {
|
|
395
|
+
Accept: "application/json",
|
|
396
|
+
Authorization: `Bearer ${this.config.apiKey}`,
|
|
397
|
+
...body !== void 0 ? { "Content-Type": "application/json" } : {}
|
|
398
|
+
},
|
|
399
|
+
body: body !== void 0 ? JSON.stringify(body) : void 0,
|
|
400
|
+
signal: controller.signal
|
|
401
|
+
});
|
|
402
|
+
status = response.status;
|
|
403
|
+
const text = await response.text();
|
|
404
|
+
try {
|
|
405
|
+
data = text ? JSON.parse(text) : null;
|
|
406
|
+
} catch {
|
|
407
|
+
data = text;
|
|
408
|
+
}
|
|
409
|
+
if (response.ok) {
|
|
410
|
+
return { ok: true, status, data };
|
|
411
|
+
}
|
|
412
|
+
} catch (error) {
|
|
413
|
+
const timedOut = error instanceof Error && error.name === "AbortError";
|
|
414
|
+
return this.fail(
|
|
415
|
+
0,
|
|
416
|
+
timedOut ? "TIMEOUT" : "NETWORK_ERROR",
|
|
417
|
+
error instanceof Error ? error.message : "network error",
|
|
418
|
+
void 0
|
|
419
|
+
);
|
|
420
|
+
} finally {
|
|
421
|
+
clearTimeout(timer);
|
|
422
|
+
}
|
|
423
|
+
const code = data && typeof data === "object" && typeof data.code === "string" && data.code || (status === 422 ? "VALIDATION_ERROR" : status === 401 ? "API_KEY_INVALID" : `HTTP_${status}`);
|
|
424
|
+
const message = data && typeof data === "object" && typeof data.message === "string" && data.message || `HTTP ${status}`;
|
|
425
|
+
return this.fail(status, code, message, data);
|
|
426
|
+
}
|
|
427
|
+
fail(status, code, message, data) {
|
|
428
|
+
if (this.config.throwOnError) {
|
|
429
|
+
throw new SignalbirdError(`Signalbird: ${code} \u2014 ${message}`, status, code, data);
|
|
430
|
+
}
|
|
431
|
+
if (this.config.debug) {
|
|
432
|
+
console.warn(`[signalbird] ${code} (HTTP ${status}): ${message}`);
|
|
433
|
+
}
|
|
434
|
+
return { ok: false, status, code, message, data };
|
|
435
|
+
}
|
|
436
|
+
};
|
|
437
|
+
function buildQuery2(query) {
|
|
438
|
+
if (!query) return "";
|
|
439
|
+
const params = new URLSearchParams();
|
|
440
|
+
for (const [key, value] of Object.entries(query)) {
|
|
441
|
+
if (value === void 0 || value === null) continue;
|
|
442
|
+
if (Array.isArray(value)) {
|
|
443
|
+
for (const item of value) params.append(`${key}[]`, String(item));
|
|
444
|
+
} else {
|
|
445
|
+
params.append(key, String(value));
|
|
446
|
+
}
|
|
447
|
+
}
|
|
448
|
+
const encoded = params.toString();
|
|
449
|
+
return encoded ? `?${encoded}` : "";
|
|
450
|
+
}
|
|
451
|
+
function seg(value) {
|
|
452
|
+
return encodeURIComponent(String(value));
|
|
453
|
+
}
|
|
454
|
+
|
|
455
|
+
// src/node/management.ts
|
|
456
|
+
var SignalbirdManagement = class {
|
|
457
|
+
constructor(config) {
|
|
458
|
+
if (!config.apiKey) {
|
|
459
|
+
throw new SignalbirdError("Signalbird: apiKey zorunlu.", 0, "NO_KEY");
|
|
460
|
+
}
|
|
461
|
+
if (!config.apiKey.startsWith("sb_")) {
|
|
462
|
+
throw new SignalbirdError(
|
|
463
|
+
"Signalbird: y\xF6netim istemcisi tak\u0131m API anahtar\u0131 ister (sb_\u2026). Telsiz (sbr_\u2026) ve uygulama (sbw_pub_\u2026) anahtarlar\u0131 burada \xE7al\u0131\u015Fmaz.",
|
|
464
|
+
0,
|
|
465
|
+
"WRONG_KEY_TYPE"
|
|
466
|
+
);
|
|
467
|
+
}
|
|
468
|
+
this.http = new SbTransport({
|
|
469
|
+
apiKey: config.apiKey,
|
|
470
|
+
baseUrl: (config.baseUrl ?? DEFAULT_BASE_URL).replace(/\/$/, ""),
|
|
471
|
+
timeout: config.timeout ?? 15e3,
|
|
472
|
+
throwOnError: config.throwOnError ?? false,
|
|
473
|
+
debug: config.debug ?? false
|
|
474
|
+
});
|
|
475
|
+
}
|
|
476
|
+
// ── Telsiz: projeler ──────────────────────────────────────────────────
|
|
477
|
+
/** Panelin Telsiz özeti: proje sayısı, günlük hacim, son olaylar. */
|
|
478
|
+
radioSummary() {
|
|
479
|
+
return this.http.request("GET", "/v1/radio/summary");
|
|
480
|
+
}
|
|
481
|
+
/** Olay akışı — kanal, seviye ve tarihe göre süzülür. */
|
|
482
|
+
radioEvents(query) {
|
|
483
|
+
return this.http.request("GET", "/v1/radio/events", void 0, query);
|
|
484
|
+
}
|
|
485
|
+
listRadioProjects() {
|
|
486
|
+
return this.http.request("GET", "/v1/radio/projects");
|
|
487
|
+
}
|
|
488
|
+
/**
|
|
489
|
+
* Proje açar.
|
|
490
|
+
*
|
|
491
|
+
* Dönen `secret` (`sbr_live_…`) YALNIZ BURADA görünür: sunucuda yalnız
|
|
492
|
+
* SHA-256 özeti saklanır. Kaybedilirse `rotateRadioSecret` ile yenilenir.
|
|
493
|
+
*/
|
|
494
|
+
createRadioProject(input) {
|
|
495
|
+
return this.http.request("POST", "/v1/radio/projects", input);
|
|
496
|
+
}
|
|
497
|
+
getRadioProject(id) {
|
|
498
|
+
return this.http.request("GET", `/v1/radio/projects/${seg(id)}`);
|
|
499
|
+
}
|
|
500
|
+
updateRadioProject(id, input) {
|
|
501
|
+
return this.http.request("PATCH", `/v1/radio/projects/${seg(id)}`, input);
|
|
502
|
+
}
|
|
503
|
+
deleteRadioProject(id) {
|
|
504
|
+
return this.http.request("DELETE", `/v1/radio/projects/${seg(id)}`);
|
|
505
|
+
}
|
|
506
|
+
/** Gizli anahtarı yeniler; eski anahtar ANINDA geçersizleşir. */
|
|
507
|
+
rotateRadioSecret(id) {
|
|
508
|
+
return this.http.request("POST", `/v1/radio/projects/${seg(id)}/rotate`);
|
|
509
|
+
}
|
|
510
|
+
// ── Telsiz: kanallar ──────────────────────────────────────────────────
|
|
511
|
+
createRadioChannel(projectId, input) {
|
|
512
|
+
return this.http.request("POST", `/v1/radio/projects/${seg(projectId)}/channels`, input);
|
|
513
|
+
}
|
|
514
|
+
/**
|
|
515
|
+
* Kanalı günceller. `key` DEĞİŞMEZ — müşterinin kodundaki `log('critical', …)`
|
|
516
|
+
* çağrısı ona bağlıdır; sunucu gönderilse de yok sayar.
|
|
517
|
+
*/
|
|
518
|
+
updateRadioChannel(projectId, channelId, input) {
|
|
519
|
+
return this.http.request(
|
|
520
|
+
"PATCH",
|
|
521
|
+
`/v1/radio/projects/${seg(projectId)}/channels/${seg(channelId)}`,
|
|
522
|
+
input
|
|
523
|
+
);
|
|
524
|
+
}
|
|
525
|
+
deleteRadioChannel(projectId, channelId) {
|
|
526
|
+
return this.http.request(
|
|
527
|
+
"DELETE",
|
|
528
|
+
`/v1/radio/projects/${seg(projectId)}/channels/${seg(channelId)}`
|
|
529
|
+
);
|
|
530
|
+
}
|
|
531
|
+
// ── Sohbet: gelen kutusu ──────────────────────────────────────────────
|
|
532
|
+
chatSummary() {
|
|
533
|
+
return this.http.request("GET", "/v1/chat/summary");
|
|
534
|
+
}
|
|
535
|
+
/** Kısa aralıklı yoklama için: yalnız değişenler + çevrimiçi ajanlar. */
|
|
536
|
+
chatUpdates() {
|
|
537
|
+
return this.http.request("GET", "/v1/chat/updates");
|
|
538
|
+
}
|
|
539
|
+
listConversations(query) {
|
|
540
|
+
return this.http.request("GET", "/v1/chat/conversations", void 0, query);
|
|
541
|
+
}
|
|
542
|
+
getConversation(id) {
|
|
543
|
+
return this.http.request("GET", `/v1/chat/conversations/${seg(id)}`);
|
|
544
|
+
}
|
|
545
|
+
/** `after` imleci `cm_…` mesaj kimliğidir; yoklamada tam listeyi çekmez. */
|
|
546
|
+
listConversationMessages(id, query) {
|
|
547
|
+
return this.http.request("GET", `/v1/chat/conversations/${seg(id)}/messages`, void 0, query);
|
|
548
|
+
}
|
|
549
|
+
/** Proaktif sohbet — ziyaretçi yazmadan ajan başlatır. */
|
|
550
|
+
startConversation(input) {
|
|
551
|
+
return this.http.request("POST", "/v1/chat/conversations", input);
|
|
552
|
+
}
|
|
553
|
+
updateConversation(id, input) {
|
|
554
|
+
return this.http.request("PATCH", `/v1/chat/conversations/${seg(id)}`, input);
|
|
555
|
+
}
|
|
556
|
+
setConversationStatus(id, status) {
|
|
557
|
+
return this.http.request("POST", `/v1/chat/conversations/${seg(id)}/status`, { status });
|
|
558
|
+
}
|
|
559
|
+
/**
|
|
560
|
+
* Atama atomiktir: `userId` verilmezse çağıran anahtarın sahibine atanır.
|
|
561
|
+
* Başkasına atanmış sohbeti devralmak `chat:write` ister.
|
|
562
|
+
*/
|
|
563
|
+
assignConversation(id, userId) {
|
|
564
|
+
return this.http.request("POST", `/v1/chat/conversations/${seg(id)}/assign`, {
|
|
565
|
+
user_id: userId ?? null
|
|
566
|
+
});
|
|
567
|
+
}
|
|
568
|
+
readConversation(id, lastMessageId) {
|
|
569
|
+
return this.http.request("POST", `/v1/chat/conversations/${seg(id)}/read`, {
|
|
570
|
+
last_message_id: lastMessageId
|
|
571
|
+
});
|
|
572
|
+
}
|
|
573
|
+
setTyping(id, isTyping) {
|
|
574
|
+
return this.http.request("POST", `/v1/chat/conversations/${seg(id)}/typing`, {
|
|
575
|
+
is_typing: isTyping
|
|
576
|
+
});
|
|
577
|
+
}
|
|
578
|
+
reply(id, input) {
|
|
579
|
+
return this.http.request("POST", `/v1/chat/conversations/${seg(id)}/messages`, input);
|
|
580
|
+
}
|
|
581
|
+
editChatMessage(id, messageId, body) {
|
|
582
|
+
return this.http.request("PATCH", `/v1/chat/conversations/${seg(id)}/messages/${seg(messageId)}`, {
|
|
583
|
+
body
|
|
584
|
+
});
|
|
585
|
+
}
|
|
586
|
+
deleteChatMessage(id, messageId) {
|
|
587
|
+
return this.http.request(
|
|
588
|
+
"DELETE",
|
|
589
|
+
`/v1/chat/conversations/${seg(id)}/messages/${seg(messageId)}`
|
|
590
|
+
);
|
|
591
|
+
}
|
|
592
|
+
/** Tepki açma/kapama — aynı emoji ikinci kez gönderilirse kaldırılır. */
|
|
593
|
+
reactToChatMessage(id, messageId, emoji) {
|
|
594
|
+
return this.http.request(
|
|
595
|
+
"POST",
|
|
596
|
+
`/v1/chat/conversations/${seg(id)}/messages/${seg(messageId)}/reactions`,
|
|
597
|
+
{ emoji }
|
|
598
|
+
);
|
|
599
|
+
}
|
|
600
|
+
// ── Sohbet: ziyaretçi ve hazır yanıtlar ───────────────────────────────
|
|
601
|
+
getVisitor(id) {
|
|
602
|
+
return this.http.request("GET", `/v1/chat/visitors/${seg(id)}`);
|
|
603
|
+
}
|
|
604
|
+
updateVisitor(id, input) {
|
|
605
|
+
return this.http.request("PATCH", `/v1/chat/visitors/${seg(id)}`, input);
|
|
606
|
+
}
|
|
607
|
+
banVisitor(id) {
|
|
608
|
+
return this.http.request("POST", `/v1/chat/visitors/${seg(id)}/ban`);
|
|
609
|
+
}
|
|
610
|
+
listCannedReplies() {
|
|
611
|
+
return this.http.request("GET", "/v1/chat/canned-replies");
|
|
612
|
+
}
|
|
613
|
+
createCannedReply(input) {
|
|
614
|
+
return this.http.request("POST", "/v1/chat/canned-replies", input);
|
|
615
|
+
}
|
|
616
|
+
updateCannedReply(id, input) {
|
|
617
|
+
return this.http.request("PATCH", `/v1/chat/canned-replies/${seg(id)}`, input);
|
|
618
|
+
}
|
|
619
|
+
deleteCannedReply(id) {
|
|
620
|
+
return this.http.request("DELETE", `/v1/chat/canned-replies/${seg(id)}`);
|
|
621
|
+
}
|
|
622
|
+
// ── Sohbet: tetikleyiciler ────────────────────────────────────────────
|
|
623
|
+
// "Şu olduğunda şunu yap." Kural KAYITTA durur, kodda değil: müşteri
|
|
624
|
+
// davranışı değiştirmek için sürüm çıkarmak zorunda kalmasın.
|
|
625
|
+
listChatTriggers() {
|
|
626
|
+
return this.http.request("GET", "/v1/chat/triggers");
|
|
627
|
+
}
|
|
628
|
+
createChatTrigger(input) {
|
|
629
|
+
return this.http.request("POST", "/v1/chat/triggers", input);
|
|
630
|
+
}
|
|
631
|
+
updateChatTrigger(id, input) {
|
|
632
|
+
return this.http.request("PATCH", `/v1/chat/triggers/${seg(id)}`, input);
|
|
633
|
+
}
|
|
634
|
+
deleteChatTrigger(id) {
|
|
635
|
+
return this.http.request("DELETE", `/v1/chat/triggers/${seg(id)}`);
|
|
636
|
+
}
|
|
637
|
+
// ── Sohbet: rapor ─────────────────────────────────────────────────────
|
|
638
|
+
/**
|
|
639
|
+
* Yanıt süresi, çözüm süresi, memnuniyet ve ajan kırılımı.
|
|
640
|
+
* Veri yoksa süreler `null` döner — 0 DEĞİL.
|
|
641
|
+
*/
|
|
642
|
+
chatReport(range = "30d") {
|
|
643
|
+
return this.http.request("GET", "/v1/chat/reports", void 0, { range });
|
|
644
|
+
}
|
|
645
|
+
// ── Uygulamalar ───────────────────────────────────────────────────────
|
|
646
|
+
listApps() {
|
|
647
|
+
return this.http.request("GET", "/v1/apps");
|
|
648
|
+
}
|
|
649
|
+
/** Yanıttaki `public_key` (`sbw_pub_…`) istemciye gömülür; gizli değildir. */
|
|
650
|
+
createApp(input) {
|
|
651
|
+
return this.http.request("POST", "/v1/apps", input);
|
|
652
|
+
}
|
|
653
|
+
getApp(id) {
|
|
654
|
+
return this.http.request("GET", `/v1/apps/${seg(id)}`);
|
|
655
|
+
}
|
|
656
|
+
updateApp(id, input) {
|
|
657
|
+
return this.http.request("PATCH", `/v1/apps/${seg(id)}`, input);
|
|
658
|
+
}
|
|
659
|
+
deleteApp(id) {
|
|
660
|
+
return this.http.request("DELETE", `/v1/apps/${seg(id)}`);
|
|
661
|
+
}
|
|
662
|
+
/** Açık anahtarı yeniler; siteye gömülü eski anahtar ANINDA çalışmaz olur. */
|
|
663
|
+
rotateAppKey(id) {
|
|
664
|
+
return this.http.request("POST", `/v1/apps/${seg(id)}/rotate-key`);
|
|
665
|
+
}
|
|
666
|
+
listAppDevices(id, query) {
|
|
667
|
+
return this.http.request("GET", `/v1/apps/${seg(id)}/devices`, void 0, query);
|
|
668
|
+
}
|
|
669
|
+
};
|
|
670
|
+
|
|
671
|
+
// src/node/partner.ts
|
|
672
|
+
var SignalbirdPartner = class {
|
|
673
|
+
constructor(config) {
|
|
674
|
+
if (!config.apiKey) {
|
|
675
|
+
throw new SignalbirdError("Signalbird: apiKey zorunlu.", 0, "NO_KEY");
|
|
676
|
+
}
|
|
677
|
+
if (!config.apiKey.startsWith("sbp_live_")) {
|
|
678
|
+
throw new SignalbirdError(
|
|
679
|
+
"Signalbird: partner istemcisi partner anahtar\u0131 ister (sbp_live_\u2026). Tak\u0131m (sb_\u2026), Telsiz (sbr_\u2026) ve uygulama (sbw_pub_\u2026) anahtarlar\u0131 burada \xE7al\u0131\u015Fmaz.",
|
|
680
|
+
0,
|
|
681
|
+
"WRONG_KEY_TYPE"
|
|
682
|
+
);
|
|
683
|
+
}
|
|
684
|
+
this.http = new SbTransport({
|
|
685
|
+
apiKey: config.apiKey,
|
|
686
|
+
baseUrl: (config.baseUrl ?? DEFAULT_BASE_URL).replace(/\/$/, ""),
|
|
687
|
+
timeout: config.timeout ?? 15e3,
|
|
688
|
+
throwOnError: config.throwOnError ?? false,
|
|
689
|
+
debug: config.debug ?? false
|
|
690
|
+
});
|
|
691
|
+
}
|
|
692
|
+
// ── Müşteri ───────────────────────────────────────────────────────────
|
|
693
|
+
/**
|
|
694
|
+
* Company + takım + owner açar. **Idempotenttir**: aynı `external_id` ile
|
|
695
|
+
* ikinci çağrı yeni kayıt açmaz, `created:false` ile var olanı döner.
|
|
696
|
+
* Anahtarlar (`keys`) yalnız ilk oluşturmada gelir.
|
|
697
|
+
*/
|
|
698
|
+
createCompany(input) {
|
|
699
|
+
return this.http.request("POST", "/v1/partner/companies", input);
|
|
700
|
+
}
|
|
701
|
+
listCompanies(query) {
|
|
702
|
+
return this.http.request("GET", "/v1/partner/companies", void 0, query);
|
|
703
|
+
}
|
|
704
|
+
getCompany(externalId) {
|
|
705
|
+
return this.http.request("GET", `/v1/partner/companies/${seg(externalId)}`);
|
|
706
|
+
}
|
|
707
|
+
updateCompany(externalId, input) {
|
|
708
|
+
return this.http.request("PATCH", `/v1/partner/companies/${seg(externalId)}`, input);
|
|
709
|
+
}
|
|
710
|
+
/** Askıya alır — SİLMEZ. Müşterinin izleme ve mesaj geçmişi durur. */
|
|
711
|
+
suspendCompany(externalId) {
|
|
712
|
+
return this.http.request("DELETE", `/v1/partner/companies/${seg(externalId)}`);
|
|
713
|
+
}
|
|
714
|
+
rotateKey(externalId, type) {
|
|
715
|
+
return this.http.request("POST", `/v1/partner/companies/${seg(externalId)}/keys/rotate`, { type });
|
|
716
|
+
}
|
|
717
|
+
// ── Domain ────────────────────────────────────────────────────────────
|
|
718
|
+
/**
|
|
719
|
+
* Domain ekler ve (istenirse) izlemeye alır. Kayıt `verified_via:'partner'`
|
|
720
|
+
* ile doğar: izleme, sohbet ve push için yeter — **e-posta/SMS kampanyası
|
|
721
|
+
* için TXT şarttır**. Yanıttaki `dns` kaydını yayınlayıp `verifyDomain`
|
|
722
|
+
* çağırmak kapıyı açar.
|
|
723
|
+
*/
|
|
724
|
+
addDomain(companyExternalId, input) {
|
|
725
|
+
return this.http.request("POST", `/v1/partner/companies/${seg(companyExternalId)}/domains`, input);
|
|
726
|
+
}
|
|
727
|
+
listDomains(companyExternalId) {
|
|
728
|
+
return this.http.request("GET", `/v1/partner/companies/${seg(companyExternalId)}/domains`);
|
|
729
|
+
}
|
|
730
|
+
getDomain(externalId) {
|
|
731
|
+
return this.http.request("GET", `/v1/partner/domains/${seg(externalId)}`);
|
|
732
|
+
}
|
|
733
|
+
/** TXT'yi hemen sorgular; eşleşirse domain kampanya kapısından geçer olur. */
|
|
734
|
+
verifyDomain(externalId) {
|
|
735
|
+
return this.http.request("POST", `/v1/partner/domains/${seg(externalId)}/verify`);
|
|
736
|
+
}
|
|
737
|
+
removeDomain(externalId) {
|
|
738
|
+
return this.http.request("DELETE", `/v1/partner/domains/${seg(externalId)}`);
|
|
739
|
+
}
|
|
740
|
+
domainUptime(externalId, range = "24h") {
|
|
741
|
+
return this.http.request("GET", `/v1/partner/domains/${seg(externalId)}/uptime`, void 0, { range });
|
|
742
|
+
}
|
|
743
|
+
/** Tek istekte müşterinin tüm domainleri — liste ekranı N+1 atmasın. */
|
|
744
|
+
companyUptime(companyExternalId, range = "24h") {
|
|
745
|
+
return this.http.request(
|
|
746
|
+
"GET",
|
|
747
|
+
`/v1/partner/companies/${seg(companyExternalId)}/uptime`,
|
|
748
|
+
void 0,
|
|
749
|
+
{ range }
|
|
750
|
+
);
|
|
751
|
+
}
|
|
752
|
+
// ── Modül yetkisi ─────────────────────────────────────────────────────
|
|
753
|
+
listModules(companyExternalId) {
|
|
754
|
+
return this.http.request("GET", `/v1/partner/companies/${seg(companyExternalId)}/modules`);
|
|
755
|
+
}
|
|
756
|
+
/** "Bu müşteri şu modül için ödeme yaptı, kullanabilir." */
|
|
757
|
+
grantModule(companyExternalId, input) {
|
|
758
|
+
return this.http.request("POST", `/v1/partner/companies/${seg(companyExternalId)}/modules`, input);
|
|
759
|
+
}
|
|
760
|
+
/** Yalnız partner'ın KENDİ verdiği hakkı geri alır; plan hakkına dokunmaz. */
|
|
761
|
+
revokeModule(companyExternalId, module) {
|
|
762
|
+
return this.http.request(
|
|
763
|
+
"DELETE",
|
|
764
|
+
`/v1/partner/companies/${seg(companyExternalId)}/modules/${seg(module)}`
|
|
765
|
+
);
|
|
766
|
+
}
|
|
767
|
+
// ── Kullanıcı ─────────────────────────────────────────────────────────
|
|
768
|
+
createUser(companyExternalId, input) {
|
|
769
|
+
return this.http.request("POST", `/v1/partner/companies/${seg(companyExternalId)}/users`, input);
|
|
770
|
+
}
|
|
771
|
+
listUsers(companyExternalId) {
|
|
772
|
+
return this.http.request("GET", `/v1/partner/companies/${seg(companyExternalId)}/users`);
|
|
773
|
+
}
|
|
774
|
+
/** Üyeliği kaldırır, kişinin Signalbird hesabını SİLMEZ. */
|
|
775
|
+
removeUser(companyExternalId, userExternalId) {
|
|
776
|
+
return this.http.request(
|
|
777
|
+
"DELETE",
|
|
778
|
+
`/v1/partner/companies/${seg(companyExternalId)}/users/${seg(userExternalId)}`
|
|
779
|
+
);
|
|
780
|
+
}
|
|
781
|
+
// ── Gömme ─────────────────────────────────────────────────────────────
|
|
782
|
+
/**
|
|
783
|
+
* Panel ekranını partner sayfasına gömmek için kısa ömürlü jeton üretir.
|
|
784
|
+
* 120 saniye yaşar ve TEK KULLANIMLIKTIR — jeton URL'de gider, log ve
|
|
785
|
+
* `Referer` başlığına düşer.
|
|
786
|
+
*/
|
|
787
|
+
createEmbedToken(companyExternalId, input) {
|
|
788
|
+
return this.http.request("POST", `/v1/partner/companies/${seg(companyExternalId)}/embed`, input);
|
|
789
|
+
}
|
|
790
|
+
};
|
|
791
|
+
function verifyWebhook(rawBody, signatureHeader, secret) {
|
|
792
|
+
if (!signatureHeader || !secret) return false;
|
|
793
|
+
const match = /^\s*sha256=([a-f0-9]+)\s*$/i.exec(signatureHeader);
|
|
794
|
+
if (!match) return false;
|
|
795
|
+
const expected = crypto.createHmac("sha256", secret).update(rawBody).digest("hex");
|
|
796
|
+
const provided = match[1].toLowerCase();
|
|
797
|
+
if (provided.length !== expected.length) return false;
|
|
798
|
+
return crypto.timingSafeEqual(Buffer.from(provided, "utf8"), Buffer.from(expected, "utf8"));
|
|
799
|
+
}
|
|
800
|
+
|
|
801
|
+
// src/node/index.ts
|
|
802
|
+
var singleton = null;
|
|
803
|
+
function signalbird(config) {
|
|
804
|
+
if (singleton && !config) {
|
|
805
|
+
return singleton;
|
|
806
|
+
}
|
|
807
|
+
const apiKey = config?.apiKey ?? process.env.SIGNALBIRD_KEY ?? "";
|
|
808
|
+
const client = new SignalbirdClient({
|
|
809
|
+
apiKey,
|
|
810
|
+
baseUrl: config?.baseUrl ?? process.env.SIGNALBIRD_URL,
|
|
811
|
+
source: config?.source ?? process.env.SIGNALBIRD_SOURCE,
|
|
812
|
+
...config
|
|
813
|
+
});
|
|
814
|
+
if (!config) {
|
|
815
|
+
singleton = client;
|
|
816
|
+
}
|
|
817
|
+
return client;
|
|
818
|
+
}
|
|
819
|
+
function resetSignalbird() {
|
|
820
|
+
singleton = null;
|
|
821
|
+
}
|
|
822
|
+
var managementSingleton = null;
|
|
823
|
+
function management(config) {
|
|
824
|
+
if (managementSingleton && !config) {
|
|
825
|
+
return managementSingleton;
|
|
826
|
+
}
|
|
827
|
+
const client = new SignalbirdManagement({
|
|
828
|
+
apiKey: config?.apiKey ?? process.env.SIGNALBIRD_API_KEY ?? process.env.SIGNALBIRD_MESSAGING_KEY ?? "",
|
|
829
|
+
baseUrl: config?.baseUrl ?? process.env.SIGNALBIRD_URL,
|
|
830
|
+
...config
|
|
831
|
+
});
|
|
832
|
+
if (!config) {
|
|
833
|
+
managementSingleton = client;
|
|
834
|
+
}
|
|
835
|
+
return client;
|
|
836
|
+
}
|
|
837
|
+
function resetManagement() {
|
|
838
|
+
managementSingleton = null;
|
|
839
|
+
}
|
|
840
|
+
|
|
841
|
+
exports.DEFAULT_BASE_URL = DEFAULT_BASE_URL;
|
|
842
|
+
exports.SignalbirdClient = SignalbirdClient;
|
|
843
|
+
exports.SignalbirdError = SignalbirdError;
|
|
844
|
+
exports.SignalbirdManagement = SignalbirdManagement;
|
|
845
|
+
exports.SignalbirdMessaging = SignalbirdMessaging;
|
|
846
|
+
exports.SignalbirdPartner = SignalbirdPartner;
|
|
847
|
+
exports.management = management;
|
|
848
|
+
exports.resetManagement = resetManagement;
|
|
849
|
+
exports.resetSignalbird = resetSignalbird;
|
|
850
|
+
exports.signalbird = signalbird;
|
|
851
|
+
exports.verifyWebhook = verifyWebhook;
|
|
852
|
+
//# sourceMappingURL=index.js.map
|
|
853
|
+
//# sourceMappingURL=index.js.map
|