@graph8/sdk 0.2.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 +281 -0
- package/dist/index.d.mts +857 -0
- package/dist/index.d.ts +857 -0
- package/dist/index.js +961 -0
- package/dist/index.js.map +1 -0
- package/dist/index.mjs +934 -0
- package/dist/index.mjs.map +1 -0
- package/dist/react.d.mts +860 -0
- package/dist/react.d.ts +860 -0
- package/dist/react.js +999 -0
- package/dist/react.js.map +1 -0
- package/dist/react.mjs +974 -0
- package/dist/react.mjs.map +1 -0
- package/package.json +50 -0
package/dist/react.mjs
ADDED
|
@@ -0,0 +1,974 @@
|
|
|
1
|
+
"use client";
|
|
2
|
+
|
|
3
|
+
// src/react.tsx
|
|
4
|
+
import { createContext, useContext, useEffect } from "react";
|
|
5
|
+
|
|
6
|
+
// src/core.ts
|
|
7
|
+
import { jitsuAnalytics } from "@jitsu/js";
|
|
8
|
+
|
|
9
|
+
// src/forms.ts
|
|
10
|
+
var DEFAULT_API = "https://be.graph8.com";
|
|
11
|
+
var createFormsClient = (writeKey, apiUrl) => {
|
|
12
|
+
const baseUrl = apiUrl || DEFAULT_API;
|
|
13
|
+
return {
|
|
14
|
+
/**
|
|
15
|
+
* Look up known fields for an email address.
|
|
16
|
+
*
|
|
17
|
+
* Use this in progressive forms: after the user enters their email,
|
|
18
|
+
* check what graph8 already knows and only show missing fields.
|
|
19
|
+
*/
|
|
20
|
+
async lookup(email) {
|
|
21
|
+
const resp = await fetch(`${baseUrl}/api/v1/public/enrich/lookup`, {
|
|
22
|
+
method: "POST",
|
|
23
|
+
headers: {
|
|
24
|
+
"Content-Type": "application/json",
|
|
25
|
+
"X-Write-Key": writeKey
|
|
26
|
+
},
|
|
27
|
+
body: JSON.stringify({ email })
|
|
28
|
+
});
|
|
29
|
+
if (!resp.ok) {
|
|
30
|
+
return { found: false, known_fields: {}, missing_fields: [] };
|
|
31
|
+
}
|
|
32
|
+
const data = await resp.json();
|
|
33
|
+
return data.data || data;
|
|
34
|
+
}
|
|
35
|
+
};
|
|
36
|
+
};
|
|
37
|
+
|
|
38
|
+
// src/utils.ts
|
|
39
|
+
var isServer = typeof window === "undefined";
|
|
40
|
+
|
|
41
|
+
// src/visitors.ts
|
|
42
|
+
var DEFAULT_API2 = "https://be.graph8.com";
|
|
43
|
+
var createVisitorsClient = (writeKey, apiUrl) => {
|
|
44
|
+
const baseUrl = apiUrl || DEFAULT_API2;
|
|
45
|
+
let intentInterval = null;
|
|
46
|
+
const headers = () => ({
|
|
47
|
+
"Content-Type": "application/json",
|
|
48
|
+
"X-Write-Key": writeKey
|
|
49
|
+
});
|
|
50
|
+
return {
|
|
51
|
+
/** Identify the current visitor's company from their IP address. */
|
|
52
|
+
async identify() {
|
|
53
|
+
if (isServer) return { company_name: null, company_domain: null, industry: null, employee_count: null, city: null, country: null, confidence: 0 };
|
|
54
|
+
const resp = await fetch(`${baseUrl}/api/v1/public/visitors/company`, { headers: headers() });
|
|
55
|
+
if (!resp.ok) return { company_name: null, company_domain: null, industry: null, employee_count: null, city: null, country: null, confidence: 0 };
|
|
56
|
+
const data = await resp.json();
|
|
57
|
+
return data.data || data;
|
|
58
|
+
},
|
|
59
|
+
/** Get engagement score for the current visitor. */
|
|
60
|
+
async score() {
|
|
61
|
+
if (isServer) return { engagement: 0, intent: "low", signals: [] };
|
|
62
|
+
const resp = await fetch(`${baseUrl}/api/v1/public/visitors/score`, { headers: headers() });
|
|
63
|
+
if (!resp.ok) return { engagement: 0, intent: "low", signals: [] };
|
|
64
|
+
const data = await resp.json();
|
|
65
|
+
return data.data || data;
|
|
66
|
+
},
|
|
67
|
+
/** Listen for visitors matching an intent level. Polls every 30 seconds. */
|
|
68
|
+
onIntent(level, callback) {
|
|
69
|
+
if (isServer) return () => {
|
|
70
|
+
};
|
|
71
|
+
const check = async () => {
|
|
72
|
+
try {
|
|
73
|
+
const [company, scoreData] = await Promise.all([
|
|
74
|
+
this.identify(),
|
|
75
|
+
this.score()
|
|
76
|
+
]);
|
|
77
|
+
if (scoreData.intent === level || level === "medium" && scoreData.intent === "high") {
|
|
78
|
+
callback({ ...company, ...scoreData });
|
|
79
|
+
}
|
|
80
|
+
} catch {
|
|
81
|
+
}
|
|
82
|
+
};
|
|
83
|
+
check();
|
|
84
|
+
intentInterval = setInterval(check, 3e4);
|
|
85
|
+
return () => {
|
|
86
|
+
if (intentInterval) clearInterval(intentInterval);
|
|
87
|
+
};
|
|
88
|
+
}
|
|
89
|
+
};
|
|
90
|
+
};
|
|
91
|
+
|
|
92
|
+
// src/copilot.ts
|
|
93
|
+
var DEFAULT_API3 = "https://be.graph8.com";
|
|
94
|
+
var createCopilotClient = (writeKey, apiUrl) => {
|
|
95
|
+
const baseUrl = apiUrl || DEFAULT_API3;
|
|
96
|
+
const listeners = /* @__PURE__ */ new Map();
|
|
97
|
+
const actions = /* @__PURE__ */ new Map();
|
|
98
|
+
let widgetEl = null;
|
|
99
|
+
const emit = (event, data = {}) => {
|
|
100
|
+
listeners.get(event)?.forEach((cb) => cb(data));
|
|
101
|
+
};
|
|
102
|
+
return {
|
|
103
|
+
/** Open the copilot widget. */
|
|
104
|
+
open(config) {
|
|
105
|
+
if (isServer) return;
|
|
106
|
+
if (widgetEl) widgetEl.remove();
|
|
107
|
+
const position = config?.position || "bottom-right";
|
|
108
|
+
const posStyle = position === "bottom-left" ? "left:16px;" : "right:16px;";
|
|
109
|
+
const iframe = document.createElement("iframe");
|
|
110
|
+
iframe.src = `${baseUrl}/copilot/embed?write_key=${writeKey}&theme=${config?.theme || "auto"}`;
|
|
111
|
+
iframe.style.cssText = `position:fixed;bottom:16px;${posStyle}width:400px;height:600px;border:none;border-radius:12px;box-shadow:0 8px 32px rgba(0,0,0,0.15);z-index:99998;`;
|
|
112
|
+
iframe.id = "g8-copilot-widget";
|
|
113
|
+
document.body.appendChild(iframe);
|
|
114
|
+
widgetEl = iframe;
|
|
115
|
+
emit("open");
|
|
116
|
+
},
|
|
117
|
+
/** Send a message to the copilot programmatically. */
|
|
118
|
+
async ask(message) {
|
|
119
|
+
const resp = await fetch(`${baseUrl}/api/v1/public/copilot/chat`, {
|
|
120
|
+
method: "POST",
|
|
121
|
+
headers: { "Content-Type": "application/json", "X-Write-Key": writeKey },
|
|
122
|
+
body: JSON.stringify({ message })
|
|
123
|
+
});
|
|
124
|
+
if (!resp.ok) return "Sorry, I could not process that request.";
|
|
125
|
+
const data = await resp.json();
|
|
126
|
+
return data.response || data.data?.response || "";
|
|
127
|
+
},
|
|
128
|
+
/** Register a custom action the copilot can trigger. */
|
|
129
|
+
registerAction(name, handler) {
|
|
130
|
+
actions.set(name, handler);
|
|
131
|
+
},
|
|
132
|
+
/** Listen for copilot events. */
|
|
133
|
+
on(event, callback) {
|
|
134
|
+
if (!listeners.has(event)) listeners.set(event, []);
|
|
135
|
+
listeners.get(event).push(callback);
|
|
136
|
+
},
|
|
137
|
+
/** Close the copilot widget. */
|
|
138
|
+
close() {
|
|
139
|
+
if (widgetEl) {
|
|
140
|
+
widgetEl.remove();
|
|
141
|
+
widgetEl = null;
|
|
142
|
+
emit("close");
|
|
143
|
+
}
|
|
144
|
+
}
|
|
145
|
+
};
|
|
146
|
+
};
|
|
147
|
+
|
|
148
|
+
// src/chat.ts
|
|
149
|
+
var DEFAULT_API4 = "https://be.graph8.com";
|
|
150
|
+
var createChatClient = (writeKey, apiUrl) => {
|
|
151
|
+
const baseUrl = apiUrl || DEFAULT_API4;
|
|
152
|
+
const listeners = /* @__PURE__ */ new Map();
|
|
153
|
+
let widgetEl = null;
|
|
154
|
+
let ws = null;
|
|
155
|
+
const emit = (event, data = {}) => {
|
|
156
|
+
listeners.get(event)?.forEach((cb) => cb(data));
|
|
157
|
+
};
|
|
158
|
+
return {
|
|
159
|
+
/** Open the chat widget. */
|
|
160
|
+
open(config) {
|
|
161
|
+
if (isServer) return;
|
|
162
|
+
if (widgetEl) widgetEl.remove();
|
|
163
|
+
const position = config?.position || "bottom-right";
|
|
164
|
+
const posStyle = position === "bottom-left" ? "left:16px;" : "right:16px;";
|
|
165
|
+
const iframe = document.createElement("iframe");
|
|
166
|
+
iframe.src = `${baseUrl}/webchat/embed?write_key=${writeKey}&theme=${config?.theme || "auto"}`;
|
|
167
|
+
iframe.style.cssText = `position:fixed;bottom:16px;${posStyle}width:380px;height:560px;border:none;border-radius:12px;box-shadow:0 8px 32px rgba(0,0,0,0.15);z-index:99997;`;
|
|
168
|
+
iframe.id = "g8-chat-widget";
|
|
169
|
+
document.body.appendChild(iframe);
|
|
170
|
+
widgetEl = iframe;
|
|
171
|
+
emit("open");
|
|
172
|
+
},
|
|
173
|
+
/** Send a message. */
|
|
174
|
+
send(message) {
|
|
175
|
+
if (ws && ws.readyState === WebSocket.OPEN) {
|
|
176
|
+
ws.send(JSON.stringify({ type: "message", content: message }));
|
|
177
|
+
}
|
|
178
|
+
},
|
|
179
|
+
/** Listen for chat events. */
|
|
180
|
+
on(event, callback) {
|
|
181
|
+
if (!listeners.has(event)) listeners.set(event, []);
|
|
182
|
+
listeners.get(event).push(callback);
|
|
183
|
+
},
|
|
184
|
+
/** Configure the chat appearance. */
|
|
185
|
+
configure(config) {
|
|
186
|
+
if (widgetEl && widgetEl instanceof HTMLIFrameElement) {
|
|
187
|
+
widgetEl.contentWindow?.postMessage({ type: "g8_chat_config", config }, "*");
|
|
188
|
+
}
|
|
189
|
+
},
|
|
190
|
+
/** Close the chat widget. */
|
|
191
|
+
close() {
|
|
192
|
+
if (ws) {
|
|
193
|
+
ws.close();
|
|
194
|
+
ws = null;
|
|
195
|
+
}
|
|
196
|
+
if (widgetEl) {
|
|
197
|
+
widgetEl.remove();
|
|
198
|
+
widgetEl = null;
|
|
199
|
+
}
|
|
200
|
+
emit("close");
|
|
201
|
+
}
|
|
202
|
+
};
|
|
203
|
+
};
|
|
204
|
+
|
|
205
|
+
// src/calendar.ts
|
|
206
|
+
var DEFAULT_API5 = "https://be.graph8.com";
|
|
207
|
+
var createCalendarClient = (apiUrl) => {
|
|
208
|
+
const baseUrl = apiUrl || DEFAULT_API5;
|
|
209
|
+
const listeners = /* @__PURE__ */ new Map();
|
|
210
|
+
return {
|
|
211
|
+
/** Show a booking modal overlay. */
|
|
212
|
+
show(config) {
|
|
213
|
+
if (isServer) return;
|
|
214
|
+
const url = `${baseUrl}/appointments/${config.username}/${config.eventType}`;
|
|
215
|
+
const params = new URLSearchParams();
|
|
216
|
+
if (config.prefill?.name) params.set("name", config.prefill.name);
|
|
217
|
+
if (config.prefill?.email) params.set("email", config.prefill.email);
|
|
218
|
+
const iframe = document.createElement("iframe");
|
|
219
|
+
iframe.src = `${url}?${params.toString()}`;
|
|
220
|
+
iframe.style.cssText = "position:fixed;top:0;left:0;width:100%;height:100%;border:none;z-index:99999;background:rgba(0,0,0,0.5);";
|
|
221
|
+
iframe.id = "g8-calendar-modal";
|
|
222
|
+
document.body.appendChild(iframe);
|
|
223
|
+
const onKey = (e) => {
|
|
224
|
+
if (e.key === "Escape") {
|
|
225
|
+
iframe.remove();
|
|
226
|
+
document.removeEventListener("keydown", onKey);
|
|
227
|
+
}
|
|
228
|
+
};
|
|
229
|
+
document.addEventListener("keydown", onKey);
|
|
230
|
+
},
|
|
231
|
+
/** Embed booking widget inline in a container element. */
|
|
232
|
+
embed(selector, config) {
|
|
233
|
+
if (isServer) return;
|
|
234
|
+
const container = document.querySelector(selector);
|
|
235
|
+
if (!container) return;
|
|
236
|
+
const url = `${baseUrl}/appointments/${config.username}/${config.eventType}`;
|
|
237
|
+
const iframe = document.createElement("iframe");
|
|
238
|
+
iframe.src = url;
|
|
239
|
+
iframe.style.cssText = "width:100%;min-height:600px;border:none;border-radius:8px;";
|
|
240
|
+
container.appendChild(iframe);
|
|
241
|
+
},
|
|
242
|
+
/** Get available time slots for an event type. */
|
|
243
|
+
async slots(username, eventSlug, range) {
|
|
244
|
+
const params = new URLSearchParams({
|
|
245
|
+
start_date: range.start,
|
|
246
|
+
end_date: range.end
|
|
247
|
+
});
|
|
248
|
+
const resp = await fetch(`${baseUrl}/appointments/public/slots?username=${username}&event_slug=${eventSlug}&${params.toString()}`);
|
|
249
|
+
if (!resp.ok) return [];
|
|
250
|
+
const data = await resp.json();
|
|
251
|
+
return data.slots || data.data || [];
|
|
252
|
+
},
|
|
253
|
+
/** Book a meeting programmatically. */
|
|
254
|
+
async book(request) {
|
|
255
|
+
const resp = await fetch(`${baseUrl}/appointments/public/bookings`, {
|
|
256
|
+
method: "POST",
|
|
257
|
+
headers: { "Content-Type": "application/json" },
|
|
258
|
+
body: JSON.stringify(request)
|
|
259
|
+
});
|
|
260
|
+
if (!resp.ok) return null;
|
|
261
|
+
const data = await resp.json();
|
|
262
|
+
const emit = listeners.get("booked");
|
|
263
|
+
if (emit) emit.forEach((cb) => cb(data));
|
|
264
|
+
return data;
|
|
265
|
+
},
|
|
266
|
+
/** Listen for calendar events. */
|
|
267
|
+
on(event, callback) {
|
|
268
|
+
if (!listeners.has(event)) listeners.set(event, []);
|
|
269
|
+
listeners.get(event).push(callback);
|
|
270
|
+
}
|
|
271
|
+
};
|
|
272
|
+
};
|
|
273
|
+
|
|
274
|
+
// src/enrich.ts
|
|
275
|
+
var DEFAULT_API6 = "https://be.graph8.com";
|
|
276
|
+
var createEnrichClient = (apiKey, apiUrl) => {
|
|
277
|
+
const baseUrl = apiUrl || DEFAULT_API6;
|
|
278
|
+
const headers = () => ({
|
|
279
|
+
"Content-Type": "application/json",
|
|
280
|
+
Authorization: `Bearer ${apiKey}`
|
|
281
|
+
});
|
|
282
|
+
return {
|
|
283
|
+
/** Look up a person by email, LinkedIn, or name + company. Costs 1 credit. */
|
|
284
|
+
async person(params) {
|
|
285
|
+
const resp = await fetch(`${baseUrl}/api/v1/enrichment/lookup/person`, {
|
|
286
|
+
method: "POST",
|
|
287
|
+
headers: headers(),
|
|
288
|
+
body: JSON.stringify(params)
|
|
289
|
+
});
|
|
290
|
+
const data = await resp.json();
|
|
291
|
+
return data.data || data;
|
|
292
|
+
},
|
|
293
|
+
/** Look up a company by domain or name. Costs 1 credit. */
|
|
294
|
+
async company(params) {
|
|
295
|
+
const resp = await fetch(`${baseUrl}/api/v1/enrichment/lookup/company`, {
|
|
296
|
+
method: "POST",
|
|
297
|
+
headers: headers(),
|
|
298
|
+
body: JSON.stringify(params)
|
|
299
|
+
});
|
|
300
|
+
const data = await resp.json();
|
|
301
|
+
return data.data || data;
|
|
302
|
+
},
|
|
303
|
+
/** Verify an email address. Costs 1 credit. */
|
|
304
|
+
async verifyEmail(email) {
|
|
305
|
+
const resp = await fetch(`${baseUrl}/api/v1/enrichment/verify-email`, {
|
|
306
|
+
method: "POST",
|
|
307
|
+
headers: headers(),
|
|
308
|
+
body: JSON.stringify({ email })
|
|
309
|
+
});
|
|
310
|
+
const data = await resp.json();
|
|
311
|
+
return data.data || data;
|
|
312
|
+
},
|
|
313
|
+
/** Search 300M+ contacts with filters. Credits charged per result. */
|
|
314
|
+
async search(filters, page = 1, limit = 25) {
|
|
315
|
+
const resp = await fetch(`${baseUrl}/api/v1/search/contacts`, {
|
|
316
|
+
method: "POST",
|
|
317
|
+
headers: headers(),
|
|
318
|
+
body: JSON.stringify({ filters, page, limit })
|
|
319
|
+
});
|
|
320
|
+
const data = await resp.json();
|
|
321
|
+
return data.data || data;
|
|
322
|
+
}
|
|
323
|
+
};
|
|
324
|
+
};
|
|
325
|
+
|
|
326
|
+
// src/sequences.ts
|
|
327
|
+
var DEFAULT_API7 = "https://be.graph8.com";
|
|
328
|
+
var createSequencesClient = (apiKey, apiUrl) => {
|
|
329
|
+
const baseUrl = apiUrl || DEFAULT_API7;
|
|
330
|
+
const headers = () => ({ "Content-Type": "application/json", Authorization: `Bearer ${apiKey}` });
|
|
331
|
+
return {
|
|
332
|
+
async list(page = 1, limit = 50) {
|
|
333
|
+
const resp = await fetch(`${baseUrl}/api/v1/sequences?page=${page}&limit=${limit}`, { headers: headers() });
|
|
334
|
+
const data = await resp.json();
|
|
335
|
+
return data.data || data;
|
|
336
|
+
},
|
|
337
|
+
async add(config) {
|
|
338
|
+
await fetch(`${baseUrl}/api/v1/sequences/${config.sequenceId}/contacts`, {
|
|
339
|
+
method: "POST",
|
|
340
|
+
headers: headers(),
|
|
341
|
+
body: JSON.stringify({ contact_ids: config.contactIds, list_id: config.listId })
|
|
342
|
+
});
|
|
343
|
+
}
|
|
344
|
+
};
|
|
345
|
+
};
|
|
346
|
+
|
|
347
|
+
// src/campaigns.ts
|
|
348
|
+
var DEFAULT_API8 = "https://be.graph8.com";
|
|
349
|
+
var createCampaignsClient = (apiKey, apiUrl) => {
|
|
350
|
+
const baseUrl = apiUrl || DEFAULT_API8;
|
|
351
|
+
const headers = () => ({ "Content-Type": "application/json", Authorization: `Bearer ${apiKey}` });
|
|
352
|
+
return {
|
|
353
|
+
async list(page = 1, limit = 50) {
|
|
354
|
+
const resp = await fetch(`${baseUrl}/api/v1/campaigns?page=${page}&limit=${limit}`, { headers: headers() });
|
|
355
|
+
const data = await resp.json();
|
|
356
|
+
return data.data || data;
|
|
357
|
+
},
|
|
358
|
+
async get(campaignId) {
|
|
359
|
+
const resp = await fetch(`${baseUrl}/api/v1/campaigns/${campaignId}`, { headers: headers() });
|
|
360
|
+
const data = await resp.json();
|
|
361
|
+
return data.data || data;
|
|
362
|
+
},
|
|
363
|
+
async create(config) {
|
|
364
|
+
const resp = await fetch(`${baseUrl}/api/v1/campaigns`, {
|
|
365
|
+
method: "POST",
|
|
366
|
+
headers: headers(),
|
|
367
|
+
body: JSON.stringify(config)
|
|
368
|
+
});
|
|
369
|
+
const data = await resp.json();
|
|
370
|
+
return data.data || data;
|
|
371
|
+
},
|
|
372
|
+
async launch(campaignId) {
|
|
373
|
+
await fetch(`${baseUrl}/api/v1/campaigns/${campaignId}/launch`, {
|
|
374
|
+
method: "POST",
|
|
375
|
+
headers: headers()
|
|
376
|
+
});
|
|
377
|
+
},
|
|
378
|
+
async stats(campaignId) {
|
|
379
|
+
const resp = await fetch(`${baseUrl}/api/v1/campaigns/${campaignId}/stats`, { headers: headers() });
|
|
380
|
+
const data = await resp.json();
|
|
381
|
+
return data.data || data;
|
|
382
|
+
}
|
|
383
|
+
};
|
|
384
|
+
};
|
|
385
|
+
|
|
386
|
+
// src/integrations.ts
|
|
387
|
+
var DEFAULT_API9 = "https://be.graph8.com";
|
|
388
|
+
var createIntegrationsClient = (apiKey, apiUrl) => {
|
|
389
|
+
const baseUrl = apiUrl || DEFAULT_API9;
|
|
390
|
+
const headers = () => ({ "Content-Type": "application/json", Authorization: `Bearer ${apiKey}` });
|
|
391
|
+
return {
|
|
392
|
+
async list() {
|
|
393
|
+
const resp = await fetch(`${baseUrl}/api/v1/integrations`, { headers: headers() });
|
|
394
|
+
const data = await resp.json();
|
|
395
|
+
return data.data || data;
|
|
396
|
+
},
|
|
397
|
+
async connect(provider, config) {
|
|
398
|
+
await fetch(`${baseUrl}/api/v1/integrations/connect`, {
|
|
399
|
+
method: "POST",
|
|
400
|
+
headers: headers(),
|
|
401
|
+
body: JSON.stringify({ provider, ...config })
|
|
402
|
+
});
|
|
403
|
+
},
|
|
404
|
+
async sync(provider, config) {
|
|
405
|
+
await fetch(`${baseUrl}/api/v1/integrations/sync`, {
|
|
406
|
+
method: "POST",
|
|
407
|
+
headers: headers(),
|
|
408
|
+
body: JSON.stringify({ provider, ...config })
|
|
409
|
+
});
|
|
410
|
+
}
|
|
411
|
+
};
|
|
412
|
+
};
|
|
413
|
+
|
|
414
|
+
// src/signals.ts
|
|
415
|
+
var DEFAULT_API10 = "https://be.graph8.com";
|
|
416
|
+
var createSignalsClient = (key, isApiKey, apiUrl) => {
|
|
417
|
+
const baseUrl = apiUrl || DEFAULT_API10;
|
|
418
|
+
const headers = () => isApiKey ? { "Content-Type": "application/json", "Authorization": `Bearer ${key}` } : { "Content-Type": "application/json", "X-Write-Key": key };
|
|
419
|
+
const endpoint = isApiKey ? "/api/v1/signals/company" : "/api/v1/public/signals/company";
|
|
420
|
+
return {
|
|
421
|
+
/** Get intent signals for a specific company domain. */
|
|
422
|
+
async company(domain) {
|
|
423
|
+
const resp = await fetch(`${baseUrl}${endpoint}?domain=${encodeURIComponent(domain)}`, { headers: headers() });
|
|
424
|
+
if (!resp.ok) return { domain, score: 0, intent: "low", signals: [], last_seen: null };
|
|
425
|
+
const data = await resp.json();
|
|
426
|
+
return data.data || data;
|
|
427
|
+
},
|
|
428
|
+
/** Stream intent signals - calls callback every 30s with latest data. */
|
|
429
|
+
stream(domains, callback) {
|
|
430
|
+
const check = async () => {
|
|
431
|
+
try {
|
|
432
|
+
const results = await Promise.all(domains.map((d) => this.company(d)));
|
|
433
|
+
callback(results);
|
|
434
|
+
} catch {
|
|
435
|
+
}
|
|
436
|
+
};
|
|
437
|
+
check();
|
|
438
|
+
const interval = setInterval(check, 3e4);
|
|
439
|
+
return () => clearInterval(interval);
|
|
440
|
+
}
|
|
441
|
+
};
|
|
442
|
+
};
|
|
443
|
+
|
|
444
|
+
// src/analytics.ts
|
|
445
|
+
var DEFAULT_API11 = "https://be.graph8.com";
|
|
446
|
+
var createAnalyticsClient = (apiKey, apiUrl) => {
|
|
447
|
+
const baseUrl = apiUrl || DEFAULT_API11;
|
|
448
|
+
const headers = () => ({ "Content-Type": "application/json", Authorization: `Bearer ${apiKey}` });
|
|
449
|
+
return {
|
|
450
|
+
async overview(config) {
|
|
451
|
+
const params = new URLSearchParams();
|
|
452
|
+
if (config?.period) params.set("period", config.period);
|
|
453
|
+
const resp = await fetch(`${baseUrl}/api/v1/analytics/overview?${params.toString()}`, { headers: headers() });
|
|
454
|
+
if (!resp.ok) return { visitors: 0, contacts_created: 0, emails_sent: 0, emails_opened: 0, replies: 0, meetings_booked: 0, period: config?.period || "30d" };
|
|
455
|
+
const data = await resp.json();
|
|
456
|
+
return data.data || data;
|
|
457
|
+
}
|
|
458
|
+
};
|
|
459
|
+
};
|
|
460
|
+
|
|
461
|
+
// src/voice.ts
|
|
462
|
+
var DEFAULT_API12 = "https://be.graph8.com";
|
|
463
|
+
var createVoiceClient = (apiKey, apiUrl) => {
|
|
464
|
+
const baseUrl = apiUrl || DEFAULT_API12;
|
|
465
|
+
const headers = () => ({ "Content-Type": "application/json", Authorization: `Bearer ${apiKey}` });
|
|
466
|
+
const listeners = /* @__PURE__ */ new Map();
|
|
467
|
+
return {
|
|
468
|
+
/** Start an AI voice session. */
|
|
469
|
+
async start(config) {
|
|
470
|
+
const resp = await fetch(`${baseUrl}/api/v1/voice/sessions`, {
|
|
471
|
+
method: "POST",
|
|
472
|
+
headers: headers(),
|
|
473
|
+
body: JSON.stringify(config)
|
|
474
|
+
});
|
|
475
|
+
const data = await resp.json();
|
|
476
|
+
return data.data || data;
|
|
477
|
+
},
|
|
478
|
+
/** Get call analysis for a completed session. */
|
|
479
|
+
async analysis(sessionId) {
|
|
480
|
+
const resp = await fetch(`${baseUrl}/api/v1/voice/sessions/${sessionId}/analysis`, { headers: headers() });
|
|
481
|
+
const data = await resp.json();
|
|
482
|
+
return data.data || data;
|
|
483
|
+
},
|
|
484
|
+
/** Listen for voice events. */
|
|
485
|
+
on(event, callback) {
|
|
486
|
+
if (!listeners.has(event)) listeners.set(event, []);
|
|
487
|
+
listeners.get(event).push(callback);
|
|
488
|
+
}
|
|
489
|
+
};
|
|
490
|
+
};
|
|
491
|
+
|
|
492
|
+
// src/pages.ts
|
|
493
|
+
var DEFAULT_API13 = "https://be.graph8.com";
|
|
494
|
+
var createPagesClient = (apiKey, apiUrl) => {
|
|
495
|
+
const baseUrl = apiUrl || DEFAULT_API13;
|
|
496
|
+
const headers = () => ({ "Content-Type": "application/json", Authorization: `Bearer ${apiKey}` });
|
|
497
|
+
return {
|
|
498
|
+
/** Clone a landing page from any URL. */
|
|
499
|
+
async clone(url) {
|
|
500
|
+
const resp = await fetch(`${baseUrl}/api/v1/landing-pages/clone-url`, {
|
|
501
|
+
method: "POST",
|
|
502
|
+
headers: headers(),
|
|
503
|
+
body: JSON.stringify({ url })
|
|
504
|
+
});
|
|
505
|
+
const data = await resp.json();
|
|
506
|
+
return data.data || data;
|
|
507
|
+
},
|
|
508
|
+
/** Create a landing page from a template. */
|
|
509
|
+
async create(config) {
|
|
510
|
+
const resp = await fetch(`${baseUrl}/api/v1/landing-pages`, {
|
|
511
|
+
method: "POST",
|
|
512
|
+
headers: headers(),
|
|
513
|
+
body: JSON.stringify(config)
|
|
514
|
+
});
|
|
515
|
+
const data = await resp.json();
|
|
516
|
+
return data.data || data;
|
|
517
|
+
},
|
|
518
|
+
/** Publish a landing page to CDN. */
|
|
519
|
+
async publish(pageId) {
|
|
520
|
+
const resp = await fetch(`${baseUrl}/api/v1/landing-pages/${pageId}/publish`, {
|
|
521
|
+
method: "POST",
|
|
522
|
+
headers: headers()
|
|
523
|
+
});
|
|
524
|
+
const data = await resp.json();
|
|
525
|
+
return { url: data.published_url || data.data?.published_url || "" };
|
|
526
|
+
}
|
|
527
|
+
};
|
|
528
|
+
};
|
|
529
|
+
|
|
530
|
+
// src/webhooks.ts
|
|
531
|
+
var DEFAULT_API14 = "https://be.graph8.com";
|
|
532
|
+
var createWebhooksClient = (apiKey, apiUrl) => {
|
|
533
|
+
const baseUrl = apiUrl || DEFAULT_API14;
|
|
534
|
+
const headers = () => ({ "Content-Type": "application/json", Authorization: `Bearer ${apiKey}` });
|
|
535
|
+
const listeners = /* @__PURE__ */ new Map();
|
|
536
|
+
let polling = false;
|
|
537
|
+
let pollInterval = null;
|
|
538
|
+
return {
|
|
539
|
+
/** Register a listener for a webhook event. Starts polling automatically. */
|
|
540
|
+
on(event, callback) {
|
|
541
|
+
if (!listeners.has(event)) listeners.set(event, []);
|
|
542
|
+
listeners.get(event).push(callback);
|
|
543
|
+
if (!polling) {
|
|
544
|
+
polling = true;
|
|
545
|
+
pollInterval = setInterval(async () => {
|
|
546
|
+
try {
|
|
547
|
+
const resp = await fetch(`${baseUrl}/api/v1/webhooks/events?since=30s`, { headers: headers() });
|
|
548
|
+
if (!resp.ok) return;
|
|
549
|
+
const data = await resp.json();
|
|
550
|
+
const events = data.data || data || [];
|
|
551
|
+
for (const evt of events) {
|
|
552
|
+
const cbs = listeners.get(evt.type);
|
|
553
|
+
if (cbs) cbs.forEach((cb) => cb(evt));
|
|
554
|
+
}
|
|
555
|
+
} catch {
|
|
556
|
+
}
|
|
557
|
+
}, 3e4);
|
|
558
|
+
}
|
|
559
|
+
},
|
|
560
|
+
/** Stop all webhook polling. */
|
|
561
|
+
stop() {
|
|
562
|
+
if (pollInterval) clearInterval(pollInterval);
|
|
563
|
+
polling = false;
|
|
564
|
+
listeners.clear();
|
|
565
|
+
}
|
|
566
|
+
};
|
|
567
|
+
};
|
|
568
|
+
|
|
569
|
+
// src/contacts.ts
|
|
570
|
+
var DEFAULT_API15 = "https://be.graph8.com";
|
|
571
|
+
var createContactsClient = (apiKey, apiUrl) => {
|
|
572
|
+
const baseUrl = apiUrl || DEFAULT_API15;
|
|
573
|
+
const headers = () => ({ "Content-Type": "application/json", Authorization: `Bearer ${apiKey}` });
|
|
574
|
+
const toQuery = (params) => {
|
|
575
|
+
const qs = new URLSearchParams();
|
|
576
|
+
for (const [k, v] of Object.entries(params)) {
|
|
577
|
+
if (v != null) qs.set(k, String(v));
|
|
578
|
+
}
|
|
579
|
+
const s = qs.toString();
|
|
580
|
+
return s ? `?${s}` : "";
|
|
581
|
+
};
|
|
582
|
+
return {
|
|
583
|
+
/** List contacts with optional filters. */
|
|
584
|
+
async list(params = {}) {
|
|
585
|
+
const resp = await fetch(`${baseUrl}/api/v1/contacts${toQuery(params)}`, { headers: headers() });
|
|
586
|
+
return resp.json();
|
|
587
|
+
},
|
|
588
|
+
/** Get a single contact by ID. */
|
|
589
|
+
async get(contactId) {
|
|
590
|
+
const resp = await fetch(`${baseUrl}/api/v1/contacts/${contactId}`, { headers: headers() });
|
|
591
|
+
const data = await resp.json();
|
|
592
|
+
return data.data || data;
|
|
593
|
+
},
|
|
594
|
+
/** Create a new contact. */
|
|
595
|
+
async create(contact) {
|
|
596
|
+
const resp = await fetch(`${baseUrl}/api/v1/contacts`, {
|
|
597
|
+
method: "POST",
|
|
598
|
+
headers: headers(),
|
|
599
|
+
body: JSON.stringify(contact)
|
|
600
|
+
});
|
|
601
|
+
const data = await resp.json();
|
|
602
|
+
return data.data || data;
|
|
603
|
+
},
|
|
604
|
+
/** Update a contact (partial). */
|
|
605
|
+
async update(contactId, fields) {
|
|
606
|
+
const resp = await fetch(`${baseUrl}/api/v1/contacts/${contactId}`, {
|
|
607
|
+
method: "PATCH",
|
|
608
|
+
headers: headers(),
|
|
609
|
+
body: JSON.stringify(fields)
|
|
610
|
+
});
|
|
611
|
+
return resp.json();
|
|
612
|
+
},
|
|
613
|
+
/** Delete a contact (soft-delete). */
|
|
614
|
+
async delete(contactId) {
|
|
615
|
+
const resp = await fetch(`${baseUrl}/api/v1/contacts/${contactId}`, {
|
|
616
|
+
method: "DELETE",
|
|
617
|
+
headers: headers()
|
|
618
|
+
});
|
|
619
|
+
return resp.json();
|
|
620
|
+
}
|
|
621
|
+
};
|
|
622
|
+
};
|
|
623
|
+
|
|
624
|
+
// src/companies.ts
|
|
625
|
+
var DEFAULT_API16 = "https://be.graph8.com";
|
|
626
|
+
var createCompaniesClient = (apiKey, apiUrl) => {
|
|
627
|
+
const baseUrl = apiUrl || DEFAULT_API16;
|
|
628
|
+
const headers = () => ({ "Content-Type": "application/json", Authorization: `Bearer ${apiKey}` });
|
|
629
|
+
const toQuery = (params) => {
|
|
630
|
+
const qs = new URLSearchParams();
|
|
631
|
+
for (const [k, v] of Object.entries(params)) {
|
|
632
|
+
if (v != null) qs.set(k, String(v));
|
|
633
|
+
}
|
|
634
|
+
const s = qs.toString();
|
|
635
|
+
return s ? `?${s}` : "";
|
|
636
|
+
};
|
|
637
|
+
return {
|
|
638
|
+
/** List companies with optional filters. */
|
|
639
|
+
async list(params = {}) {
|
|
640
|
+
const resp = await fetch(`${baseUrl}/api/v1/companies${toQuery(params)}`, { headers: headers() });
|
|
641
|
+
return resp.json();
|
|
642
|
+
},
|
|
643
|
+
/** Get a single company by ID. */
|
|
644
|
+
async get(companyId) {
|
|
645
|
+
const resp = await fetch(`${baseUrl}/api/v1/companies/${companyId}`, { headers: headers() });
|
|
646
|
+
const data = await resp.json();
|
|
647
|
+
return data.data || data;
|
|
648
|
+
},
|
|
649
|
+
/** Get contacts belonging to a company. */
|
|
650
|
+
async contacts(companyId, limit = 50, offset = 0) {
|
|
651
|
+
const resp = await fetch(
|
|
652
|
+
`${baseUrl}/api/v1/companies/${companyId}/contacts?limit=${limit}&offset=${offset}`,
|
|
653
|
+
{ headers: headers() }
|
|
654
|
+
);
|
|
655
|
+
return resp.json();
|
|
656
|
+
},
|
|
657
|
+
/** Update a company (partial). */
|
|
658
|
+
async update(companyId, fields) {
|
|
659
|
+
const resp = await fetch(`${baseUrl}/api/v1/companies/${companyId}`, {
|
|
660
|
+
method: "PATCH",
|
|
661
|
+
headers: headers(),
|
|
662
|
+
body: JSON.stringify(fields)
|
|
663
|
+
});
|
|
664
|
+
return resp.json();
|
|
665
|
+
},
|
|
666
|
+
/** Delete a company (soft-delete). */
|
|
667
|
+
async delete(companyId) {
|
|
668
|
+
const resp = await fetch(`${baseUrl}/api/v1/companies/${companyId}`, {
|
|
669
|
+
method: "DELETE",
|
|
670
|
+
headers: headers()
|
|
671
|
+
});
|
|
672
|
+
return resp.json();
|
|
673
|
+
}
|
|
674
|
+
};
|
|
675
|
+
};
|
|
676
|
+
|
|
677
|
+
// src/lists.ts
|
|
678
|
+
var DEFAULT_API17 = "https://be.graph8.com";
|
|
679
|
+
var createListsClient = (apiKey, apiUrl) => {
|
|
680
|
+
const baseUrl = apiUrl || DEFAULT_API17;
|
|
681
|
+
const headers = () => ({ "Content-Type": "application/json", Authorization: `Bearer ${apiKey}` });
|
|
682
|
+
return {
|
|
683
|
+
/** List all lists. */
|
|
684
|
+
async list(page = 1, limit = 50) {
|
|
685
|
+
const resp = await fetch(`${baseUrl}/api/v1/lists?page=${page}&limit=${limit}`, { headers: headers() });
|
|
686
|
+
return resp.json();
|
|
687
|
+
},
|
|
688
|
+
/** Create a new list. */
|
|
689
|
+
async create(title, type = "contacts") {
|
|
690
|
+
const resp = await fetch(`${baseUrl}/api/v1/lists`, {
|
|
691
|
+
method: "POST",
|
|
692
|
+
headers: headers(),
|
|
693
|
+
body: JSON.stringify({ title, type })
|
|
694
|
+
});
|
|
695
|
+
const data = await resp.json();
|
|
696
|
+
return data.data || data;
|
|
697
|
+
},
|
|
698
|
+
/** Delete a list (soft-delete). */
|
|
699
|
+
async delete(listId) {
|
|
700
|
+
const resp = await fetch(`${baseUrl}/api/v1/lists/${listId}`, {
|
|
701
|
+
method: "DELETE",
|
|
702
|
+
headers: headers()
|
|
703
|
+
});
|
|
704
|
+
return resp.json();
|
|
705
|
+
},
|
|
706
|
+
/** Get contacts in a list. */
|
|
707
|
+
async contacts(listId, page = 1, limit = 50) {
|
|
708
|
+
const resp = await fetch(
|
|
709
|
+
`${baseUrl}/api/v1/lists/${listId}/contacts?page=${page}&limit=${limit}`,
|
|
710
|
+
{ headers: headers() }
|
|
711
|
+
);
|
|
712
|
+
return resp.json();
|
|
713
|
+
},
|
|
714
|
+
/** Add contacts to a list. */
|
|
715
|
+
async addContacts(listId, contactIds) {
|
|
716
|
+
const resp = await fetch(`${baseUrl}/api/v1/lists/${listId}/contacts`, {
|
|
717
|
+
method: "POST",
|
|
718
|
+
headers: headers(),
|
|
719
|
+
body: JSON.stringify({ contact_ids: contactIds })
|
|
720
|
+
});
|
|
721
|
+
return resp.json();
|
|
722
|
+
},
|
|
723
|
+
/** Remove contacts from a list. */
|
|
724
|
+
async removeContacts(listId, contactIds) {
|
|
725
|
+
const resp = await fetch(`${baseUrl}/api/v1/lists/${listId}/contacts`, {
|
|
726
|
+
method: "DELETE",
|
|
727
|
+
headers: headers(),
|
|
728
|
+
body: JSON.stringify({ contact_ids: contactIds })
|
|
729
|
+
});
|
|
730
|
+
return resp.json();
|
|
731
|
+
}
|
|
732
|
+
};
|
|
733
|
+
};
|
|
734
|
+
|
|
735
|
+
// src/core.ts
|
|
736
|
+
var DEFAULT_HOST = "https://t.graph8.com";
|
|
737
|
+
var DEFAULT_API18 = "https://be.graph8.com";
|
|
738
|
+
var G8 = class {
|
|
739
|
+
constructor() {
|
|
740
|
+
/** @internal */
|
|
741
|
+
this.client = null;
|
|
742
|
+
/** @internal */
|
|
743
|
+
this.config = null;
|
|
744
|
+
/** @internal */
|
|
745
|
+
this._forms = null;
|
|
746
|
+
/** @internal */
|
|
747
|
+
this._visitors = null;
|
|
748
|
+
/** @internal */
|
|
749
|
+
this._copilot = null;
|
|
750
|
+
/** @internal */
|
|
751
|
+
this._chat = null;
|
|
752
|
+
/** @internal */
|
|
753
|
+
this._calendar = null;
|
|
754
|
+
/** @internal */
|
|
755
|
+
this._enrich = null;
|
|
756
|
+
/** @internal */
|
|
757
|
+
this._sequences = null;
|
|
758
|
+
/** @internal */
|
|
759
|
+
this._campaigns = null;
|
|
760
|
+
/** @internal */
|
|
761
|
+
this._integrations = null;
|
|
762
|
+
/** @internal */
|
|
763
|
+
this._signals = null;
|
|
764
|
+
/** @internal */
|
|
765
|
+
this._analytics = null;
|
|
766
|
+
/** @internal */
|
|
767
|
+
this._voice = null;
|
|
768
|
+
/** @internal */
|
|
769
|
+
this._pages = null;
|
|
770
|
+
/** @internal */
|
|
771
|
+
this._webhooks = null;
|
|
772
|
+
/** @internal */
|
|
773
|
+
this._contacts = null;
|
|
774
|
+
/** @internal */
|
|
775
|
+
this._companies = null;
|
|
776
|
+
/** @internal */
|
|
777
|
+
this._lists = null;
|
|
778
|
+
}
|
|
779
|
+
/**
|
|
780
|
+
* Initialize the graph8 SDK. Must be called before any other method.
|
|
781
|
+
* Safe to call on the server (SSR) - becomes a no-op for tracking.
|
|
782
|
+
*/
|
|
783
|
+
init(config) {
|
|
784
|
+
this.config = config;
|
|
785
|
+
if (!isServer) {
|
|
786
|
+
this.client = jitsuAnalytics({
|
|
787
|
+
host: config.host || DEFAULT_HOST,
|
|
788
|
+
writeKey: config.writeKey || "",
|
|
789
|
+
debug: config.debug
|
|
790
|
+
});
|
|
791
|
+
}
|
|
792
|
+
const apiUrl = config.apiUrl || DEFAULT_API18;
|
|
793
|
+
const writeKey = config.writeKey || "";
|
|
794
|
+
const apiKey = config.apiKey || "";
|
|
795
|
+
if (writeKey) {
|
|
796
|
+
this._forms = createFormsClient(writeKey, apiUrl);
|
|
797
|
+
this._visitors = createVisitorsClient(writeKey, apiUrl);
|
|
798
|
+
this._copilot = createCopilotClient(writeKey, apiUrl);
|
|
799
|
+
this._chat = createChatClient(writeKey, apiUrl);
|
|
800
|
+
this._calendar = createCalendarClient(apiUrl);
|
|
801
|
+
this._signals = createSignalsClient(writeKey, false, apiUrl);
|
|
802
|
+
}
|
|
803
|
+
if (apiKey) {
|
|
804
|
+
this._enrich = createEnrichClient(apiKey, apiUrl);
|
|
805
|
+
this._sequences = createSequencesClient(apiKey, apiUrl);
|
|
806
|
+
this._campaigns = createCampaignsClient(apiKey, apiUrl);
|
|
807
|
+
this._integrations = createIntegrationsClient(apiKey, apiUrl);
|
|
808
|
+
this._analytics = createAnalyticsClient(apiKey, apiUrl);
|
|
809
|
+
this._voice = createVoiceClient(apiKey, apiUrl);
|
|
810
|
+
this._pages = createPagesClient(apiKey, apiUrl);
|
|
811
|
+
this._webhooks = createWebhooksClient(apiKey, apiUrl);
|
|
812
|
+
this._contacts = createContactsClient(apiKey, apiUrl);
|
|
813
|
+
this._companies = createCompaniesClient(apiKey, apiUrl);
|
|
814
|
+
this._lists = createListsClient(apiKey, apiUrl);
|
|
815
|
+
this._signals = createSignalsClient(apiKey, true, apiUrl);
|
|
816
|
+
}
|
|
817
|
+
}
|
|
818
|
+
// -- Core tracking (via Jitsu) --
|
|
819
|
+
/** Track a custom event. */
|
|
820
|
+
track(event, properties) {
|
|
821
|
+
this.client?.track(event, properties);
|
|
822
|
+
}
|
|
823
|
+
/** Identify a user with properties. */
|
|
824
|
+
identify(userId, properties) {
|
|
825
|
+
this.client?.identify(userId, properties);
|
|
826
|
+
}
|
|
827
|
+
/** Track a page view. */
|
|
828
|
+
page(properties) {
|
|
829
|
+
this.client?.page(properties);
|
|
830
|
+
}
|
|
831
|
+
/** Clear user identity (on logout). */
|
|
832
|
+
reset() {
|
|
833
|
+
this.client?.reset();
|
|
834
|
+
}
|
|
835
|
+
// -- Module accessors --
|
|
836
|
+
/** Progressive form helpers. */
|
|
837
|
+
get forms() {
|
|
838
|
+
this._assertInit();
|
|
839
|
+
return this._forms;
|
|
840
|
+
}
|
|
841
|
+
/** Visitor intelligence - IP to company, engagement scoring. */
|
|
842
|
+
get visitors() {
|
|
843
|
+
this._assertInit();
|
|
844
|
+
return this._visitors;
|
|
845
|
+
}
|
|
846
|
+
/** AI copilot widget. */
|
|
847
|
+
get copilot() {
|
|
848
|
+
this._assertInit();
|
|
849
|
+
return this._copilot;
|
|
850
|
+
}
|
|
851
|
+
/** Webchat widget. */
|
|
852
|
+
get chat() {
|
|
853
|
+
this._assertInit();
|
|
854
|
+
return this._chat;
|
|
855
|
+
}
|
|
856
|
+
/** Calendar and booking. */
|
|
857
|
+
get calendar() {
|
|
858
|
+
this._assertInit();
|
|
859
|
+
return this._calendar;
|
|
860
|
+
}
|
|
861
|
+
/** Enrichment API (requires API key). */
|
|
862
|
+
get enrich() {
|
|
863
|
+
this._assertKey("enrich");
|
|
864
|
+
return this._enrich;
|
|
865
|
+
}
|
|
866
|
+
/** Sequences (requires API key). */
|
|
867
|
+
get sequences() {
|
|
868
|
+
this._assertKey("sequences");
|
|
869
|
+
return this._sequences;
|
|
870
|
+
}
|
|
871
|
+
/** Campaigns (requires API key). */
|
|
872
|
+
get campaigns() {
|
|
873
|
+
this._assertKey("campaigns");
|
|
874
|
+
return this._campaigns;
|
|
875
|
+
}
|
|
876
|
+
/** CRM integrations (requires API key). */
|
|
877
|
+
get integrations() {
|
|
878
|
+
this._assertKey("integrations");
|
|
879
|
+
return this._integrations;
|
|
880
|
+
}
|
|
881
|
+
/** Intent signals. */
|
|
882
|
+
get signals() {
|
|
883
|
+
this._assertInit();
|
|
884
|
+
return this._signals;
|
|
885
|
+
}
|
|
886
|
+
/** Analytics (requires API key). */
|
|
887
|
+
get analytics() {
|
|
888
|
+
this._assertKey("analytics");
|
|
889
|
+
return this._analytics;
|
|
890
|
+
}
|
|
891
|
+
/** Voice AI (requires API key). */
|
|
892
|
+
get voice() {
|
|
893
|
+
this._assertKey("voice");
|
|
894
|
+
return this._voice;
|
|
895
|
+
}
|
|
896
|
+
/** Landing pages (requires API key). */
|
|
897
|
+
get pages() {
|
|
898
|
+
this._assertKey("pages");
|
|
899
|
+
return this._pages;
|
|
900
|
+
}
|
|
901
|
+
/** Webhook event listeners (requires API key). */
|
|
902
|
+
get webhooks() {
|
|
903
|
+
this._assertKey("webhooks");
|
|
904
|
+
return this._webhooks;
|
|
905
|
+
}
|
|
906
|
+
/** Contacts CRUD (requires API key). */
|
|
907
|
+
get contacts() {
|
|
908
|
+
this._assertKey("contacts");
|
|
909
|
+
return this._contacts;
|
|
910
|
+
}
|
|
911
|
+
/** Companies CRUD (requires API key). */
|
|
912
|
+
get companies() {
|
|
913
|
+
this._assertKey("companies");
|
|
914
|
+
return this._companies;
|
|
915
|
+
}
|
|
916
|
+
/** Lists management (requires API key). */
|
|
917
|
+
get lists() {
|
|
918
|
+
this._assertKey("lists");
|
|
919
|
+
return this._lists;
|
|
920
|
+
}
|
|
921
|
+
/** Whether the SDK has been initialized. */
|
|
922
|
+
get initialized() {
|
|
923
|
+
return this.config !== null;
|
|
924
|
+
}
|
|
925
|
+
/** @internal */
|
|
926
|
+
_assertInit() {
|
|
927
|
+
if (!this.config) throw new Error("g8.init() must be called first");
|
|
928
|
+
}
|
|
929
|
+
/** @internal */
|
|
930
|
+
_assertKey(module) {
|
|
931
|
+
this._assertInit();
|
|
932
|
+
if (!this.config.apiKey) throw new Error(`g8.${module} requires an API key. Use g8.init({ apiKey: '...' })`);
|
|
933
|
+
}
|
|
934
|
+
};
|
|
935
|
+
var g8 = new G8();
|
|
936
|
+
|
|
937
|
+
// src/react.tsx
|
|
938
|
+
import { jsx } from "react/jsx-runtime";
|
|
939
|
+
var G8Context = createContext(g8);
|
|
940
|
+
var G8Provider = ({
|
|
941
|
+
writeKey,
|
|
942
|
+
host,
|
|
943
|
+
config,
|
|
944
|
+
children
|
|
945
|
+
}) => {
|
|
946
|
+
useEffect(() => {
|
|
947
|
+
if (!g8.initialized) {
|
|
948
|
+
g8.init({ writeKey, host, ...config });
|
|
949
|
+
}
|
|
950
|
+
}, [writeKey, host, config]);
|
|
951
|
+
return /* @__PURE__ */ jsx(G8Context.Provider, { value: g8, children });
|
|
952
|
+
};
|
|
953
|
+
var useG8 = () => {
|
|
954
|
+
const client = useContext(G8Context);
|
|
955
|
+
return {
|
|
956
|
+
/** Track a custom event */
|
|
957
|
+
track: client.track.bind(client),
|
|
958
|
+
/** Identify a user */
|
|
959
|
+
identify: client.identify.bind(client),
|
|
960
|
+
/** Track a page view */
|
|
961
|
+
page: client.page.bind(client),
|
|
962
|
+
/** Clear user identity */
|
|
963
|
+
reset: client.reset.bind(client),
|
|
964
|
+
/** Progressive form helpers */
|
|
965
|
+
forms: client.forms,
|
|
966
|
+
/** Raw g8 client instance */
|
|
967
|
+
g8: client
|
|
968
|
+
};
|
|
969
|
+
};
|
|
970
|
+
export {
|
|
971
|
+
G8Provider,
|
|
972
|
+
useG8
|
|
973
|
+
};
|
|
974
|
+
//# sourceMappingURL=react.mjs.map
|