plugeen 0.0.12 → 0.0.15
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 +46 -41
- package/dist/index.d.cts +9 -8
- package/dist/index.d.ts +9 -8
- package/dist/index.js +46 -42
- package/dist/plugeen.global.js +1 -1
- package/package.json +1 -1
package/dist/index.cjs
CHANGED
|
@@ -1,5 +1,15 @@
|
|
|
1
1
|
'use strict';
|
|
2
2
|
|
|
3
|
+
// src/helpers/try-catch.ts
|
|
4
|
+
async function tryCatch(promise) {
|
|
5
|
+
try {
|
|
6
|
+
const result = await promise;
|
|
7
|
+
return [result, null];
|
|
8
|
+
} catch (err) {
|
|
9
|
+
return [null, err instanceof Error ? err : new Error(String(err))];
|
|
10
|
+
}
|
|
11
|
+
}
|
|
12
|
+
|
|
3
13
|
// src/helpers/logger.ts
|
|
4
14
|
function createLogger(debug) {
|
|
5
15
|
if (!debug) {
|
|
@@ -96,10 +106,9 @@ function getOrCreateSessionId() {
|
|
|
96
106
|
// src/http-client/index.ts
|
|
97
107
|
var delay = (ms) => new Promise((resolve) => setTimeout(resolve, ms));
|
|
98
108
|
var HttpClient = class {
|
|
99
|
-
constructor(baseUrl, apiKey
|
|
109
|
+
constructor(baseUrl, apiKey) {
|
|
100
110
|
this.baseUrl = baseUrl;
|
|
101
111
|
this.apiKey = apiKey;
|
|
102
|
-
this.maxRetries = maxRetries;
|
|
103
112
|
}
|
|
104
113
|
headers(method) {
|
|
105
114
|
const h = {
|
|
@@ -110,7 +119,7 @@ var HttpClient = class {
|
|
|
110
119
|
if (method !== "GET") h["Content-Type"] = "application/json";
|
|
111
120
|
return h;
|
|
112
121
|
}
|
|
113
|
-
async request(path, {
|
|
122
|
+
async request(path, { retries = 0, method, body, searchParams }, attempt = 0) {
|
|
114
123
|
const sufix = searchParams ? `?${new URLSearchParams(searchParams).toString()}` : "";
|
|
115
124
|
const url = `${this.baseUrl}${path}${sufix}`;
|
|
116
125
|
try {
|
|
@@ -120,46 +129,45 @@ var HttpClient = class {
|
|
|
120
129
|
credentials: "omit",
|
|
121
130
|
body: body ? JSON.stringify(body) : void 0
|
|
122
131
|
});
|
|
123
|
-
if (res.status === 401 || res.status === 404)
|
|
124
|
-
|
|
125
|
-
|
|
126
|
-
|
|
127
|
-
|
|
128
|
-
|
|
129
|
-
|
|
130
|
-
|
|
131
|
-
|
|
132
|
+
if (res.status === 401 || res.status === 404) {
|
|
133
|
+
const json = await res.json().catch(() => null);
|
|
134
|
+
throw json || new Error(String(res.status));
|
|
135
|
+
}
|
|
136
|
+
if ((res.status >= 500 || res.status === 429) && retries > 0) {
|
|
137
|
+
await delay((1 + attempt) * 1e3);
|
|
138
|
+
return this.request(
|
|
139
|
+
path,
|
|
140
|
+
{ body, retries: retries - 1, method },
|
|
141
|
+
attempt + 1
|
|
142
|
+
);
|
|
132
143
|
}
|
|
133
144
|
if (res.status >= 200 && res.status < 300) {
|
|
134
|
-
|
|
135
|
-
|
|
136
|
-
|
|
137
|
-
|
|
138
|
-
return [null, "Failed to parse json"];
|
|
139
|
-
}
|
|
145
|
+
const json = await res.json().catch(() => {
|
|
146
|
+
throw new Error("Failed to parse json");
|
|
147
|
+
});
|
|
148
|
+
return json.data;
|
|
140
149
|
}
|
|
141
|
-
|
|
150
|
+
throw new Error("Error");
|
|
142
151
|
} catch (err) {
|
|
143
|
-
if (err instanceof TypeError &&
|
|
144
|
-
|
|
145
|
-
|
|
146
|
-
return this.get(path, {
|
|
147
|
-
attempt: attempt + 1
|
|
148
|
-
});
|
|
152
|
+
if (err instanceof TypeError && retries > 0) {
|
|
153
|
+
await delay(1e3);
|
|
154
|
+
return this.get(path, { retries: retries - 1 });
|
|
149
155
|
}
|
|
150
|
-
|
|
156
|
+
throw err;
|
|
151
157
|
}
|
|
152
158
|
}
|
|
153
159
|
async post(path, body, options) {
|
|
154
160
|
return this.request(path, {
|
|
155
|
-
|
|
161
|
+
...options,
|
|
162
|
+
retries: options?.retries ?? 0,
|
|
156
163
|
body,
|
|
157
164
|
method: "POST"
|
|
158
165
|
});
|
|
159
166
|
}
|
|
160
167
|
async get(path, options) {
|
|
161
168
|
return this.request(path, {
|
|
162
|
-
|
|
169
|
+
...options,
|
|
170
|
+
retries: options?.retries ?? 0,
|
|
163
171
|
method: "GET"
|
|
164
172
|
});
|
|
165
173
|
}
|
|
@@ -470,14 +478,12 @@ function initIdentitiesModule(http, logger) {
|
|
|
470
478
|
logger.log("Identities module started");
|
|
471
479
|
return {
|
|
472
480
|
async identify(distinctId, data) {
|
|
473
|
-
const
|
|
474
|
-
|
|
475
|
-
|
|
476
|
-
|
|
477
|
-
}
|
|
478
|
-
});
|
|
481
|
+
const result = await http.post(
|
|
482
|
+
"/v1/identities",
|
|
483
|
+
{ ...data, id: distinctId }
|
|
484
|
+
);
|
|
479
485
|
setIdentityId(distinctId);
|
|
480
|
-
return
|
|
486
|
+
return result;
|
|
481
487
|
}
|
|
482
488
|
};
|
|
483
489
|
}
|
|
@@ -486,9 +492,7 @@ function initIdentitiesModule(http, logger) {
|
|
|
486
492
|
function initEventsModule(http, logger) {
|
|
487
493
|
logger.log("Events module started");
|
|
488
494
|
return {
|
|
489
|
-
track:
|
|
490
|
-
return http.post("/v1/events", { name, data, source: "sdk" });
|
|
491
|
-
}
|
|
495
|
+
track: (name, data = {}) => http.post("/v1/events", { name, data, source: "sdk" })
|
|
492
496
|
};
|
|
493
497
|
}
|
|
494
498
|
|
|
@@ -496,9 +500,9 @@ function initEventsModule(http, logger) {
|
|
|
496
500
|
function initFeatureFlagsModule(http, logger) {
|
|
497
501
|
logger.log("Feature Flags module started");
|
|
498
502
|
return {
|
|
499
|
-
get:
|
|
500
|
-
|
|
501
|
-
}
|
|
503
|
+
get: (name) => http.get(`/v1/feature-flags`, {
|
|
504
|
+
searchParams: { key: name }
|
|
505
|
+
})
|
|
502
506
|
};
|
|
503
507
|
}
|
|
504
508
|
|
|
@@ -543,3 +547,4 @@ function createPlugeen(apiKey, options) {
|
|
|
543
547
|
}
|
|
544
548
|
|
|
545
549
|
exports.createPlugeen = createPlugeen;
|
|
550
|
+
exports.tryCatch = tryCatch;
|
package/dist/index.d.cts
CHANGED
|
@@ -56,26 +56,25 @@ type ClientModules = (typeof modules)[number];
|
|
|
56
56
|
type SdkOptions = {
|
|
57
57
|
apiUrl: string;
|
|
58
58
|
debug: boolean;
|
|
59
|
-
environment?: string;
|
|
60
59
|
service?: string;
|
|
61
60
|
} & Record<ClientModules, boolean>;
|
|
62
61
|
type TrackFn = (event: string, data: Record<string, unknown>) => void;
|
|
63
|
-
type TupleResponse<T> = Promise<[T, null] | [null,
|
|
62
|
+
type TupleResponse<T> = Promise<[T, null] | [null, Error]>;
|
|
64
63
|
type EventsModule = {
|
|
65
|
-
track<T = unknown>(name: string, data?: Record<string, unknown>):
|
|
64
|
+
track<T = unknown>(name: string, data?: Record<string, unknown>): Promise<T>;
|
|
66
65
|
};
|
|
67
66
|
type IdentitiesModule = {
|
|
68
|
-
identify(distinctId: string, data?: Omit<IdentitySchema, "id">):
|
|
67
|
+
identify(distinctId: string, data?: Omit<IdentitySchema, "id">): Promise<IdentitySchema>;
|
|
69
68
|
};
|
|
70
69
|
interface FeatureFlagsModule {
|
|
71
|
-
get(key: string):
|
|
70
|
+
get(key: string): Promise<FeatureFlagsSchema>;
|
|
72
71
|
}
|
|
73
72
|
interface LogsModule {
|
|
74
|
-
send(payload: LogsSchema):
|
|
73
|
+
send(payload: LogsSchema): Promise<FeatureFlagsSchema>;
|
|
75
74
|
}
|
|
76
75
|
interface Plugeen {
|
|
77
76
|
track: TrackFn;
|
|
78
|
-
identify: (distinctId: string, data: Omit<IdentitySchema, "id">) =>
|
|
77
|
+
identify: (distinctId: string, data: Omit<IdentitySchema, "id">) => Promise<IdentitySchema>;
|
|
79
78
|
featureFlags: FeatureFlagsModule;
|
|
80
79
|
logs: LogsModule;
|
|
81
80
|
}
|
|
@@ -85,6 +84,8 @@ declare global {
|
|
|
85
84
|
}
|
|
86
85
|
}
|
|
87
86
|
|
|
87
|
+
declare function tryCatch<T>(promise: Promise<T>): Promise<[T, null] | [null, Error]>;
|
|
88
|
+
|
|
88
89
|
declare function createPlugeen(apiKey: string, options: Partial<SdkOptions>): Plugeen;
|
|
89
90
|
|
|
90
|
-
export { type AnalyticsSchema, type EventsModule, type EventsSchema, type FeatureFlagsModule, type FeatureFlagsSchema, type IdentitiesModule, type IdentitySchema, type LogsModule, type LogsSchema, type MetricName, type Plugeen, type SdkOptions, type TrackFn, type TupleResponse, type WebVitalsSchema, createPlugeen, webVitalsMetrics };
|
|
91
|
+
export { type AnalyticsSchema, type EventsModule, type EventsSchema, type FeatureFlagsModule, type FeatureFlagsSchema, type IdentitiesModule, type IdentitySchema, type LogsModule, type LogsSchema, type MetricName, type Plugeen, type SdkOptions, type TrackFn, type TupleResponse, type WebVitalsSchema, createPlugeen, tryCatch, webVitalsMetrics };
|
package/dist/index.d.ts
CHANGED
|
@@ -56,26 +56,25 @@ type ClientModules = (typeof modules)[number];
|
|
|
56
56
|
type SdkOptions = {
|
|
57
57
|
apiUrl: string;
|
|
58
58
|
debug: boolean;
|
|
59
|
-
environment?: string;
|
|
60
59
|
service?: string;
|
|
61
60
|
} & Record<ClientModules, boolean>;
|
|
62
61
|
type TrackFn = (event: string, data: Record<string, unknown>) => void;
|
|
63
|
-
type TupleResponse<T> = Promise<[T, null] | [null,
|
|
62
|
+
type TupleResponse<T> = Promise<[T, null] | [null, Error]>;
|
|
64
63
|
type EventsModule = {
|
|
65
|
-
track<T = unknown>(name: string, data?: Record<string, unknown>):
|
|
64
|
+
track<T = unknown>(name: string, data?: Record<string, unknown>): Promise<T>;
|
|
66
65
|
};
|
|
67
66
|
type IdentitiesModule = {
|
|
68
|
-
identify(distinctId: string, data?: Omit<IdentitySchema, "id">):
|
|
67
|
+
identify(distinctId: string, data?: Omit<IdentitySchema, "id">): Promise<IdentitySchema>;
|
|
69
68
|
};
|
|
70
69
|
interface FeatureFlagsModule {
|
|
71
|
-
get(key: string):
|
|
70
|
+
get(key: string): Promise<FeatureFlagsSchema>;
|
|
72
71
|
}
|
|
73
72
|
interface LogsModule {
|
|
74
|
-
send(payload: LogsSchema):
|
|
73
|
+
send(payload: LogsSchema): Promise<FeatureFlagsSchema>;
|
|
75
74
|
}
|
|
76
75
|
interface Plugeen {
|
|
77
76
|
track: TrackFn;
|
|
78
|
-
identify: (distinctId: string, data: Omit<IdentitySchema, "id">) =>
|
|
77
|
+
identify: (distinctId: string, data: Omit<IdentitySchema, "id">) => Promise<IdentitySchema>;
|
|
79
78
|
featureFlags: FeatureFlagsModule;
|
|
80
79
|
logs: LogsModule;
|
|
81
80
|
}
|
|
@@ -85,6 +84,8 @@ declare global {
|
|
|
85
84
|
}
|
|
86
85
|
}
|
|
87
86
|
|
|
87
|
+
declare function tryCatch<T>(promise: Promise<T>): Promise<[T, null] | [null, Error]>;
|
|
88
|
+
|
|
88
89
|
declare function createPlugeen(apiKey: string, options: Partial<SdkOptions>): Plugeen;
|
|
89
90
|
|
|
90
|
-
export { type AnalyticsSchema, type EventsModule, type EventsSchema, type FeatureFlagsModule, type FeatureFlagsSchema, type IdentitiesModule, type IdentitySchema, type LogsModule, type LogsSchema, type MetricName, type Plugeen, type SdkOptions, type TrackFn, type TupleResponse, type WebVitalsSchema, createPlugeen, webVitalsMetrics };
|
|
91
|
+
export { type AnalyticsSchema, type EventsModule, type EventsSchema, type FeatureFlagsModule, type FeatureFlagsSchema, type IdentitiesModule, type IdentitySchema, type LogsModule, type LogsSchema, type MetricName, type Plugeen, type SdkOptions, type TrackFn, type TupleResponse, type WebVitalsSchema, createPlugeen, tryCatch, webVitalsMetrics };
|
package/dist/index.js
CHANGED
|
@@ -1,3 +1,13 @@
|
|
|
1
|
+
// src/helpers/try-catch.ts
|
|
2
|
+
async function tryCatch(promise) {
|
|
3
|
+
try {
|
|
4
|
+
const result = await promise;
|
|
5
|
+
return [result, null];
|
|
6
|
+
} catch (err) {
|
|
7
|
+
return [null, err instanceof Error ? err : new Error(String(err))];
|
|
8
|
+
}
|
|
9
|
+
}
|
|
10
|
+
|
|
1
11
|
// src/helpers/logger.ts
|
|
2
12
|
function createLogger(debug) {
|
|
3
13
|
if (!debug) {
|
|
@@ -94,10 +104,9 @@ function getOrCreateSessionId() {
|
|
|
94
104
|
// src/http-client/index.ts
|
|
95
105
|
var delay = (ms) => new Promise((resolve) => setTimeout(resolve, ms));
|
|
96
106
|
var HttpClient = class {
|
|
97
|
-
constructor(baseUrl, apiKey
|
|
107
|
+
constructor(baseUrl, apiKey) {
|
|
98
108
|
this.baseUrl = baseUrl;
|
|
99
109
|
this.apiKey = apiKey;
|
|
100
|
-
this.maxRetries = maxRetries;
|
|
101
110
|
}
|
|
102
111
|
headers(method) {
|
|
103
112
|
const h = {
|
|
@@ -108,7 +117,7 @@ var HttpClient = class {
|
|
|
108
117
|
if (method !== "GET") h["Content-Type"] = "application/json";
|
|
109
118
|
return h;
|
|
110
119
|
}
|
|
111
|
-
async request(path, {
|
|
120
|
+
async request(path, { retries = 0, method, body, searchParams }, attempt = 0) {
|
|
112
121
|
const sufix = searchParams ? `?${new URLSearchParams(searchParams).toString()}` : "";
|
|
113
122
|
const url = `${this.baseUrl}${path}${sufix}`;
|
|
114
123
|
try {
|
|
@@ -118,46 +127,45 @@ var HttpClient = class {
|
|
|
118
127
|
credentials: "omit",
|
|
119
128
|
body: body ? JSON.stringify(body) : void 0
|
|
120
129
|
});
|
|
121
|
-
if (res.status === 401 || res.status === 404)
|
|
122
|
-
|
|
123
|
-
|
|
124
|
-
|
|
125
|
-
|
|
126
|
-
|
|
127
|
-
|
|
128
|
-
|
|
129
|
-
|
|
130
|
+
if (res.status === 401 || res.status === 404) {
|
|
131
|
+
const json = await res.json().catch(() => null);
|
|
132
|
+
throw json || new Error(String(res.status));
|
|
133
|
+
}
|
|
134
|
+
if ((res.status >= 500 || res.status === 429) && retries > 0) {
|
|
135
|
+
await delay((1 + attempt) * 1e3);
|
|
136
|
+
return this.request(
|
|
137
|
+
path,
|
|
138
|
+
{ body, retries: retries - 1, method },
|
|
139
|
+
attempt + 1
|
|
140
|
+
);
|
|
130
141
|
}
|
|
131
142
|
if (res.status >= 200 && res.status < 300) {
|
|
132
|
-
|
|
133
|
-
|
|
134
|
-
|
|
135
|
-
|
|
136
|
-
return [null, "Failed to parse json"];
|
|
137
|
-
}
|
|
143
|
+
const json = await res.json().catch(() => {
|
|
144
|
+
throw new Error("Failed to parse json");
|
|
145
|
+
});
|
|
146
|
+
return json.data;
|
|
138
147
|
}
|
|
139
|
-
|
|
148
|
+
throw new Error("Error");
|
|
140
149
|
} catch (err) {
|
|
141
|
-
if (err instanceof TypeError &&
|
|
142
|
-
|
|
143
|
-
|
|
144
|
-
return this.get(path, {
|
|
145
|
-
attempt: attempt + 1
|
|
146
|
-
});
|
|
150
|
+
if (err instanceof TypeError && retries > 0) {
|
|
151
|
+
await delay(1e3);
|
|
152
|
+
return this.get(path, { retries: retries - 1 });
|
|
147
153
|
}
|
|
148
|
-
|
|
154
|
+
throw err;
|
|
149
155
|
}
|
|
150
156
|
}
|
|
151
157
|
async post(path, body, options) {
|
|
152
158
|
return this.request(path, {
|
|
153
|
-
|
|
159
|
+
...options,
|
|
160
|
+
retries: options?.retries ?? 0,
|
|
154
161
|
body,
|
|
155
162
|
method: "POST"
|
|
156
163
|
});
|
|
157
164
|
}
|
|
158
165
|
async get(path, options) {
|
|
159
166
|
return this.request(path, {
|
|
160
|
-
|
|
167
|
+
...options,
|
|
168
|
+
retries: options?.retries ?? 0,
|
|
161
169
|
method: "GET"
|
|
162
170
|
});
|
|
163
171
|
}
|
|
@@ -468,14 +476,12 @@ function initIdentitiesModule(http, logger) {
|
|
|
468
476
|
logger.log("Identities module started");
|
|
469
477
|
return {
|
|
470
478
|
async identify(distinctId, data) {
|
|
471
|
-
const
|
|
472
|
-
|
|
473
|
-
|
|
474
|
-
|
|
475
|
-
}
|
|
476
|
-
});
|
|
479
|
+
const result = await http.post(
|
|
480
|
+
"/v1/identities",
|
|
481
|
+
{ ...data, id: distinctId }
|
|
482
|
+
);
|
|
477
483
|
setIdentityId(distinctId);
|
|
478
|
-
return
|
|
484
|
+
return result;
|
|
479
485
|
}
|
|
480
486
|
};
|
|
481
487
|
}
|
|
@@ -484,9 +490,7 @@ function initIdentitiesModule(http, logger) {
|
|
|
484
490
|
function initEventsModule(http, logger) {
|
|
485
491
|
logger.log("Events module started");
|
|
486
492
|
return {
|
|
487
|
-
track:
|
|
488
|
-
return http.post("/v1/events", { name, data, source: "sdk" });
|
|
489
|
-
}
|
|
493
|
+
track: (name, data = {}) => http.post("/v1/events", { name, data, source: "sdk" })
|
|
490
494
|
};
|
|
491
495
|
}
|
|
492
496
|
|
|
@@ -494,9 +498,9 @@ function initEventsModule(http, logger) {
|
|
|
494
498
|
function initFeatureFlagsModule(http, logger) {
|
|
495
499
|
logger.log("Feature Flags module started");
|
|
496
500
|
return {
|
|
497
|
-
get:
|
|
498
|
-
|
|
499
|
-
}
|
|
501
|
+
get: (name) => http.get(`/v1/feature-flags`, {
|
|
502
|
+
searchParams: { key: name }
|
|
503
|
+
})
|
|
500
504
|
};
|
|
501
505
|
}
|
|
502
506
|
|
|
@@ -540,4 +544,4 @@ function createPlugeen(apiKey, options) {
|
|
|
540
544
|
return plugeen;
|
|
541
545
|
}
|
|
542
546
|
|
|
543
|
-
export { createPlugeen };
|
|
547
|
+
export { createPlugeen, tryCatch };
|
package/dist/plugeen.global.js
CHANGED
|
@@ -1,2 +1,2 @@
|
|
|
1
1
|
/* plugeen v0.1.0 | https://plugeen.app */
|
|
2
|
-
"use strict";var plugeen=(()=>{function
|
|
2
|
+
"use strict";var plugeen=(()=>{function b(){if(typeof document>"u")return null;let e=document.currentScript;if(!e){let o=document.getElementsByTagName("script");for(let i of Array.from(o))if(i.src&&(i.src.includes("/plugeen.global")||i.src.includes("/plugeen."))){e=i;break}}if(!e)return null;let t={},r=e.getAttribute("data-api-key")??void 0;t.apiUrl=e.getAttribute("data-api-url")??"",t.service=e.getAttribute("data-service")??"",t.analytics=e.getAttribute("data-analytics")==="true",t.webVitals=e.getAttribute("data-web-vitals")==="true",t.errors=e.getAttribute("data-errors")==="true";let n=e.getAttribute("data-debug");return n!==null&&(t.debug=n==="true"||n===""),{apiKey:r,...t}}function h(e){return e?{log:(...t)=>console.log("[plugeen]",...t),warn:(...t)=>console.warn("[plugeen]",...t),error:(...t)=>console.error("[plugeen]",...t)}:{log:()=>{},warn:()=>{},error:()=>{}}}function g(){if(typeof crypto<"u"&&typeof crypto.randomUUID=="function")return crypto.randomUUID();if(typeof crypto<"u"&&typeof crypto.getRandomValues=="function"){let e=new Uint8Array(16);crypto.getRandomValues(e),e[6]=e[6]&15|64,e[8]=e[8]&63|128;let t=Array.from(e).map(r=>r.toString(16).padStart(2,"0")).join("");return`${t.slice(0,8)}-${t.slice(8,12)}-${t.slice(12,16)}-${t.slice(16,20)}-${t.slice(20)}`}return"xxxxxxxx-xxxx-4xxx-yxxx-xxxxxxxxxxxx".replace(/[xy]/g,e=>{let t=Math.floor(Math.random()*16);return(e==="x"?t:t&3|8).toString(16)})}var f="plugeen_anon_id",m="plugeen_session_id",d="plugeen_session_ts";var P=18e5,c={};function E(){try{let e=localStorage.getItem(f);return e||(e=`anon_${g()}`,localStorage.setItem(f,e)),e}catch{return c[f]||(c[f]=`anon_${g()}`),c[f]}}function I(e){try{localStorage.setItem(f,e)}catch{c[f]=e}}function y(){try{let e=sessionStorage.getItem(m),t=sessionStorage.getItem(d);if(e&&t&&Date.now()-parseInt(t,10)<P)return sessionStorage.setItem(d,String(Date.now())),e;sessionStorage.removeItem(m),sessionStorage.removeItem(d);let r=`sess_${g()}`;return sessionStorage.setItem(m,r),sessionStorage.setItem(d,String(Date.now())),r}catch{let e=c[m],t=c[d];if(e&&t&&Date.now()-parseInt(t,10)<P)return c[d]=String(Date.now()),e;let r=`sess_${g()}`;return c[m]=r,c[d]=String(Date.now()),r}}var k=e=>new Promise(t=>setTimeout(t,e)),w=class{constructor(t,r){this.baseUrl=t;this.apiKey=r}headers(t){let r={Authorization:`Bearer ${this.apiKey}`,"x-identity-id":E(),"x-session-id":y()};return t!=="GET"&&(r["Content-Type"]="application/json"),r}async request(t,{retries:r=0,method:n,body:o,searchParams:i},s=0){let l=i?`?${new URLSearchParams(i).toString()}`:"",u=`${this.baseUrl}${t}${l}`;try{let a=await fetch(u,{method:n,headers:this.headers(n),credentials:"omit",body:o?JSON.stringify(o):void 0});if(a.status===401||a.status===404)throw await a.json().catch(()=>null)||new Error(String(a.status));if((a.status>=500||a.status===429)&&r>0)return await k((1+s)*1e3),this.request(t,{body:o,retries:r-1,method:n},s+1);if(a.status>=200&&a.status<300)return(await a.json().catch(()=>{throw new Error("Failed to parse json")})).data;throw new Error("Error")}catch(a){if(a instanceof TypeError&&r>0)return await k(1e3),this.get(t,{retries:r-1});throw a}}async post(t,r,n){return this.request(t,{...n,retries:n?.retries??0,body:r,method:"POST"})}async get(t,r){return this.request(t,{...r,retries:r?.retries??0,method:"GET"})}beacon(t,r){if(typeof navigator>"u"||!navigator.sendBeacon)return!1;try{let n=new Blob([JSON.stringify(r)],{type:"application/json"});return navigator.sendBeacon(`${this.baseUrl}${t}`,n)}catch{return!1}}};function T(e,t){if(typeof window>"u")return;t.log("Analytics module started");let r=Date.now(),n=0,o=window.location.href,i=()=>{n++,e.post("/v1/analytics",{event:"page_view",url:window.location.href,title:document.title,sessionId:y(),referrer:document.referrer||void 0,screenWidth:window.innerWidth,screenHeight:window.innerHeight})},s=(a=!1)=>{let p={event:"page_exit",url:window.location.href,title:document.title,sessionId:y(),referrer:document.referrer||void 0,screenWidth:window.innerWidth,screenHeight:window.innerHeight,metadata:{timeOnPage:Math.round((Date.now()-r)/1e3),pageCount:n}};a?e.beacon("/v1/analytics",p):e.post("/v1/analytics",p)},l=()=>{window.location.href!==o&&(s(),r=Date.now(),o=window.location.href,i())},u=a=>{let p=history[a].bind(history);history[a]=(...V)=>{p(...V),l()}};u("pushState"),u("replaceState"),window.addEventListener("popstate",l),window.addEventListener("beforeunload",()=>s(!0)),document.addEventListener("visibilitychange",()=>document.visibilityState==="hidden"&&s(!0)),i()}var H=["chrome-extension://","moz-extension://","safari-extension://","edge-extension://"];function v(e){if(!e)return!1;let t=e.toLowerCase();return H.some(r=>t.includes(r))}function M(e,t){typeof window>"u"||(t.log("Errors module started"),window.addEventListener("error",r=>{v(r.filename)||v(r.error?.stack)||r.error===null&&r.message==="Script error."||e.post("/v1/logs",{message:r.message||"Unknown Error",level:"error",url:window.location.href,source:"client",metadata:{stack:r.error?.stack,type:r.error?.name}})}),window.addEventListener("unhandledrejection",r=>{let{reason:n}=r;if(v(n?.stack))return;let o="Unknown Error",i;n instanceof Error?(o=n.message,i=n.stack):typeof n=="string"?o=n:n!==null&&typeof n=="object"&&"message"in n&&(o=String(n.message)),e.post("/v1/logs",{message:o,url:window.location.href,source:"client",level:"error",metadata:{stack:i,type:"UnhandledRejection"}})}))}function x(){return performance.getEntriesByType("navigation")[0]?.activationStart??0}function R(){let e=performance.getEntriesByType("navigation")[0];if(e&&e.responseStart>0&&e.responseStart<performance.now())return e}function S(e,t,r){try{if(!PerformanceObserver.supportedEntryTypes.includes(e))return;let n=new PerformanceObserver(o=>{Promise.resolve().then(()=>t(o.getEntries()))});return n.observe({type:e,buffered:!0,...r??{}}),n}catch{return}}function D(e){let t=new Set;S("paint",r=>{for(let n of r)if(n.name==="first-contentful-paint"&&!t.has("first-contentful-paint")){t.add("first-contentful-paint");let o=Math.max(n.startTime-x(),0);e("first-contentful-paint",Math.round(o))}})}function N(e){let t=!1,r=S("largest-contentful-paint",o=>{if(t)return;let i=o[o.length-1];if(i){let s=Math.max(i.startTime-x(),0);e("largest-contentful-paint",Math.round(s))}});if(!r)return;let n=()=>{if(t)return;t=!0;let o=r.takeRecords();if(o.length>0){let i=o[o.length-1],s=Math.max(i.startTime-x(),0);e("largest-contentful-paint",Math.round(s))}r.disconnect()};for(let o of["keydown","click","visibilitychange"])addEventListener(o,n,{capture:!0,once:!0})}function $(e){let t=0,r=[],n=0;S("layout-shift",o=>{for(let i of o){let s=i;if(s.hadRecentInput)continue;let l=r[r.length-1],u=r[0];if(r.length>0&&l&&u&&s.startTime-l.startTime<1e3&&s.startTime-u.startTime<5e3?(t+=s.value,r.push(s)):(t=s.value,r=[s]),t>n){n=t;let a=Math.round(n*1e4)/1e4;e("cumulative-layout-shift",a)}}})}function j(e){let t=R();if(!t)return;let r=Math.max(t.responseStart-x(),0);e("time-to-first-byte",Math.round(r))}function W(e){let t=new Map,r=0;S("event",n=>{for(let o of n){let i=o;if(!i.interactionId)continue;let s=t.get(i.interactionId)??0;i.duration>s&&(t.set(i.interactionId,i.duration),i.duration>r&&(r=i.duration,e("interaction-to-next-paint",Math.round(i.duration))))}},{durationThreshold:40})}function B(e){if(typeof requestAnimationFrame>"u")return;let t=0,r=2e3,n=performance.now(),o=()=>{t++,performance.now()-n<r?requestAnimationFrame(o):e("frames-per-second",Math.round(t/r*1e3))};document.readyState==="complete"?requestAnimationFrame(o):window.addEventListener("load",()=>requestAnimationFrame(o),{once:!0})}function L(){if(!(typeof window<"u")||!(typeof PerformanceObserver<"u"))return[];let r=new Map;return D((n,o)=>r.set(n,o)),N((n,o)=>r.set(n,o)),$((n,o)=>r.set(n,o)),j((n,o)=>r.set(n,o)),W((n,o)=>r.set(n,o)),B((n,o)=>r.set(n,o)),Array.from(r).map(([n,o])=>({name:n,value:o}))}function C(e,t){t.log("Web Vitals module started"),e.post("/v1/web-vitals",{url:window.location.href,metrics:L()})}function O(e,t){return t.log("Identities module started"),{async identify(r,n){let o=await e.post("/v1/identities",{...n,id:r});return I(r),o}}}function _(e,t){return t.log("Events module started"),{track:(r,n={})=>e.post("/v1/events",{name:r,data:n,source:"sdk"})}}function F(e,t){return t.log("Feature Flags module started"),{get:r=>e.get("/v1/feature-flags",{searchParams:{key:r}})}}function U(e,t){return t.log("Logs module started"),{send:r=>e.post("/v1/logs",r)}}function A(e,t){let r={apiUrl:"https://dev.plugeen.app/api",debug:!1,analytics:!1,webVitals:!1,errors:!1,...t},n=h(r.debug);if(!e)throw new TypeError("[plugeen] data-api-key is required");let o=new w(r.apiUrl,e),i={track:_(o,n).track,identify:O(o,n).identify,featureFlags:F(o,n),logs:U(o,n)};return typeof window<"u"&&(r.analytics&&T(o,n),r.webVitals&&C(o,n),r.errors&&M(o,n)),n.log(`Running on ${typeof window>"u"?"server":"client"} side`),i}function q(){let e=b(),t=h(!!e?.debug);if(e){if(!e.apiKey)return t.warn("Data-api-key is required.")}else return t.warn("Failed to start script");t.log("Started");let r=A(e.apiKey,e);return window.plugeen=r,r}window.plugeen||q();})();
|