@deway-ai/web-sdk 0.36.0 → 0.37.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/dist/loader.es.js +137 -161
- package/dist/loader.umd.js +1 -1
- package/package.json +3 -75
package/dist/loader.es.js
CHANGED
|
@@ -5,8 +5,7 @@ class S {
|
|
|
5
5
|
try {
|
|
6
6
|
const t = JSON.stringify(e);
|
|
7
7
|
window.localStorage.setItem(w, t);
|
|
8
|
-
} catch
|
|
9
|
-
console.warn("Failed to save SDK config to localStorage:", t);
|
|
8
|
+
} catch {
|
|
10
9
|
}
|
|
11
10
|
}
|
|
12
11
|
loadConfig() {
|
|
@@ -14,8 +13,8 @@ class S {
|
|
|
14
13
|
try {
|
|
15
14
|
const e = window.localStorage.getItem(w);
|
|
16
15
|
return e ? JSON.parse(e) : null;
|
|
17
|
-
} catch
|
|
18
|
-
return
|
|
16
|
+
} catch {
|
|
17
|
+
return null;
|
|
19
18
|
}
|
|
20
19
|
return null;
|
|
21
20
|
}
|
|
@@ -31,114 +30,122 @@ class S {
|
|
|
31
30
|
getThinkingMessages() {
|
|
32
31
|
return this.loadConfig()?.thinkingMessages ?? p;
|
|
33
32
|
}
|
|
33
|
+
getTalkToHumanBtnTxt() {
|
|
34
|
+
return this.loadConfig()?.talkToHumanBtnTxt ?? "Talk to rep";
|
|
35
|
+
}
|
|
34
36
|
getHumanHandoffUrl() {
|
|
35
37
|
return this.loadConfig()?.humanHandoffUrl;
|
|
36
38
|
}
|
|
39
|
+
getFeatureFlags() {
|
|
40
|
+
return this.loadConfig()?.featureFlags ?? {};
|
|
41
|
+
}
|
|
42
|
+
getFeatureFlag(e) {
|
|
43
|
+
return this.getFeatureFlags()[e] ?? !1;
|
|
44
|
+
}
|
|
45
|
+
getSmhaEndpoint() {
|
|
46
|
+
return this.loadConfig()?.smhaEndpoint;
|
|
47
|
+
}
|
|
37
48
|
}
|
|
38
49
|
class s {
|
|
39
50
|
static CACHE_KEY = "deway-sdk-cache";
|
|
40
51
|
static DB_NAME = "DewaySdk";
|
|
41
52
|
static DB_VERSION = 1;
|
|
42
53
|
static STORE_NAME = "sdk";
|
|
43
|
-
async cacheSDK(e, t,
|
|
54
|
+
async cacheSDK(e, t, i, n) {
|
|
44
55
|
try {
|
|
45
56
|
const c = (await this.openIndexedDB()).transaction([s.STORE_NAME], "readwrite").objectStore(s.STORE_NAME);
|
|
46
57
|
await new Promise((h, y) => {
|
|
47
|
-
const
|
|
58
|
+
const l = c.put({
|
|
48
59
|
id: "latest",
|
|
49
60
|
code: e,
|
|
50
61
|
version: t,
|
|
51
|
-
checksum:
|
|
62
|
+
checksum: i,
|
|
52
63
|
signature: n,
|
|
53
64
|
timestamp: Date.now()
|
|
54
65
|
});
|
|
55
|
-
|
|
56
|
-
})
|
|
66
|
+
l.onsuccess = () => h(l.result), l.onerror = () => y(l.error);
|
|
67
|
+
});
|
|
57
68
|
} catch {
|
|
58
69
|
try {
|
|
59
|
-
const
|
|
70
|
+
const o = JSON.stringify({
|
|
60
71
|
code: e,
|
|
61
72
|
version: t,
|
|
62
|
-
checksum:
|
|
73
|
+
checksum: i,
|
|
63
74
|
signature: n,
|
|
64
75
|
timestamp: Date.now()
|
|
65
76
|
});
|
|
66
|
-
localStorage.setItem(s.CACHE_KEY,
|
|
67
|
-
} catch
|
|
68
|
-
console.warn("Unable to cache SDK:", a);
|
|
77
|
+
localStorage.setItem(s.CACHE_KEY, o);
|
|
78
|
+
} catch {
|
|
69
79
|
}
|
|
70
80
|
}
|
|
71
81
|
}
|
|
72
82
|
async getCachedSDK() {
|
|
73
83
|
try {
|
|
74
|
-
const
|
|
75
|
-
const c =
|
|
76
|
-
c.onsuccess = () =>
|
|
84
|
+
const i = (await this.openIndexedDB()).transaction([s.STORE_NAME], "readonly").objectStore(s.STORE_NAME), n = await new Promise((a, o) => {
|
|
85
|
+
const c = i.get("latest");
|
|
86
|
+
c.onsuccess = () => a(c.result || null), c.onerror = () => o(c.error);
|
|
77
87
|
});
|
|
78
88
|
if (n)
|
|
79
|
-
return
|
|
89
|
+
return n;
|
|
80
90
|
} catch {
|
|
81
|
-
console.debug("IndexedDB unavailable, trying localStorage");
|
|
82
91
|
}
|
|
83
92
|
try {
|
|
84
93
|
const e = localStorage.getItem(s.CACHE_KEY);
|
|
85
94
|
if (e)
|
|
86
|
-
return
|
|
87
|
-
} catch
|
|
88
|
-
console.warn("Failed to read from localStorage:", e);
|
|
95
|
+
return JSON.parse(e);
|
|
96
|
+
} catch {
|
|
89
97
|
}
|
|
90
98
|
return null;
|
|
91
99
|
}
|
|
92
100
|
openIndexedDB() {
|
|
93
101
|
return new Promise((e, t) => {
|
|
94
|
-
const
|
|
95
|
-
|
|
96
|
-
const
|
|
97
|
-
|
|
102
|
+
const i = indexedDB.open(s.DB_NAME, s.DB_VERSION);
|
|
103
|
+
i.onerror = () => t(i.error), i.onsuccess = () => e(i.result), i.onupgradeneeded = (n) => {
|
|
104
|
+
const a = n.target.result;
|
|
105
|
+
a.objectStoreNames.contains(s.STORE_NAME) || a.createObjectStore(s.STORE_NAME, { keyPath: "id" });
|
|
98
106
|
};
|
|
99
107
|
});
|
|
100
108
|
}
|
|
101
109
|
}
|
|
102
|
-
async function
|
|
103
|
-
const t = new TextEncoder().encode(r),
|
|
104
|
-
return Array.from(new Uint8Array(
|
|
110
|
+
async function E(r) {
|
|
111
|
+
const t = new TextEncoder().encode(r), i = await crypto.subtle.digest("SHA-256", t);
|
|
112
|
+
return Array.from(new Uint8Array(i)).map((a) => a.toString(16).padStart(2, "0")).join("");
|
|
105
113
|
}
|
|
106
114
|
function g(r) {
|
|
107
115
|
const e = atob(r), t = new Uint8Array(e.length);
|
|
108
|
-
for (let
|
|
109
|
-
t[
|
|
116
|
+
for (let i = 0; i < e.length; i++)
|
|
117
|
+
t[i] = e.charCodeAt(i);
|
|
110
118
|
return t;
|
|
111
119
|
}
|
|
112
|
-
function
|
|
120
|
+
function C(r) {
|
|
113
121
|
const e = new Uint8Array(r.length / 2);
|
|
114
122
|
for (let t = 0; t < r.length; t += 2)
|
|
115
123
|
e[t / 2] = Number.parseInt(r.substr(t, 2), 16);
|
|
116
124
|
return e;
|
|
117
125
|
}
|
|
118
|
-
async function
|
|
126
|
+
async function b(r, e, t) {
|
|
119
127
|
try {
|
|
120
|
-
const
|
|
121
|
-
return await crypto.subtle.verify("Ed25519",
|
|
122
|
-
} catch
|
|
123
|
-
return
|
|
128
|
+
const i = g(r), n = C(e), a = g(t), o = await crypto.subtle.importKey("raw", i, { name: "Ed25519" }, !1, ["verify"]);
|
|
129
|
+
return await crypto.subtle.verify("Ed25519", o, a, n);
|
|
130
|
+
} catch {
|
|
131
|
+
return !1;
|
|
124
132
|
}
|
|
125
133
|
}
|
|
126
|
-
async function
|
|
134
|
+
async function D(r, e, t, i) {
|
|
127
135
|
if (!e || !t)
|
|
128
136
|
throw new Error("SDK verification failed: Missing security headers");
|
|
129
|
-
if (await
|
|
137
|
+
if (await E(r) !== e)
|
|
130
138
|
throw new Error("SDK verification failed: Checksum mismatch - content tampered");
|
|
131
|
-
if (!await
|
|
139
|
+
if (!await b(i, e, t))
|
|
132
140
|
throw new Error("SDK verification failed: Invalid signature - content tampered");
|
|
133
141
|
}
|
|
134
|
-
class
|
|
142
|
+
class A {
|
|
135
143
|
cleanApiEndpoint(e) {
|
|
136
144
|
return e.trim().replace(/\/+$/, "");
|
|
137
145
|
}
|
|
138
|
-
async fetchSDK(e, t,
|
|
146
|
+
async fetchSDK(e, t, i) {
|
|
139
147
|
try {
|
|
140
|
-
|
|
141
|
-
const n = this.cleanApiEndpoint(t), i = await fetch(`${n}/sdk-serve/sdk/v0`, {
|
|
148
|
+
const n = this.cleanApiEndpoint(t), a = await fetch(`${n}/sdk-serve/sdk/v0`, {
|
|
142
149
|
method: "GET",
|
|
143
150
|
headers: {
|
|
144
151
|
Accept: "application/javascript",
|
|
@@ -146,37 +153,31 @@ class K {
|
|
|
146
153
|
Origin: window?.location?.origin || ""
|
|
147
154
|
}
|
|
148
155
|
});
|
|
149
|
-
return
|
|
150
|
-
} catch
|
|
151
|
-
return
|
|
156
|
+
return a.ok ? this.handleSuccessfulFetch(a, i) : null;
|
|
157
|
+
} catch {
|
|
158
|
+
return null;
|
|
152
159
|
}
|
|
153
160
|
}
|
|
154
161
|
async handleSuccessfulFetch(e, t) {
|
|
155
|
-
const
|
|
156
|
-
if (
|
|
157
|
-
|
|
158
|
-
|
|
159
|
-
}
|
|
160
|
-
return await C(a, o, i, t), { code: a, version: n, checksum: o, signature: i || "" };
|
|
162
|
+
const i = e.headers.get("x-sdk-checksum"), n = e.headers.get("x-sdk-version"), a = e.headers.get("x-sdk-signature"), o = await e.text();
|
|
163
|
+
if (!n || !o || !i)
|
|
164
|
+
throw Object.fromEntries(e.headers.entries()), new Error("Invalid SDK response: missing version, code, or checksum");
|
|
165
|
+
return await D(o, i, a, t), { code: o, version: n, checksum: i, signature: a || "" };
|
|
161
166
|
}
|
|
162
167
|
}
|
|
163
|
-
class
|
|
168
|
+
class m {
|
|
164
169
|
static MAX_QUEUE_SIZE = 50;
|
|
165
170
|
commandQueue = [];
|
|
166
171
|
queueCommand(e, ...t) {
|
|
167
|
-
this.commandQueue.length >=
|
|
172
|
+
this.commandQueue.length >= m.MAX_QUEUE_SIZE && this.commandQueue.shift(), this.commandQueue.push({ method: e, args: t });
|
|
168
173
|
}
|
|
169
174
|
replayQueuedCommands() {
|
|
170
175
|
if (this.commandQueue.length === 0)
|
|
171
176
|
return;
|
|
172
|
-
console.info(`Replaying ${this.commandQueue.length} queued commands`);
|
|
173
177
|
const e = [...this.commandQueue];
|
|
174
|
-
if (this.commandQueue = [],
|
|
175
|
-
|
|
176
|
-
|
|
177
|
-
}
|
|
178
|
-
for (const t of e)
|
|
179
|
-
this.replayCommand(t);
|
|
178
|
+
if (this.commandQueue = [], !!this.isSDKAvailable())
|
|
179
|
+
for (const t of e)
|
|
180
|
+
this.replayCommand(t);
|
|
180
181
|
}
|
|
181
182
|
clearQueue() {
|
|
182
183
|
this.commandQueue = [];
|
|
@@ -186,14 +187,13 @@ class u {
|
|
|
186
187
|
}
|
|
187
188
|
replayCommand(e) {
|
|
188
189
|
try {
|
|
189
|
-
const t = window.Deway,
|
|
190
|
-
typeof
|
|
191
|
-
} catch
|
|
192
|
-
console.error(`Failed to replay command ${e.method}:`, t);
|
|
190
|
+
const t = window.Deway, i = t?.[e.method];
|
|
191
|
+
typeof i == "function" && i.apply(t, e.args);
|
|
192
|
+
} catch {
|
|
193
193
|
}
|
|
194
194
|
}
|
|
195
195
|
}
|
|
196
|
-
class
|
|
196
|
+
class u {
|
|
197
197
|
static CACHE_KEY = "deway-remote-config-cache";
|
|
198
198
|
/**
|
|
199
199
|
* Caches remote configuration in localStorage
|
|
@@ -204,14 +204,13 @@ class f {
|
|
|
204
204
|
*/
|
|
205
205
|
async cacheRemoteConfig(e, t) {
|
|
206
206
|
try {
|
|
207
|
-
const
|
|
207
|
+
const i = {
|
|
208
208
|
config: e,
|
|
209
209
|
ttl_seconds: t,
|
|
210
210
|
timestamp: Date.now()
|
|
211
211
|
};
|
|
212
|
-
localStorage.setItem(
|
|
213
|
-
} catch
|
|
214
|
-
console.warn("Failed to cache remote config:", o);
|
|
212
|
+
localStorage.setItem(u.CACHE_KEY, JSON.stringify(i));
|
|
213
|
+
} catch {
|
|
215
214
|
}
|
|
216
215
|
}
|
|
217
216
|
/**
|
|
@@ -222,13 +221,10 @@ class f {
|
|
|
222
221
|
*/
|
|
223
222
|
async getCachedRemoteConfig() {
|
|
224
223
|
try {
|
|
225
|
-
const e = localStorage.getItem(
|
|
226
|
-
|
|
227
|
-
|
|
228
|
-
|
|
229
|
-
return console.debug("Found cached remote configuration"), t;
|
|
230
|
-
} catch (e) {
|
|
231
|
-
return console.warn("Failed to read cached remote config:", e), null;
|
|
224
|
+
const e = localStorage.getItem(u.CACHE_KEY);
|
|
225
|
+
return e ? JSON.parse(e) : null;
|
|
226
|
+
} catch {
|
|
227
|
+
return null;
|
|
232
228
|
}
|
|
233
229
|
}
|
|
234
230
|
/**
|
|
@@ -240,8 +236,8 @@ class f {
|
|
|
240
236
|
* @returns true if cache is still valid
|
|
241
237
|
*/
|
|
242
238
|
isCacheValid(e, t) {
|
|
243
|
-
const
|
|
244
|
-
return
|
|
239
|
+
const i = Date.now(), n = e + t * 1e3;
|
|
240
|
+
return i < n;
|
|
245
241
|
}
|
|
246
242
|
}
|
|
247
243
|
class v {
|
|
@@ -258,8 +254,7 @@ class v {
|
|
|
258
254
|
*/
|
|
259
255
|
async fetchRemoteConfig(e, t) {
|
|
260
256
|
try {
|
|
261
|
-
|
|
262
|
-
const o = this.cleanApiEndpoint(t), n = await fetch(`${o}/sdk-remote-config-serve/`, {
|
|
257
|
+
const i = this.cleanApiEndpoint(t), n = await fetch(`${i}/sdk-remote-config-serve/`, {
|
|
263
258
|
method: "GET",
|
|
264
259
|
headers: {
|
|
265
260
|
Accept: "application/json",
|
|
@@ -267,37 +262,33 @@ class v {
|
|
|
267
262
|
Origin: window?.location?.origin || ""
|
|
268
263
|
}
|
|
269
264
|
});
|
|
270
|
-
|
|
271
|
-
|
|
272
|
-
|
|
273
|
-
}
|
|
274
|
-
return console.warn(`Failed to fetch remote config: HTTP ${n.status}: ${n.statusText}`), null;
|
|
275
|
-
} catch (o) {
|
|
276
|
-
return console.warn("Failed to fetch remote config from server:", o), null;
|
|
265
|
+
return n.ok ? await n.json() : null;
|
|
266
|
+
} catch {
|
|
267
|
+
return null;
|
|
277
268
|
}
|
|
278
269
|
}
|
|
279
270
|
}
|
|
280
|
-
class
|
|
271
|
+
class K {
|
|
281
272
|
async executeSDK(e) {
|
|
282
273
|
return new Promise((t) => {
|
|
283
274
|
try {
|
|
284
275
|
if (!this.isDocumentReady()) {
|
|
285
|
-
|
|
276
|
+
t(!1);
|
|
286
277
|
return;
|
|
287
278
|
}
|
|
288
|
-
const
|
|
289
|
-
|
|
279
|
+
const i = document.createElement("script");
|
|
280
|
+
i.textContent = e, i.type = "text/javascript";
|
|
290
281
|
let n = !1;
|
|
291
|
-
const
|
|
292
|
-
n || (n = !0, this.cleanupScript(
|
|
282
|
+
const a = (o) => {
|
|
283
|
+
n || (n = !0, this.cleanupScript(i), t(o));
|
|
293
284
|
};
|
|
294
|
-
|
|
295
|
-
|
|
296
|
-
},
|
|
297
|
-
!n && this.verifySDKLoaded() ?
|
|
285
|
+
i.onerror = () => {
|
|
286
|
+
a(!1);
|
|
287
|
+
}, i.onload = () => a(!0), document.head.appendChild(i), setTimeout(() => {
|
|
288
|
+
!n && this.verifySDKLoaded() ? a(!0) : n || a(!1);
|
|
298
289
|
}, 100);
|
|
299
|
-
} catch
|
|
300
|
-
|
|
290
|
+
} catch {
|
|
291
|
+
t(!1);
|
|
301
292
|
}
|
|
302
293
|
});
|
|
303
294
|
}
|
|
@@ -310,14 +301,13 @@ class A {
|
|
|
310
301
|
cleanupScript(e) {
|
|
311
302
|
try {
|
|
312
303
|
e.parentNode && e.parentNode.removeChild(e);
|
|
313
|
-
} catch
|
|
314
|
-
console.debug("Failed to cleanup script element:", t);
|
|
304
|
+
} catch {
|
|
315
305
|
}
|
|
316
306
|
}
|
|
317
307
|
}
|
|
318
|
-
class
|
|
308
|
+
class k {
|
|
319
309
|
validateConfig(e) {
|
|
320
|
-
return e
|
|
310
|
+
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);
|
|
321
311
|
}
|
|
322
312
|
isValidUrl(e) {
|
|
323
313
|
try {
|
|
@@ -327,13 +317,13 @@ class F {
|
|
|
327
317
|
}
|
|
328
318
|
}
|
|
329
319
|
}
|
|
330
|
-
const
|
|
320
|
+
const f = {
|
|
331
321
|
apiEndpoint: "https://service.deway.app",
|
|
332
322
|
publicKey: "9d3dBUvqyUQ7egd5j5uORdHSqZ7VFWOu+ud/SWt9WUY=",
|
|
333
323
|
isDevelopment: !1,
|
|
334
324
|
autoShowBubble: !1
|
|
335
325
|
};
|
|
336
|
-
class
|
|
326
|
+
class B {
|
|
337
327
|
isLoaded = !1;
|
|
338
328
|
isLoading = !1;
|
|
339
329
|
cacheManager;
|
|
@@ -345,32 +335,25 @@ class x {
|
|
|
345
335
|
remoteConfigCache;
|
|
346
336
|
sdkConfigStore;
|
|
347
337
|
constructor() {
|
|
348
|
-
this.cacheManager = new s(), this.scriptExecutor = new
|
|
338
|
+
this.cacheManager = new s(), this.scriptExecutor = new K(), this.commandQueue = new m(), this.sdkFetcher = new A(), this.configValidator = new k(), this.sdkConfigStore = new S(), this.remoteConfigFetcher = new v(), this.remoteConfigCache = new u();
|
|
349
339
|
}
|
|
350
340
|
init(e) {
|
|
351
341
|
this.performInit(e).catch((t) => {
|
|
352
|
-
console.error("Failed to initialize Deway SDK:", t);
|
|
353
342
|
});
|
|
354
343
|
}
|
|
355
344
|
async performInit(e) {
|
|
356
345
|
try {
|
|
357
346
|
if (!this.canInitialize())
|
|
358
347
|
return;
|
|
359
|
-
const t = this.isInitializationPayload(e),
|
|
360
|
-
if (!this.configValidator.validateConfig(
|
|
361
|
-
console.error("Invalid config provided to Deway SDK");
|
|
348
|
+
const t = this.isInitializationPayload(e), i = t ? e.localConfig : e;
|
|
349
|
+
if (!this.configValidator.validateConfig(i))
|
|
362
350
|
return;
|
|
363
|
-
}
|
|
364
351
|
this.isLoading = !0;
|
|
365
|
-
const n =
|
|
366
|
-
if (!
|
|
367
|
-
return;
|
|
368
|
-
const h = t ? e : this.createInitializationPayload(c, o);
|
|
369
|
-
if (!await this.scriptExecutor.executeSDK(a.code)) {
|
|
370
|
-
console.error("SDK execution failed");
|
|
352
|
+
const n = i.apiEndpoint || f.apiEndpoint, a = i.publicKey || f.publicKey, [o, c] = await Promise.all([this.fetchOrLoadSDK(i.appKey, n, a), this.fetchRemoteConfigWithCache(i, n)]);
|
|
353
|
+
if (!o)
|
|
371
354
|
return;
|
|
372
|
-
|
|
373
|
-
if (!this.initializeSDK(h))
|
|
355
|
+
const h = t ? e : this.createInitializationPayload(c, i);
|
|
356
|
+
if (!await this.scriptExecutor.executeSDK(o.code) || !this.initializeSDK(h))
|
|
374
357
|
return;
|
|
375
358
|
this.commandQueue.replayQueuedCommands(), this.isLoaded = !0;
|
|
376
359
|
} finally {
|
|
@@ -381,7 +364,7 @@ class x {
|
|
|
381
364
|
return "localConfig" in e && "remoteConfig" in e && "defaults" in e;
|
|
382
365
|
}
|
|
383
366
|
canInitialize() {
|
|
384
|
-
return this.isLoaded
|
|
367
|
+
return !(this.isLoaded || this.isLoading);
|
|
385
368
|
}
|
|
386
369
|
/**
|
|
387
370
|
* Fetches remote config from backend with cache fallback
|
|
@@ -389,15 +372,14 @@ class x {
|
|
|
389
372
|
*/
|
|
390
373
|
async fetchRemoteConfigWithCache(e, t) {
|
|
391
374
|
this.sdkConfigStore.saveConfig(e);
|
|
392
|
-
const
|
|
393
|
-
if (
|
|
394
|
-
return await this.remoteConfigCache.cacheRemoteConfig(
|
|
395
|
-
console.info("Using cached remote config as fallback");
|
|
375
|
+
const i = await this.remoteConfigFetcher.fetchRemoteConfig(e.appKey, t);
|
|
376
|
+
if (i)
|
|
377
|
+
return await this.remoteConfigCache.cacheRemoteConfig(i.config, i.ttl_seconds), i;
|
|
396
378
|
const n = await this.remoteConfigCache.getCachedRemoteConfig();
|
|
397
379
|
return n ? {
|
|
398
380
|
config: n.config,
|
|
399
381
|
ttl_seconds: n.ttl_seconds
|
|
400
|
-
} :
|
|
382
|
+
} : null;
|
|
401
383
|
}
|
|
402
384
|
/**
|
|
403
385
|
* Creates initialization payload for backend SDK (NEW LOADER v0.29.0+)
|
|
@@ -408,90 +390,84 @@ class x {
|
|
|
408
390
|
return {
|
|
409
391
|
localConfig: t,
|
|
410
392
|
remoteConfig: e?.config ?? null,
|
|
411
|
-
defaults:
|
|
393
|
+
defaults: f
|
|
412
394
|
};
|
|
413
395
|
}
|
|
414
|
-
async fetchOrLoadSDK(e, t,
|
|
415
|
-
const n = await this.sdkFetcher.fetchSDK(e, t,
|
|
416
|
-
return n ? (await this.cacheManager.cacheSDK(n.code, n.version, n.checksum, n.signature), n) :
|
|
396
|
+
async fetchOrLoadSDK(e, t, i) {
|
|
397
|
+
const n = await this.sdkFetcher.fetchSDK(e, t, i);
|
|
398
|
+
return n ? (await this.cacheManager.cacheSDK(n.code, n.version, n.checksum, n.signature), n) : this.loadFromCache();
|
|
417
399
|
}
|
|
418
400
|
async loadFromCache() {
|
|
419
401
|
const e = await this.cacheManager.getCachedSDK();
|
|
420
|
-
return e ?
|
|
402
|
+
return e ? { code: e.code, version: e.version } : null;
|
|
421
403
|
}
|
|
422
404
|
initializeSDK(e) {
|
|
423
405
|
if (!this.isSDKAvailable())
|
|
424
|
-
return
|
|
406
|
+
return !1;
|
|
425
407
|
try {
|
|
426
|
-
return window.Deway?.init(e),
|
|
427
|
-
} catch
|
|
428
|
-
return
|
|
408
|
+
return window.Deway?.init(e), !0;
|
|
409
|
+
} catch {
|
|
410
|
+
return !1;
|
|
429
411
|
}
|
|
430
412
|
}
|
|
431
413
|
identify(e) {
|
|
432
414
|
try {
|
|
433
415
|
this.isLoaded && this.isSDKAvailable() ? window.Deway?.identify(e) : this.commandQueue.queueCommand("identify", e);
|
|
434
|
-
} catch
|
|
435
|
-
console.error("Failed to identify user:", t);
|
|
416
|
+
} catch {
|
|
436
417
|
}
|
|
437
418
|
}
|
|
438
419
|
reportEvent(e, t) {
|
|
439
420
|
try {
|
|
440
421
|
this.isLoaded && this.isSDKAvailable() ? window.Deway?.reportEvent(e, t) : this.commandQueue.queueCommand("reportEvent", e, t);
|
|
441
|
-
} catch
|
|
442
|
-
console.error("Failed to report event:", o);
|
|
422
|
+
} catch {
|
|
443
423
|
}
|
|
444
424
|
}
|
|
445
425
|
setUserProfile(e) {
|
|
446
426
|
try {
|
|
447
427
|
this.isLoaded && this.isSDKAvailable() ? window.Deway?.setUserProfile(e) : this.commandQueue.queueCommand("setUserProfile", e);
|
|
448
|
-
} catch
|
|
449
|
-
console.error("Failed to set user profile:", t);
|
|
428
|
+
} catch {
|
|
450
429
|
}
|
|
451
430
|
}
|
|
452
431
|
showBubble(e) {
|
|
453
432
|
try {
|
|
454
433
|
this.isLoaded && this.isSDKAvailable() ? window.Deway?.showBubble(e) : this.commandQueue.queueCommand("showBubble", e);
|
|
455
|
-
} catch
|
|
456
|
-
console.error("Failed to show bubble:", t);
|
|
434
|
+
} catch {
|
|
457
435
|
}
|
|
458
436
|
}
|
|
459
437
|
hideBubble() {
|
|
460
438
|
try {
|
|
461
439
|
this.isLoaded && this.isSDKAvailable() ? window.Deway?.hideBubble() : this.commandQueue.queueCommand("hideBubble");
|
|
462
|
-
} catch
|
|
463
|
-
console.error("Failed to hide bubble:", e);
|
|
440
|
+
} catch {
|
|
464
441
|
}
|
|
465
442
|
}
|
|
466
443
|
isBubbleVisible() {
|
|
467
444
|
try {
|
|
468
445
|
return this.isLoaded && this.isSDKAvailable() ? window.Deway?.isBubbleVisible() ?? !1 : !1;
|
|
469
|
-
} catch
|
|
470
|
-
return
|
|
446
|
+
} catch {
|
|
447
|
+
return !1;
|
|
471
448
|
}
|
|
472
449
|
}
|
|
473
450
|
destroy() {
|
|
474
451
|
try {
|
|
475
452
|
this.isLoaded && this.isSDKAvailable() ? window.Deway?.destroy() : this.commandQueue.queueCommand("destroy"), this.commandQueue.clearQueue();
|
|
476
|
-
} catch
|
|
477
|
-
console.error("Failed to destroy SDK:", e);
|
|
453
|
+
} catch {
|
|
478
454
|
}
|
|
479
455
|
}
|
|
480
456
|
isSDKAvailable() {
|
|
481
457
|
return typeof window < "u" && "Deway" in window && !!window.Deway;
|
|
482
458
|
}
|
|
483
459
|
}
|
|
484
|
-
const
|
|
485
|
-
init: (r) =>
|
|
486
|
-
identify: (r) =>
|
|
487
|
-
reportEvent: (r, e) =>
|
|
488
|
-
setUserProfile: (r) =>
|
|
489
|
-
showBubble: (r) =>
|
|
490
|
-
hideBubble: () =>
|
|
491
|
-
isBubbleVisible: () =>
|
|
492
|
-
destroy: () =>
|
|
460
|
+
const d = new B(), x = {
|
|
461
|
+
init: (r) => d.init(r),
|
|
462
|
+
identify: (r) => d.identify(r),
|
|
463
|
+
reportEvent: (r, e) => d.reportEvent(r, e),
|
|
464
|
+
setUserProfile: (r) => d.setUserProfile(r),
|
|
465
|
+
showBubble: (r) => d.showBubble(r),
|
|
466
|
+
hideBubble: () => d.hideBubble(),
|
|
467
|
+
isBubbleVisible: () => d.isBubbleVisible(),
|
|
468
|
+
destroy: () => d.destroy()
|
|
493
469
|
};
|
|
494
|
-
typeof window < "u" && (window.Deway =
|
|
470
|
+
typeof window < "u" && (window.Deway = x);
|
|
495
471
|
export {
|
|
496
|
-
|
|
472
|
+
x as default
|
|
497
473
|
};
|
package/dist/loader.umd.js
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
(function(d,u){typeof exports=="object"&&typeof module<"u"?module.exports=u():typeof define=="function"&&define.amd?define(u):(d=typeof globalThis<"u"?globalThis:d||self,d.Deway=u())})(this,(function(){"use strict";const d="deway-sdk-config",u=["Understanding intent","Reading web page","Browsing the docs","Enriching context","Validating understanding","Crafting response"];class b{saveConfig(e){if(window?.localStorage)try{const t=JSON.stringify(e);window.localStorage.setItem(d,t)}catch(t){console.warn("Failed to save SDK config to localStorage:",t)}}loadConfig(){if(window?.localStorage)try{const e=window.localStorage.getItem(d);return e?JSON.parse(e):null}catch(e){return console.warn("Failed to load SDK config from localStorage:",e),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}getHumanHandoffUrl(){return this.loadConfig()?.humanHandoffUrl}}class s{static CACHE_KEY="deway-sdk-cache";static DB_NAME="DewaySdk";static DB_VERSION=1;static STORE_NAME="sdk";async cacheSDK(e,t,o,n){try{const c=(await this.openIndexedDB()).transaction([s.STORE_NAME],"readwrite").objectStore(s.STORE_NAME);await new Promise((w,S)=>{const f=c.put({id:"latest",code:e,version:t,checksum:o,signature:n,timestamp:Date.now()});f.onsuccess=()=>w(f.result),f.onerror=()=>S(f.error)}),console.debug("SDK cached in IndexedDB")}catch{try{const a=JSON.stringify({code:e,version:t,checksum:o,signature:n,timestamp:Date.now()});localStorage.setItem(s.CACHE_KEY,a),console.debug("SDK cached in localStorage")}catch(a){console.warn("Unable to cache SDK:",a)}}}async getCachedSDK(){try{const o=(await this.openIndexedDB()).transaction([s.STORE_NAME],"readonly").objectStore(s.STORE_NAME),n=await new Promise((i,a)=>{const c=o.get("latest");c.onsuccess=()=>i(c.result||null),c.onerror=()=>a(c.error)});if(n)return console.debug("Found cached SDK in IndexedDB"),n}catch{console.debug("IndexedDB unavailable, trying localStorage")}try{const e=localStorage.getItem(s.CACHE_KEY);if(e)return console.debug("Found cached SDK in localStorage"),JSON.parse(e)}catch(e){console.warn("Failed to read from localStorage:",e)}return null}openIndexedDB(){return new Promise((e,t)=>{const o=indexedDB.open(s.DB_NAME,s.DB_VERSION);o.onerror=()=>t(o.error),o.onsuccess=()=>e(o.result),o.onupgradeneeded=n=>{const i=n.target.result;i.objectStoreNames.contains(s.STORE_NAME)||i.createObjectStore(s.STORE_NAME,{keyPath:"id"})}})}}async function D(r){const t=new TextEncoder().encode(r),o=await crypto.subtle.digest("SHA-256",t);return Array.from(new Uint8Array(o)).map(i=>i.toString(16).padStart(2,"0")).join("")}function g(r){const e=atob(r),t=new Uint8Array(e.length);for(let o=0;o<e.length;o++)t[o]=e.charCodeAt(o);return t}function E(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 C(r,e,t){try{const o=g(r),n=E(e),i=g(t),a=await crypto.subtle.importKey("raw",o,{name:"Ed25519"},!1,["verify"]);return await crypto.subtle.verify("Ed25519",a,i,n)}catch(o){return console.error("Ed25519 signature verification failed:",o),!1}}async function K(r,e,t,o){if(!e||!t)throw new Error("SDK verification failed: Missing security headers");if(await D(r)!==e)throw new Error("SDK verification failed: Checksum mismatch - content tampered");if(!await C(o,e,t))throw new Error("SDK verification failed: Invalid signature - content tampered")}class v{cleanApiEndpoint(e){return e.trim().replace(/\/+$/,"")}async fetchSDK(e,t,o){try{console.info("Fetching Deway SDK from backend...");const n=this.cleanApiEndpoint(t),i=await fetch(`${n}/sdk-serve/sdk/v0`,{method:"GET",headers:{Accept:"application/javascript","deway-app-key":e,Origin:window?.location?.origin||""}});return i.ok?this.handleSuccessfulFetch(i,o):(console.warn(`Failed to fetch SDK: HTTP ${i.status}: ${i.statusText}`),null)}catch(n){return console.warn("Failed to fetch SDK from server:",n),null}}async handleSuccessfulFetch(e,t){const o=e.headers.get("x-sdk-checksum"),n=e.headers.get("x-sdk-version"),i=e.headers.get("x-sdk-signature"),a=await e.text();if(console.info(`Fetched Deway SDK version ${n}`),!n||!a||!o){const c=Object.fromEntries(e.headers.entries());throw console.error(`Failed to get required data from sdk fetch. Headers: ${JSON.stringify(c)}`),new Error("Invalid SDK response: missing version, code, or checksum")}return await K(a,o,i,t),{code:a,version:n,checksum:o,signature:i||""}}}class h{static MAX_QUEUE_SIZE=50;commandQueue=[];queueCommand(e,...t){this.commandQueue.length>=h.MAX_QUEUE_SIZE&&(console.warn(`Command queue full (${h.MAX_QUEUE_SIZE} commands). Discarding oldest command.`),this.commandQueue.shift()),this.commandQueue.push({method:e,args:t}),console.debug(`Queued command: ${e} (queue size: ${this.commandQueue.length})`)}replayQueuedCommands(){if(this.commandQueue.length===0)return;console.info(`Replaying ${this.commandQueue.length} queued commands`);const e=[...this.commandQueue];if(this.commandQueue=[],!this.isSDKAvailable()){console.warn("Deway SDK not available for command replay");return}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,o=t?.[e.method];typeof o=="function"?o.apply(t,e.args):console.warn(`Method ${e.method} not found on Deway SDK`)}catch(t){console.error(`Failed to replay command ${e.method}:`,t)}}}class m{static CACHE_KEY="deway-remote-config-cache";async cacheRemoteConfig(e,t){try{const o={config:e,ttl_seconds:t,timestamp:Date.now()};localStorage.setItem(m.CACHE_KEY,JSON.stringify(o)),console.debug("Remote configuration cached in localStorage")}catch(o){console.warn("Failed to cache remote config:",o)}}async getCachedRemoteConfig(){try{const e=localStorage.getItem(m.CACHE_KEY);if(!e)return null;const t=JSON.parse(e);return console.debug("Found cached remote configuration"),t}catch(e){return console.warn("Failed to read cached remote config:",e),null}}isCacheValid(e,t){const o=Date.now(),n=e+t*1e3;return o<n}}class A{cleanApiEndpoint(e){return e.trim().replace(/\/+$/,"")}async fetchRemoteConfig(e,t){try{console.info("Fetching remote configuration from backend...");const o=this.cleanApiEndpoint(t),n=await fetch(`${o}/sdk-remote-config-serve/`,{method:"GET",headers:{Accept:"application/json","deway-app-key":e,Origin:window?.location?.origin||""}});if(n.ok){const i=await n.json();return console.info("Remote configuration fetched successfully"),i}return console.warn(`Failed to fetch remote config: HTTP ${n.status}: ${n.statusText}`),null}catch(o){return console.warn("Failed to fetch remote config from server:",o),null}}}class F{async executeSDK(e){return new Promise(t=>{try{if(!this.isDocumentReady()){console.error("Document is not available for script execution"),t(!1);return}const o=document.createElement("script");o.textContent=e,o.type="text/javascript";let n=!1;const i=a=>{n||(n=!0,this.cleanupScript(o),t(a))};o.onerror=()=>{console.error("Script execution failed"),i(!1)},o.onload=()=>i(!0),document.head.appendChild(o),setTimeout(()=>{!n&&this.verifySDKLoaded()?i(!0):n||(console.error("SDK execution timeout - Deway object not found"),i(!1))},100)}catch(o){console.error("Failed to execute SDK script:",o),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(t){console.debug("Failed to cleanup script element:",t)}}}class x{validateConfig(e){return e?!e.appKey||e.appKey.trim().length===0?(console.error("Config.appKey is required and must be a non-empty string"),!1):e.apiEndpoint!==void 0&&!this.isValidUrl(e.apiEndpoint)?(console.error("Config.apiEndpoint must be a valid URL"),!1):e.publicKey!==void 0&&e.publicKey.trim().length===0?(console.error("Config.publicKey must be a non-empty string if provided"),!1):!0:(console.error("Config is required"),!1)}isValidUrl(e){try{return new URL(e),!0}catch{return!1}}}const y={apiEndpoint:"https://service.deway.app",publicKey:"9d3dBUvqyUQ7egd5j5uORdHSqZ7VFWOu+ud/SWt9WUY=",isDevelopment:!1,autoShowBubble:!1};class k{isLoaded=!1;isLoading=!1;cacheManager;scriptExecutor;commandQueue;sdkFetcher;configValidator;remoteConfigFetcher;remoteConfigCache;sdkConfigStore;constructor(){this.cacheManager=new s,this.scriptExecutor=new F,this.commandQueue=new h,this.sdkFetcher=new v,this.configValidator=new x,this.sdkConfigStore=new b,this.remoteConfigFetcher=new A,this.remoteConfigCache=new m}init(e){this.performInit(e).catch(t=>{console.error("Failed to initialize Deway SDK:",t)})}async performInit(e){try{if(!this.canInitialize())return;const t=this.isInitializationPayload(e),o=t?e.localConfig:e;if(!this.configValidator.validateConfig(o)){console.error("Invalid config provided to Deway SDK");return}this.isLoading=!0;const n=o.apiEndpoint||y.apiEndpoint,i=o.publicKey||y.publicKey,[a,c]=await Promise.all([this.fetchOrLoadSDK(o.appKey,n,i),this.fetchRemoteConfigWithCache(o,n)]);if(!a)return;const w=t?e:this.createInitializationPayload(c,o);if(!await this.scriptExecutor.executeSDK(a.code)){console.error("SDK execution failed");return}if(!this.initializeSDK(w))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?(console.warn("Deway SDK already initialized"),!1):this.isLoading?(console.warn("Deway SDK initialization already in progress"),!1):!0}async fetchRemoteConfigWithCache(e,t){this.sdkConfigStore.saveConfig(e);const o=await this.remoteConfigFetcher.fetchRemoteConfig(e.appKey,t);if(o)return await this.remoteConfigCache.cacheRemoteConfig(o.config,o.ttl_seconds),o;console.info("Using cached remote config as fallback");const n=await this.remoteConfigCache.getCachedRemoteConfig();return n?{config:n.config,ttl_seconds:n.ttl_seconds}:(console.warn("No remote config available (fetch failed and no cache)"),null)}createInitializationPayload(e,t){return{localConfig:t,remoteConfig:e?.config??null,defaults:y}}async fetchOrLoadSDK(e,t,o){const n=await this.sdkFetcher.fetchSDK(e,t,o);return n?(await this.cacheManager.cacheSDK(n.code,n.version,n.checksum,n.signature),n):(console.warn("Failed to fetch SDK from server, attempting cache fallback"),this.loadFromCache())}async loadFromCache(){const e=await this.cacheManager.getCachedSDK();return e?(console.info(`Loading cached Deway SDK version ${e.version}`),{code:e.code,version:e.version}):(console.error("SDK unavailable: Network error and no cached version found"),null)}initializeSDK(e){if(!this.isSDKAvailable())return console.error("SDK execution failed: Deway object not found after loading"),!1;try{return window.Deway?.init(e),console.info("Deway SDK initialized successfully with payload"),!0}catch(t){return console.error("Failed to initialize SDK with payload:",t),!1}}identify(e){try{this.isLoaded&&this.isSDKAvailable()?window.Deway?.identify(e):this.commandQueue.queueCommand("identify",e)}catch(t){console.error("Failed to identify user:",t)}}reportEvent(e,t){try{this.isLoaded&&this.isSDKAvailable()?window.Deway?.reportEvent(e,t):this.commandQueue.queueCommand("reportEvent",e,t)}catch(o){console.error("Failed to report event:",o)}}setUserProfile(e){try{this.isLoaded&&this.isSDKAvailable()?window.Deway?.setUserProfile(e):this.commandQueue.queueCommand("setUserProfile",e)}catch(t){console.error("Failed to set user profile:",t)}}showBubble(e){try{this.isLoaded&&this.isSDKAvailable()?window.Deway?.showBubble(e):this.commandQueue.queueCommand("showBubble",e)}catch(t){console.error("Failed to show bubble:",t)}}hideBubble(){try{this.isLoaded&&this.isSDKAvailable()?window.Deway?.hideBubble():this.commandQueue.queueCommand("hideBubble")}catch(e){console.error("Failed to hide bubble:",e)}}isBubbleVisible(){try{return this.isLoaded&&this.isSDKAvailable()?window.Deway?.isBubbleVisible()??!1:!1}catch(e){return console.error("Failed to check bubble visibility:",e),!1}}destroy(){try{this.isLoaded&&this.isSDKAvailable()?window.Deway?.destroy():this.commandQueue.queueCommand("destroy"),this.commandQueue.clearQueue()}catch(e){console.error("Failed to destroy SDK:",e)}}isSDKAvailable(){return typeof window<"u"&&"Deway"in window&&!!window.Deway}}const l=new k,p={init:r=>l.init(r),identify:r=>l.identify(r),reportEvent:(r,e)=>l.reportEvent(r,e),setUserProfile:r=>l.setUserProfile(r),showBubble:r=>l.showBubble(r),hideBubble:()=>l.hideBubble(),isBubbleVisible:()=>l.isBubbleVisible(),destroy:()=>l.destroy()};return typeof window<"u"&&(window.Deway=p),p}));
|
|
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 E{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 rep"}getHumanHandoffUrl(){return this.loadConfig()?.humanHandoffUrl}getFeatureFlags(){return this.loadConfig()?.featureFlags??{}}getFeatureFlag(e){return this.getFeatureFlags()[e]??!1}getSmhaEndpoint(){return this.loadConfig()?.smhaEndpoint}}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((w,S)=>{const f=d.put({id:"latest",code:e,version:t,checksum:i,signature:n,timestamp:Date.now()});f.onsuccess=()=>w(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 C(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 g(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 b(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 D(r,e,t){try{const i=g(r),n=b(e),o=g(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 A(r,e,t,i){if(!e||!t)throw new Error("SDK verification failed: Missing security headers");if(await C(r)!==e)throw new Error("SDK verification failed: Checksum mismatch - content tampered");if(!await D(i,e,t))throw new Error("SDK verification failed: Invalid signature - content tampered")}class v{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 A(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,autoShowBubble:!1};class B{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 v,this.configValidator=new x,this.sdkConfigStore=new E,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 w=t?e:this.createInitializationPayload(d,i);if(!await this.scriptExecutor.executeSDK(a.code)||!this.initializeSDK(w))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{}}showBubble(e){try{this.isLoaded&&this.isSDKAvailable()?window.Deway?.showBubble(e):this.commandQueue.queueCommand("showBubble",e)}catch{}}hideBubble(){try{this.isLoaded&&this.isSDKAvailable()?window.Deway?.hideBubble():this.commandQueue.queueCommand("hideBubble")}catch{}}isBubbleVisible(){try{return this.isLoaded&&this.isSDKAvailable()?window.Deway?.isBubbleVisible()??!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 B,p={init:r=>c.init(r),identify:r=>c.identify(r),reportEvent:(r,e)=>c.reportEvent(r,e),setUserProfile:r=>c.setUserProfile(r),showBubble:r=>c.showBubble(r),hideBubble:()=>c.hideBubble(),isBubbleVisible:()=>c.isBubbleVisible(),destroy:()=>c.destroy()};return typeof window<"u"&&(window.Deway=p),p}));
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@deway-ai/web-sdk",
|
|
3
|
-
"version": "0.
|
|
3
|
+
"version": "0.37.0",
|
|
4
4
|
"type": "module",
|
|
5
5
|
"description": "Deway's Web SDK",
|
|
6
6
|
"main": "dist/loader.umd.js",
|
|
@@ -17,47 +17,6 @@
|
|
|
17
17
|
"dist/loader.*",
|
|
18
18
|
"dist/backend.*"
|
|
19
19
|
],
|
|
20
|
-
"scripts": {
|
|
21
|
-
"build:iframe": "node scripts/build-deway-bubble-iframe-bundle.js && node scripts/build-options-menu-iframe-bundle.js && node scripts/build-page-guide-iframe-bundle.js",
|
|
22
|
-
"build:iframe:dev": "node scripts/build-deway-bubble-iframe-bundle.js --dev && node scripts/build-options-menu-iframe-bundle.js --dev && node scripts/build-page-guide-iframe-bundle.js --dev",
|
|
23
|
-
"build:iframe:prod": "node scripts/build-deway-bubble-iframe-bundle.js && node scripts/build-options-menu-iframe-bundle.js && node scripts/build-page-guide-iframe-bundle.js",
|
|
24
|
-
"build:loader:dev": "vite build --config vite.config.loader.ts --mode development",
|
|
25
|
-
"build:loader:prod": "vite build --config vite.config.loader.ts --mode production",
|
|
26
|
-
"prebuild:backend:dev": "pnpm build:iframe:dev",
|
|
27
|
-
"build:backend:dev": "vite build --config vite.config.backend.ts --mode development",
|
|
28
|
-
"prebuild:backend:prod": "pnpm build:iframe:prod",
|
|
29
|
-
"build:backend:prod": "vite build --config vite.config.backend.ts --mode production",
|
|
30
|
-
"build:dev": "pnpm build:loader:dev && pnpm build:backend:dev",
|
|
31
|
-
"build:prod": "pnpm build:loader:prod && pnpm build:backend:prod",
|
|
32
|
-
"deploy:test": "node scripts/deploy-to-dev-env.js test",
|
|
33
|
-
"deploy:alon": "node scripts/deploy-to-dev-env.js alon",
|
|
34
|
-
"deploy:noy": "node scripts/deploy-to-dev-env.js noy",
|
|
35
|
-
"deploy:demo": "node scripts/deploy-to-dev-env.js demo",
|
|
36
|
-
"preserve:test": "pnpm deploy:test",
|
|
37
|
-
"serve:test": "http-server . -p 2999 -c-1 -o /demo-site/?env=test",
|
|
38
|
-
"preserve:alon": "pnpm deploy:alon",
|
|
39
|
-
"serve:alon": "http-server . -p 2999 -c-1 -o /demo-site/?env=alon",
|
|
40
|
-
"preserve:noy": "pnpm deploy:noy",
|
|
41
|
-
"serve:noy": "http-server . -p 2999 -c-1 -o /demo-site/?env=noy",
|
|
42
|
-
"preserve:demo": "pnpm deploy:demo",
|
|
43
|
-
"serve:demo": "http-server . -p 2999 -c-1 -o /demo-site/?env=demo",
|
|
44
|
-
"preserve:extension": "node ./scripts/version-burning.js && pnpm build:prod",
|
|
45
|
-
"serve:extension": "http-server . -p 2999 -c-1",
|
|
46
|
-
"postserve:extension": "node ./scripts/version-burning.js",
|
|
47
|
-
"preserve:prod": "node ./scripts/version-burning.js && pnpm build:prod",
|
|
48
|
-
"serve:prod": "http-server . -p 2999 -c-1",
|
|
49
|
-
"postserve:prod": "node ./scripts/version-burning.js",
|
|
50
|
-
"lint": "biome check --write .",
|
|
51
|
-
"typecheck:tests": "tsc --noEmit --project tsconfig.tests.json",
|
|
52
|
-
"test:unit": "vitest run --coverage --config vitest.config.ts",
|
|
53
|
-
"check": "pnpm lint && pnpm typecheck:tests && pnpm test:unit",
|
|
54
|
-
"test:e2e:ui": "TEST_ENV=noy playwright test --ui",
|
|
55
|
-
"test:e2e:debug": "TEST_ENV=noy playwright test --debug",
|
|
56
|
-
"test:e2e:headed": "TEST_ENV=noy playwright test --headed",
|
|
57
|
-
"test:e2e:test": "TEST_ENV=test playwright test",
|
|
58
|
-
"test:e2e:alon": "TEST_ENV=alon playwright test",
|
|
59
|
-
"test:e2e:noy": "TEST_ENV=noy playwright test"
|
|
60
|
-
},
|
|
61
20
|
"keywords": [
|
|
62
21
|
"walkthrough",
|
|
63
22
|
"guide",
|
|
@@ -73,38 +32,7 @@
|
|
|
73
32
|
"type": "git",
|
|
74
33
|
"url": "git+https://github.com/Deway-AI/deway-web-sdk.git"
|
|
75
34
|
},
|
|
76
|
-
"dependencies": {
|
|
77
|
-
"markdown-it": "^14.1.0",
|
|
78
|
-
"pako": "^2.1.0"
|
|
79
|
-
},
|
|
80
|
-
"devDependencies": {
|
|
81
|
-
"@aws-sdk/client-cloudwatch-logs": "^3.919.0",
|
|
82
|
-
"@aws-sdk/client-s3": "^3.925.0",
|
|
83
|
-
"@axe-core/playwright": "^4.11.0",
|
|
84
|
-
"@biomejs/biome": "^2.2.4",
|
|
85
|
-
"@faker-js/faker": "^10.0.0",
|
|
86
|
-
"@playwright/test": "^1.55.1",
|
|
87
|
-
"@types/jsdom": "^21.1.7",
|
|
88
|
-
"@types/markdown-it": "^14.1.2",
|
|
89
|
-
"@types/node": "^22.18.1",
|
|
90
|
-
"@types/pako": "^2.0.4",
|
|
91
|
-
"@vitest/coverage-v8": "^3.2.4",
|
|
92
|
-
"axe-core": "^4.11.0",
|
|
93
|
-
"fishery": "^2.3.1",
|
|
94
|
-
"http-server": "^14.1.1",
|
|
95
|
-
"jsdom": "^26.1.0",
|
|
96
|
-
"ky": "^1.11.0",
|
|
97
|
-
"p-event": "^7.0.0",
|
|
98
|
-
"p-timeout": "^7.0.1",
|
|
99
|
-
"ts-node": "^10.9.2",
|
|
100
|
-
"typescript": "^5.9.2",
|
|
101
|
-
"vite": "7.1.11",
|
|
102
|
-
"vite-plugin-dts": "^4.5.4",
|
|
103
|
-
"vitest": "^3.2.4",
|
|
104
|
-
"zod": "^4.1.12"
|
|
105
|
-
},
|
|
106
35
|
"engines": {
|
|
107
36
|
"node": ">=22.0.0"
|
|
108
|
-
}
|
|
109
|
-
|
|
110
|
-
}
|
|
37
|
+
}
|
|
38
|
+
}
|