plugeen 0.0.4
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/dist/index.cjs +571 -0
- package/dist/index.d.cts +73 -0
- package/dist/index.d.ts +73 -0
- package/dist/index.js +544 -0
- package/dist/plugeen.global.js +1 -0
- package/package.json +43 -0
package/dist/index.cjs
ADDED
|
@@ -0,0 +1,571 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
var __defProp = Object.defineProperty;
|
|
3
|
+
var __getOwnPropDesc = Object.getOwnPropertyDescriptor;
|
|
4
|
+
var __getOwnPropNames = Object.getOwnPropertyNames;
|
|
5
|
+
var __hasOwnProp = Object.prototype.hasOwnProperty;
|
|
6
|
+
var __export = (target, all) => {
|
|
7
|
+
for (var name in all)
|
|
8
|
+
__defProp(target, name, { get: all[name], enumerable: true });
|
|
9
|
+
};
|
|
10
|
+
var __copyProps = (to, from, except, desc) => {
|
|
11
|
+
if (from && typeof from === "object" || typeof from === "function") {
|
|
12
|
+
for (let key of __getOwnPropNames(from))
|
|
13
|
+
if (!__hasOwnProp.call(to, key) && key !== except)
|
|
14
|
+
__defProp(to, key, { get: () => from[key], enumerable: !(desc = __getOwnPropDesc(from, key)) || desc.enumerable });
|
|
15
|
+
}
|
|
16
|
+
return to;
|
|
17
|
+
};
|
|
18
|
+
var __toCommonJS = (mod) => __copyProps(__defProp({}, "__esModule", { value: true }), mod);
|
|
19
|
+
|
|
20
|
+
// src/index.ts
|
|
21
|
+
var src_exports = {};
|
|
22
|
+
__export(src_exports, {
|
|
23
|
+
createSdk: () => createSdk
|
|
24
|
+
});
|
|
25
|
+
module.exports = __toCommonJS(src_exports);
|
|
26
|
+
|
|
27
|
+
// src/lib/helpers/brand.ts
|
|
28
|
+
var APP_NAME = "Plugeen";
|
|
29
|
+
var APP_PREFIX = APP_NAME.toLowerCase().slice(0, 2);
|
|
30
|
+
|
|
31
|
+
// src/lib/helpers/storage.ts
|
|
32
|
+
function withPrefix(key) {
|
|
33
|
+
return `${APP_PREFIX}_${key}`;
|
|
34
|
+
}
|
|
35
|
+
function ensureServerStore() {
|
|
36
|
+
if (!globalThis.Plugeen) {
|
|
37
|
+
globalThis.Plugeen = {};
|
|
38
|
+
}
|
|
39
|
+
return globalThis.Plugeen;
|
|
40
|
+
}
|
|
41
|
+
function serverStorage() {
|
|
42
|
+
const set = (key, value) => {
|
|
43
|
+
ensureServerStore()[key] = value;
|
|
44
|
+
return value;
|
|
45
|
+
};
|
|
46
|
+
const get = (key) => ensureServerStore()[key];
|
|
47
|
+
return {
|
|
48
|
+
get,
|
|
49
|
+
set
|
|
50
|
+
};
|
|
51
|
+
}
|
|
52
|
+
function clientStorage() {
|
|
53
|
+
const set = (key, value) => {
|
|
54
|
+
localStorage.setItem(
|
|
55
|
+
withPrefix(key),
|
|
56
|
+
typeof value === "string" ? value : JSON.stringify(value)
|
|
57
|
+
);
|
|
58
|
+
return value;
|
|
59
|
+
};
|
|
60
|
+
const get = (key) => {
|
|
61
|
+
try {
|
|
62
|
+
const raw = localStorage.getItem(withPrefix(key));
|
|
63
|
+
if (!raw) throw new Error("No data found");
|
|
64
|
+
if (typeof raw === "string") return raw;
|
|
65
|
+
return JSON.parse(raw);
|
|
66
|
+
} catch {
|
|
67
|
+
return void 0;
|
|
68
|
+
}
|
|
69
|
+
};
|
|
70
|
+
return {
|
|
71
|
+
get,
|
|
72
|
+
set
|
|
73
|
+
};
|
|
74
|
+
}
|
|
75
|
+
function getStorage() {
|
|
76
|
+
if (typeof window === "undefined") return serverStorage();
|
|
77
|
+
return clientStorage();
|
|
78
|
+
}
|
|
79
|
+
|
|
80
|
+
// src/lib/helpers/identity.ts
|
|
81
|
+
function getOrCreateIdentity() {
|
|
82
|
+
const storage = getStorage();
|
|
83
|
+
const identity = storage.get("identity");
|
|
84
|
+
if (identity) return identity;
|
|
85
|
+
const newId = crypto.randomUUID();
|
|
86
|
+
storage.set("identity", newId);
|
|
87
|
+
return newId;
|
|
88
|
+
}
|
|
89
|
+
|
|
90
|
+
// src/lib/helpers/session.ts
|
|
91
|
+
var SESSION_KEY = "pl_session";
|
|
92
|
+
function getOrCreateSessionId() {
|
|
93
|
+
try {
|
|
94
|
+
const existing = sessionStorage.getItem(SESSION_KEY);
|
|
95
|
+
if (existing) return existing;
|
|
96
|
+
throw new Error("No session ID");
|
|
97
|
+
} catch {
|
|
98
|
+
const id = crypto.randomUUID();
|
|
99
|
+
sessionStorage.setItem(SESSION_KEY, id);
|
|
100
|
+
return id;
|
|
101
|
+
}
|
|
102
|
+
}
|
|
103
|
+
|
|
104
|
+
// src/lib/helpers/api/index.ts
|
|
105
|
+
function getHeaders(apiKey, method) {
|
|
106
|
+
const headers = new Headers();
|
|
107
|
+
const identity = getStorage().get("identity");
|
|
108
|
+
headers.append("x-identity-id", identity || getOrCreateIdentity());
|
|
109
|
+
headers.set("Authorization", `Bearer ${apiKey}`);
|
|
110
|
+
headers.set("x-session-id", getOrCreateSessionId());
|
|
111
|
+
if (method === "POST" || method === "PUT") {
|
|
112
|
+
headers.set("Content-Type", "application/json");
|
|
113
|
+
}
|
|
114
|
+
return headers;
|
|
115
|
+
}
|
|
116
|
+
async function fetcher(params) {
|
|
117
|
+
return fetch(`${params.options.baseUrl}${params.url}`, {
|
|
118
|
+
method: params.method,
|
|
119
|
+
body: params.body ? JSON.stringify({ ...params.body, source: "api" }) : void 0,
|
|
120
|
+
headers: getHeaders(params.apiKey, params.method)
|
|
121
|
+
}).then((response) => response.json()).then((response) => response.data);
|
|
122
|
+
}
|
|
123
|
+
var createApi = (apiKey, options) => {
|
|
124
|
+
return {
|
|
125
|
+
post: (url, body) => fetcher({ url, method: "POST", body, options, apiKey }),
|
|
126
|
+
put: (url, body) => fetcher({ url, method: "PUT", body, options, apiKey }),
|
|
127
|
+
get: (url) => fetcher({ url, method: "GET", options, apiKey })
|
|
128
|
+
};
|
|
129
|
+
};
|
|
130
|
+
|
|
131
|
+
// src/lib/helpers/plugins.ts
|
|
132
|
+
var plugins = {
|
|
133
|
+
insights: {
|
|
134
|
+
registry: "insights",
|
|
135
|
+
identifier: "insight.created",
|
|
136
|
+
schema: {
|
|
137
|
+
queryName: "Checkout funnel",
|
|
138
|
+
chartType: "line"
|
|
139
|
+
}
|
|
140
|
+
},
|
|
141
|
+
analytics: {
|
|
142
|
+
registry: "analytics",
|
|
143
|
+
identifier: "analytics.page_view",
|
|
144
|
+
schema: {
|
|
145
|
+
event: "page_view",
|
|
146
|
+
path: "/pricing",
|
|
147
|
+
url: "https://example.com/pricing",
|
|
148
|
+
title: "Pricing",
|
|
149
|
+
referrer: "https://google.com",
|
|
150
|
+
sessionId: "session_01"
|
|
151
|
+
}
|
|
152
|
+
},
|
|
153
|
+
"session.replay": {
|
|
154
|
+
registry: "session.replay",
|
|
155
|
+
identifier: "session.replay.recording",
|
|
156
|
+
schema: {
|
|
157
|
+
sessionId: "session_01HX8PDMW3Q8D4",
|
|
158
|
+
visitorId: "visitor_01",
|
|
159
|
+
durationMs: 184e3,
|
|
160
|
+
pageCount: 7,
|
|
161
|
+
clickCount: 34,
|
|
162
|
+
rageClicks: 2,
|
|
163
|
+
deadClicks: 1,
|
|
164
|
+
hasError: true,
|
|
165
|
+
device: "desktop",
|
|
166
|
+
browser: "Chrome",
|
|
167
|
+
path: "/checkout"
|
|
168
|
+
}
|
|
169
|
+
},
|
|
170
|
+
"feature.flags": {
|
|
171
|
+
registry: "feature.flags",
|
|
172
|
+
identifier: "feature.flag.evaluated",
|
|
173
|
+
schema: {
|
|
174
|
+
flagKey: "new-checkout",
|
|
175
|
+
enabled: true,
|
|
176
|
+
variant: "treatment",
|
|
177
|
+
reason: "rollout",
|
|
178
|
+
userId: "user_01",
|
|
179
|
+
environment: "production"
|
|
180
|
+
}
|
|
181
|
+
},
|
|
182
|
+
experiments: {
|
|
183
|
+
registry: "experiments",
|
|
184
|
+
identifier: "experiment.exposed",
|
|
185
|
+
schema: {
|
|
186
|
+
experimentKey: "pricing-page-test",
|
|
187
|
+
variant: "variant-b",
|
|
188
|
+
userId: "user_01",
|
|
189
|
+
metric: "signup",
|
|
190
|
+
converted: true,
|
|
191
|
+
value: 49
|
|
192
|
+
}
|
|
193
|
+
},
|
|
194
|
+
surveys: {
|
|
195
|
+
registry: "surveys",
|
|
196
|
+
identifier: "survey.response",
|
|
197
|
+
schema: {
|
|
198
|
+
surveyId: "nps-q2",
|
|
199
|
+
question: "How likely are you to recommend us?",
|
|
200
|
+
response: "The dashboard is fast",
|
|
201
|
+
rating: 9,
|
|
202
|
+
sentiment: "positive",
|
|
203
|
+
userId: "user_01",
|
|
204
|
+
path: "/dashboard"
|
|
205
|
+
}
|
|
206
|
+
},
|
|
207
|
+
"log.tracing": {
|
|
208
|
+
registry: "log.tracing",
|
|
209
|
+
identifier: "log.error",
|
|
210
|
+
schema: {
|
|
211
|
+
level: "error",
|
|
212
|
+
message: "Checkout failed to create payment intent",
|
|
213
|
+
traceId: "trace_01HX8PK2B9M8A1",
|
|
214
|
+
spanId: "span_checkout",
|
|
215
|
+
service: "payments-api",
|
|
216
|
+
environment: "production",
|
|
217
|
+
route: "POST /api/checkout",
|
|
218
|
+
release: "2026.04.25",
|
|
219
|
+
runtime: "nodejs",
|
|
220
|
+
file: "src/server/checkout.ts",
|
|
221
|
+
line: 142,
|
|
222
|
+
stack: "Error: payment intent failed"
|
|
223
|
+
}
|
|
224
|
+
},
|
|
225
|
+
"contact.chat": {
|
|
226
|
+
registry: "contact.chat",
|
|
227
|
+
identifier: "floating.chat.message",
|
|
228
|
+
schema: {
|
|
229
|
+
id: "chat_123",
|
|
230
|
+
origin: "system",
|
|
231
|
+
message: "I want some help",
|
|
232
|
+
resolved: false
|
|
233
|
+
}
|
|
234
|
+
}
|
|
235
|
+
};
|
|
236
|
+
|
|
237
|
+
// src/lib/plugins/analytics/index.ts
|
|
238
|
+
function initAnalytics(api) {
|
|
239
|
+
const init = () => {
|
|
240
|
+
if (typeof window === "undefined") return;
|
|
241
|
+
const changePage = () => {
|
|
242
|
+
api.post("/plugins/analytics", {
|
|
243
|
+
event: "page_view",
|
|
244
|
+
url: location.href,
|
|
245
|
+
title: document.title,
|
|
246
|
+
referrer: document.referrer ?? "",
|
|
247
|
+
sessionId: getOrCreateSessionId()
|
|
248
|
+
});
|
|
249
|
+
};
|
|
250
|
+
const pushState = history.pushState;
|
|
251
|
+
history.pushState = function(...args) {
|
|
252
|
+
pushState.apply(this, args);
|
|
253
|
+
changePage();
|
|
254
|
+
};
|
|
255
|
+
window.addEventListener("popstate", changePage);
|
|
256
|
+
changePage();
|
|
257
|
+
};
|
|
258
|
+
return init();
|
|
259
|
+
}
|
|
260
|
+
|
|
261
|
+
// src/lib/plugins/chat/index.tsx
|
|
262
|
+
var import_hooks = require("preact/hooks");
|
|
263
|
+
|
|
264
|
+
// src/lib/helpers/ui.ts
|
|
265
|
+
var import_preact = require("preact");
|
|
266
|
+
var noopUnmount = () => {
|
|
267
|
+
};
|
|
268
|
+
function getOrCreateRoot(target, id) {
|
|
269
|
+
const existing = document.getElementById(id);
|
|
270
|
+
if (existing instanceof HTMLDivElement) {
|
|
271
|
+
return existing;
|
|
272
|
+
}
|
|
273
|
+
const container = document.createElement("div");
|
|
274
|
+
container.id = id;
|
|
275
|
+
target.appendChild(container);
|
|
276
|
+
return container;
|
|
277
|
+
}
|
|
278
|
+
function renderUI({
|
|
279
|
+
component: Component,
|
|
280
|
+
id
|
|
281
|
+
}) {
|
|
282
|
+
if (typeof document === "undefined") {
|
|
283
|
+
return { render: () => void 0, unmount: noopUnmount };
|
|
284
|
+
}
|
|
285
|
+
const target = document.body;
|
|
286
|
+
const mount = () => {
|
|
287
|
+
const container = getOrCreateRoot(document.body, id);
|
|
288
|
+
if (container.parentElement !== target) {
|
|
289
|
+
target.appendChild(container);
|
|
290
|
+
}
|
|
291
|
+
(0, import_preact.render)(Component, container);
|
|
292
|
+
return container;
|
|
293
|
+
};
|
|
294
|
+
return {
|
|
295
|
+
render: mount,
|
|
296
|
+
unmount: () => {
|
|
297
|
+
const el = document.getElementById(id);
|
|
298
|
+
if (el) {
|
|
299
|
+
(0, import_preact.render)(null, el);
|
|
300
|
+
el.remove();
|
|
301
|
+
}
|
|
302
|
+
}
|
|
303
|
+
};
|
|
304
|
+
}
|
|
305
|
+
|
|
306
|
+
// src/lib/plugins/chat/index.tsx
|
|
307
|
+
var import_jsx_runtime = require("preact/jsx-runtime");
|
|
308
|
+
var pluginName = "contact.chat";
|
|
309
|
+
function FloatingChat({ id, api, accentColor }) {
|
|
310
|
+
const [open, setOpen] = (0, import_hooks.useState)(false);
|
|
311
|
+
const onSubmit = (e) => {
|
|
312
|
+
e.preventDefault();
|
|
313
|
+
const data = new FormData(e.currentTarget);
|
|
314
|
+
const message = String(data.get("message") ?? "");
|
|
315
|
+
api.post("/plugins/chat", {
|
|
316
|
+
id,
|
|
317
|
+
message,
|
|
318
|
+
origin: "plugin",
|
|
319
|
+
resolved: false
|
|
320
|
+
});
|
|
321
|
+
e.currentTarget.reset();
|
|
322
|
+
};
|
|
323
|
+
return /* @__PURE__ */ (0, import_jsx_runtime.jsxs)(
|
|
324
|
+
"div",
|
|
325
|
+
{
|
|
326
|
+
style: {
|
|
327
|
+
position: "fixed",
|
|
328
|
+
right: "24px",
|
|
329
|
+
bottom: "24px",
|
|
330
|
+
zIndex: "9999",
|
|
331
|
+
fontFamily: "system-ui, sans-serif"
|
|
332
|
+
},
|
|
333
|
+
children: [
|
|
334
|
+
open && /* @__PURE__ */ (0, import_jsx_runtime.jsxs)(
|
|
335
|
+
"div",
|
|
336
|
+
{
|
|
337
|
+
style: {
|
|
338
|
+
width: "320px",
|
|
339
|
+
marginBottom: "12px",
|
|
340
|
+
borderRadius: "12px",
|
|
341
|
+
boxShadow: "0 8px 32px rgba(0,0,0,0.18)",
|
|
342
|
+
background: "#fff",
|
|
343
|
+
overflow: "hidden",
|
|
344
|
+
border: "1px solid #e5e7eb"
|
|
345
|
+
},
|
|
346
|
+
children: [
|
|
347
|
+
/* @__PURE__ */ (0, import_jsx_runtime.jsx)(
|
|
348
|
+
"div",
|
|
349
|
+
{
|
|
350
|
+
style: {
|
|
351
|
+
background: accentColor,
|
|
352
|
+
color: "#fff",
|
|
353
|
+
padding: "14px 16px",
|
|
354
|
+
fontWeight: "600",
|
|
355
|
+
fontSize: "14px"
|
|
356
|
+
},
|
|
357
|
+
children: "Chat with us"
|
|
358
|
+
}
|
|
359
|
+
),
|
|
360
|
+
/* @__PURE__ */ (0, import_jsx_runtime.jsxs)(
|
|
361
|
+
"form",
|
|
362
|
+
{
|
|
363
|
+
onSubmit: (values) => onSubmit(values),
|
|
364
|
+
style: { padding: "12px 16px" },
|
|
365
|
+
children: [
|
|
366
|
+
/* @__PURE__ */ (0, import_jsx_runtime.jsx)(
|
|
367
|
+
"textarea",
|
|
368
|
+
{
|
|
369
|
+
name: "message",
|
|
370
|
+
placeholder: "Send us a message\u2026",
|
|
371
|
+
rows: 3,
|
|
372
|
+
style: {
|
|
373
|
+
width: "100%",
|
|
374
|
+
border: "1px solid #e5e7eb",
|
|
375
|
+
borderRadius: "8px",
|
|
376
|
+
padding: "8px",
|
|
377
|
+
fontSize: "13px",
|
|
378
|
+
resize: "none",
|
|
379
|
+
outline: "none",
|
|
380
|
+
boxSizing: "border-box"
|
|
381
|
+
}
|
|
382
|
+
}
|
|
383
|
+
),
|
|
384
|
+
/* @__PURE__ */ (0, import_jsx_runtime.jsx)(
|
|
385
|
+
"button",
|
|
386
|
+
{
|
|
387
|
+
type: "submit",
|
|
388
|
+
style: {
|
|
389
|
+
marginTop: "8px",
|
|
390
|
+
width: "100%",
|
|
391
|
+
background: accentColor,
|
|
392
|
+
color: "#fff",
|
|
393
|
+
border: "none",
|
|
394
|
+
borderRadius: "8px",
|
|
395
|
+
padding: "8px 0",
|
|
396
|
+
fontWeight: "600",
|
|
397
|
+
fontSize: "13px",
|
|
398
|
+
cursor: "pointer"
|
|
399
|
+
},
|
|
400
|
+
children: "Send"
|
|
401
|
+
}
|
|
402
|
+
)
|
|
403
|
+
]
|
|
404
|
+
}
|
|
405
|
+
)
|
|
406
|
+
]
|
|
407
|
+
}
|
|
408
|
+
),
|
|
409
|
+
/* @__PURE__ */ (0, import_jsx_runtime.jsx)(
|
|
410
|
+
"button",
|
|
411
|
+
{
|
|
412
|
+
type: "button",
|
|
413
|
+
onClick: () => setOpen((v) => !v),
|
|
414
|
+
"aria-label": "Open chat",
|
|
415
|
+
style: {
|
|
416
|
+
width: "52px",
|
|
417
|
+
height: "52px",
|
|
418
|
+
borderRadius: "50%",
|
|
419
|
+
background: accentColor,
|
|
420
|
+
border: "none",
|
|
421
|
+
cursor: "pointer",
|
|
422
|
+
display: "flex",
|
|
423
|
+
alignItems: "center",
|
|
424
|
+
justifyContent: "center",
|
|
425
|
+
boxShadow: "0 4px 16px rgba(0,0,0,0.18)",
|
|
426
|
+
marginLeft: "auto"
|
|
427
|
+
},
|
|
428
|
+
children: /* @__PURE__ */ (0, import_jsx_runtime.jsxs)(
|
|
429
|
+
"svg",
|
|
430
|
+
{
|
|
431
|
+
width: "24",
|
|
432
|
+
height: "24",
|
|
433
|
+
viewBox: "0 0 24 24",
|
|
434
|
+
fill: "none",
|
|
435
|
+
stroke: "#fff",
|
|
436
|
+
"stroke-width": "2",
|
|
437
|
+
"stroke-linecap": "round",
|
|
438
|
+
"stroke-linejoin": "round",
|
|
439
|
+
children: [
|
|
440
|
+
/* @__PURE__ */ (0, import_jsx_runtime.jsx)("title", { children: "Svg" }),
|
|
441
|
+
open ? /* @__PURE__ */ (0, import_jsx_runtime.jsxs)(import_jsx_runtime.Fragment, { children: [
|
|
442
|
+
/* @__PURE__ */ (0, import_jsx_runtime.jsx)("line", { x1: "18", y1: "6", x2: "6", y2: "18" }),
|
|
443
|
+
/* @__PURE__ */ (0, import_jsx_runtime.jsx)("line", { x1: "6", y1: "6", x2: "18", y2: "18" })
|
|
444
|
+
] }) : /* @__PURE__ */ (0, import_jsx_runtime.jsx)("path", { d: "M21 15a2 2 0 0 1-2 2H7l-4 4V5a2 2 0 0 1 2-2h14a2 2 0 0 1 2 2z" })
|
|
445
|
+
]
|
|
446
|
+
}
|
|
447
|
+
)
|
|
448
|
+
}
|
|
449
|
+
)
|
|
450
|
+
]
|
|
451
|
+
}
|
|
452
|
+
);
|
|
453
|
+
}
|
|
454
|
+
function initChat(api, options) {
|
|
455
|
+
const id = crypto.randomUUID();
|
|
456
|
+
const { render } = renderUI({
|
|
457
|
+
component: /* @__PURE__ */ (0, import_jsx_runtime.jsx)(FloatingChat, { id, api, accentColor: options.accentColor }),
|
|
458
|
+
id: pluginName
|
|
459
|
+
});
|
|
460
|
+
return render();
|
|
461
|
+
}
|
|
462
|
+
|
|
463
|
+
// src/lib/plugins/events/index.ts
|
|
464
|
+
function initEvents(api) {
|
|
465
|
+
return {
|
|
466
|
+
create: (eventName, data) => api.post("/events", { name: eventName, data })
|
|
467
|
+
};
|
|
468
|
+
}
|
|
469
|
+
|
|
470
|
+
// src/lib/plugins/experiments/index.ts
|
|
471
|
+
function initExperiments(api) {
|
|
472
|
+
return {
|
|
473
|
+
get: (experimentId) => api.get(`/plugins/experiments/${experimentId}`)
|
|
474
|
+
};
|
|
475
|
+
}
|
|
476
|
+
|
|
477
|
+
// src/lib/plugins/feature-flags/index.ts
|
|
478
|
+
function initFeatureFlags(api) {
|
|
479
|
+
return {
|
|
480
|
+
get: async (flagKey) => {
|
|
481
|
+
return api.get(`/plugins/feature-flags/${flagKey}`);
|
|
482
|
+
}
|
|
483
|
+
};
|
|
484
|
+
}
|
|
485
|
+
|
|
486
|
+
// src/lib/plugins/identities/index.ts
|
|
487
|
+
function initIdentities(api) {
|
|
488
|
+
const storage = getStorage();
|
|
489
|
+
async function set(distinctId, data) {
|
|
490
|
+
const res = await api.post("/identities", { ...data, id: distinctId });
|
|
491
|
+
storage.set("identity", distinctId);
|
|
492
|
+
return res;
|
|
493
|
+
}
|
|
494
|
+
return {
|
|
495
|
+
// get,
|
|
496
|
+
set
|
|
497
|
+
};
|
|
498
|
+
}
|
|
499
|
+
|
|
500
|
+
// src/lib/plugins/log-tracing/index.ts
|
|
501
|
+
function initLogTracing(api) {
|
|
502
|
+
return {
|
|
503
|
+
send: (data) => api.post("/plugins/logs", data)
|
|
504
|
+
};
|
|
505
|
+
}
|
|
506
|
+
|
|
507
|
+
// src/lib/plugins/surveys/index.ts
|
|
508
|
+
function initSurveys(api) {
|
|
509
|
+
return {
|
|
510
|
+
submit: (data) => api.post("/plugins/surveys", data)
|
|
511
|
+
};
|
|
512
|
+
}
|
|
513
|
+
|
|
514
|
+
// src/lib/plugins/index.ts
|
|
515
|
+
var getConfigs = (apiKey, options) => {
|
|
516
|
+
const api = createApi(apiKey, options);
|
|
517
|
+
return {
|
|
518
|
+
events: initEvents(api),
|
|
519
|
+
identities: initIdentities(api),
|
|
520
|
+
featureFlags: initFeatureFlags(api),
|
|
521
|
+
logs: initLogTracing(api),
|
|
522
|
+
surveys: initSurveys(api),
|
|
523
|
+
experiments: initExperiments(api)
|
|
524
|
+
};
|
|
525
|
+
};
|
|
526
|
+
var getInitializer = (apiKey, options) => {
|
|
527
|
+
const allPlugins = Object.keys(plugins);
|
|
528
|
+
return allPlugins.map((plugin) => {
|
|
529
|
+
const api = createApi(apiKey, options);
|
|
530
|
+
return {
|
|
531
|
+
analytics: () => initAnalytics(api),
|
|
532
|
+
"contact.chat": () => initChat(api, options),
|
|
533
|
+
"feature.flags": () => {
|
|
534
|
+
},
|
|
535
|
+
experiments: () => {
|
|
536
|
+
},
|
|
537
|
+
"log.tracing": () => {
|
|
538
|
+
},
|
|
539
|
+
"session.replay": () => {
|
|
540
|
+
},
|
|
541
|
+
insights: () => {
|
|
542
|
+
},
|
|
543
|
+
surveys: () => {
|
|
544
|
+
}
|
|
545
|
+
}[plugin];
|
|
546
|
+
});
|
|
547
|
+
};
|
|
548
|
+
|
|
549
|
+
// src/lib/index.ts
|
|
550
|
+
var defaultOptions = {
|
|
551
|
+
baseUrl: "https://plugeen.app/api"
|
|
552
|
+
};
|
|
553
|
+
function createSdk(apiKey, options) {
|
|
554
|
+
if (!apiKey) {
|
|
555
|
+
console.warn("[Plugeen] Missing data-api-key attribute.");
|
|
556
|
+
}
|
|
557
|
+
const _options = {
|
|
558
|
+
...defaultOptions,
|
|
559
|
+
...options
|
|
560
|
+
};
|
|
561
|
+
if (apiKey) {
|
|
562
|
+
getInitializer(apiKey, _options).forEach((item) => {
|
|
563
|
+
item();
|
|
564
|
+
});
|
|
565
|
+
}
|
|
566
|
+
return getConfigs(apiKey, _options);
|
|
567
|
+
}
|
|
568
|
+
// Annotate the CommonJS export names for ESM import in node:
|
|
569
|
+
0 && (module.exports = {
|
|
570
|
+
createSdk
|
|
571
|
+
});
|
package/dist/index.d.cts
ADDED
|
@@ -0,0 +1,73 @@
|
|
|
1
|
+
type Plugin = {
|
|
2
|
+
identifier: "floating.chat";
|
|
3
|
+
slug: string;
|
|
4
|
+
settings: {
|
|
5
|
+
accentColor: string;
|
|
6
|
+
};
|
|
7
|
+
} | {
|
|
8
|
+
slug: string;
|
|
9
|
+
identifier: "analytics";
|
|
10
|
+
};
|
|
11
|
+
type Options = {
|
|
12
|
+
baseUrl?: string;
|
|
13
|
+
accentColor?: string;
|
|
14
|
+
};
|
|
15
|
+
type Identity = {
|
|
16
|
+
distinctId: string;
|
|
17
|
+
name?: string;
|
|
18
|
+
email?: string;
|
|
19
|
+
metadata?: Record<string, unknown>;
|
|
20
|
+
};
|
|
21
|
+
declare global {
|
|
22
|
+
var Plugeen: {
|
|
23
|
+
identity?: unknown;
|
|
24
|
+
};
|
|
25
|
+
}
|
|
26
|
+
|
|
27
|
+
declare function createSdk(apiKey: string, options?: Partial<Options>): {
|
|
28
|
+
events: {
|
|
29
|
+
create: (eventName: string, data: Record<string, unknown>) => Promise<unknown>;
|
|
30
|
+
};
|
|
31
|
+
identities: {
|
|
32
|
+
set: (distinctId: string, data?: Omit<Identity, "distinctId">) => Promise<unknown>;
|
|
33
|
+
};
|
|
34
|
+
featureFlags: {
|
|
35
|
+
get: (flagKey: string) => Promise<{
|
|
36
|
+
key: string;
|
|
37
|
+
enabled: boolean;
|
|
38
|
+
value: unknown;
|
|
39
|
+
description?: string;
|
|
40
|
+
}>;
|
|
41
|
+
};
|
|
42
|
+
logs: {
|
|
43
|
+
send: (data: {
|
|
44
|
+
level: "error" | "debug" | "info" | "warn" | "fatal";
|
|
45
|
+
message: string;
|
|
46
|
+
traceId?: string;
|
|
47
|
+
spanId?: string;
|
|
48
|
+
service?: string;
|
|
49
|
+
environment?: string;
|
|
50
|
+
route?: string;
|
|
51
|
+
release?: string;
|
|
52
|
+
runtime?: string;
|
|
53
|
+
file?: string;
|
|
54
|
+
line?: number;
|
|
55
|
+
stack?: string;
|
|
56
|
+
}) => Promise<unknown>;
|
|
57
|
+
};
|
|
58
|
+
surveys: {
|
|
59
|
+
submit: (data: {
|
|
60
|
+
surveyId: string;
|
|
61
|
+
question: string;
|
|
62
|
+
response: string;
|
|
63
|
+
rating?: number;
|
|
64
|
+
sentiment?: "positive" | "neutral" | "negative";
|
|
65
|
+
path?: string;
|
|
66
|
+
}) => Promise<unknown>;
|
|
67
|
+
};
|
|
68
|
+
experiments: {
|
|
69
|
+
get: (experimentId: string) => Promise<unknown>;
|
|
70
|
+
};
|
|
71
|
+
};
|
|
72
|
+
|
|
73
|
+
export { type Identity, type Options, type Plugin, createSdk };
|
package/dist/index.d.ts
ADDED
|
@@ -0,0 +1,73 @@
|
|
|
1
|
+
type Plugin = {
|
|
2
|
+
identifier: "floating.chat";
|
|
3
|
+
slug: string;
|
|
4
|
+
settings: {
|
|
5
|
+
accentColor: string;
|
|
6
|
+
};
|
|
7
|
+
} | {
|
|
8
|
+
slug: string;
|
|
9
|
+
identifier: "analytics";
|
|
10
|
+
};
|
|
11
|
+
type Options = {
|
|
12
|
+
baseUrl?: string;
|
|
13
|
+
accentColor?: string;
|
|
14
|
+
};
|
|
15
|
+
type Identity = {
|
|
16
|
+
distinctId: string;
|
|
17
|
+
name?: string;
|
|
18
|
+
email?: string;
|
|
19
|
+
metadata?: Record<string, unknown>;
|
|
20
|
+
};
|
|
21
|
+
declare global {
|
|
22
|
+
var Plugeen: {
|
|
23
|
+
identity?: unknown;
|
|
24
|
+
};
|
|
25
|
+
}
|
|
26
|
+
|
|
27
|
+
declare function createSdk(apiKey: string, options?: Partial<Options>): {
|
|
28
|
+
events: {
|
|
29
|
+
create: (eventName: string, data: Record<string, unknown>) => Promise<unknown>;
|
|
30
|
+
};
|
|
31
|
+
identities: {
|
|
32
|
+
set: (distinctId: string, data?: Omit<Identity, "distinctId">) => Promise<unknown>;
|
|
33
|
+
};
|
|
34
|
+
featureFlags: {
|
|
35
|
+
get: (flagKey: string) => Promise<{
|
|
36
|
+
key: string;
|
|
37
|
+
enabled: boolean;
|
|
38
|
+
value: unknown;
|
|
39
|
+
description?: string;
|
|
40
|
+
}>;
|
|
41
|
+
};
|
|
42
|
+
logs: {
|
|
43
|
+
send: (data: {
|
|
44
|
+
level: "error" | "debug" | "info" | "warn" | "fatal";
|
|
45
|
+
message: string;
|
|
46
|
+
traceId?: string;
|
|
47
|
+
spanId?: string;
|
|
48
|
+
service?: string;
|
|
49
|
+
environment?: string;
|
|
50
|
+
route?: string;
|
|
51
|
+
release?: string;
|
|
52
|
+
runtime?: string;
|
|
53
|
+
file?: string;
|
|
54
|
+
line?: number;
|
|
55
|
+
stack?: string;
|
|
56
|
+
}) => Promise<unknown>;
|
|
57
|
+
};
|
|
58
|
+
surveys: {
|
|
59
|
+
submit: (data: {
|
|
60
|
+
surveyId: string;
|
|
61
|
+
question: string;
|
|
62
|
+
response: string;
|
|
63
|
+
rating?: number;
|
|
64
|
+
sentiment?: "positive" | "neutral" | "negative";
|
|
65
|
+
path?: string;
|
|
66
|
+
}) => Promise<unknown>;
|
|
67
|
+
};
|
|
68
|
+
experiments: {
|
|
69
|
+
get: (experimentId: string) => Promise<unknown>;
|
|
70
|
+
};
|
|
71
|
+
};
|
|
72
|
+
|
|
73
|
+
export { type Identity, type Options, type Plugin, createSdk };
|
package/dist/index.js
ADDED
|
@@ -0,0 +1,544 @@
|
|
|
1
|
+
// src/lib/helpers/brand.ts
|
|
2
|
+
var APP_NAME = "Plugeen";
|
|
3
|
+
var APP_PREFIX = APP_NAME.toLowerCase().slice(0, 2);
|
|
4
|
+
|
|
5
|
+
// src/lib/helpers/storage.ts
|
|
6
|
+
function withPrefix(key) {
|
|
7
|
+
return `${APP_PREFIX}_${key}`;
|
|
8
|
+
}
|
|
9
|
+
function ensureServerStore() {
|
|
10
|
+
if (!globalThis.Plugeen) {
|
|
11
|
+
globalThis.Plugeen = {};
|
|
12
|
+
}
|
|
13
|
+
return globalThis.Plugeen;
|
|
14
|
+
}
|
|
15
|
+
function serverStorage() {
|
|
16
|
+
const set = (key, value) => {
|
|
17
|
+
ensureServerStore()[key] = value;
|
|
18
|
+
return value;
|
|
19
|
+
};
|
|
20
|
+
const get = (key) => ensureServerStore()[key];
|
|
21
|
+
return {
|
|
22
|
+
get,
|
|
23
|
+
set
|
|
24
|
+
};
|
|
25
|
+
}
|
|
26
|
+
function clientStorage() {
|
|
27
|
+
const set = (key, value) => {
|
|
28
|
+
localStorage.setItem(
|
|
29
|
+
withPrefix(key),
|
|
30
|
+
typeof value === "string" ? value : JSON.stringify(value)
|
|
31
|
+
);
|
|
32
|
+
return value;
|
|
33
|
+
};
|
|
34
|
+
const get = (key) => {
|
|
35
|
+
try {
|
|
36
|
+
const raw = localStorage.getItem(withPrefix(key));
|
|
37
|
+
if (!raw) throw new Error("No data found");
|
|
38
|
+
if (typeof raw === "string") return raw;
|
|
39
|
+
return JSON.parse(raw);
|
|
40
|
+
} catch {
|
|
41
|
+
return void 0;
|
|
42
|
+
}
|
|
43
|
+
};
|
|
44
|
+
return {
|
|
45
|
+
get,
|
|
46
|
+
set
|
|
47
|
+
};
|
|
48
|
+
}
|
|
49
|
+
function getStorage() {
|
|
50
|
+
if (typeof window === "undefined") return serverStorage();
|
|
51
|
+
return clientStorage();
|
|
52
|
+
}
|
|
53
|
+
|
|
54
|
+
// src/lib/helpers/identity.ts
|
|
55
|
+
function getOrCreateIdentity() {
|
|
56
|
+
const storage = getStorage();
|
|
57
|
+
const identity = storage.get("identity");
|
|
58
|
+
if (identity) return identity;
|
|
59
|
+
const newId = crypto.randomUUID();
|
|
60
|
+
storage.set("identity", newId);
|
|
61
|
+
return newId;
|
|
62
|
+
}
|
|
63
|
+
|
|
64
|
+
// src/lib/helpers/session.ts
|
|
65
|
+
var SESSION_KEY = "pl_session";
|
|
66
|
+
function getOrCreateSessionId() {
|
|
67
|
+
try {
|
|
68
|
+
const existing = sessionStorage.getItem(SESSION_KEY);
|
|
69
|
+
if (existing) return existing;
|
|
70
|
+
throw new Error("No session ID");
|
|
71
|
+
} catch {
|
|
72
|
+
const id = crypto.randomUUID();
|
|
73
|
+
sessionStorage.setItem(SESSION_KEY, id);
|
|
74
|
+
return id;
|
|
75
|
+
}
|
|
76
|
+
}
|
|
77
|
+
|
|
78
|
+
// src/lib/helpers/api/index.ts
|
|
79
|
+
function getHeaders(apiKey, method) {
|
|
80
|
+
const headers = new Headers();
|
|
81
|
+
const identity = getStorage().get("identity");
|
|
82
|
+
headers.append("x-identity-id", identity || getOrCreateIdentity());
|
|
83
|
+
headers.set("Authorization", `Bearer ${apiKey}`);
|
|
84
|
+
headers.set("x-session-id", getOrCreateSessionId());
|
|
85
|
+
if (method === "POST" || method === "PUT") {
|
|
86
|
+
headers.set("Content-Type", "application/json");
|
|
87
|
+
}
|
|
88
|
+
return headers;
|
|
89
|
+
}
|
|
90
|
+
async function fetcher(params) {
|
|
91
|
+
return fetch(`${params.options.baseUrl}${params.url}`, {
|
|
92
|
+
method: params.method,
|
|
93
|
+
body: params.body ? JSON.stringify({ ...params.body, source: "api" }) : void 0,
|
|
94
|
+
headers: getHeaders(params.apiKey, params.method)
|
|
95
|
+
}).then((response) => response.json()).then((response) => response.data);
|
|
96
|
+
}
|
|
97
|
+
var createApi = (apiKey, options) => {
|
|
98
|
+
return {
|
|
99
|
+
post: (url, body) => fetcher({ url, method: "POST", body, options, apiKey }),
|
|
100
|
+
put: (url, body) => fetcher({ url, method: "PUT", body, options, apiKey }),
|
|
101
|
+
get: (url) => fetcher({ url, method: "GET", options, apiKey })
|
|
102
|
+
};
|
|
103
|
+
};
|
|
104
|
+
|
|
105
|
+
// src/lib/helpers/plugins.ts
|
|
106
|
+
var plugins = {
|
|
107
|
+
insights: {
|
|
108
|
+
registry: "insights",
|
|
109
|
+
identifier: "insight.created",
|
|
110
|
+
schema: {
|
|
111
|
+
queryName: "Checkout funnel",
|
|
112
|
+
chartType: "line"
|
|
113
|
+
}
|
|
114
|
+
},
|
|
115
|
+
analytics: {
|
|
116
|
+
registry: "analytics",
|
|
117
|
+
identifier: "analytics.page_view",
|
|
118
|
+
schema: {
|
|
119
|
+
event: "page_view",
|
|
120
|
+
path: "/pricing",
|
|
121
|
+
url: "https://example.com/pricing",
|
|
122
|
+
title: "Pricing",
|
|
123
|
+
referrer: "https://google.com",
|
|
124
|
+
sessionId: "session_01"
|
|
125
|
+
}
|
|
126
|
+
},
|
|
127
|
+
"session.replay": {
|
|
128
|
+
registry: "session.replay",
|
|
129
|
+
identifier: "session.replay.recording",
|
|
130
|
+
schema: {
|
|
131
|
+
sessionId: "session_01HX8PDMW3Q8D4",
|
|
132
|
+
visitorId: "visitor_01",
|
|
133
|
+
durationMs: 184e3,
|
|
134
|
+
pageCount: 7,
|
|
135
|
+
clickCount: 34,
|
|
136
|
+
rageClicks: 2,
|
|
137
|
+
deadClicks: 1,
|
|
138
|
+
hasError: true,
|
|
139
|
+
device: "desktop",
|
|
140
|
+
browser: "Chrome",
|
|
141
|
+
path: "/checkout"
|
|
142
|
+
}
|
|
143
|
+
},
|
|
144
|
+
"feature.flags": {
|
|
145
|
+
registry: "feature.flags",
|
|
146
|
+
identifier: "feature.flag.evaluated",
|
|
147
|
+
schema: {
|
|
148
|
+
flagKey: "new-checkout",
|
|
149
|
+
enabled: true,
|
|
150
|
+
variant: "treatment",
|
|
151
|
+
reason: "rollout",
|
|
152
|
+
userId: "user_01",
|
|
153
|
+
environment: "production"
|
|
154
|
+
}
|
|
155
|
+
},
|
|
156
|
+
experiments: {
|
|
157
|
+
registry: "experiments",
|
|
158
|
+
identifier: "experiment.exposed",
|
|
159
|
+
schema: {
|
|
160
|
+
experimentKey: "pricing-page-test",
|
|
161
|
+
variant: "variant-b",
|
|
162
|
+
userId: "user_01",
|
|
163
|
+
metric: "signup",
|
|
164
|
+
converted: true,
|
|
165
|
+
value: 49
|
|
166
|
+
}
|
|
167
|
+
},
|
|
168
|
+
surveys: {
|
|
169
|
+
registry: "surveys",
|
|
170
|
+
identifier: "survey.response",
|
|
171
|
+
schema: {
|
|
172
|
+
surveyId: "nps-q2",
|
|
173
|
+
question: "How likely are you to recommend us?",
|
|
174
|
+
response: "The dashboard is fast",
|
|
175
|
+
rating: 9,
|
|
176
|
+
sentiment: "positive",
|
|
177
|
+
userId: "user_01",
|
|
178
|
+
path: "/dashboard"
|
|
179
|
+
}
|
|
180
|
+
},
|
|
181
|
+
"log.tracing": {
|
|
182
|
+
registry: "log.tracing",
|
|
183
|
+
identifier: "log.error",
|
|
184
|
+
schema: {
|
|
185
|
+
level: "error",
|
|
186
|
+
message: "Checkout failed to create payment intent",
|
|
187
|
+
traceId: "trace_01HX8PK2B9M8A1",
|
|
188
|
+
spanId: "span_checkout",
|
|
189
|
+
service: "payments-api",
|
|
190
|
+
environment: "production",
|
|
191
|
+
route: "POST /api/checkout",
|
|
192
|
+
release: "2026.04.25",
|
|
193
|
+
runtime: "nodejs",
|
|
194
|
+
file: "src/server/checkout.ts",
|
|
195
|
+
line: 142,
|
|
196
|
+
stack: "Error: payment intent failed"
|
|
197
|
+
}
|
|
198
|
+
},
|
|
199
|
+
"contact.chat": {
|
|
200
|
+
registry: "contact.chat",
|
|
201
|
+
identifier: "floating.chat.message",
|
|
202
|
+
schema: {
|
|
203
|
+
id: "chat_123",
|
|
204
|
+
origin: "system",
|
|
205
|
+
message: "I want some help",
|
|
206
|
+
resolved: false
|
|
207
|
+
}
|
|
208
|
+
}
|
|
209
|
+
};
|
|
210
|
+
|
|
211
|
+
// src/lib/plugins/analytics/index.ts
|
|
212
|
+
function initAnalytics(api) {
|
|
213
|
+
const init = () => {
|
|
214
|
+
if (typeof window === "undefined") return;
|
|
215
|
+
const changePage = () => {
|
|
216
|
+
api.post("/plugins/analytics", {
|
|
217
|
+
event: "page_view",
|
|
218
|
+
url: location.href,
|
|
219
|
+
title: document.title,
|
|
220
|
+
referrer: document.referrer ?? "",
|
|
221
|
+
sessionId: getOrCreateSessionId()
|
|
222
|
+
});
|
|
223
|
+
};
|
|
224
|
+
const pushState = history.pushState;
|
|
225
|
+
history.pushState = function(...args) {
|
|
226
|
+
pushState.apply(this, args);
|
|
227
|
+
changePage();
|
|
228
|
+
};
|
|
229
|
+
window.addEventListener("popstate", changePage);
|
|
230
|
+
changePage();
|
|
231
|
+
};
|
|
232
|
+
return init();
|
|
233
|
+
}
|
|
234
|
+
|
|
235
|
+
// src/lib/plugins/chat/index.tsx
|
|
236
|
+
import { useState } from "preact/hooks";
|
|
237
|
+
|
|
238
|
+
// src/lib/helpers/ui.ts
|
|
239
|
+
import { render as preactRender } from "preact";
|
|
240
|
+
var noopUnmount = () => {
|
|
241
|
+
};
|
|
242
|
+
function getOrCreateRoot(target, id) {
|
|
243
|
+
const existing = document.getElementById(id);
|
|
244
|
+
if (existing instanceof HTMLDivElement) {
|
|
245
|
+
return existing;
|
|
246
|
+
}
|
|
247
|
+
const container = document.createElement("div");
|
|
248
|
+
container.id = id;
|
|
249
|
+
target.appendChild(container);
|
|
250
|
+
return container;
|
|
251
|
+
}
|
|
252
|
+
function renderUI({
|
|
253
|
+
component: Component,
|
|
254
|
+
id
|
|
255
|
+
}) {
|
|
256
|
+
if (typeof document === "undefined") {
|
|
257
|
+
return { render: () => void 0, unmount: noopUnmount };
|
|
258
|
+
}
|
|
259
|
+
const target = document.body;
|
|
260
|
+
const mount = () => {
|
|
261
|
+
const container = getOrCreateRoot(document.body, id);
|
|
262
|
+
if (container.parentElement !== target) {
|
|
263
|
+
target.appendChild(container);
|
|
264
|
+
}
|
|
265
|
+
preactRender(Component, container);
|
|
266
|
+
return container;
|
|
267
|
+
};
|
|
268
|
+
return {
|
|
269
|
+
render: mount,
|
|
270
|
+
unmount: () => {
|
|
271
|
+
const el = document.getElementById(id);
|
|
272
|
+
if (el) {
|
|
273
|
+
preactRender(null, el);
|
|
274
|
+
el.remove();
|
|
275
|
+
}
|
|
276
|
+
}
|
|
277
|
+
};
|
|
278
|
+
}
|
|
279
|
+
|
|
280
|
+
// src/lib/plugins/chat/index.tsx
|
|
281
|
+
import { Fragment, jsx, jsxs } from "preact/jsx-runtime";
|
|
282
|
+
var pluginName = "contact.chat";
|
|
283
|
+
function FloatingChat({ id, api, accentColor }) {
|
|
284
|
+
const [open, setOpen] = useState(false);
|
|
285
|
+
const onSubmit = (e) => {
|
|
286
|
+
e.preventDefault();
|
|
287
|
+
const data = new FormData(e.currentTarget);
|
|
288
|
+
const message = String(data.get("message") ?? "");
|
|
289
|
+
api.post("/plugins/chat", {
|
|
290
|
+
id,
|
|
291
|
+
message,
|
|
292
|
+
origin: "plugin",
|
|
293
|
+
resolved: false
|
|
294
|
+
});
|
|
295
|
+
e.currentTarget.reset();
|
|
296
|
+
};
|
|
297
|
+
return /* @__PURE__ */ jsxs(
|
|
298
|
+
"div",
|
|
299
|
+
{
|
|
300
|
+
style: {
|
|
301
|
+
position: "fixed",
|
|
302
|
+
right: "24px",
|
|
303
|
+
bottom: "24px",
|
|
304
|
+
zIndex: "9999",
|
|
305
|
+
fontFamily: "system-ui, sans-serif"
|
|
306
|
+
},
|
|
307
|
+
children: [
|
|
308
|
+
open && /* @__PURE__ */ jsxs(
|
|
309
|
+
"div",
|
|
310
|
+
{
|
|
311
|
+
style: {
|
|
312
|
+
width: "320px",
|
|
313
|
+
marginBottom: "12px",
|
|
314
|
+
borderRadius: "12px",
|
|
315
|
+
boxShadow: "0 8px 32px rgba(0,0,0,0.18)",
|
|
316
|
+
background: "#fff",
|
|
317
|
+
overflow: "hidden",
|
|
318
|
+
border: "1px solid #e5e7eb"
|
|
319
|
+
},
|
|
320
|
+
children: [
|
|
321
|
+
/* @__PURE__ */ jsx(
|
|
322
|
+
"div",
|
|
323
|
+
{
|
|
324
|
+
style: {
|
|
325
|
+
background: accentColor,
|
|
326
|
+
color: "#fff",
|
|
327
|
+
padding: "14px 16px",
|
|
328
|
+
fontWeight: "600",
|
|
329
|
+
fontSize: "14px"
|
|
330
|
+
},
|
|
331
|
+
children: "Chat with us"
|
|
332
|
+
}
|
|
333
|
+
),
|
|
334
|
+
/* @__PURE__ */ jsxs(
|
|
335
|
+
"form",
|
|
336
|
+
{
|
|
337
|
+
onSubmit: (values) => onSubmit(values),
|
|
338
|
+
style: { padding: "12px 16px" },
|
|
339
|
+
children: [
|
|
340
|
+
/* @__PURE__ */ jsx(
|
|
341
|
+
"textarea",
|
|
342
|
+
{
|
|
343
|
+
name: "message",
|
|
344
|
+
placeholder: "Send us a message\u2026",
|
|
345
|
+
rows: 3,
|
|
346
|
+
style: {
|
|
347
|
+
width: "100%",
|
|
348
|
+
border: "1px solid #e5e7eb",
|
|
349
|
+
borderRadius: "8px",
|
|
350
|
+
padding: "8px",
|
|
351
|
+
fontSize: "13px",
|
|
352
|
+
resize: "none",
|
|
353
|
+
outline: "none",
|
|
354
|
+
boxSizing: "border-box"
|
|
355
|
+
}
|
|
356
|
+
}
|
|
357
|
+
),
|
|
358
|
+
/* @__PURE__ */ jsx(
|
|
359
|
+
"button",
|
|
360
|
+
{
|
|
361
|
+
type: "submit",
|
|
362
|
+
style: {
|
|
363
|
+
marginTop: "8px",
|
|
364
|
+
width: "100%",
|
|
365
|
+
background: accentColor,
|
|
366
|
+
color: "#fff",
|
|
367
|
+
border: "none",
|
|
368
|
+
borderRadius: "8px",
|
|
369
|
+
padding: "8px 0",
|
|
370
|
+
fontWeight: "600",
|
|
371
|
+
fontSize: "13px",
|
|
372
|
+
cursor: "pointer"
|
|
373
|
+
},
|
|
374
|
+
children: "Send"
|
|
375
|
+
}
|
|
376
|
+
)
|
|
377
|
+
]
|
|
378
|
+
}
|
|
379
|
+
)
|
|
380
|
+
]
|
|
381
|
+
}
|
|
382
|
+
),
|
|
383
|
+
/* @__PURE__ */ jsx(
|
|
384
|
+
"button",
|
|
385
|
+
{
|
|
386
|
+
type: "button",
|
|
387
|
+
onClick: () => setOpen((v) => !v),
|
|
388
|
+
"aria-label": "Open chat",
|
|
389
|
+
style: {
|
|
390
|
+
width: "52px",
|
|
391
|
+
height: "52px",
|
|
392
|
+
borderRadius: "50%",
|
|
393
|
+
background: accentColor,
|
|
394
|
+
border: "none",
|
|
395
|
+
cursor: "pointer",
|
|
396
|
+
display: "flex",
|
|
397
|
+
alignItems: "center",
|
|
398
|
+
justifyContent: "center",
|
|
399
|
+
boxShadow: "0 4px 16px rgba(0,0,0,0.18)",
|
|
400
|
+
marginLeft: "auto"
|
|
401
|
+
},
|
|
402
|
+
children: /* @__PURE__ */ jsxs(
|
|
403
|
+
"svg",
|
|
404
|
+
{
|
|
405
|
+
width: "24",
|
|
406
|
+
height: "24",
|
|
407
|
+
viewBox: "0 0 24 24",
|
|
408
|
+
fill: "none",
|
|
409
|
+
stroke: "#fff",
|
|
410
|
+
"stroke-width": "2",
|
|
411
|
+
"stroke-linecap": "round",
|
|
412
|
+
"stroke-linejoin": "round",
|
|
413
|
+
children: [
|
|
414
|
+
/* @__PURE__ */ jsx("title", { children: "Svg" }),
|
|
415
|
+
open ? /* @__PURE__ */ jsxs(Fragment, { children: [
|
|
416
|
+
/* @__PURE__ */ jsx("line", { x1: "18", y1: "6", x2: "6", y2: "18" }),
|
|
417
|
+
/* @__PURE__ */ jsx("line", { x1: "6", y1: "6", x2: "18", y2: "18" })
|
|
418
|
+
] }) : /* @__PURE__ */ jsx("path", { d: "M21 15a2 2 0 0 1-2 2H7l-4 4V5a2 2 0 0 1 2-2h14a2 2 0 0 1 2 2z" })
|
|
419
|
+
]
|
|
420
|
+
}
|
|
421
|
+
)
|
|
422
|
+
}
|
|
423
|
+
)
|
|
424
|
+
]
|
|
425
|
+
}
|
|
426
|
+
);
|
|
427
|
+
}
|
|
428
|
+
function initChat(api, options) {
|
|
429
|
+
const id = crypto.randomUUID();
|
|
430
|
+
const { render } = renderUI({
|
|
431
|
+
component: /* @__PURE__ */ jsx(FloatingChat, { id, api, accentColor: options.accentColor }),
|
|
432
|
+
id: pluginName
|
|
433
|
+
});
|
|
434
|
+
return render();
|
|
435
|
+
}
|
|
436
|
+
|
|
437
|
+
// src/lib/plugins/events/index.ts
|
|
438
|
+
function initEvents(api) {
|
|
439
|
+
return {
|
|
440
|
+
create: (eventName, data) => api.post("/events", { name: eventName, data })
|
|
441
|
+
};
|
|
442
|
+
}
|
|
443
|
+
|
|
444
|
+
// src/lib/plugins/experiments/index.ts
|
|
445
|
+
function initExperiments(api) {
|
|
446
|
+
return {
|
|
447
|
+
get: (experimentId) => api.get(`/plugins/experiments/${experimentId}`)
|
|
448
|
+
};
|
|
449
|
+
}
|
|
450
|
+
|
|
451
|
+
// src/lib/plugins/feature-flags/index.ts
|
|
452
|
+
function initFeatureFlags(api) {
|
|
453
|
+
return {
|
|
454
|
+
get: async (flagKey) => {
|
|
455
|
+
return api.get(`/plugins/feature-flags/${flagKey}`);
|
|
456
|
+
}
|
|
457
|
+
};
|
|
458
|
+
}
|
|
459
|
+
|
|
460
|
+
// src/lib/plugins/identities/index.ts
|
|
461
|
+
function initIdentities(api) {
|
|
462
|
+
const storage = getStorage();
|
|
463
|
+
async function set(distinctId, data) {
|
|
464
|
+
const res = await api.post("/identities", { ...data, id: distinctId });
|
|
465
|
+
storage.set("identity", distinctId);
|
|
466
|
+
return res;
|
|
467
|
+
}
|
|
468
|
+
return {
|
|
469
|
+
// get,
|
|
470
|
+
set
|
|
471
|
+
};
|
|
472
|
+
}
|
|
473
|
+
|
|
474
|
+
// src/lib/plugins/log-tracing/index.ts
|
|
475
|
+
function initLogTracing(api) {
|
|
476
|
+
return {
|
|
477
|
+
send: (data) => api.post("/plugins/logs", data)
|
|
478
|
+
};
|
|
479
|
+
}
|
|
480
|
+
|
|
481
|
+
// src/lib/plugins/surveys/index.ts
|
|
482
|
+
function initSurveys(api) {
|
|
483
|
+
return {
|
|
484
|
+
submit: (data) => api.post("/plugins/surveys", data)
|
|
485
|
+
};
|
|
486
|
+
}
|
|
487
|
+
|
|
488
|
+
// src/lib/plugins/index.ts
|
|
489
|
+
var getConfigs = (apiKey, options) => {
|
|
490
|
+
const api = createApi(apiKey, options);
|
|
491
|
+
return {
|
|
492
|
+
events: initEvents(api),
|
|
493
|
+
identities: initIdentities(api),
|
|
494
|
+
featureFlags: initFeatureFlags(api),
|
|
495
|
+
logs: initLogTracing(api),
|
|
496
|
+
surveys: initSurveys(api),
|
|
497
|
+
experiments: initExperiments(api)
|
|
498
|
+
};
|
|
499
|
+
};
|
|
500
|
+
var getInitializer = (apiKey, options) => {
|
|
501
|
+
const allPlugins = Object.keys(plugins);
|
|
502
|
+
return allPlugins.map((plugin) => {
|
|
503
|
+
const api = createApi(apiKey, options);
|
|
504
|
+
return {
|
|
505
|
+
analytics: () => initAnalytics(api),
|
|
506
|
+
"contact.chat": () => initChat(api, options),
|
|
507
|
+
"feature.flags": () => {
|
|
508
|
+
},
|
|
509
|
+
experiments: () => {
|
|
510
|
+
},
|
|
511
|
+
"log.tracing": () => {
|
|
512
|
+
},
|
|
513
|
+
"session.replay": () => {
|
|
514
|
+
},
|
|
515
|
+
insights: () => {
|
|
516
|
+
},
|
|
517
|
+
surveys: () => {
|
|
518
|
+
}
|
|
519
|
+
}[plugin];
|
|
520
|
+
});
|
|
521
|
+
};
|
|
522
|
+
|
|
523
|
+
// src/lib/index.ts
|
|
524
|
+
var defaultOptions = {
|
|
525
|
+
baseUrl: "https://plugeen.app/api"
|
|
526
|
+
};
|
|
527
|
+
function createSdk(apiKey, options) {
|
|
528
|
+
if (!apiKey) {
|
|
529
|
+
console.warn("[Plugeen] Missing data-api-key attribute.");
|
|
530
|
+
}
|
|
531
|
+
const _options = {
|
|
532
|
+
...defaultOptions,
|
|
533
|
+
...options
|
|
534
|
+
};
|
|
535
|
+
if (apiKey) {
|
|
536
|
+
getInitializer(apiKey, _options).forEach((item) => {
|
|
537
|
+
item();
|
|
538
|
+
});
|
|
539
|
+
}
|
|
540
|
+
return getConfigs(apiKey, _options);
|
|
541
|
+
}
|
|
542
|
+
export {
|
|
543
|
+
createSdk
|
|
544
|
+
};
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
"use strict";var Plugeen=(()=>{var V=Object.defineProperty;var Ze=Object.getOwnPropertyDescriptor;var et=Object.getOwnPropertyNames;var tt=Object.prototype.hasOwnProperty;var nt=(e,t)=>{for(var n in t)V(e,n,{get:t[n],enumerable:!0})},rt=(e,t,n,r)=>{if(t&&typeof t=="object"||typeof t=="function")for(let o of et(t))!tt.call(e,o)&&o!==n&&V(e,o,{get:()=>t[o],enumerable:!(r=Ze(t,o))||r.enumerable});return e};var ot=e=>rt(V({},"__esModule",{value:!0}),e);var Ht={};nt(Ht,{api:()=>At});var it="Plugeen",ue=it.toLowerCase().slice(0,2);function le(e){return`${ue}_${e}`}function ce(){return globalThis.Plugeen||(globalThis.Plugeen={}),globalThis.Plugeen}function _t(){return{get:n=>ce()[n],set:(n,r)=>(ce()[n]=r,r)}}function st(){return{get:n=>{try{let r=localStorage.getItem(le(n));if(!r)throw new Error("No data found");return typeof r=="string"?r:JSON.parse(r)}catch{return}},set:(n,r)=>(localStorage.setItem(le(n),typeof r=="string"?r:JSON.stringify(r)),r)}}function A(){return typeof window>"u"?_t():st()}function pe(){let e=A(),t=e.get("identity");if(t)return t;let n=crypto.randomUUID();return e.set("identity",n),n}var fe="pl_session";function F(){try{let e=sessionStorage.getItem(fe);if(e)return e;throw new Error("No session ID")}catch{let e=crypto.randomUUID();return sessionStorage.setItem(fe,e),e}}function at(e,t){let n=new Headers,r=A().get("identity");return n.append("x-identity-id",r||pe()),n.set("Authorization",`Bearer ${e}`),n.set("x-session-id",F()),(t==="POST"||t==="PUT")&&n.set("Content-Type","application/json"),n}async function J(e){return fetch(`${e.options.baseUrl}${e.url}`,{method:e.method,body:e.body?JSON.stringify({...e.body,source:"api"}):void 0,headers:at(e.apiKey,e.method)}).then(t=>t.json()).then(t=>t.data)}var K=(e,t)=>({post:(n,r)=>J({url:n,method:"POST",body:r,options:t,apiKey:e}),put:(n,r)=>J({url:n,method:"PUT",body:r,options:t,apiKey:e}),get:n=>J({url:n,method:"GET",options:t,apiKey:e})});var de={insights:{registry:"insights",identifier:"insight.created",schema:{queryName:"Checkout funnel",chartType:"line"}},analytics:{registry:"analytics",identifier:"analytics.page_view",schema:{event:"page_view",path:"/pricing",url:"https://example.com/pricing",title:"Pricing",referrer:"https://google.com",sessionId:"session_01"}},"session.replay":{registry:"session.replay",identifier:"session.replay.recording",schema:{sessionId:"session_01HX8PDMW3Q8D4",visitorId:"visitor_01",durationMs:184e3,pageCount:7,clickCount:34,rageClicks:2,deadClicks:1,hasError:!0,device:"desktop",browser:"Chrome",path:"/checkout"}},"feature.flags":{registry:"feature.flags",identifier:"feature.flag.evaluated",schema:{flagKey:"new-checkout",enabled:!0,variant:"treatment",reason:"rollout",userId:"user_01",environment:"production"}},experiments:{registry:"experiments",identifier:"experiment.exposed",schema:{experimentKey:"pricing-page-test",variant:"variant-b",userId:"user_01",metric:"signup",converted:!0,value:49}},surveys:{registry:"surveys",identifier:"survey.response",schema:{surveyId:"nps-q2",question:"How likely are you to recommend us?",response:"The dashboard is fast",rating:9,sentiment:"positive",userId:"user_01",path:"/dashboard"}},"log.tracing":{registry:"log.tracing",identifier:"log.error",schema:{level:"error",message:"Checkout failed to create payment intent",traceId:"trace_01HX8PK2B9M8A1",spanId:"span_checkout",service:"payments-api",environment:"production",route:"POST /api/checkout",release:"2026.04.25",runtime:"nodejs",file:"src/server/checkout.ts",line:142,stack:"Error: payment intent failed"}},"contact.chat":{registry:"contact.chat",identifier:"floating.chat.message",schema:{id:"chat_123",origin:"system",message:"I want some help",resolved:!1}}};function me(e){return(()=>{if(typeof window>"u")return;let n=()=>{e.post("/plugins/analytics",{event:"page_view",url:location.href,title:document.title,referrer:document.referrer??"",sessionId:F()})},r=history.pushState;history.pushState=function(...o){r.apply(this,o),n()},window.addEventListener("popstate",n),n()})()}var $,d,be,ut,E,ge,xe,ke,we,Y,X,G,lt,O={},Pe=[],ct=/acit|ex(?:s|g|n|p|$)|rph|grid|ows|mnc|ntw|ine[ch]|zoo|^ord|itera/i,z=Array.isArray;function P(e,t){for(var n in t)e[n]=t[n];return e}function Z(e){e&&e.parentNode&&e.parentNode.removeChild(e)}function pt(e,t,n){var r,o,i,s={};for(i in t)i=="key"?r=t[i]:i=="ref"?o=t[i]:s[i]=t[i];if(arguments.length>2&&(s.children=arguments.length>3?$.call(arguments,2):n),typeof e=="function"&&e.defaultProps!=null)for(i in e.defaultProps)s[i]===void 0&&(s[i]=e.defaultProps[i]);return M(e,s,r,o,null)}function M(e,t,n,r,o){var i={type:e,props:t,key:n,ref:r,__k:null,__:null,__b:0,__e:null,__c:null,constructor:void 0,__v:o??++be,__i:-1,__u:0};return o==null&&d.vnode!=null&&d.vnode(i),i}function C(e){return e.children}function j(e,t){this.props=e,this.context=t}function H(e,t){if(t==null)return e.__?H(e.__,e.__i+1):null;for(var n;t<e.__k.length;t++)if((n=e.__k[t])!=null&&n.__e!=null)return n.__e;return typeof e.type=="function"?H(e):null}function Se(e){var t,n;if((e=e.__)!=null&&e.__c!=null){for(e.__e=e.__c.base=null,t=0;t<e.__k.length;t++)if((n=e.__k[t])!=null&&n.__e!=null){e.__e=e.__c.base=n.__e;break}return Se(e)}}function he(e){(!e.__d&&(e.__d=!0)&&E.push(e)&&!W.__r++||ge!=d.debounceRendering)&&((ge=d.debounceRendering)||xe)(W)}function W(){for(var e,t,n,r,o,i,s,u=1;E.length;)E.length>u&&E.sort(ke),e=E.shift(),u=E.length,e.__d&&(n=void 0,r=void 0,o=(r=(t=e).__v).__e,i=[],s=[],t.__P&&((n=P({},r)).__v=r.__v+1,d.vnode&&d.vnode(n),ee(t.__P,n,r,t.__n,t.__P.namespaceURI,32&r.__u?[o]:null,i,o??H(r),!!(32&r.__u),s),n.__v=r.__v,n.__.__k[n.__i]=n,Ee(i,n,s),r.__e=r.__=null,n.__e!=o&&Se(n)));W.__r=0}function Ce(e,t,n,r,o,i,s,u,l,a,p){var _,f,c,v,k,b,g,m=r&&r.__k||Pe,S=t.length;for(l=ft(n,t,m,l,S),_=0;_<S;_++)(c=n.__k[_])!=null&&(f=c.__i==-1?O:m[c.__i]||O,c.__i=_,b=ee(e,c,f,o,i,s,u,l,a,p),v=c.__e,c.ref&&f.ref!=c.ref&&(f.ref&&te(f.ref,null,c),p.push(c.ref,c.__c||v,c)),k==null&&v!=null&&(k=v),(g=!!(4&c.__u))||f.__k===c.__k?l=Te(c,l,e,g):typeof c.type=="function"&&b!==void 0?l=b:v&&(l=v.nextSibling),c.__u&=-7);return n.__e=k,l}function ft(e,t,n,r,o){var i,s,u,l,a,p=n.length,_=p,f=0;for(e.__k=new Array(o),i=0;i<o;i++)(s=t[i])!=null&&typeof s!="boolean"&&typeof s!="function"?(typeof s=="string"||typeof s=="number"||typeof s=="bigint"||s.constructor==String?s=e.__k[i]=M(null,s,null,null,null):z(s)?s=e.__k[i]=M(C,{children:s},null,null,null):s.constructor===void 0&&s.__b>0?s=e.__k[i]=M(s.type,s.props,s.key,s.ref?s.ref:null,s.__v):e.__k[i]=s,l=i+f,s.__=e,s.__b=e.__b+1,u=null,(a=s.__i=dt(s,n,l,_))!=-1&&(_--,(u=n[a])&&(u.__u|=2)),u==null||u.__v==null?(a==-1&&(o>p?f--:o<p&&f++),typeof s.type!="function"&&(s.__u|=4)):a!=l&&(a==l-1?f--:a==l+1?f++:(a>l?f--:f++,s.__u|=4))):e.__k[i]=null;if(_)for(i=0;i<p;i++)(u=n[i])!=null&&(2&u.__u)==0&&(u.__e==r&&(r=H(u)),Ae(u,u));return r}function Te(e,t,n,r){var o,i;if(typeof e.type=="function"){for(o=e.__k,i=0;o&&i<o.length;i++)o[i]&&(o[i].__=e,t=Te(o[i],t,n,r));return t}e.__e!=t&&(r&&(t&&e.type&&!t.parentNode&&(t=H(e)),n.insertBefore(e.__e,t||null)),t=e.__e);do t=t&&t.nextSibling;while(t!=null&&t.nodeType==8);return t}function dt(e,t,n,r){var o,i,s,u=e.key,l=e.type,a=t[n],p=a!=null&&(2&a.__u)==0;if(a===null&&u==null||p&&u==a.key&&l==a.type)return n;if(r>(p?1:0)){for(o=n-1,i=n+1;o>=0||i<t.length;)if((a=t[s=o>=0?o--:i++])!=null&&(2&a.__u)==0&&u==a.key&&l==a.type)return s}return-1}function ye(e,t,n){t[0]=="-"?e.setProperty(t,n??""):e[t]=n==null?"":typeof n!="number"||ct.test(t)?n:n+"px"}function R(e,t,n,r,o){var i,s;e:if(t=="style")if(typeof n=="string")e.style.cssText=n;else{if(typeof r=="string"&&(e.style.cssText=r=""),r)for(t in r)n&&t in n||ye(e.style,t,"");if(n)for(t in n)r&&n[t]==r[t]||ye(e.style,t,n[t])}else if(t[0]=="o"&&t[1]=="n")i=t!=(t=t.replace(we,"$1")),s=t.toLowerCase(),t=s in e||t=="onFocusOut"||t=="onFocusIn"?s.slice(2):t.slice(2),e.l||(e.l={}),e.l[t+i]=n,n?r?n.u=r.u:(n.u=Y,e.addEventListener(t,i?G:X,i)):e.removeEventListener(t,i?G:X,i);else{if(o=="http://www.w3.org/2000/svg")t=t.replace(/xlink(H|:h)/,"h").replace(/sName$/,"s");else if(t!="width"&&t!="height"&&t!="href"&&t!="list"&&t!="form"&&t!="tabIndex"&&t!="download"&&t!="rowSpan"&&t!="colSpan"&&t!="role"&&t!="popover"&&t in e)try{e[t]=n??"";break e}catch{}typeof n=="function"||(n==null||n===!1&&t[4]!="-"?e.removeAttribute(t):e.setAttribute(t,t=="popover"&&n==1?"":n))}}function ve(e){return function(t){if(this.l){var n=this.l[t.type+e];if(t.t==null)t.t=Y++;else if(t.t<n.u)return;return n(d.event?d.event(t):t)}}}function ee(e,t,n,r,o,i,s,u,l,a){var p,_,f,c,v,k,b,g,m,S,T,D,N,ae,L,U,q,w=t.type;if(t.constructor!==void 0)return null;128&n.__u&&(l=!!(32&n.__u),i=[u=t.__e=n.__e]),(p=d.__b)&&p(t);e:if(typeof w=="function")try{if(g=t.props,m="prototype"in w&&w.prototype.render,S=(p=w.contextType)&&r[p.__c],T=p?S?S.props.value:p.__:r,n.__c?b=(_=t.__c=n.__c).__=_.__E:(m?t.__c=_=new w(g,T):(t.__c=_=new j(g,T),_.constructor=w,_.render=gt),S&&S.sub(_),_.state||(_.state={}),_.__n=r,f=_.__d=!0,_.__h=[],_._sb=[]),m&&_.__s==null&&(_.__s=_.state),m&&w.getDerivedStateFromProps!=null&&(_.__s==_.state&&(_.__s=P({},_.__s)),P(_.__s,w.getDerivedStateFromProps(g,_.__s))),c=_.props,v=_.state,_.__v=t,f)m&&w.getDerivedStateFromProps==null&&_.componentWillMount!=null&&_.componentWillMount(),m&&_.componentDidMount!=null&&_.__h.push(_.componentDidMount);else{if(m&&w.getDerivedStateFromProps==null&&g!==c&&_.componentWillReceiveProps!=null&&_.componentWillReceiveProps(g,T),t.__v==n.__v||!_.__e&&_.shouldComponentUpdate!=null&&_.shouldComponentUpdate(g,_.__s,T)===!1){for(t.__v!=n.__v&&(_.props=g,_.state=_.__s,_.__d=!1),t.__e=n.__e,t.__k=n.__k,t.__k.some(function(I){I&&(I.__=t)}),D=0;D<_._sb.length;D++)_.__h.push(_._sb[D]);_._sb=[],_.__h.length&&s.push(_);break e}_.componentWillUpdate!=null&&_.componentWillUpdate(g,_.__s,T),m&&_.componentDidUpdate!=null&&_.__h.push(function(){_.componentDidUpdate(c,v,k)})}if(_.context=T,_.props=g,_.__P=e,_.__e=!1,N=d.__r,ae=0,m){for(_.state=_.__s,_.__d=!1,N&&N(t),p=_.render(_.props,_.state,_.context),L=0;L<_._sb.length;L++)_.__h.push(_._sb[L]);_._sb=[]}else do _.__d=!1,N&&N(t),p=_.render(_.props,_.state,_.context),_.state=_.__s;while(_.__d&&++ae<25);_.state=_.__s,_.getChildContext!=null&&(r=P(P({},r),_.getChildContext())),m&&!f&&_.getSnapshotBeforeUpdate!=null&&(k=_.getSnapshotBeforeUpdate(c,v)),U=p,p!=null&&p.type===C&&p.key==null&&(U=Ie(p.props.children)),u=Ce(e,z(U)?U:[U],t,n,r,o,i,s,u,l,a),_.base=t.__e,t.__u&=-161,_.__h.length&&s.push(_),b&&(_.__E=_.__=null)}catch(I){if(t.__v=null,l||i!=null)if(I.then){for(t.__u|=l?160:128;u&&u.nodeType==8&&u.nextSibling;)u=u.nextSibling;i[i.indexOf(u)]=null,t.__e=u}else{for(q=i.length;q--;)Z(i[q]);Q(t)}else t.__e=n.__e,t.__k=n.__k,I.then||Q(t);d.__e(I,t,n)}else i==null&&t.__v==n.__v?(t.__k=n.__k,t.__e=n.__e):u=t.__e=mt(n.__e,t,n,r,o,i,s,l,a);return(p=d.diffed)&&p(t),128&t.__u?void 0:u}function Q(e){e&&e.__c&&(e.__c.__e=!0),e&&e.__k&&e.__k.forEach(Q)}function Ee(e,t,n){for(var r=0;r<n.length;r++)te(n[r],n[++r],n[++r]);d.__c&&d.__c(t,e),e.some(function(o){try{e=o.__h,o.__h=[],e.some(function(i){i.call(o)})}catch(i){d.__e(i,o.__v)}})}function Ie(e){return typeof e!="object"||e==null||e.__b&&e.__b>0?e:z(e)?e.map(Ie):P({},e)}function mt(e,t,n,r,o,i,s,u,l){var a,p,_,f,c,v,k,b=n.props||O,g=t.props,m=t.type;if(m=="svg"?o="http://www.w3.org/2000/svg":m=="math"?o="http://www.w3.org/1998/Math/MathML":o||(o="http://www.w3.org/1999/xhtml"),i!=null){for(a=0;a<i.length;a++)if((c=i[a])&&"setAttribute"in c==!!m&&(m?c.localName==m:c.nodeType==3)){e=c,i[a]=null;break}}if(e==null){if(m==null)return document.createTextNode(g);e=document.createElementNS(o,m,g.is&&g),u&&(d.__m&&d.__m(t,i),u=!1),i=null}if(m==null)b===g||u&&e.data==g||(e.data=g);else{if(i=i&&$.call(e.childNodes),!u&&i!=null)for(b={},a=0;a<e.attributes.length;a++)b[(c=e.attributes[a]).name]=c.value;for(a in b)if(c=b[a],a!="children"){if(a=="dangerouslySetInnerHTML")_=c;else if(!(a in g)){if(a=="value"&&"defaultValue"in g||a=="checked"&&"defaultChecked"in g)continue;R(e,a,null,c,o)}}for(a in g)c=g[a],a=="children"?f=c:a=="dangerouslySetInnerHTML"?p=c:a=="value"?v=c:a=="checked"?k=c:u&&typeof c!="function"||b[a]===c||R(e,a,c,b[a],o);if(p)u||_&&(p.__html==_.__html||p.__html==e.innerHTML)||(e.innerHTML=p.__html),t.__k=[];else if(_&&(e.innerHTML=""),Ce(t.type=="template"?e.content:e,z(f)?f:[f],t,n,r,m=="foreignObject"?"http://www.w3.org/1999/xhtml":o,i,s,i?i[0]:n.__k&&H(n,0),u,l),i!=null)for(a=i.length;a--;)Z(i[a]);u||(a="value",m=="progress"&&v==null?e.removeAttribute("value"):v!=null&&(v!==e[a]||m=="progress"&&!v||m=="option"&&v!=b[a])&&R(e,a,v,b[a],o),a="checked",k!=null&&k!=e[a]&&R(e,a,k,b[a],o))}return e}function te(e,t,n){try{if(typeof e=="function"){var r=typeof e.__u=="function";r&&e.__u(),r&&t==null||(e.__u=e(t))}else e.current=t}catch(o){d.__e(o,n)}}function Ae(e,t,n){var r,o;if(d.unmount&&d.unmount(e),(r=e.ref)&&(r.current&&r.current!=e.__e||te(r,null,t)),(r=e.__c)!=null){if(r.componentWillUnmount)try{r.componentWillUnmount()}catch(i){d.__e(i,t)}r.base=r.__P=null}if(r=e.__k)for(o=0;o<r.length;o++)r[o]&&Ae(r[o],t,n||typeof e.type!="function");n||Z(e.__e),e.__c=e.__=e.__e=void 0}function gt(e,t,n){return this.constructor(e,n)}function ne(e,t,n){var r,o,i,s;t==document&&(t=document.documentElement),d.__&&d.__(e,t),o=(r=typeof n=="function")?null:n&&n.__k||t.__k,i=[],s=[],ee(t,e=(!r&&n||t).__k=pt(C,null,[e]),o||O,O,t.namespaceURI,!r&&n?[n]:o?null:t.firstChild?$.call(t.childNodes):null,i,!r&&n?n:o?o.__e:t.firstChild,r,s),Ee(i,e,s)}$=Pe.slice,d={__e:function(e,t,n,r){for(var o,i,s;t=t.__;)if((o=t.__c)&&!o.__)try{if((i=o.constructor)&&i.getDerivedStateFromError!=null&&(o.setState(i.getDerivedStateFromError(e)),s=o.__d),o.componentDidCatch!=null&&(o.componentDidCatch(e,r||{}),s=o.__d),s)return o.__E=o}catch(u){e=u}throw e}},be=0,ut=function(e){return e!=null&&e.constructor===void 0},j.prototype.setState=function(e,t){var n;n=this.__s!=null&&this.__s!=this.state?this.__s:this.__s=P({},this.state),typeof e=="function"&&(e=e(P({},n),this.props)),e&&P(n,e),e!=null&&this.__v&&(t&&this._sb.push(t),he(this))},j.prototype.forceUpdate=function(e){this.__v&&(this.__e=!0,e&&this.__h.push(e),he(this))},j.prototype.render=C,E=[],xe=typeof Promise=="function"?Promise.prototype.then.bind(Promise.resolve()):setTimeout,ke=function(e,t){return e.__v.__b-t.__v.__b},W.__r=0,we=/(PointerCapture)$|Capture$/i,Y=0,X=ve(!1),G=ve(!0),lt=0;var oe,h,re,He,ie=0,Me=[],y=d,Ne=y.__b,Ue=y.__r,Oe=y.diffed,De=y.__c,Le=y.unmount,Fe=y.__;function ht(e,t){y.__h&&y.__h(h,e,ie||t),ie=0;var n=h.__H||(h.__H={__:[],__h:[]});return e>=n.__.length&&n.__.push({}),n.__[e]}function je(e){return ie=1,yt(We,e)}function yt(e,t,n){var r=ht(oe++,2);if(r.t=e,!r.__c&&(r.__=[n?n(t):We(void 0,t),function(u){var l=r.__N?r.__N[0]:r.__[0],a=r.t(l,u);l!==a&&(r.__N=[a,r.__[1]],r.__c.setState({}))}],r.__c=h,!h.__f)){var o=function(u,l,a){if(!r.__c.__H)return!0;var p=r.__c.__H.__.filter(function(f){return!!f.__c});if(p.every(function(f){return!f.__N}))return!i||i.call(this,u,l,a);var _=r.__c.props!==u;return p.forEach(function(f){if(f.__N){var c=f.__[0];f.__=f.__N,f.__N=void 0,c!==f.__[0]&&(_=!0)}}),i&&i.call(this,u,l,a)||_};h.__f=!0;var i=h.shouldComponentUpdate,s=h.componentWillUpdate;h.componentWillUpdate=function(u,l,a){if(this.__e){var p=i;i=void 0,o(u,l,a),i=p}s&&s.call(this,u,l,a)},h.shouldComponentUpdate=o}return r.__N||r.__}function vt(){for(var e;e=Me.shift();)if(e.__P&&e.__H)try{e.__H.__h.forEach(B),e.__H.__h.forEach(_e),e.__H.__h=[]}catch(t){e.__H.__h=[],y.__e(t,e.__v)}}y.__b=function(e){h=null,Ne&&Ne(e)},y.__=function(e,t){e&&t.__k&&t.__k.__m&&(e.__m=t.__k.__m),Fe&&Fe(e,t)},y.__r=function(e){Ue&&Ue(e),oe=0;var t=(h=e.__c).__H;t&&(re===h?(t.__h=[],h.__h=[],t.__.forEach(function(n){n.__N&&(n.__=n.__N),n.u=n.__N=void 0})):(t.__h.forEach(B),t.__h.forEach(_e),t.__h=[],oe=0)),re=h},y.diffed=function(e){Oe&&Oe(e);var t=e.__c;t&&t.__H&&(t.__H.__h.length&&(Me.push(t)!==1&&He===y.requestAnimationFrame||((He=y.requestAnimationFrame)||bt)(vt)),t.__H.__.forEach(function(n){n.u&&(n.__H=n.u),n.u=void 0})),re=h=null},y.__c=function(e,t){t.some(function(n){try{n.__h.forEach(B),n.__h=n.__h.filter(function(r){return!r.__||_e(r)})}catch(r){t.some(function(o){o.__h&&(o.__h=[])}),t=[],y.__e(r,n.__v)}}),De&&De(e,t)},y.unmount=function(e){Le&&Le(e);var t,n=e.__c;n&&n.__H&&(n.__H.__.forEach(function(r){try{B(r)}catch(o){t=o}}),n.__H=void 0,t&&y.__e(t,n.__v))};var Re=typeof requestAnimationFrame=="function";function bt(e){var t,n=function(){clearTimeout(r),Re&&cancelAnimationFrame(t),setTimeout(e)},r=setTimeout(n,35);Re&&(t=requestAnimationFrame(n))}function B(e){var t=h,n=e.__c;typeof n=="function"&&(e.__c=void 0,n()),h=t}function _e(e){var t=h;e.__c=e.__(),h=t}function We(e,t){return typeof t=="function"?t(e):t}var xt=()=>{};function kt(e,t){let n=document.getElementById(t);if(n instanceof HTMLDivElement)return n;let r=document.createElement("div");return r.id=t,e.appendChild(r),r}function $e({component:e,id:t}){if(typeof document>"u")return{render:()=>{},unmount:xt};let n=document.body;return{render:()=>{let o=kt(document.body,t);return o.parentElement!==n&&n.appendChild(o),ne(e,o),o},unmount:()=>{let o=document.getElementById(t);o&&(ne(null,o),o.remove())}}}var wt=0;function x(e,t,n,r,o,i){t||(t={});var s,u,l=t;if("ref"in l)for(u in l={},t)u=="ref"?s=t[u]:l[u]=t[u];var a={type:e,props:l,key:n,ref:s,__k:null,__:null,__b:0,__e:null,__c:null,constructor:void 0,__v:--wt,__i:-1,__u:0,__source:o,__self:i};if(typeof e=="function"&&(s=e.defaultProps))for(u in s)l[u]===void 0&&(l[u]=s[u]);return d.vnode&&d.vnode(a),a}var Pt="contact.chat";function St({id:e,api:t,accentColor:n}){let[r,o]=je(!1),i=s=>{s.preventDefault();let u=new FormData(s.currentTarget),l=String(u.get("message")??"");t.post("/plugins/chat",{id:e,message:l,origin:"plugin",resolved:!1}),s.currentTarget.reset()};return x("div",{style:{position:"fixed",right:"24px",bottom:"24px",zIndex:"9999",fontFamily:"system-ui, sans-serif"},children:[r&&x("div",{style:{width:"320px",marginBottom:"12px",borderRadius:"12px",boxShadow:"0 8px 32px rgba(0,0,0,0.18)",background:"#fff",overflow:"hidden",border:"1px solid #e5e7eb"},children:[x("div",{style:{background:n,color:"#fff",padding:"14px 16px",fontWeight:"600",fontSize:"14px"},children:"Chat with us"}),x("form",{onSubmit:s=>i(s),style:{padding:"12px 16px"},children:[x("textarea",{name:"message",placeholder:"Send us a message\u2026",rows:3,style:{width:"100%",border:"1px solid #e5e7eb",borderRadius:"8px",padding:"8px",fontSize:"13px",resize:"none",outline:"none",boxSizing:"border-box"}}),x("button",{type:"submit",style:{marginTop:"8px",width:"100%",background:n,color:"#fff",border:"none",borderRadius:"8px",padding:"8px 0",fontWeight:"600",fontSize:"13px",cursor:"pointer"},children:"Send"})]})]}),x("button",{type:"button",onClick:()=>o(s=>!s),"aria-label":"Open chat",style:{width:"52px",height:"52px",borderRadius:"50%",background:n,border:"none",cursor:"pointer",display:"flex",alignItems:"center",justifyContent:"center",boxShadow:"0 4px 16px rgba(0,0,0,0.18)",marginLeft:"auto"},children:x("svg",{width:"24",height:"24",viewBox:"0 0 24 24",fill:"none",stroke:"#fff","stroke-width":"2","stroke-linecap":"round","stroke-linejoin":"round",children:[x("title",{children:"Svg"}),r?x(C,{children:[x("line",{x1:"18",y1:"6",x2:"6",y2:"18"}),x("line",{x1:"6",y1:"6",x2:"18",y2:"18"})]}):x("path",{d:"M21 15a2 2 0 0 1-2 2H7l-4 4V5a2 2 0 0 1 2-2h14a2 2 0 0 1 2 2z"})]})})]})}function ze(e,t){let n=crypto.randomUUID(),{render:r}=$e({component:x(St,{id:n,api:e,accentColor:t.accentColor}),id:Pt});return r()}function Be(e){return{create:(t,n)=>e.post("/events",{name:t,data:n})}}function qe(e){return{get:t=>e.get(`/plugins/experiments/${t}`)}}function Ve(e){return{get:async t=>e.get(`/plugins/feature-flags/${t}`)}}function Je(e){let t=A();async function n(r,o){let i=await e.post("/identities",{...o,id:r});return t.set("identity",r),i}return{set:n}}function Ke(e){return{send:t=>e.post("/plugins/logs",t)}}function Xe(e){return{submit:t=>e.post("/plugins/surveys",t)}}var Ge=(e,t)=>{let n=K(e,t);return{events:Be(n),identities:Je(n),featureFlags:Ve(n),logs:Ke(n),surveys:Xe(n),experiments:qe(n)}},Qe=(e,t)=>Object.keys(de).map(r=>{let o=K(e,t);return{analytics:()=>me(o),"contact.chat":()=>ze(o,t),"feature.flags":()=>{},experiments:()=>{},"log.tracing":()=>{},"session.replay":()=>{},insights:()=>{},surveys:()=>{}}[r]});var Ct={baseUrl:"https://plugeen.app/api"};function Ye(e,t){e||console.warn("[Plugeen] Missing data-api-key attribute.");let n={...Ct,...t};return e&&Qe(e,n).forEach(r=>{r()}),Ge(e,n)}var se=document.currentScript,Tt=se?.dataset.apiKey??"",Et=se?.dataset.baseUrl??"https://plugeen.app/api",It=se?.dataset.accentColor||"#4f46e5",At=Ye(Tt,{baseUrl:Et,accentColor:It});return ot(Ht);})();
|
package/package.json
ADDED
|
@@ -0,0 +1,43 @@
|
|
|
1
|
+
{
|
|
2
|
+
"name": "plugeen",
|
|
3
|
+
"version": "0.0.4",
|
|
4
|
+
"scripts": {
|
|
5
|
+
"dev:server": "bun --watch src/example/server.ts",
|
|
6
|
+
"build": "tsup",
|
|
7
|
+
"prepublishOnly": "npm run build",
|
|
8
|
+
"biome": "biome check",
|
|
9
|
+
"typecheck": "tsc --project tsconfig.json --noEmit"
|
|
10
|
+
},
|
|
11
|
+
"type": "module",
|
|
12
|
+
"main": "./dist/index.cjs",
|
|
13
|
+
"module": "./dist/index.js",
|
|
14
|
+
"browser": "./dist/index.js",
|
|
15
|
+
"unpkg": "./dist/plugeen.global.js",
|
|
16
|
+
"jsdelivr": "./dist/plugeen.global.js",
|
|
17
|
+
"dependencies": {
|
|
18
|
+
"@types/bun": "1.3.13",
|
|
19
|
+
"concurrently": "9.2.1",
|
|
20
|
+
"lucide-react": "1.14.0",
|
|
21
|
+
"preact": "10.28.2",
|
|
22
|
+
"preact-render-to-string": "6.6.7"
|
|
23
|
+
},
|
|
24
|
+
"devDependencies": {
|
|
25
|
+
"@biomejs/biome": "2.4.8",
|
|
26
|
+
"@types/node": "^25.6.0",
|
|
27
|
+
"tsup": "8.5.1",
|
|
28
|
+
"typescript": "5.9.3"
|
|
29
|
+
},
|
|
30
|
+
"exports": {
|
|
31
|
+
".": {
|
|
32
|
+
"types": "./dist/index.d.ts",
|
|
33
|
+
"import": "./dist/index.js",
|
|
34
|
+
"require": "./dist/index.cjs",
|
|
35
|
+
"default": "./dist/index.js"
|
|
36
|
+
},
|
|
37
|
+
"./package.json": "./package.json"
|
|
38
|
+
},
|
|
39
|
+
"files": [
|
|
40
|
+
"dist"
|
|
41
|
+
],
|
|
42
|
+
"types": "dist/index.d.ts"
|
|
43
|
+
}
|