@deflectbot/deflect-sdk 1.3.0 → 1.3.2
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.js +167 -199
- package/dist/index.min.js +1 -0
- package/package.json +9 -7
- package/.gitattributes +0 -2
- package/dist/deflect.global.min.js +0 -1
- package/dist/global.js +0 -7
- package/dist/types/global.d.ts +0 -7
- package/dist/types/index.d.ts +0 -35
- package/eslint.config.mjs +0 -12
- package/src/global.ts +0 -18
- package/src/index.ts +0 -238
- package/src/types/window.d.ts +0 -6
- package/tsconfig.json +0 -22
package/dist/index.js
CHANGED
|
@@ -1,226 +1,194 @@
|
|
|
1
|
-
|
|
2
|
-
|
|
3
|
-
|
|
4
|
-
|
|
5
|
-
|
|
6
|
-
|
|
7
|
-
|
|
8
|
-
});
|
|
9
|
-
};
|
|
10
|
-
class Deflect {
|
|
1
|
+
"use strict";
|
|
2
|
+
(() => {
|
|
3
|
+
var __defProp = Object.defineProperty;
|
|
4
|
+
var __name = (target, value) => __defProp(target, "name", { value, configurable: true });
|
|
5
|
+
|
|
6
|
+
// src/index.ts
|
|
7
|
+
var Deflect = class {
|
|
11
8
|
constructor() {
|
|
12
|
-
|
|
13
|
-
|
|
14
|
-
|
|
15
|
-
|
|
16
|
-
|
|
9
|
+
this.config = null;
|
|
10
|
+
this.scriptCache = null;
|
|
11
|
+
this.isWarmupInProgress = false;
|
|
12
|
+
this.initializeGlobalState();
|
|
13
|
+
this.setupAutomaticWarmup();
|
|
14
|
+
}
|
|
15
|
+
static {
|
|
16
|
+
__name(this, "Deflect");
|
|
17
17
|
}
|
|
18
18
|
initializeGlobalState() {
|
|
19
|
-
|
|
20
|
-
|
|
21
|
-
window.Deflect = window.Deflect || {};
|
|
19
|
+
if (typeof window === "undefined") return;
|
|
20
|
+
window.Deflect = window.Deflect || {};
|
|
22
21
|
}
|
|
23
22
|
setupAutomaticWarmup() {
|
|
24
|
-
|
|
25
|
-
|
|
26
|
-
|
|
27
|
-
|
|
28
|
-
|
|
29
|
-
|
|
30
|
-
|
|
31
|
-
|
|
32
|
-
|
|
33
|
-
|
|
34
|
-
|
|
35
|
-
|
|
36
|
-
|
|
37
|
-
|
|
38
|
-
|
|
39
|
-
|
|
40
|
-
|
|
41
|
-
|
|
42
|
-
}
|
|
43
|
-
catch (_b) {
|
|
44
|
-
/* empty */
|
|
45
|
-
}
|
|
46
|
-
finally {
|
|
47
|
-
this.isWarmupInProgress = false;
|
|
48
|
-
}
|
|
49
|
-
});
|
|
23
|
+
if (typeof window === "undefined") return;
|
|
24
|
+
if (document.readyState === "loading") {
|
|
25
|
+
document.addEventListener("DOMContentLoaded", () => this.tryWarmup());
|
|
26
|
+
} else {
|
|
27
|
+
setTimeout(() => this.tryWarmup(), 100);
|
|
28
|
+
}
|
|
29
|
+
}
|
|
30
|
+
async tryWarmup() {
|
|
31
|
+
if (!this.config?.actionId || this.isWarmupInProgress || this.scriptCache) {
|
|
32
|
+
return;
|
|
33
|
+
}
|
|
34
|
+
this.isWarmupInProgress = true;
|
|
35
|
+
try {
|
|
36
|
+
this.scriptCache = await this.fetchScript();
|
|
37
|
+
} catch {
|
|
38
|
+
} finally {
|
|
39
|
+
this.isWarmupInProgress = false;
|
|
40
|
+
}
|
|
50
41
|
}
|
|
51
42
|
buildScriptUrl(actionId) {
|
|
52
|
-
|
|
53
|
-
|
|
54
|
-
|
|
55
|
-
|
|
56
|
-
|
|
57
|
-
|
|
58
|
-
|
|
59
|
-
|
|
60
|
-
|
|
61
|
-
|
|
62
|
-
|
|
63
|
-
|
|
64
|
-
|
|
65
|
-
|
|
66
|
-
|
|
67
|
-
|
|
68
|
-
|
|
69
|
-
|
|
70
|
-
|
|
71
|
-
|
|
72
|
-
|
|
73
|
-
|
|
74
|
-
|
|
75
|
-
|
|
76
|
-
|
|
77
|
-
|
|
78
|
-
|
|
79
|
-
|
|
80
|
-
|
|
81
|
-
|
|
82
|
-
|
|
83
|
-
|
|
84
|
-
|
|
85
|
-
try {
|
|
86
|
-
yield readyPromise;
|
|
87
|
-
const token = yield this.getTokenFromScript();
|
|
88
|
-
this.prefetchNextScript();
|
|
89
|
-
return token;
|
|
90
|
-
}
|
|
91
|
-
finally {
|
|
92
|
-
this.cleanup(blobUrl, scriptElement);
|
|
93
|
-
}
|
|
94
|
-
});
|
|
43
|
+
const baseUrl = this.config?.scriptUrl || "https://js.deflect.bot/main.js";
|
|
44
|
+
const nonce = Date.now().toString();
|
|
45
|
+
return `${baseUrl}?action_id=${actionId}&_=${nonce}`;
|
|
46
|
+
}
|
|
47
|
+
async fetchScript() {
|
|
48
|
+
if (!this.config?.actionId) {
|
|
49
|
+
throw new Error("actionId is required");
|
|
50
|
+
}
|
|
51
|
+
const url = this.buildScriptUrl(this.config.actionId);
|
|
52
|
+
const response = await fetch(url, { cache: "no-store" });
|
|
53
|
+
if (!response.ok) {
|
|
54
|
+
throw new Error(`Failed to fetch script: ${response.status}`);
|
|
55
|
+
}
|
|
56
|
+
return {
|
|
57
|
+
content: await response.text(),
|
|
58
|
+
sessionId: response.headers.get("session_id") || void 0
|
|
59
|
+
};
|
|
60
|
+
}
|
|
61
|
+
async executeScript(script) {
|
|
62
|
+
if (script.sessionId && typeof window !== "undefined") {
|
|
63
|
+
window.Deflect.sessionId = script.sessionId;
|
|
64
|
+
}
|
|
65
|
+
const readyPromise = this.createReadyPromise();
|
|
66
|
+
const blobUrl = this.createScriptBlob(script.content);
|
|
67
|
+
const scriptElement = await this.loadScriptElement(blobUrl);
|
|
68
|
+
try {
|
|
69
|
+
await readyPromise;
|
|
70
|
+
const token = await this.getTokenFromScript();
|
|
71
|
+
this.prefetchNextScript();
|
|
72
|
+
return token;
|
|
73
|
+
} finally {
|
|
74
|
+
this.cleanup(blobUrl, scriptElement);
|
|
75
|
+
}
|
|
95
76
|
}
|
|
96
77
|
prefetchNextScript() {
|
|
97
|
-
|
|
78
|
+
this.tryWarmup().catch(() => {
|
|
79
|
+
});
|
|
98
80
|
}
|
|
99
81
|
createReadyPromise() {
|
|
100
|
-
|
|
101
|
-
|
|
102
|
-
|
|
103
|
-
|
|
104
|
-
|
|
105
|
-
|
|
106
|
-
|
|
107
|
-
|
|
108
|
-
|
|
109
|
-
|
|
82
|
+
return new Promise((resolve) => {
|
|
83
|
+
if (typeof window !== "undefined") {
|
|
84
|
+
window.Deflect.ready = {
|
|
85
|
+
promise: new Promise((innerResolve) => {
|
|
86
|
+
window.Deflect.ready.resolve = innerResolve;
|
|
87
|
+
}),
|
|
88
|
+
resolve: /* @__PURE__ */ __name(() => resolve(), "resolve")
|
|
89
|
+
};
|
|
90
|
+
}
|
|
91
|
+
});
|
|
110
92
|
}
|
|
111
93
|
createScriptBlob(content) {
|
|
112
|
-
|
|
113
|
-
|
|
114
|
-
}
|
|
115
|
-
loadScriptElement(blobUrl) {
|
|
116
|
-
|
|
117
|
-
|
|
118
|
-
|
|
119
|
-
|
|
120
|
-
|
|
121
|
-
|
|
122
|
-
|
|
123
|
-
|
|
124
|
-
|
|
125
|
-
|
|
126
|
-
|
|
127
|
-
|
|
128
|
-
|
|
129
|
-
|
|
130
|
-
|
|
131
|
-
|
|
132
|
-
|
|
133
|
-
|
|
134
|
-
try {
|
|
135
|
-
return yield window.Deflect.getToken();
|
|
136
|
-
}
|
|
137
|
-
catch (error) {
|
|
138
|
-
throw new Error(`Script execution failed: ${error}`);
|
|
139
|
-
}
|
|
140
|
-
});
|
|
94
|
+
const blob = new Blob([content], { type: "text/javascript" });
|
|
95
|
+
return URL.createObjectURL(blob);
|
|
96
|
+
}
|
|
97
|
+
async loadScriptElement(blobUrl) {
|
|
98
|
+
return new Promise((resolve, reject) => {
|
|
99
|
+
const script = document.createElement("script");
|
|
100
|
+
script.type = "module";
|
|
101
|
+
script.src = blobUrl;
|
|
102
|
+
script.onload = () => resolve(script);
|
|
103
|
+
script.onerror = () => reject(new Error("Script failed to load"));
|
|
104
|
+
document.head.appendChild(script);
|
|
105
|
+
});
|
|
106
|
+
}
|
|
107
|
+
async getTokenFromScript() {
|
|
108
|
+
if (typeof window === "undefined" || typeof window.Deflect?.getToken !== "function") {
|
|
109
|
+
throw new Error("Script did not load properly - getToken not available");
|
|
110
|
+
}
|
|
111
|
+
try {
|
|
112
|
+
return await window.Deflect.getToken();
|
|
113
|
+
} catch (error) {
|
|
114
|
+
throw new Error(`Script execution failed: ${error}`);
|
|
115
|
+
}
|
|
141
116
|
}
|
|
142
117
|
cleanup(blobUrl, scriptElement) {
|
|
143
|
-
|
|
144
|
-
|
|
145
|
-
|
|
146
|
-
|
|
147
|
-
|
|
148
|
-
}
|
|
118
|
+
URL.revokeObjectURL(blobUrl);
|
|
119
|
+
scriptElement.remove();
|
|
120
|
+
if (typeof window !== "undefined" && window.Deflect?.getToken) {
|
|
121
|
+
delete window.Deflect.getToken;
|
|
122
|
+
}
|
|
149
123
|
}
|
|
150
124
|
configure(params) {
|
|
151
|
-
|
|
152
|
-
|
|
153
|
-
|
|
154
|
-
|
|
155
|
-
|
|
156
|
-
|
|
157
|
-
|
|
158
|
-
|
|
159
|
-
this.tryWarmup();
|
|
125
|
+
if (!params.actionId?.trim()) {
|
|
126
|
+
throw new Error("actionId is required and cannot be empty");
|
|
127
|
+
}
|
|
128
|
+
this.config = { ...params };
|
|
129
|
+
if (typeof window !== "undefined") {
|
|
130
|
+
window.Deflect.actionId = params.actionId;
|
|
131
|
+
}
|
|
132
|
+
this.tryWarmup();
|
|
160
133
|
}
|
|
161
134
|
// Deprecated name kept for backward compatibility
|
|
162
|
-
solveChallenge() {
|
|
163
|
-
|
|
164
|
-
|
|
165
|
-
|
|
166
|
-
|
|
167
|
-
|
|
168
|
-
|
|
169
|
-
|
|
170
|
-
|
|
171
|
-
|
|
172
|
-
|
|
173
|
-
|
|
174
|
-
|
|
175
|
-
|
|
176
|
-
|
|
177
|
-
|
|
178
|
-
|
|
179
|
-
|
|
180
|
-
|
|
181
|
-
|
|
182
|
-
|
|
183
|
-
|
|
184
|
-
|
|
185
|
-
|
|
186
|
-
|
|
187
|
-
|
|
188
|
-
return false;
|
|
189
|
-
}
|
|
190
|
-
try {
|
|
191
|
-
yield this.tryWarmup();
|
|
192
|
-
return this.scriptCache !== null;
|
|
193
|
-
}
|
|
194
|
-
catch (_b) {
|
|
195
|
-
return false;
|
|
196
|
-
}
|
|
197
|
-
});
|
|
135
|
+
async solveChallenge() {
|
|
136
|
+
return this.getToken();
|
|
137
|
+
}
|
|
138
|
+
async getToken() {
|
|
139
|
+
if (!this.config?.actionId) {
|
|
140
|
+
throw new Error("Must call configure() before solveChallenge()");
|
|
141
|
+
}
|
|
142
|
+
let script;
|
|
143
|
+
if (this.scriptCache && !this.isWarmupInProgress) {
|
|
144
|
+
script = this.scriptCache;
|
|
145
|
+
this.scriptCache = null;
|
|
146
|
+
} else {
|
|
147
|
+
script = await this.fetchScript();
|
|
148
|
+
}
|
|
149
|
+
return this.executeScript(script);
|
|
150
|
+
}
|
|
151
|
+
async warmup() {
|
|
152
|
+
if (!this.config?.actionId) {
|
|
153
|
+
return false;
|
|
154
|
+
}
|
|
155
|
+
try {
|
|
156
|
+
await this.tryWarmup();
|
|
157
|
+
return this.scriptCache !== null;
|
|
158
|
+
} catch {
|
|
159
|
+
return false;
|
|
160
|
+
}
|
|
198
161
|
}
|
|
199
162
|
clearCache() {
|
|
200
|
-
|
|
163
|
+
this.scriptCache = null;
|
|
201
164
|
}
|
|
202
165
|
/**
|
|
203
166
|
* Inject a fresh token as a hidden input into a form. Only accepts a submit event from onsubmit.
|
|
204
167
|
* Usage: <form ... onsubmit="return Deflect.injectToken(event)">
|
|
205
168
|
* Returns false to prevent double submit.
|
|
206
169
|
*/
|
|
207
|
-
injectToken(event) {
|
|
208
|
-
|
|
209
|
-
|
|
210
|
-
|
|
211
|
-
|
|
212
|
-
|
|
213
|
-
|
|
214
|
-
|
|
215
|
-
|
|
216
|
-
|
|
217
|
-
|
|
218
|
-
|
|
219
|
-
|
|
220
|
-
|
|
221
|
-
|
|
222
|
-
|
|
223
|
-
|
|
224
|
-
}
|
|
225
|
-
}
|
|
226
|
-
|
|
170
|
+
async injectToken(event) {
|
|
171
|
+
if (!event || !event.target || !(event.target instanceof HTMLFormElement)) {
|
|
172
|
+
throw new Error("injectToken: must be called from a form submit event");
|
|
173
|
+
}
|
|
174
|
+
event.preventDefault();
|
|
175
|
+
const form = event.target;
|
|
176
|
+
const token = await this.getToken();
|
|
177
|
+
Array.from(form.querySelectorAll('input[name="deflect_token"]')).forEach(
|
|
178
|
+
(el) => el.remove()
|
|
179
|
+
);
|
|
180
|
+
const hidden = document.createElement("input");
|
|
181
|
+
hidden.type = "hidden";
|
|
182
|
+
hidden.name = "deflect_token";
|
|
183
|
+
hidden.value = token;
|
|
184
|
+
form.appendChild(hidden);
|
|
185
|
+
form.submit();
|
|
186
|
+
return false;
|
|
187
|
+
}
|
|
188
|
+
};
|
|
189
|
+
var DeflectInstance = new Deflect();
|
|
190
|
+
if (typeof window !== "undefined") {
|
|
191
|
+
window.Deflect = DeflectInstance;
|
|
192
|
+
}
|
|
193
|
+
var src_default = DeflectInstance;
|
|
194
|
+
})();
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
"use strict";(()=>{var o=class{constructor(){this.config=null;this.scriptCache=null;this.isWarmupInProgress=!1;this.initializeGlobalState(),this.setupAutomaticWarmup()}initializeGlobalState(){typeof window>"u"||(window.Deflect=window.Deflect||{})}setupAutomaticWarmup(){typeof window>"u"||(document.readyState==="loading"?document.addEventListener("DOMContentLoaded",()=>this.tryWarmup()):setTimeout(()=>this.tryWarmup(),100))}async tryWarmup(){if(!(!this.config?.actionId||this.isWarmupInProgress||this.scriptCache)){this.isWarmupInProgress=!0;try{this.scriptCache=await this.fetchScript()}catch{}finally{this.isWarmupInProgress=!1}}}buildScriptUrl(e){let t=this.config?.scriptUrl||"https://js.deflect.bot/main.js",r=Date.now().toString();return`${t}?action_id=${e}&_=${r}`}async fetchScript(){if(!this.config?.actionId)throw new Error("actionId is required");let e=this.buildScriptUrl(this.config.actionId),t=await fetch(e,{cache:"no-store"});if(!t.ok)throw new Error(`Failed to fetch script: ${t.status}`);return{content:await t.text(),sessionId:t.headers.get("session_id")||void 0}}async executeScript(e){e.sessionId&&typeof window<"u"&&(window.Deflect.sessionId=e.sessionId);let t=this.createReadyPromise(),r=this.createScriptBlob(e.content),i=await this.loadScriptElement(r);try{await t;let n=await this.getTokenFromScript();return this.prefetchNextScript(),n}finally{this.cleanup(r,i)}}prefetchNextScript(){this.tryWarmup().catch(()=>{})}createReadyPromise(){return new Promise(e=>{typeof window<"u"&&(window.Deflect.ready={promise:new Promise(t=>{window.Deflect.ready.resolve=t}),resolve:()=>e()})})}createScriptBlob(e){let t=new Blob([e],{type:"text/javascript"});return URL.createObjectURL(t)}async loadScriptElement(e){return new Promise((t,r)=>{let i=document.createElement("script");i.type="module",i.src=e,i.onload=()=>t(i),i.onerror=()=>r(new Error("Script failed to load")),document.head.appendChild(i)})}async getTokenFromScript(){if(typeof window>"u"||typeof window.Deflect?.getToken!="function")throw new Error("Script did not load properly - getToken not available");try{return await window.Deflect.getToken()}catch(e){throw new Error(`Script execution failed: ${e}`)}}cleanup(e,t){URL.revokeObjectURL(e),t.remove(),typeof window<"u"&&window.Deflect?.getToken&&delete window.Deflect.getToken}configure(e){if(!e.actionId?.trim())throw new Error("actionId is required and cannot be empty");this.config={...e},typeof window<"u"&&(window.Deflect.actionId=e.actionId),this.tryWarmup()}async solveChallenge(){return this.getToken()}async getToken(){if(!this.config?.actionId)throw new Error("Must call configure() before solveChallenge()");let e;return this.scriptCache&&!this.isWarmupInProgress?(e=this.scriptCache,this.scriptCache=null):e=await this.fetchScript(),this.executeScript(e)}async warmup(){if(!this.config?.actionId)return!1;try{return await this.tryWarmup(),this.scriptCache!==null}catch{return!1}}clearCache(){this.scriptCache=null}async injectToken(e){if(!e||!e.target||!(e.target instanceof HTMLFormElement))throw new Error("injectToken: must be called from a form submit event");e.preventDefault();let t=e.target,r=await this.getToken();Array.from(t.querySelectorAll('input[name="deflect_token"]')).forEach(n=>n.remove());let i=document.createElement("input");return i.type="hidden",i.name="deflect_token",i.value=r,t.appendChild(i),t.submit(),!1}},c=new o;typeof window<"u"&&(window.Deflect=c);var a=c;})();
|
package/package.json
CHANGED
|
@@ -1,12 +1,15 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@deflectbot/deflect-sdk",
|
|
3
|
-
"version": "1.3.
|
|
3
|
+
"version": "1.3.2",
|
|
4
4
|
"description": "SDK for deflect.bot - Use it for seamless captcha integration on any website.",
|
|
5
|
-
"main": "dist/index.js",
|
|
6
|
-
"
|
|
5
|
+
"main": "dist/index.min.js",
|
|
6
|
+
"unpkg": "dist/index.min.js",
|
|
7
|
+
"jsdelivr": "dist/index.min.js",
|
|
8
|
+
"files": [
|
|
9
|
+
"dist/**/*"
|
|
10
|
+
],
|
|
7
11
|
"scripts": {
|
|
8
|
-
"build": "
|
|
9
|
-
"build:global": "esbuild src/global.ts --bundle --format=iife --global-name=Deflect --minify --outfile=dist/deflect.global.min.js"
|
|
12
|
+
"build": "esbuild src/index.ts --bundle --format=iife --outfile=dist/index.js --keep-names && esbuild src/index.ts --bundle --format=iife --minify --outfile=dist/index.min.js"
|
|
10
13
|
},
|
|
11
14
|
"author": "Deflect",
|
|
12
15
|
"license": "MIT",
|
|
@@ -20,6 +23,5 @@
|
|
|
20
23
|
},
|
|
21
24
|
"publishConfig": {
|
|
22
25
|
"access": "public"
|
|
23
|
-
}
|
|
24
|
-
"dependencies": {}
|
|
26
|
+
}
|
|
25
27
|
}
|
package/.gitattributes
DELETED
|
@@ -1 +0,0 @@
|
|
|
1
|
-
"use strict";var Deflect=(()=>{var c=Object.defineProperty;var l=Object.getOwnPropertyDescriptor;var d=Object.getOwnPropertyNames;var p=Object.prototype.hasOwnProperty;var f=(n,e)=>{for(var t in e)c(n,t,{get:e[t],enumerable:!0})},u=(n,e,t,r)=>{if(e&&typeof e=="object"||typeof e=="function")for(let i of d(e))!p.call(n,i)&&i!==t&&c(n,i,{get:()=>e[i],enumerable:!(r=l(e,i))||r.enumerable});return n};var h=n=>u(c({},"__esModule",{value:!0}),n);var m={};f(m,{default:()=>w});var s=class{constructor(){this.config=null;this.scriptCache=null;this.isWarmupInProgress=!1;this.initializeGlobalState(),this.setupAutomaticWarmup()}initializeGlobalState(){typeof window>"u"||(window.Deflect=window.Deflect||{})}setupAutomaticWarmup(){typeof window>"u"||(document.readyState==="loading"?document.addEventListener("DOMContentLoaded",()=>this.tryWarmup()):setTimeout(()=>this.tryWarmup(),100))}async tryWarmup(){if(!(!this.config?.actionId||this.isWarmupInProgress||this.scriptCache)){this.isWarmupInProgress=!0;try{this.scriptCache=await this.fetchScript()}catch{}finally{this.isWarmupInProgress=!1}}}buildScriptUrl(e){let t=this.config?.scriptUrl||"https://js.deflect.bot/main.js";if(this.config?.scriptUrl)return t;let r=Date.now().toString();return`${t}?action_id=${e}&_=${r}`}async fetchScript(){if(!this.config?.actionId)throw new Error("actionId is required");let e=this.buildScriptUrl(this.config.actionId),t=await fetch(e,{cache:"no-store"});if(!t.ok)throw new Error(`Failed to fetch script: ${t.status}`);return{content:await t.text(),sessionId:t.headers.get("session_id")||void 0}}async executeScript(e){e.sessionId&&typeof window<"u"&&(window.Deflect.sessionId=e.sessionId);let t=this.createReadyPromise(),r=this.createScriptBlob(e.content),i=await this.loadScriptElement(r);try{await t;let o=await this.getTokenFromScript();return this.prefetchNextScript(),o}finally{this.cleanup(r,i)}}prefetchNextScript(){this.tryWarmup().catch(()=>{})}createReadyPromise(){return new Promise(e=>{typeof window<"u"&&(window.Deflect.ready={promise:new Promise(t=>{window.Deflect.ready.resolve=t}),resolve:()=>e()})})}createScriptBlob(e){let t=new Blob([e],{type:"text/javascript"});return URL.createObjectURL(t)}async loadScriptElement(e){return new Promise((t,r)=>{let i=document.createElement("script");i.type="module",i.src=e,i.onload=()=>t(i),i.onerror=()=>r(new Error("Script failed to load")),document.head.appendChild(i)})}async getTokenFromScript(){if(typeof window>"u"||typeof window.Deflect?.getToken!="function")throw new Error("Script did not load properly - getToken not available");try{return await window.Deflect.getToken()}catch(e){throw new Error(`Script execution failed: ${e}`)}}cleanup(e,t){URL.revokeObjectURL(e),t.remove(),typeof window<"u"&&window.Deflect?.getToken&&delete window.Deflect.getToken}configure(e){if(!e.actionId?.trim())throw new Error("actionId is required and cannot be empty");this.config={...e},typeof window<"u"&&(window.Deflect.actionId=e.actionId),this.tryWarmup()}async solveChallenge(){return this.getToken()}async getToken(){if(!this.config?.actionId)throw new Error("Must call configure() before solveChallenge()");let e;return this.scriptCache&&!this.isWarmupInProgress?(e=this.scriptCache,this.scriptCache=null):e=await this.fetchScript(),this.executeScript(e)}async warmup(){if(!this.config?.actionId)return!1;try{return await this.tryWarmup(),this.scriptCache!==null}catch{return!1}}clearCache(){this.scriptCache=null}async injectToken(e){if(!e||!e.target||!(e.target instanceof HTMLFormElement))throw new Error("injectToken: must be called from a form submit event");e.preventDefault();let t=e.target,r=await this.getToken();Array.from(t.querySelectorAll('input[name="deflect_token"]')).forEach(o=>o.remove());let i=document.createElement("input");return i.type="hidden",i.name="deflect_token",i.value=r,t.appendChild(i),t.submit(),!1}},a=new s;typeof window<"u"&&(window.Deflect=a);var w=a;return h(m);})();
|
package/dist/global.js
DELETED
|
@@ -1,7 +0,0 @@
|
|
|
1
|
-
// Re-export the default instance while also assigning it to window.Deflect for non-module usage.
|
|
2
|
-
import DeflectInstance from "./index";
|
|
3
|
-
if (typeof window !== "undefined") {
|
|
4
|
-
// Avoid overwriting if a user already attached something custom.
|
|
5
|
-
window.Deflect = DeflectInstance;
|
|
6
|
-
}
|
|
7
|
-
export default DeflectInstance;
|
package/dist/types/global.d.ts
DELETED
package/dist/types/index.d.ts
DELETED
|
@@ -1,35 +0,0 @@
|
|
|
1
|
-
interface DeflectConfig {
|
|
2
|
-
actionId: string;
|
|
3
|
-
scriptUrl?: string;
|
|
4
|
-
}
|
|
5
|
-
declare class Deflect {
|
|
6
|
-
private config;
|
|
7
|
-
private scriptCache;
|
|
8
|
-
private isWarmupInProgress;
|
|
9
|
-
constructor();
|
|
10
|
-
private initializeGlobalState;
|
|
11
|
-
private setupAutomaticWarmup;
|
|
12
|
-
private tryWarmup;
|
|
13
|
-
private buildScriptUrl;
|
|
14
|
-
private fetchScript;
|
|
15
|
-
private executeScript;
|
|
16
|
-
private prefetchNextScript;
|
|
17
|
-
private createReadyPromise;
|
|
18
|
-
private createScriptBlob;
|
|
19
|
-
private loadScriptElement;
|
|
20
|
-
private getTokenFromScript;
|
|
21
|
-
private cleanup;
|
|
22
|
-
configure(params: DeflectConfig): void;
|
|
23
|
-
solveChallenge(): Promise<string>;
|
|
24
|
-
getToken(): Promise<string>;
|
|
25
|
-
warmup(): Promise<boolean>;
|
|
26
|
-
clearCache(): void;
|
|
27
|
-
/**
|
|
28
|
-
* Inject a fresh token as a hidden input into a form. Only accepts a submit event from onsubmit.
|
|
29
|
-
* Usage: <form ... onsubmit="return Deflect.injectToken(event)">
|
|
30
|
-
* Returns false to prevent double submit.
|
|
31
|
-
*/
|
|
32
|
-
injectToken(event: SubmitEvent): Promise<false>;
|
|
33
|
-
}
|
|
34
|
-
declare const _default: Deflect;
|
|
35
|
-
export default _default;
|
package/eslint.config.mjs
DELETED
|
@@ -1,12 +0,0 @@
|
|
|
1
|
-
import globals from "globals";
|
|
2
|
-
import pluginJs from "@eslint/js";
|
|
3
|
-
import tseslint from "typescript-eslint";
|
|
4
|
-
|
|
5
|
-
|
|
6
|
-
/** @type {import('eslint').Linter.Config[]} */
|
|
7
|
-
export default [
|
|
8
|
-
{files: ["**/*.{js,mjs,cjs,ts}"]},
|
|
9
|
-
{languageOptions: { globals: globals.browser }},
|
|
10
|
-
pluginJs.configs.recommended,
|
|
11
|
-
...tseslint.configs.recommended,
|
|
12
|
-
];
|
package/src/global.ts
DELETED
|
@@ -1,18 +0,0 @@
|
|
|
1
|
-
// Re-export the default instance while also assigning it to window.Deflect for non-module usage.
|
|
2
|
-
import DeflectInstance from "./index";
|
|
3
|
-
|
|
4
|
-
// Ensure side effects (constructor) already ran on import.
|
|
5
|
-
// Attach to window for classic script tag usage.
|
|
6
|
-
declare global {
|
|
7
|
-
interface Window {
|
|
8
|
-
// eslint-disable-next-line @typescript-eslint/no-explicit-any -- SDK attaches dynamic shape at runtime
|
|
9
|
-
Deflect: any;
|
|
10
|
-
}
|
|
11
|
-
}
|
|
12
|
-
|
|
13
|
-
if (typeof window !== "undefined") {
|
|
14
|
-
// Avoid overwriting if a user already attached something custom.
|
|
15
|
-
window.Deflect = DeflectInstance;
|
|
16
|
-
}
|
|
17
|
-
|
|
18
|
-
export default DeflectInstance;
|
package/src/index.ts
DELETED
|
@@ -1,238 +0,0 @@
|
|
|
1
|
-
interface DeflectConfig {
|
|
2
|
-
actionId: string;
|
|
3
|
-
scriptUrl?: string;
|
|
4
|
-
}
|
|
5
|
-
|
|
6
|
-
interface DeflectScript {
|
|
7
|
-
sessionId?: string;
|
|
8
|
-
content: string;
|
|
9
|
-
}
|
|
10
|
-
|
|
11
|
-
class Deflect {
|
|
12
|
-
private config: DeflectConfig | null = null;
|
|
13
|
-
private scriptCache: DeflectScript | null = null;
|
|
14
|
-
private isWarmupInProgress = false;
|
|
15
|
-
|
|
16
|
-
constructor() {
|
|
17
|
-
this.initializeGlobalState();
|
|
18
|
-
this.setupAutomaticWarmup();
|
|
19
|
-
}
|
|
20
|
-
|
|
21
|
-
private initializeGlobalState(): void {
|
|
22
|
-
if (typeof window === "undefined") return;
|
|
23
|
-
window.Deflect = window.Deflect || {};
|
|
24
|
-
}
|
|
25
|
-
|
|
26
|
-
private setupAutomaticWarmup(): void {
|
|
27
|
-
if (typeof window === "undefined") return;
|
|
28
|
-
|
|
29
|
-
if (document.readyState === "loading") {
|
|
30
|
-
document.addEventListener("DOMContentLoaded", () => this.tryWarmup());
|
|
31
|
-
} else {
|
|
32
|
-
setTimeout(() => this.tryWarmup(), 100);
|
|
33
|
-
}
|
|
34
|
-
}
|
|
35
|
-
|
|
36
|
-
private async tryWarmup(): Promise<void> {
|
|
37
|
-
if (!this.config?.actionId || this.isWarmupInProgress || this.scriptCache) {
|
|
38
|
-
return;
|
|
39
|
-
}
|
|
40
|
-
|
|
41
|
-
this.isWarmupInProgress = true;
|
|
42
|
-
|
|
43
|
-
try {
|
|
44
|
-
this.scriptCache = await this.fetchScript();
|
|
45
|
-
} catch {
|
|
46
|
-
/* empty */
|
|
47
|
-
} finally {
|
|
48
|
-
this.isWarmupInProgress = false;
|
|
49
|
-
}
|
|
50
|
-
}
|
|
51
|
-
|
|
52
|
-
private buildScriptUrl(actionId: string): string {
|
|
53
|
-
const baseUrl = this.config?.scriptUrl || "https://js.deflect.bot/main.js";
|
|
54
|
-
|
|
55
|
-
if (this.config?.scriptUrl) {
|
|
56
|
-
return baseUrl;
|
|
57
|
-
}
|
|
58
|
-
|
|
59
|
-
const nonce = Date.now().toString();
|
|
60
|
-
return `${baseUrl}?action_id=${actionId}&_=${nonce}`;
|
|
61
|
-
}
|
|
62
|
-
|
|
63
|
-
private async fetchScript(): Promise<DeflectScript> {
|
|
64
|
-
if (!this.config?.actionId) {
|
|
65
|
-
throw new Error("actionId is required");
|
|
66
|
-
}
|
|
67
|
-
|
|
68
|
-
const url = this.buildScriptUrl(this.config.actionId);
|
|
69
|
-
const response = await fetch(url, { cache: "no-store" });
|
|
70
|
-
|
|
71
|
-
if (!response.ok) {
|
|
72
|
-
throw new Error(`Failed to fetch script: ${response.status}`);
|
|
73
|
-
}
|
|
74
|
-
|
|
75
|
-
return {
|
|
76
|
-
content: await response.text(),
|
|
77
|
-
sessionId: response.headers.get("session_id") || undefined,
|
|
78
|
-
};
|
|
79
|
-
}
|
|
80
|
-
|
|
81
|
-
private async executeScript(script: DeflectScript): Promise<string> {
|
|
82
|
-
if (script.sessionId && typeof window !== "undefined") {
|
|
83
|
-
window.Deflect.sessionId = script.sessionId;
|
|
84
|
-
}
|
|
85
|
-
|
|
86
|
-
const readyPromise = this.createReadyPromise();
|
|
87
|
-
|
|
88
|
-
const blobUrl = this.createScriptBlob(script.content);
|
|
89
|
-
const scriptElement = await this.loadScriptElement(blobUrl);
|
|
90
|
-
|
|
91
|
-
try {
|
|
92
|
-
await readyPromise;
|
|
93
|
-
|
|
94
|
-
const token = await this.getTokenFromScript();
|
|
95
|
-
|
|
96
|
-
this.prefetchNextScript();
|
|
97
|
-
|
|
98
|
-
return token;
|
|
99
|
-
} finally {
|
|
100
|
-
this.cleanup(blobUrl, scriptElement);
|
|
101
|
-
}
|
|
102
|
-
}
|
|
103
|
-
|
|
104
|
-
private prefetchNextScript(): void {
|
|
105
|
-
this.tryWarmup().catch(() => {});
|
|
106
|
-
}
|
|
107
|
-
|
|
108
|
-
private createReadyPromise(): Promise<void> {
|
|
109
|
-
return new Promise<void>((resolve) => {
|
|
110
|
-
if (typeof window !== "undefined") {
|
|
111
|
-
window.Deflect.ready = {
|
|
112
|
-
promise: new Promise<void>((innerResolve) => {
|
|
113
|
-
window.Deflect.ready.resolve = innerResolve;
|
|
114
|
-
}),
|
|
115
|
-
resolve: () => resolve(),
|
|
116
|
-
};
|
|
117
|
-
}
|
|
118
|
-
});
|
|
119
|
-
}
|
|
120
|
-
|
|
121
|
-
private createScriptBlob(content: string): string {
|
|
122
|
-
const blob = new Blob([content], { type: "text/javascript" });
|
|
123
|
-
return URL.createObjectURL(blob);
|
|
124
|
-
}
|
|
125
|
-
|
|
126
|
-
private async loadScriptElement(blobUrl: string): Promise<HTMLScriptElement> {
|
|
127
|
-
return new Promise((resolve, reject) => {
|
|
128
|
-
const script = document.createElement("script");
|
|
129
|
-
script.type = "module";
|
|
130
|
-
script.src = blobUrl;
|
|
131
|
-
|
|
132
|
-
script.onload = () => resolve(script);
|
|
133
|
-
script.onerror = () => reject(new Error("Script failed to load"));
|
|
134
|
-
|
|
135
|
-
document.head.appendChild(script);
|
|
136
|
-
});
|
|
137
|
-
}
|
|
138
|
-
|
|
139
|
-
private async getTokenFromScript(): Promise<string> {
|
|
140
|
-
if (
|
|
141
|
-
typeof window === "undefined" ||
|
|
142
|
-
typeof window.Deflect?.getToken !== "function"
|
|
143
|
-
) {
|
|
144
|
-
throw new Error("Script did not load properly - getToken not available");
|
|
145
|
-
}
|
|
146
|
-
|
|
147
|
-
try {
|
|
148
|
-
return await window.Deflect.getToken();
|
|
149
|
-
} catch (error) {
|
|
150
|
-
throw new Error(`Script execution failed: ${error}`);
|
|
151
|
-
}
|
|
152
|
-
}
|
|
153
|
-
|
|
154
|
-
private cleanup(blobUrl: string, scriptElement: HTMLScriptElement): void {
|
|
155
|
-
URL.revokeObjectURL(blobUrl);
|
|
156
|
-
scriptElement.remove();
|
|
157
|
-
|
|
158
|
-
if (typeof window !== "undefined" && window.Deflect?.getToken) {
|
|
159
|
-
delete window.Deflect.getToken;
|
|
160
|
-
}
|
|
161
|
-
}
|
|
162
|
-
|
|
163
|
-
public configure(params: DeflectConfig): void {
|
|
164
|
-
if (!params.actionId?.trim()) {
|
|
165
|
-
throw new Error("actionId is required and cannot be empty");
|
|
166
|
-
}
|
|
167
|
-
this.config = { ...params };
|
|
168
|
-
if (typeof window !== "undefined") {
|
|
169
|
-
window.Deflect.actionId = params.actionId;
|
|
170
|
-
}
|
|
171
|
-
this.tryWarmup();
|
|
172
|
-
}
|
|
173
|
-
|
|
174
|
-
// Deprecated name kept for backward compatibility
|
|
175
|
-
public async solveChallenge(): Promise<string> {
|
|
176
|
-
return this.getToken();
|
|
177
|
-
}
|
|
178
|
-
|
|
179
|
-
public async getToken(): Promise<string> {
|
|
180
|
-
if (!this.config?.actionId) {
|
|
181
|
-
throw new Error("Must call configure() before solveChallenge()");
|
|
182
|
-
}
|
|
183
|
-
|
|
184
|
-
let script: DeflectScript;
|
|
185
|
-
|
|
186
|
-
if (this.scriptCache && !this.isWarmupInProgress) {
|
|
187
|
-
script = this.scriptCache;
|
|
188
|
-
this.scriptCache = null;
|
|
189
|
-
} else {
|
|
190
|
-
script = await this.fetchScript();
|
|
191
|
-
}
|
|
192
|
-
|
|
193
|
-
return this.executeScript(script);
|
|
194
|
-
}
|
|
195
|
-
|
|
196
|
-
public async warmup(): Promise<boolean> {
|
|
197
|
-
if (!this.config?.actionId) {
|
|
198
|
-
return false;
|
|
199
|
-
}
|
|
200
|
-
|
|
201
|
-
try {
|
|
202
|
-
await this.tryWarmup();
|
|
203
|
-
return this.scriptCache !== null;
|
|
204
|
-
} catch {
|
|
205
|
-
return false;
|
|
206
|
-
}
|
|
207
|
-
}
|
|
208
|
-
|
|
209
|
-
public clearCache(): void {
|
|
210
|
-
this.scriptCache = null;
|
|
211
|
-
}
|
|
212
|
-
|
|
213
|
-
/**
|
|
214
|
-
* Inject a fresh token as a hidden input into a form. Only accepts a submit event from onsubmit.
|
|
215
|
-
* Usage: <form ... onsubmit="return Deflect.injectToken(event)">
|
|
216
|
-
* Returns false to prevent double submit.
|
|
217
|
-
*/
|
|
218
|
-
public async injectToken(event: SubmitEvent): Promise<false> {
|
|
219
|
-
if (!event || !event.target || !(event.target instanceof HTMLFormElement)) {
|
|
220
|
-
throw new Error("injectToken: must be called from a form submit event");
|
|
221
|
-
}
|
|
222
|
-
event.preventDefault();
|
|
223
|
-
const form = event.target;
|
|
224
|
-
const token = await this.getToken();
|
|
225
|
-
Array.from(form.querySelectorAll('input[name="deflect_token"]')).forEach(
|
|
226
|
-
(el) => el.remove()
|
|
227
|
-
);
|
|
228
|
-
const hidden = document.createElement("input");
|
|
229
|
-
hidden.type = "hidden";
|
|
230
|
-
hidden.name = "deflect_token";
|
|
231
|
-
hidden.value = token;
|
|
232
|
-
form.appendChild(hidden);
|
|
233
|
-
form.submit();
|
|
234
|
-
return false;
|
|
235
|
-
}
|
|
236
|
-
}
|
|
237
|
-
|
|
238
|
-
export default new Deflect();
|
package/src/types/window.d.ts
DELETED
|
@@ -1,6 +0,0 @@
|
|
|
1
|
-
// Global window augmentation for Deflect SDK.
|
|
2
|
-
// Using 'any' here keeps backward compatibility and avoids circular type issues.
|
|
3
|
-
interface Window {
|
|
4
|
-
// eslint-disable-next-line @typescript-eslint/no-explicit-any -- SDK attaches dynamic shape at runtime
|
|
5
|
-
Deflect: any;
|
|
6
|
-
}
|
package/tsconfig.json
DELETED
|
@@ -1,22 +0,0 @@
|
|
|
1
|
-
{
|
|
2
|
-
"compilerOptions": {
|
|
3
|
-
"target": "ES2015", // Set target to ES2015 or later
|
|
4
|
-
"module": "ESNext", // Use ES module syntax
|
|
5
|
-
"moduleResolution": "node", // Resolve modules like Node.js
|
|
6
|
-
"strict": true, // Enable strict type-checking
|
|
7
|
-
"declaration": true, // Enable generation of .d.ts files
|
|
8
|
-
"declarationDir": "./dist/types", // Directory for .d.ts files
|
|
9
|
-
"esModuleInterop": true, // Allow importing non-ESM modules
|
|
10
|
-
"skipLibCheck": true, // Skip type checking of declaration files
|
|
11
|
-
"outDir": "./dist", // Output directory for JavaScript files
|
|
12
|
-
"lib": ["ES2015", "DOM"], // Add ES2015 and DOM libraries
|
|
13
|
-
"jsx": "preserve" // For JSX compatibility in Vue
|
|
14
|
-
},
|
|
15
|
-
"include": [
|
|
16
|
-
"src/**/*"
|
|
17
|
-
],
|
|
18
|
-
"exclude": [
|
|
19
|
-
"node_modules",
|
|
20
|
-
"dist"
|
|
21
|
-
]
|
|
22
|
-
}
|