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 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
+ });
@@ -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 };
@@ -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
+ }