@deway-ai/web-sdk 0.40.0 → 0.42.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/README.md +9 -9
- package/dist/loader.d.ts +2 -2
- package/dist/loader.es.js +56 -53
- package/dist/loader.umd.js +1 -1
- package/package.json +1 -1
package/README.md
CHANGED
|
@@ -87,7 +87,7 @@ Deway.init({
|
|
|
87
87
|
apiEndpoint: string | undefined, // Optional: Custom API endpoint
|
|
88
88
|
wsEndpoint: string | undefined, // Optional: Custom WebSocket endpoint
|
|
89
89
|
isDevelopment: boolean | undefined, // Optional: Enable dev mode logging (default: false)
|
|
90
|
-
|
|
90
|
+
autoShowBookmark: boolean | undefined, // Optional: Auto-show bubble (default: true)
|
|
91
91
|
bubbleConfig: BubbleConfig | undefined, // Optional: Bubble appearance customization
|
|
92
92
|
});
|
|
93
93
|
```
|
|
@@ -113,7 +113,7 @@ enum BubblePosition {
|
|
|
113
113
|
Deway.init({
|
|
114
114
|
appKey: 'your-app-key',
|
|
115
115
|
isDevelopment: true,
|
|
116
|
-
|
|
116
|
+
autoShowBookmark: true,
|
|
117
117
|
bubbleConfig: {
|
|
118
118
|
position: 'bottom-left'
|
|
119
119
|
}
|
|
@@ -177,17 +177,17 @@ Deway.setUserProfile({
|
|
|
177
177
|
- Profile is upserted (created if new, replaced if exists)
|
|
178
178
|
- Profile data completely replaces existing profile on each call
|
|
179
179
|
|
|
180
|
-
### `Deway.
|
|
180
|
+
### `Deway.showBookmark(config?)`
|
|
181
181
|
|
|
182
|
-
Show the AI chat
|
|
182
|
+
Show the AI chat bookmark. Optional configuration for appearance customization.
|
|
183
183
|
|
|
184
|
-
### `Deway.
|
|
184
|
+
### `Deway.hideBookmark()`
|
|
185
185
|
|
|
186
|
-
Hide the AI chat
|
|
186
|
+
Hide the AI chat bookmark.
|
|
187
187
|
|
|
188
|
-
### `Deway.
|
|
188
|
+
### `Deway.isBookmarkVisible()`
|
|
189
189
|
|
|
190
|
-
Check if the
|
|
190
|
+
Check if the bookmark is currently visible.
|
|
191
191
|
|
|
192
192
|
### `Deway.destroy()`
|
|
193
193
|
|
|
@@ -291,7 +291,7 @@ prerequisite calls were made.
|
|
|
291
291
|
|
|
292
292
|
### Bubble doesn't appear
|
|
293
293
|
|
|
294
|
-
- Check `
|
|
294
|
+
- Check `autoShowBookmark` is set to `true` OR manually call `Deway.showBookmark()`
|
|
295
295
|
- Verify `Deway.init()` was called with valid `appKey`
|
|
296
296
|
- Check browser console for initialization errors
|
|
297
297
|
|
package/dist/loader.d.ts
CHANGED
|
@@ -1,8 +1,8 @@
|
|
|
1
|
-
import {
|
|
1
|
+
import { BookmarkConfig } from '../deway-bookmark/models/bookmark-config';
|
|
2
2
|
import { DewayConfig } from '../sdk/types';
|
|
3
3
|
import { IDeway } from '../sdk/types';
|
|
4
4
|
|
|
5
|
-
export {
|
|
5
|
+
export { BookmarkConfig }
|
|
6
6
|
|
|
7
7
|
declare const Deway: IDeway;
|
|
8
8
|
export default Deway;
|
package/dist/loader.es.js
CHANGED
|
@@ -1,17 +1,17 @@
|
|
|
1
|
-
const
|
|
1
|
+
const g = "deway-sdk-config", p = ["Understanding intent", "Reading web page", "Browsing the docs", "Enriching context", "Validating understanding", "Crafting response"];
|
|
2
2
|
class S {
|
|
3
3
|
saveConfig(e) {
|
|
4
4
|
if (window?.localStorage)
|
|
5
5
|
try {
|
|
6
6
|
const t = JSON.stringify(e);
|
|
7
|
-
window.localStorage.setItem(
|
|
7
|
+
window.localStorage.setItem(g, t);
|
|
8
8
|
} catch {
|
|
9
9
|
}
|
|
10
10
|
}
|
|
11
11
|
loadConfig() {
|
|
12
12
|
if (window?.localStorage)
|
|
13
13
|
try {
|
|
14
|
-
const e = window.localStorage.getItem(
|
|
14
|
+
const e = window.localStorage.getItem(g);
|
|
15
15
|
return e ? JSON.parse(e) : null;
|
|
16
16
|
} catch {
|
|
17
17
|
return null;
|
|
@@ -42,6 +42,9 @@ class S {
|
|
|
42
42
|
getFeatureFlag(e) {
|
|
43
43
|
return this.getFeatureFlags()[e] ?? !1;
|
|
44
44
|
}
|
|
45
|
+
getPromptSuggestions() {
|
|
46
|
+
return this.loadConfig()?.promptSuggestions;
|
|
47
|
+
}
|
|
45
48
|
}
|
|
46
49
|
class s {
|
|
47
50
|
static CACHE_KEY = "deway-sdk-cache";
|
|
@@ -51,7 +54,7 @@ class s {
|
|
|
51
54
|
async cacheSDK(e, t, i, n) {
|
|
52
55
|
try {
|
|
53
56
|
const c = (await this.openIndexedDB()).transaction([s.STORE_NAME], "readwrite").objectStore(s.STORE_NAME);
|
|
54
|
-
await new Promise((
|
|
57
|
+
await new Promise((f, y) => {
|
|
55
58
|
const l = c.put({
|
|
56
59
|
id: "latest",
|
|
57
60
|
code: e,
|
|
@@ -60,27 +63,27 @@ class s {
|
|
|
60
63
|
signature: n,
|
|
61
64
|
timestamp: Date.now()
|
|
62
65
|
});
|
|
63
|
-
l.onsuccess = () =>
|
|
66
|
+
l.onsuccess = () => f(l.result), l.onerror = () => y(l.error);
|
|
64
67
|
});
|
|
65
68
|
} catch {
|
|
66
69
|
try {
|
|
67
|
-
const
|
|
70
|
+
const a = JSON.stringify({
|
|
68
71
|
code: e,
|
|
69
72
|
version: t,
|
|
70
73
|
checksum: i,
|
|
71
74
|
signature: n,
|
|
72
75
|
timestamp: Date.now()
|
|
73
76
|
});
|
|
74
|
-
localStorage.setItem(s.CACHE_KEY,
|
|
77
|
+
localStorage.setItem(s.CACHE_KEY, a);
|
|
75
78
|
} catch {
|
|
76
79
|
}
|
|
77
80
|
}
|
|
78
81
|
}
|
|
79
82
|
async getCachedSDK() {
|
|
80
83
|
try {
|
|
81
|
-
const i = (await this.openIndexedDB()).transaction([s.STORE_NAME], "readonly").objectStore(s.STORE_NAME), n = await new Promise((
|
|
84
|
+
const i = (await this.openIndexedDB()).transaction([s.STORE_NAME], "readonly").objectStore(s.STORE_NAME), n = await new Promise((o, a) => {
|
|
82
85
|
const c = i.get("latest");
|
|
83
|
-
c.onsuccess = () =>
|
|
86
|
+
c.onsuccess = () => o(c.result || null), c.onerror = () => a(c.error);
|
|
84
87
|
});
|
|
85
88
|
if (n)
|
|
86
89
|
return n;
|
|
@@ -98,17 +101,17 @@ class s {
|
|
|
98
101
|
return new Promise((e, t) => {
|
|
99
102
|
const i = indexedDB.open(s.DB_NAME, s.DB_VERSION);
|
|
100
103
|
i.onerror = () => t(i.error), i.onsuccess = () => e(i.result), i.onupgradeneeded = (n) => {
|
|
101
|
-
const
|
|
102
|
-
|
|
104
|
+
const o = n.target.result;
|
|
105
|
+
o.objectStoreNames.contains(s.STORE_NAME) || o.createObjectStore(s.STORE_NAME, { keyPath: "id" });
|
|
103
106
|
};
|
|
104
107
|
});
|
|
105
108
|
}
|
|
106
109
|
}
|
|
107
110
|
async function C(r) {
|
|
108
111
|
const t = new TextEncoder().encode(r), i = await crypto.subtle.digest("SHA-256", t);
|
|
109
|
-
return Array.from(new Uint8Array(i)).map((
|
|
112
|
+
return Array.from(new Uint8Array(i)).map((o) => o.toString(16).padStart(2, "0")).join("");
|
|
110
113
|
}
|
|
111
|
-
function
|
|
114
|
+
function w(r) {
|
|
112
115
|
const e = atob(r), t = new Uint8Array(e.length);
|
|
113
116
|
for (let i = 0; i < e.length; i++)
|
|
114
117
|
t[i] = e.charCodeAt(i);
|
|
@@ -120,29 +123,29 @@ function E(r) {
|
|
|
120
123
|
e[t / 2] = Number.parseInt(r.substr(t, 2), 16);
|
|
121
124
|
return e;
|
|
122
125
|
}
|
|
123
|
-
async function
|
|
126
|
+
async function D(r, e, t) {
|
|
124
127
|
try {
|
|
125
|
-
const i =
|
|
126
|
-
return await crypto.subtle.verify("Ed25519",
|
|
128
|
+
const i = w(r), n = E(e), o = w(t), a = await crypto.subtle.importKey("raw", i, { name: "Ed25519" }, !1, ["verify"]);
|
|
129
|
+
return await crypto.subtle.verify("Ed25519", a, o, n);
|
|
127
130
|
} catch {
|
|
128
131
|
return !1;
|
|
129
132
|
}
|
|
130
133
|
}
|
|
131
|
-
async function
|
|
134
|
+
async function A(r, e, t, i) {
|
|
132
135
|
if (!e || !t)
|
|
133
136
|
throw new Error("SDK verification failed: Missing security headers");
|
|
134
137
|
if (await C(r) !== e)
|
|
135
138
|
throw new Error("SDK verification failed: Checksum mismatch - content tampered");
|
|
136
|
-
if (!await
|
|
139
|
+
if (!await D(i, e, t))
|
|
137
140
|
throw new Error("SDK verification failed: Invalid signature - content tampered");
|
|
138
141
|
}
|
|
139
|
-
class
|
|
142
|
+
class v {
|
|
140
143
|
cleanApiEndpoint(e) {
|
|
141
144
|
return e.trim().replace(/\/+$/, "");
|
|
142
145
|
}
|
|
143
146
|
async fetchSDK(e, t, i) {
|
|
144
147
|
try {
|
|
145
|
-
const n = this.cleanApiEndpoint(t),
|
|
148
|
+
const n = this.cleanApiEndpoint(t), o = await fetch(`${n}/sdk-serve/sdk/v0`, {
|
|
146
149
|
method: "GET",
|
|
147
150
|
headers: {
|
|
148
151
|
Accept: "application/javascript",
|
|
@@ -150,23 +153,23 @@ class A {
|
|
|
150
153
|
Origin: window?.location?.origin || ""
|
|
151
154
|
}
|
|
152
155
|
});
|
|
153
|
-
return
|
|
156
|
+
return o.ok ? this.handleSuccessfulFetch(o, i) : null;
|
|
154
157
|
} catch {
|
|
155
158
|
return null;
|
|
156
159
|
}
|
|
157
160
|
}
|
|
158
161
|
async handleSuccessfulFetch(e, t) {
|
|
159
|
-
const i = e.headers.get("x-sdk-checksum"), n = e.headers.get("x-sdk-version"),
|
|
160
|
-
if (!n || !
|
|
162
|
+
const i = e.headers.get("x-sdk-checksum"), n = e.headers.get("x-sdk-version"), o = e.headers.get("x-sdk-signature"), a = await e.text();
|
|
163
|
+
if (!n || !a || !i)
|
|
161
164
|
throw Object.fromEntries(e.headers.entries()), new Error("Invalid SDK response: missing version, code, or checksum");
|
|
162
|
-
return await
|
|
165
|
+
return await A(a, i, o, t), { code: a, version: n, checksum: i, signature: o || "" };
|
|
163
166
|
}
|
|
164
167
|
}
|
|
165
|
-
class
|
|
168
|
+
class m {
|
|
166
169
|
static MAX_QUEUE_SIZE = 50;
|
|
167
170
|
commandQueue = [];
|
|
168
171
|
queueCommand(e, ...t) {
|
|
169
|
-
this.commandQueue.length >=
|
|
172
|
+
this.commandQueue.length >= m.MAX_QUEUE_SIZE && this.commandQueue.shift(), this.commandQueue.push({ method: e, args: t });
|
|
170
173
|
}
|
|
171
174
|
replayQueuedCommands() {
|
|
172
175
|
if (this.commandQueue.length === 0)
|
|
@@ -237,7 +240,7 @@ class u {
|
|
|
237
240
|
return i < n;
|
|
238
241
|
}
|
|
239
242
|
}
|
|
240
|
-
class
|
|
243
|
+
class b {
|
|
241
244
|
cleanApiEndpoint(e) {
|
|
242
245
|
return e.trim().replace(/\/+$/, "");
|
|
243
246
|
}
|
|
@@ -276,13 +279,13 @@ class K {
|
|
|
276
279
|
const i = document.createElement("script");
|
|
277
280
|
i.textContent = e, i.type = "text/javascript";
|
|
278
281
|
let n = !1;
|
|
279
|
-
const
|
|
280
|
-
n || (n = !0, this.cleanupScript(i), t(
|
|
282
|
+
const o = (a) => {
|
|
283
|
+
n || (n = !0, this.cleanupScript(i), t(a));
|
|
281
284
|
};
|
|
282
285
|
i.onerror = () => {
|
|
283
|
-
|
|
284
|
-
}, i.onload = () =>
|
|
285
|
-
!n && this.verifySDKLoaded() ?
|
|
286
|
+
o(!1);
|
|
287
|
+
}, i.onload = () => o(!0), document.head.appendChild(i), setTimeout(() => {
|
|
288
|
+
!n && this.verifySDKLoaded() ? o(!0) : n || o(!1);
|
|
286
289
|
}, 100);
|
|
287
290
|
} catch {
|
|
288
291
|
t(!1);
|
|
@@ -314,13 +317,13 @@ class k {
|
|
|
314
317
|
}
|
|
315
318
|
}
|
|
316
319
|
}
|
|
317
|
-
const
|
|
320
|
+
const h = {
|
|
318
321
|
apiEndpoint: "https://service.deway.app",
|
|
319
322
|
publicKey: "9d3dBUvqyUQ7egd5j5uORdHSqZ7VFWOu+ud/SWt9WUY=",
|
|
320
323
|
isDevelopment: !1,
|
|
321
|
-
|
|
324
|
+
autoShowBookmark: !1
|
|
322
325
|
};
|
|
323
|
-
class
|
|
326
|
+
class x {
|
|
324
327
|
isLoaded = !1;
|
|
325
328
|
isLoading = !1;
|
|
326
329
|
cacheManager;
|
|
@@ -332,7 +335,7 @@ class B {
|
|
|
332
335
|
remoteConfigCache;
|
|
333
336
|
sdkConfigStore;
|
|
334
337
|
constructor() {
|
|
335
|
-
this.cacheManager = new s(), this.scriptExecutor = new K(), this.commandQueue = new
|
|
338
|
+
this.cacheManager = new s(), this.scriptExecutor = new K(), this.commandQueue = new m(), this.sdkFetcher = new v(), this.configValidator = new k(), this.sdkConfigStore = new S(), this.remoteConfigFetcher = new b(), this.remoteConfigCache = new u();
|
|
336
339
|
}
|
|
337
340
|
init(e) {
|
|
338
341
|
this.performInit(e).catch((t) => {
|
|
@@ -346,11 +349,11 @@ class B {
|
|
|
346
349
|
if (!this.configValidator.validateConfig(i))
|
|
347
350
|
return;
|
|
348
351
|
this.isLoading = !0;
|
|
349
|
-
const n = i.apiEndpoint ||
|
|
350
|
-
if (!
|
|
352
|
+
const n = i.apiEndpoint || h.apiEndpoint, o = i.publicKey || h.publicKey, [a, c] = await Promise.all([this.fetchOrLoadSDK(i.appKey, n, o), this.fetchRemoteConfigWithCache(i, n)]);
|
|
353
|
+
if (!a)
|
|
351
354
|
return;
|
|
352
|
-
const
|
|
353
|
-
if (!await this.scriptExecutor.executeSDK(
|
|
355
|
+
const f = t ? e : this.createInitializationPayload(c, i);
|
|
356
|
+
if (!await this.scriptExecutor.executeSDK(a.code) || !this.initializeSDK(f))
|
|
354
357
|
return;
|
|
355
358
|
this.commandQueue.replayQueuedCommands(), this.isLoaded = !0;
|
|
356
359
|
} finally {
|
|
@@ -387,7 +390,7 @@ class B {
|
|
|
387
390
|
return {
|
|
388
391
|
localConfig: t,
|
|
389
392
|
remoteConfig: e?.config ?? null,
|
|
390
|
-
defaults:
|
|
393
|
+
defaults: h
|
|
391
394
|
};
|
|
392
395
|
}
|
|
393
396
|
async fetchOrLoadSDK(e, t, i) {
|
|
@@ -425,21 +428,21 @@ class B {
|
|
|
425
428
|
} catch {
|
|
426
429
|
}
|
|
427
430
|
}
|
|
428
|
-
|
|
431
|
+
show(e) {
|
|
429
432
|
try {
|
|
430
|
-
this.isLoaded && this.isSDKAvailable() ? window.Deway?.
|
|
433
|
+
this.isLoaded && this.isSDKAvailable() ? window.Deway?.show(e) : this.commandQueue.queueCommand("show", e);
|
|
431
434
|
} catch {
|
|
432
435
|
}
|
|
433
436
|
}
|
|
434
|
-
|
|
437
|
+
hide() {
|
|
435
438
|
try {
|
|
436
|
-
this.isLoaded && this.isSDKAvailable() ? window.Deway?.
|
|
439
|
+
this.isLoaded && this.isSDKAvailable() ? window.Deway?.hide() : this.commandQueue.queueCommand("hide");
|
|
437
440
|
} catch {
|
|
438
441
|
}
|
|
439
442
|
}
|
|
440
|
-
|
|
443
|
+
isVisible() {
|
|
441
444
|
try {
|
|
442
|
-
return this.isLoaded && this.isSDKAvailable() ? window.Deway?.
|
|
445
|
+
return this.isLoaded && this.isSDKAvailable() ? window.Deway?.isVisible() ?? !1 : !1;
|
|
443
446
|
} catch {
|
|
444
447
|
return !1;
|
|
445
448
|
}
|
|
@@ -454,17 +457,17 @@ class B {
|
|
|
454
457
|
return typeof window < "u" && "Deway" in window && !!window.Deway;
|
|
455
458
|
}
|
|
456
459
|
}
|
|
457
|
-
const d = new
|
|
460
|
+
const d = new x(), I = {
|
|
458
461
|
init: (r) => d.init(r),
|
|
459
462
|
identify: (r) => d.identify(r),
|
|
460
463
|
reportEvent: (r, e) => d.reportEvent(r, e),
|
|
461
464
|
setUserProfile: (r) => d.setUserProfile(r),
|
|
462
|
-
|
|
463
|
-
|
|
464
|
-
|
|
465
|
+
show: (r) => d.show(r),
|
|
466
|
+
hide: () => d.hide(),
|
|
467
|
+
isVisible: () => d.isVisible(),
|
|
465
468
|
destroy: () => d.destroy()
|
|
466
469
|
};
|
|
467
|
-
typeof window < "u" && (window.Deway =
|
|
470
|
+
typeof window < "u" && (window.Deway = I);
|
|
468
471
|
export {
|
|
469
|
-
|
|
472
|
+
I as default
|
|
470
473
|
};
|
package/dist/loader.umd.js
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
(function(l,u){typeof exports=="object"&&typeof module<"u"?module.exports=u():typeof define=="function"&&define.amd?define(u):(l=typeof globalThis<"u"?globalThis:l||self,l.Deway=u())})(this,(function(){"use strict";const l="deway-sdk-config",u=["Understanding intent","Reading web page","Browsing the docs","Enriching context","Validating understanding","Crafting response"];class C{saveConfig(e){if(window?.localStorage)try{const t=JSON.stringify(e);window.localStorage.setItem(l,t)}catch{}}loadConfig(){if(window?.localStorage)try{const e=window.localStorage.getItem(l);return e?JSON.parse(e):null}catch{return null}return null}getExcludedVendors(){return this.loadConfig()?.excludedVendors??[]}getAssistantName(){return this.loadConfig()?.assistantName??"Assistant"}getAiDisclaimer(){return this.loadConfig()?.aiDisclaimer}getThinkingMessages(){return this.loadConfig()?.thinkingMessages??u}getTalkToHumanBtnTxt(){return this.loadConfig()?.talkToHumanBtnTxt??"talk to Support"}getHumanHandoffUrl(){return this.loadConfig()?.humanHandoffUrl}getFeatureFlags(){return this.loadConfig()?.featureFlags??{}}getFeatureFlag(e){return this.getFeatureFlags()[e]??!1}}class s{static CACHE_KEY="deway-sdk-cache";static DB_NAME="DewaySdk";static DB_VERSION=1;static STORE_NAME="sdk";async cacheSDK(e,t,i,n){try{const d=(await this.openIndexedDB()).transaction([s.STORE_NAME],"readwrite").objectStore(s.STORE_NAME);await new Promise((
|
|
1
|
+
(function(l,u){typeof exports=="object"&&typeof module<"u"?module.exports=u():typeof define=="function"&&define.amd?define(u):(l=typeof globalThis<"u"?globalThis:l||self,l.Deway=u())})(this,(function(){"use strict";const l="deway-sdk-config",u=["Understanding intent","Reading web page","Browsing the docs","Enriching context","Validating understanding","Crafting response"];class C{saveConfig(e){if(window?.localStorage)try{const t=JSON.stringify(e);window.localStorage.setItem(l,t)}catch{}}loadConfig(){if(window?.localStorage)try{const e=window.localStorage.getItem(l);return e?JSON.parse(e):null}catch{return null}return null}getExcludedVendors(){return this.loadConfig()?.excludedVendors??[]}getAssistantName(){return this.loadConfig()?.assistantName??"Assistant"}getAiDisclaimer(){return this.loadConfig()?.aiDisclaimer}getThinkingMessages(){return this.loadConfig()?.thinkingMessages??u}getTalkToHumanBtnTxt(){return this.loadConfig()?.talkToHumanBtnTxt??"talk to Support"}getHumanHandoffUrl(){return this.loadConfig()?.humanHandoffUrl}getFeatureFlags(){return this.loadConfig()?.featureFlags??{}}getFeatureFlag(e){return this.getFeatureFlags()[e]??!1}getPromptSuggestions(){return this.loadConfig()?.promptSuggestions}}class s{static CACHE_KEY="deway-sdk-cache";static DB_NAME="DewaySdk";static DB_VERSION=1;static STORE_NAME="sdk";async cacheSDK(e,t,i,n){try{const d=(await this.openIndexedDB()).transaction([s.STORE_NAME],"readwrite").objectStore(s.STORE_NAME);await new Promise((g,S)=>{const f=d.put({id:"latest",code:e,version:t,checksum:i,signature:n,timestamp:Date.now()});f.onsuccess=()=>g(f.result),f.onerror=()=>S(f.error)})}catch{try{const a=JSON.stringify({code:e,version:t,checksum:i,signature:n,timestamp:Date.now()});localStorage.setItem(s.CACHE_KEY,a)}catch{}}}async getCachedSDK(){try{const i=(await this.openIndexedDB()).transaction([s.STORE_NAME],"readonly").objectStore(s.STORE_NAME),n=await new Promise((o,a)=>{const d=i.get("latest");d.onsuccess=()=>o(d.result||null),d.onerror=()=>a(d.error)});if(n)return n}catch{}try{const e=localStorage.getItem(s.CACHE_KEY);if(e)return JSON.parse(e)}catch{}return null}openIndexedDB(){return new Promise((e,t)=>{const i=indexedDB.open(s.DB_NAME,s.DB_VERSION);i.onerror=()=>t(i.error),i.onsuccess=()=>e(i.result),i.onupgradeneeded=n=>{const o=n.target.result;o.objectStoreNames.contains(s.STORE_NAME)||o.createObjectStore(s.STORE_NAME,{keyPath:"id"})}})}}async function E(r){const t=new TextEncoder().encode(r),i=await crypto.subtle.digest("SHA-256",t);return Array.from(new Uint8Array(i)).map(o=>o.toString(16).padStart(2,"0")).join("")}function w(r){const e=atob(r),t=new Uint8Array(e.length);for(let i=0;i<e.length;i++)t[i]=e.charCodeAt(i);return t}function D(r){const e=new Uint8Array(r.length/2);for(let t=0;t<r.length;t+=2)e[t/2]=Number.parseInt(r.substr(t,2),16);return e}async function A(r,e,t){try{const i=w(r),n=D(e),o=w(t),a=await crypto.subtle.importKey("raw",i,{name:"Ed25519"},!1,["verify"]);return await crypto.subtle.verify("Ed25519",a,o,n)}catch{return!1}}async function v(r,e,t,i){if(!e||!t)throw new Error("SDK verification failed: Missing security headers");if(await E(r)!==e)throw new Error("SDK verification failed: Checksum mismatch - content tampered");if(!await A(i,e,t))throw new Error("SDK verification failed: Invalid signature - content tampered")}class b{cleanApiEndpoint(e){return e.trim().replace(/\/+$/,"")}async fetchSDK(e,t,i){try{const n=this.cleanApiEndpoint(t),o=await fetch(`${n}/sdk-serve/sdk/v0`,{method:"GET",headers:{Accept:"application/javascript","deway-app-key":e,Origin:window?.location?.origin||""}});return o.ok?this.handleSuccessfulFetch(o,i):null}catch{return null}}async handleSuccessfulFetch(e,t){const i=e.headers.get("x-sdk-checksum"),n=e.headers.get("x-sdk-version"),o=e.headers.get("x-sdk-signature"),a=await e.text();if(!n||!a||!i)throw Object.fromEntries(e.headers.entries()),new Error("Invalid SDK response: missing version, code, or checksum");return await v(a,i,o,t),{code:a,version:n,checksum:i,signature:o||""}}}class m{static MAX_QUEUE_SIZE=50;commandQueue=[];queueCommand(e,...t){this.commandQueue.length>=m.MAX_QUEUE_SIZE&&this.commandQueue.shift(),this.commandQueue.push({method:e,args:t})}replayQueuedCommands(){if(this.commandQueue.length===0)return;const e=[...this.commandQueue];if(this.commandQueue=[],!!this.isSDKAvailable())for(const t of e)this.replayCommand(t)}clearQueue(){this.commandQueue=[]}isSDKAvailable(){return typeof window<"u"&&"Deway"in window&&!!window.Deway}replayCommand(e){try{const t=window.Deway,i=t?.[e.method];typeof i=="function"&&i.apply(t,e.args)}catch{}}}class h{static CACHE_KEY="deway-remote-config-cache";async cacheRemoteConfig(e,t){try{const i={config:e,ttl_seconds:t,timestamp:Date.now()};localStorage.setItem(h.CACHE_KEY,JSON.stringify(i))}catch{}}async getCachedRemoteConfig(){try{const e=localStorage.getItem(h.CACHE_KEY);return e?JSON.parse(e):null}catch{return null}}isCacheValid(e,t){const i=Date.now(),n=e+t*1e3;return i<n}}class K{cleanApiEndpoint(e){return e.trim().replace(/\/+$/,"")}async fetchRemoteConfig(e,t){try{const i=this.cleanApiEndpoint(t),n=await fetch(`${i}/sdk-remote-config-serve/`,{method:"GET",headers:{Accept:"application/json","deway-app-key":e,Origin:window?.location?.origin||""}});return n.ok?await n.json():null}catch{return null}}}class k{async executeSDK(e){return new Promise(t=>{try{if(!this.isDocumentReady()){t(!1);return}const i=document.createElement("script");i.textContent=e,i.type="text/javascript";let n=!1;const o=a=>{n||(n=!0,this.cleanupScript(i),t(a))};i.onerror=()=>{o(!1)},i.onload=()=>o(!0),document.head.appendChild(i),setTimeout(()=>{!n&&this.verifySDKLoaded()?o(!0):n||o(!1)},100)}catch{t(!1)}})}isDocumentReady(){return typeof document<"u"&&document.head!=null}verifySDKLoaded(){return typeof window<"u"&&"Deway"in window&&!!window.Deway}cleanupScript(e){try{e.parentNode&&e.parentNode.removeChild(e)}catch{}}}class x{validateConfig(e){return!(!e||!e.appKey||e.appKey.trim().length===0||e.apiEndpoint!==void 0&&!this.isValidUrl(e.apiEndpoint)||e.publicKey!==void 0&&e.publicKey.trim().length===0)}isValidUrl(e){try{return new URL(e),!0}catch{return!1}}}const y={apiEndpoint:"https://service.deway.app",publicKey:"9d3dBUvqyUQ7egd5j5uORdHSqZ7VFWOu+ud/SWt9WUY=",isDevelopment:!1,autoShowBookmark:!1};class I{isLoaded=!1;isLoading=!1;cacheManager;scriptExecutor;commandQueue;sdkFetcher;configValidator;remoteConfigFetcher;remoteConfigCache;sdkConfigStore;constructor(){this.cacheManager=new s,this.scriptExecutor=new k,this.commandQueue=new m,this.sdkFetcher=new b,this.configValidator=new x,this.sdkConfigStore=new C,this.remoteConfigFetcher=new K,this.remoteConfigCache=new h}init(e){this.performInit(e).catch(t=>{})}async performInit(e){try{if(!this.canInitialize())return;const t=this.isInitializationPayload(e),i=t?e.localConfig:e;if(!this.configValidator.validateConfig(i))return;this.isLoading=!0;const n=i.apiEndpoint||y.apiEndpoint,o=i.publicKey||y.publicKey,[a,d]=await Promise.all([this.fetchOrLoadSDK(i.appKey,n,o),this.fetchRemoteConfigWithCache(i,n)]);if(!a)return;const g=t?e:this.createInitializationPayload(d,i);if(!await this.scriptExecutor.executeSDK(a.code)||!this.initializeSDK(g))return;this.commandQueue.replayQueuedCommands(),this.isLoaded=!0}finally{this.isLoading=!1}}isInitializationPayload(e){return"localConfig"in e&&"remoteConfig"in e&&"defaults"in e}canInitialize(){return!(this.isLoaded||this.isLoading)}async fetchRemoteConfigWithCache(e,t){this.sdkConfigStore.saveConfig(e);const i=await this.remoteConfigFetcher.fetchRemoteConfig(e.appKey,t);if(i)return await this.remoteConfigCache.cacheRemoteConfig(i.config,i.ttl_seconds),i;const n=await this.remoteConfigCache.getCachedRemoteConfig();return n?{config:n.config,ttl_seconds:n.ttl_seconds}:null}createInitializationPayload(e,t){return{localConfig:t,remoteConfig:e?.config??null,defaults:y}}async fetchOrLoadSDK(e,t,i){const n=await this.sdkFetcher.fetchSDK(e,t,i);return n?(await this.cacheManager.cacheSDK(n.code,n.version,n.checksum,n.signature),n):this.loadFromCache()}async loadFromCache(){const e=await this.cacheManager.getCachedSDK();return e?{code:e.code,version:e.version}:null}initializeSDK(e){if(!this.isSDKAvailable())return!1;try{return window.Deway?.init(e),!0}catch{return!1}}identify(e){try{this.isLoaded&&this.isSDKAvailable()?window.Deway?.identify(e):this.commandQueue.queueCommand("identify",e)}catch{}}reportEvent(e,t){try{this.isLoaded&&this.isSDKAvailable()?window.Deway?.reportEvent(e,t):this.commandQueue.queueCommand("reportEvent",e,t)}catch{}}setUserProfile(e){try{this.isLoaded&&this.isSDKAvailable()?window.Deway?.setUserProfile(e):this.commandQueue.queueCommand("setUserProfile",e)}catch{}}show(e){try{this.isLoaded&&this.isSDKAvailable()?window.Deway?.show(e):this.commandQueue.queueCommand("show",e)}catch{}}hide(){try{this.isLoaded&&this.isSDKAvailable()?window.Deway?.hide():this.commandQueue.queueCommand("hide")}catch{}}isVisible(){try{return this.isLoaded&&this.isSDKAvailable()?window.Deway?.isVisible()??!1:!1}catch{return!1}}destroy(){try{this.isLoaded&&this.isSDKAvailable()?window.Deway?.destroy():this.commandQueue.queueCommand("destroy"),this.commandQueue.clearQueue()}catch{}}isSDKAvailable(){return typeof window<"u"&&"Deway"in window&&!!window.Deway}}const c=new I,p={init:r=>c.init(r),identify:r=>c.identify(r),reportEvent:(r,e)=>c.reportEvent(r,e),setUserProfile:r=>c.setUserProfile(r),show:r=>c.show(r),hide:()=>c.hide(),isVisible:()=>c.isVisible(),destroy:()=>c.destroy()};return typeof window<"u"&&(window.Deway=p),p}));
|