@deflectbot/deflect-sdk 1.3.6 → 1.3.7
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.d.ts +42 -0
- package/dist/index.esm.js +218 -0
- package/dist/index.js +225 -194
- package/dist/index.min.js +1 -1
- package/package.json +9 -2
package/dist/index.d.ts
ADDED
|
@@ -0,0 +1,42 @@
|
|
|
1
|
+
interface DeflectConfig {
|
|
2
|
+
actionId: string;
|
|
3
|
+
scriptUrl?: string;
|
|
4
|
+
}
|
|
5
|
+
declare global {
|
|
6
|
+
interface Window {
|
|
7
|
+
Deflect: any;
|
|
8
|
+
}
|
|
9
|
+
}
|
|
10
|
+
declare class Deflect {
|
|
11
|
+
private config;
|
|
12
|
+
private scriptCache;
|
|
13
|
+
private isWarmupInProgress;
|
|
14
|
+
private hasWarmupError;
|
|
15
|
+
constructor();
|
|
16
|
+
private initializeGlobalState;
|
|
17
|
+
private setupAutomaticWarmup;
|
|
18
|
+
private tryWarmup;
|
|
19
|
+
private buildScriptUrl;
|
|
20
|
+
private fetchScript;
|
|
21
|
+
private executeScript;
|
|
22
|
+
private prefetchNextScript;
|
|
23
|
+
private waitForGetToken;
|
|
24
|
+
private createScriptBlob;
|
|
25
|
+
private loadScriptElement;
|
|
26
|
+
private getTokenFromScript;
|
|
27
|
+
private cleanup;
|
|
28
|
+
configure(params: DeflectConfig): void;
|
|
29
|
+
private isTestMode;
|
|
30
|
+
solveChallenge(): Promise<string>;
|
|
31
|
+
getToken(): Promise<string>;
|
|
32
|
+
warmup(): Promise<boolean>;
|
|
33
|
+
clearCache(): void;
|
|
34
|
+
/**
|
|
35
|
+
* Inject a fresh token as a hidden input into a form. Only accepts a submit event from onsubmit.
|
|
36
|
+
* Usage: <form ... onsubmit="return Deflect.injectToken(event)">
|
|
37
|
+
* Returns false to prevent double submit.
|
|
38
|
+
*/
|
|
39
|
+
injectToken(event: SubmitEvent): Promise<false>;
|
|
40
|
+
}
|
|
41
|
+
declare const DeflectInstance: Deflect;
|
|
42
|
+
export default DeflectInstance;
|
|
@@ -0,0 +1,218 @@
|
|
|
1
|
+
class Deflect {
|
|
2
|
+
constructor() {
|
|
3
|
+
this.config = null;
|
|
4
|
+
this.scriptCache = null;
|
|
5
|
+
this.isWarmupInProgress = false;
|
|
6
|
+
this.hasWarmupError = false;
|
|
7
|
+
this.initializeGlobalState();
|
|
8
|
+
this.setupAutomaticWarmup();
|
|
9
|
+
}
|
|
10
|
+
initializeGlobalState() {
|
|
11
|
+
if (typeof window === "undefined") return;
|
|
12
|
+
window.Deflect = window.Deflect || {};
|
|
13
|
+
}
|
|
14
|
+
setupAutomaticWarmup() {
|
|
15
|
+
if (typeof window === "undefined") return;
|
|
16
|
+
if (document.readyState === "loading") {
|
|
17
|
+
document.addEventListener("DOMContentLoaded", () => this.tryWarmup());
|
|
18
|
+
} else {
|
|
19
|
+
setTimeout(() => this.tryWarmup(), 100);
|
|
20
|
+
}
|
|
21
|
+
}
|
|
22
|
+
async tryWarmup() {
|
|
23
|
+
if (!this.config?.actionId || this.isWarmupInProgress || this.scriptCache || this.hasWarmupError) {
|
|
24
|
+
return;
|
|
25
|
+
}
|
|
26
|
+
this.isWarmupInProgress = true;
|
|
27
|
+
try {
|
|
28
|
+
this.scriptCache = await this.fetchScript();
|
|
29
|
+
this.hasWarmupError = false;
|
|
30
|
+
} catch {
|
|
31
|
+
this.hasWarmupError = true;
|
|
32
|
+
} finally {
|
|
33
|
+
this.isWarmupInProgress = false;
|
|
34
|
+
}
|
|
35
|
+
}
|
|
36
|
+
buildScriptUrl(actionId) {
|
|
37
|
+
const baseUrl = this.config?.scriptUrl || "https://js.deflect.bot/main.js";
|
|
38
|
+
const nonce = Date.now().toString();
|
|
39
|
+
return `${baseUrl}?action_id=${actionId}&_=${nonce}`;
|
|
40
|
+
}
|
|
41
|
+
async fetchScript() {
|
|
42
|
+
if (!this.config?.actionId) {
|
|
43
|
+
throw new Error("actionId is required");
|
|
44
|
+
}
|
|
45
|
+
const url = this.buildScriptUrl(this.config.actionId);
|
|
46
|
+
const response = await fetch(url, { cache: "no-store" });
|
|
47
|
+
if (!response.ok) {
|
|
48
|
+
throw new Error(`Failed to fetch script: ${response.status}`);
|
|
49
|
+
}
|
|
50
|
+
const content = await response.text();
|
|
51
|
+
try {
|
|
52
|
+
const maybeError = JSON.parse(content);
|
|
53
|
+
if (maybeError.success === false || maybeError.error) {
|
|
54
|
+
throw new Error(maybeError.error || "Script fetch failed");
|
|
55
|
+
}
|
|
56
|
+
} catch (e) {
|
|
57
|
+
if (e instanceof SyntaxError) {
|
|
58
|
+
} else {
|
|
59
|
+
throw e;
|
|
60
|
+
}
|
|
61
|
+
}
|
|
62
|
+
return {
|
|
63
|
+
content,
|
|
64
|
+
sessionId: response.headers.get("session_id") || void 0
|
|
65
|
+
};
|
|
66
|
+
}
|
|
67
|
+
async executeScript(script) {
|
|
68
|
+
if (script.sessionId && typeof window !== "undefined") {
|
|
69
|
+
window.Deflect.sessionId = script.sessionId;
|
|
70
|
+
}
|
|
71
|
+
const blobUrl = this.createScriptBlob(script.content);
|
|
72
|
+
const scriptElement = await this.loadScriptElement(blobUrl);
|
|
73
|
+
try {
|
|
74
|
+
await this.waitForGetToken();
|
|
75
|
+
const token = await this.getTokenFromScript();
|
|
76
|
+
this.prefetchNextScript();
|
|
77
|
+
return token;
|
|
78
|
+
} finally {
|
|
79
|
+
this.cleanup(blobUrl, scriptElement);
|
|
80
|
+
}
|
|
81
|
+
}
|
|
82
|
+
prefetchNextScript() {
|
|
83
|
+
if (!this.hasWarmupError) {
|
|
84
|
+
this.tryWarmup().catch(() => {
|
|
85
|
+
});
|
|
86
|
+
}
|
|
87
|
+
}
|
|
88
|
+
async waitForGetToken() {
|
|
89
|
+
return new Promise((resolve) => {
|
|
90
|
+
const checkInterval = setInterval(() => {
|
|
91
|
+
if (typeof window !== "undefined" && typeof window.Deflect?.getToken === "function") {
|
|
92
|
+
clearInterval(checkInterval);
|
|
93
|
+
resolve();
|
|
94
|
+
}
|
|
95
|
+
}, 10);
|
|
96
|
+
setTimeout(() => {
|
|
97
|
+
clearInterval(checkInterval);
|
|
98
|
+
resolve();
|
|
99
|
+
}, 1e4);
|
|
100
|
+
});
|
|
101
|
+
}
|
|
102
|
+
createScriptBlob(content) {
|
|
103
|
+
const blob = new Blob([content], { type: "text/javascript" });
|
|
104
|
+
return URL.createObjectURL(blob);
|
|
105
|
+
}
|
|
106
|
+
async loadScriptElement(blobUrl) {
|
|
107
|
+
return new Promise((resolve, reject) => {
|
|
108
|
+
const script = document.createElement("script");
|
|
109
|
+
script.type = "module";
|
|
110
|
+
script.src = blobUrl;
|
|
111
|
+
script.onload = () => resolve(script);
|
|
112
|
+
script.onerror = () => reject(new Error("Script failed to load"));
|
|
113
|
+
document.head.appendChild(script);
|
|
114
|
+
});
|
|
115
|
+
}
|
|
116
|
+
async getTokenFromScript() {
|
|
117
|
+
if (typeof window === "undefined" || typeof window.Deflect?.getToken !== "function") {
|
|
118
|
+
throw new Error("Script did not load properly - getToken not available");
|
|
119
|
+
}
|
|
120
|
+
try {
|
|
121
|
+
return await window.Deflect.getToken();
|
|
122
|
+
} catch (error) {
|
|
123
|
+
throw new Error(`Script execution failed: ${error}`);
|
|
124
|
+
}
|
|
125
|
+
}
|
|
126
|
+
cleanup(blobUrl, scriptElement) {
|
|
127
|
+
URL.revokeObjectURL(blobUrl);
|
|
128
|
+
scriptElement.remove();
|
|
129
|
+
if (typeof window !== "undefined" && window.Deflect?.getToken) {
|
|
130
|
+
delete window.Deflect.getToken;
|
|
131
|
+
}
|
|
132
|
+
}
|
|
133
|
+
configure(params) {
|
|
134
|
+
if (!params.actionId?.trim()) {
|
|
135
|
+
throw new Error("actionId is required and cannot be empty");
|
|
136
|
+
}
|
|
137
|
+
if (this.config?.actionId === params.actionId) {
|
|
138
|
+
return;
|
|
139
|
+
}
|
|
140
|
+
this.hasWarmupError = false;
|
|
141
|
+
this.scriptCache = null;
|
|
142
|
+
this.config = { ...params };
|
|
143
|
+
if (typeof window !== "undefined") {
|
|
144
|
+
window.Deflect.actionId = params.actionId;
|
|
145
|
+
}
|
|
146
|
+
if (!this.isTestMode()) {
|
|
147
|
+
this.tryWarmup();
|
|
148
|
+
}
|
|
149
|
+
}
|
|
150
|
+
isTestMode() {
|
|
151
|
+
return this.config?.actionId === "t/FFFFFFFFFFFFF/111111111" || this.config?.actionId === "t/FFFFFFFFFFFFF/000000000";
|
|
152
|
+
}
|
|
153
|
+
// Deprecated name kept for backward compatibility
|
|
154
|
+
async solveChallenge() {
|
|
155
|
+
return this.getToken();
|
|
156
|
+
}
|
|
157
|
+
async getToken() {
|
|
158
|
+
if (!this.config?.actionId) {
|
|
159
|
+
throw new Error("Must call configure() before solveChallenge()");
|
|
160
|
+
}
|
|
161
|
+
if (this.isTestMode()) {
|
|
162
|
+
return "TESTTOKEN";
|
|
163
|
+
}
|
|
164
|
+
let script;
|
|
165
|
+
if (this.scriptCache && !this.isWarmupInProgress) {
|
|
166
|
+
script = this.scriptCache;
|
|
167
|
+
this.scriptCache = null;
|
|
168
|
+
} else {
|
|
169
|
+
script = await this.fetchScript();
|
|
170
|
+
}
|
|
171
|
+
return this.executeScript(script);
|
|
172
|
+
}
|
|
173
|
+
async warmup() {
|
|
174
|
+
if (!this.config?.actionId) {
|
|
175
|
+
return false;
|
|
176
|
+
}
|
|
177
|
+
try {
|
|
178
|
+
await this.tryWarmup();
|
|
179
|
+
return this.scriptCache !== null;
|
|
180
|
+
} catch {
|
|
181
|
+
return false;
|
|
182
|
+
}
|
|
183
|
+
}
|
|
184
|
+
clearCache() {
|
|
185
|
+
this.scriptCache = null;
|
|
186
|
+
}
|
|
187
|
+
/**
|
|
188
|
+
* Inject a fresh token as a hidden input into a form. Only accepts a submit event from onsubmit.
|
|
189
|
+
* Usage: <form ... onsubmit="return Deflect.injectToken(event)">
|
|
190
|
+
* Returns false to prevent double submit.
|
|
191
|
+
*/
|
|
192
|
+
async injectToken(event) {
|
|
193
|
+
if (!event || !event.target || !(event.target instanceof HTMLFormElement)) {
|
|
194
|
+
throw new Error("injectToken: must be called from a form submit event");
|
|
195
|
+
}
|
|
196
|
+
event.preventDefault();
|
|
197
|
+
const form = event.target;
|
|
198
|
+
const token = await this.getToken();
|
|
199
|
+
Array.from(form.querySelectorAll('input[name="deflect_token"]')).forEach(
|
|
200
|
+
(el) => el.remove()
|
|
201
|
+
);
|
|
202
|
+
const hidden = document.createElement("input");
|
|
203
|
+
hidden.type = "hidden";
|
|
204
|
+
hidden.name = "deflect_token";
|
|
205
|
+
hidden.value = token;
|
|
206
|
+
form.appendChild(hidden);
|
|
207
|
+
form.submit();
|
|
208
|
+
return false;
|
|
209
|
+
}
|
|
210
|
+
}
|
|
211
|
+
const DeflectInstance = new Deflect();
|
|
212
|
+
if (typeof window !== "undefined") {
|
|
213
|
+
window.Deflect = DeflectInstance;
|
|
214
|
+
}
|
|
215
|
+
var src_default = DeflectInstance;
|
|
216
|
+
export {
|
|
217
|
+
src_default as default
|
|
218
|
+
};
|
package/dist/index.js
CHANGED
|
@@ -1,194 +1,225 @@
|
|
|
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 {
|
|
8
|
-
constructor() {
|
|
9
|
-
this.config = null;
|
|
10
|
-
this.scriptCache = null;
|
|
11
|
-
this.isWarmupInProgress = false;
|
|
12
|
-
this.
|
|
13
|
-
this.
|
|
14
|
-
|
|
15
|
-
|
|
16
|
-
|
|
17
|
-
|
|
18
|
-
|
|
19
|
-
|
|
20
|
-
|
|
21
|
-
|
|
22
|
-
|
|
23
|
-
|
|
24
|
-
if (
|
|
25
|
-
|
|
26
|
-
|
|
27
|
-
|
|
28
|
-
|
|
29
|
-
|
|
30
|
-
|
|
31
|
-
|
|
32
|
-
|
|
33
|
-
|
|
34
|
-
|
|
35
|
-
|
|
36
|
-
|
|
37
|
-
|
|
38
|
-
|
|
39
|
-
|
|
40
|
-
|
|
41
|
-
|
|
42
|
-
|
|
43
|
-
|
|
44
|
-
|
|
45
|
-
|
|
46
|
-
|
|
47
|
-
|
|
48
|
-
|
|
49
|
-
|
|
50
|
-
|
|
51
|
-
|
|
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
|
-
|
|
86
|
-
|
|
87
|
-
|
|
88
|
-
|
|
89
|
-
|
|
90
|
-
|
|
91
|
-
|
|
92
|
-
|
|
93
|
-
|
|
94
|
-
|
|
95
|
-
|
|
96
|
-
}
|
|
97
|
-
async
|
|
98
|
-
return new Promise((resolve
|
|
99
|
-
const
|
|
100
|
-
|
|
101
|
-
|
|
102
|
-
|
|
103
|
-
|
|
104
|
-
|
|
105
|
-
|
|
106
|
-
|
|
107
|
-
|
|
108
|
-
|
|
109
|
-
|
|
110
|
-
|
|
111
|
-
|
|
112
|
-
|
|
113
|
-
|
|
114
|
-
|
|
115
|
-
|
|
116
|
-
|
|
117
|
-
|
|
118
|
-
|
|
119
|
-
|
|
120
|
-
|
|
121
|
-
|
|
122
|
-
|
|
123
|
-
|
|
124
|
-
|
|
125
|
-
|
|
126
|
-
|
|
127
|
-
|
|
128
|
-
|
|
129
|
-
|
|
130
|
-
window.Deflect.
|
|
131
|
-
}
|
|
132
|
-
|
|
133
|
-
|
|
134
|
-
|
|
135
|
-
|
|
136
|
-
|
|
137
|
-
|
|
138
|
-
|
|
139
|
-
|
|
140
|
-
|
|
141
|
-
|
|
142
|
-
|
|
143
|
-
if (
|
|
144
|
-
|
|
145
|
-
|
|
146
|
-
|
|
147
|
-
|
|
148
|
-
}
|
|
149
|
-
|
|
150
|
-
|
|
151
|
-
|
|
152
|
-
if (
|
|
153
|
-
|
|
154
|
-
}
|
|
155
|
-
|
|
156
|
-
|
|
157
|
-
|
|
158
|
-
|
|
159
|
-
|
|
160
|
-
|
|
161
|
-
}
|
|
162
|
-
|
|
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
|
-
|
|
189
|
-
|
|
190
|
-
|
|
191
|
-
|
|
192
|
-
|
|
193
|
-
|
|
194
|
-
|
|
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 {
|
|
8
|
+
constructor() {
|
|
9
|
+
this.config = null;
|
|
10
|
+
this.scriptCache = null;
|
|
11
|
+
this.isWarmupInProgress = false;
|
|
12
|
+
this.hasWarmupError = false;
|
|
13
|
+
this.initializeGlobalState();
|
|
14
|
+
this.setupAutomaticWarmup();
|
|
15
|
+
}
|
|
16
|
+
static {
|
|
17
|
+
__name(this, "Deflect");
|
|
18
|
+
}
|
|
19
|
+
initializeGlobalState() {
|
|
20
|
+
if (typeof window === "undefined") return;
|
|
21
|
+
window.Deflect = window.Deflect || {};
|
|
22
|
+
}
|
|
23
|
+
setupAutomaticWarmup() {
|
|
24
|
+
if (typeof window === "undefined") return;
|
|
25
|
+
if (document.readyState === "loading") {
|
|
26
|
+
document.addEventListener("DOMContentLoaded", () => this.tryWarmup());
|
|
27
|
+
} else {
|
|
28
|
+
setTimeout(() => this.tryWarmup(), 100);
|
|
29
|
+
}
|
|
30
|
+
}
|
|
31
|
+
async tryWarmup() {
|
|
32
|
+
if (!this.config?.actionId || this.isWarmupInProgress || this.scriptCache || this.hasWarmupError) {
|
|
33
|
+
return;
|
|
34
|
+
}
|
|
35
|
+
this.isWarmupInProgress = true;
|
|
36
|
+
try {
|
|
37
|
+
this.scriptCache = await this.fetchScript();
|
|
38
|
+
this.hasWarmupError = false;
|
|
39
|
+
} catch {
|
|
40
|
+
this.hasWarmupError = true;
|
|
41
|
+
} finally {
|
|
42
|
+
this.isWarmupInProgress = false;
|
|
43
|
+
}
|
|
44
|
+
}
|
|
45
|
+
buildScriptUrl(actionId) {
|
|
46
|
+
const baseUrl = this.config?.scriptUrl || "https://js.deflect.bot/main.js";
|
|
47
|
+
const nonce = Date.now().toString();
|
|
48
|
+
return `${baseUrl}?action_id=${actionId}&_=${nonce}`;
|
|
49
|
+
}
|
|
50
|
+
async fetchScript() {
|
|
51
|
+
if (!this.config?.actionId) {
|
|
52
|
+
throw new Error("actionId is required");
|
|
53
|
+
}
|
|
54
|
+
const url = this.buildScriptUrl(this.config.actionId);
|
|
55
|
+
const response = await fetch(url, { cache: "no-store" });
|
|
56
|
+
if (!response.ok) {
|
|
57
|
+
throw new Error(`Failed to fetch script: ${response.status}`);
|
|
58
|
+
}
|
|
59
|
+
const content = await response.text();
|
|
60
|
+
try {
|
|
61
|
+
const maybeError = JSON.parse(content);
|
|
62
|
+
if (maybeError.success === false || maybeError.error) {
|
|
63
|
+
throw new Error(maybeError.error || "Script fetch failed");
|
|
64
|
+
}
|
|
65
|
+
} catch (e) {
|
|
66
|
+
if (e instanceof SyntaxError) {
|
|
67
|
+
} else {
|
|
68
|
+
throw e;
|
|
69
|
+
}
|
|
70
|
+
}
|
|
71
|
+
return {
|
|
72
|
+
content,
|
|
73
|
+
sessionId: response.headers.get("session_id") || void 0
|
|
74
|
+
};
|
|
75
|
+
}
|
|
76
|
+
async executeScript(script) {
|
|
77
|
+
if (script.sessionId && typeof window !== "undefined") {
|
|
78
|
+
window.Deflect.sessionId = script.sessionId;
|
|
79
|
+
}
|
|
80
|
+
const blobUrl = this.createScriptBlob(script.content);
|
|
81
|
+
const scriptElement = await this.loadScriptElement(blobUrl);
|
|
82
|
+
try {
|
|
83
|
+
await this.waitForGetToken();
|
|
84
|
+
const token = await this.getTokenFromScript();
|
|
85
|
+
this.prefetchNextScript();
|
|
86
|
+
return token;
|
|
87
|
+
} finally {
|
|
88
|
+
this.cleanup(blobUrl, scriptElement);
|
|
89
|
+
}
|
|
90
|
+
}
|
|
91
|
+
prefetchNextScript() {
|
|
92
|
+
if (!this.hasWarmupError) {
|
|
93
|
+
this.tryWarmup().catch(() => {
|
|
94
|
+
});
|
|
95
|
+
}
|
|
96
|
+
}
|
|
97
|
+
async waitForGetToken() {
|
|
98
|
+
return new Promise((resolve) => {
|
|
99
|
+
const checkInterval = setInterval(() => {
|
|
100
|
+
if (typeof window !== "undefined" && typeof window.Deflect?.getToken === "function") {
|
|
101
|
+
clearInterval(checkInterval);
|
|
102
|
+
resolve();
|
|
103
|
+
}
|
|
104
|
+
}, 10);
|
|
105
|
+
setTimeout(() => {
|
|
106
|
+
clearInterval(checkInterval);
|
|
107
|
+
resolve();
|
|
108
|
+
}, 1e4);
|
|
109
|
+
});
|
|
110
|
+
}
|
|
111
|
+
createScriptBlob(content) {
|
|
112
|
+
const blob = new Blob([content], { type: "text/javascript" });
|
|
113
|
+
return URL.createObjectURL(blob);
|
|
114
|
+
}
|
|
115
|
+
async loadScriptElement(blobUrl) {
|
|
116
|
+
return new Promise((resolve, reject) => {
|
|
117
|
+
const script = document.createElement("script");
|
|
118
|
+
script.type = "module";
|
|
119
|
+
script.src = blobUrl;
|
|
120
|
+
script.onload = () => resolve(script);
|
|
121
|
+
script.onerror = () => reject(new Error("Script failed to load"));
|
|
122
|
+
document.head.appendChild(script);
|
|
123
|
+
});
|
|
124
|
+
}
|
|
125
|
+
async getTokenFromScript() {
|
|
126
|
+
if (typeof window === "undefined" || typeof window.Deflect?.getToken !== "function") {
|
|
127
|
+
throw new Error("Script did not load properly - getToken not available");
|
|
128
|
+
}
|
|
129
|
+
try {
|
|
130
|
+
return await window.Deflect.getToken();
|
|
131
|
+
} catch (error) {
|
|
132
|
+
throw new Error(`Script execution failed: ${error}`);
|
|
133
|
+
}
|
|
134
|
+
}
|
|
135
|
+
cleanup(blobUrl, scriptElement) {
|
|
136
|
+
URL.revokeObjectURL(blobUrl);
|
|
137
|
+
scriptElement.remove();
|
|
138
|
+
if (typeof window !== "undefined" && window.Deflect?.getToken) {
|
|
139
|
+
delete window.Deflect.getToken;
|
|
140
|
+
}
|
|
141
|
+
}
|
|
142
|
+
configure(params) {
|
|
143
|
+
if (!params.actionId?.trim()) {
|
|
144
|
+
throw new Error("actionId is required and cannot be empty");
|
|
145
|
+
}
|
|
146
|
+
if (this.config?.actionId === params.actionId) {
|
|
147
|
+
return;
|
|
148
|
+
}
|
|
149
|
+
this.hasWarmupError = false;
|
|
150
|
+
this.scriptCache = null;
|
|
151
|
+
this.config = { ...params };
|
|
152
|
+
if (typeof window !== "undefined") {
|
|
153
|
+
window.Deflect.actionId = params.actionId;
|
|
154
|
+
}
|
|
155
|
+
if (!this.isTestMode()) {
|
|
156
|
+
this.tryWarmup();
|
|
157
|
+
}
|
|
158
|
+
}
|
|
159
|
+
isTestMode() {
|
|
160
|
+
return this.config?.actionId === "t/FFFFFFFFFFFFF/111111111" || this.config?.actionId === "t/FFFFFFFFFFFFF/000000000";
|
|
161
|
+
}
|
|
162
|
+
// Deprecated name kept for backward compatibility
|
|
163
|
+
async solveChallenge() {
|
|
164
|
+
return this.getToken();
|
|
165
|
+
}
|
|
166
|
+
async getToken() {
|
|
167
|
+
if (!this.config?.actionId) {
|
|
168
|
+
throw new Error("Must call configure() before solveChallenge()");
|
|
169
|
+
}
|
|
170
|
+
if (this.isTestMode()) {
|
|
171
|
+
return "TESTTOKEN";
|
|
172
|
+
}
|
|
173
|
+
let script;
|
|
174
|
+
if (this.scriptCache && !this.isWarmupInProgress) {
|
|
175
|
+
script = this.scriptCache;
|
|
176
|
+
this.scriptCache = null;
|
|
177
|
+
} else {
|
|
178
|
+
script = await this.fetchScript();
|
|
179
|
+
}
|
|
180
|
+
return this.executeScript(script);
|
|
181
|
+
}
|
|
182
|
+
async warmup() {
|
|
183
|
+
if (!this.config?.actionId) {
|
|
184
|
+
return false;
|
|
185
|
+
}
|
|
186
|
+
try {
|
|
187
|
+
await this.tryWarmup();
|
|
188
|
+
return this.scriptCache !== null;
|
|
189
|
+
} catch {
|
|
190
|
+
return false;
|
|
191
|
+
}
|
|
192
|
+
}
|
|
193
|
+
clearCache() {
|
|
194
|
+
this.scriptCache = null;
|
|
195
|
+
}
|
|
196
|
+
/**
|
|
197
|
+
* Inject a fresh token as a hidden input into a form. Only accepts a submit event from onsubmit.
|
|
198
|
+
* Usage: <form ... onsubmit="return Deflect.injectToken(event)">
|
|
199
|
+
* Returns false to prevent double submit.
|
|
200
|
+
*/
|
|
201
|
+
async injectToken(event) {
|
|
202
|
+
if (!event || !event.target || !(event.target instanceof HTMLFormElement)) {
|
|
203
|
+
throw new Error("injectToken: must be called from a form submit event");
|
|
204
|
+
}
|
|
205
|
+
event.preventDefault();
|
|
206
|
+
const form = event.target;
|
|
207
|
+
const token = await this.getToken();
|
|
208
|
+
Array.from(form.querySelectorAll('input[name="deflect_token"]')).forEach(
|
|
209
|
+
(el) => el.remove()
|
|
210
|
+
);
|
|
211
|
+
const hidden = document.createElement("input");
|
|
212
|
+
hidden.type = "hidden";
|
|
213
|
+
hidden.name = "deflect_token";
|
|
214
|
+
hidden.value = token;
|
|
215
|
+
form.appendChild(hidden);
|
|
216
|
+
form.submit();
|
|
217
|
+
return false;
|
|
218
|
+
}
|
|
219
|
+
};
|
|
220
|
+
var DeflectInstance = new Deflect();
|
|
221
|
+
if (typeof window !== "undefined") {
|
|
222
|
+
window.Deflect = DeflectInstance;
|
|
223
|
+
}
|
|
224
|
+
var src_default = DeflectInstance;
|
|
225
|
+
})();
|
package/dist/index.min.js
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
"use strict";(()=>{var
|
|
1
|
+
"use strict";(()=>{var n=class{constructor(){this.config=null;this.scriptCache=null;this.isWarmupInProgress=!1;this.hasWarmupError=!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.hasWarmupError)){this.isWarmupInProgress=!0;try{this.scriptCache=await this.fetchScript(),this.hasWarmupError=!1}catch{this.hasWarmupError=!0}finally{this.isWarmupInProgress=!1}}}buildScriptUrl(t){let e=this.config?.scriptUrl||"https://js.deflect.bot/main.js",r=Date.now().toString();return`${e}?action_id=${t}&_=${r}`}async fetchScript(){if(!this.config?.actionId)throw new Error("actionId is required");let t=this.buildScriptUrl(this.config.actionId),e=await fetch(t,{cache:"no-store"});if(!e.ok)throw new Error(`Failed to fetch script: ${e.status}`);let r=await e.text();try{let i=JSON.parse(r);if(i.success===!1||i.error)throw new Error(i.error||"Script fetch failed")}catch(i){if(!(i instanceof SyntaxError))throw i}return{content:r,sessionId:e.headers.get("session_id")||void 0}}async executeScript(t){t.sessionId&&typeof window<"u"&&(window.Deflect.sessionId=t.sessionId);let e=this.createScriptBlob(t.content),r=await this.loadScriptElement(e);try{await this.waitForGetToken();let i=await this.getTokenFromScript();return this.prefetchNextScript(),i}finally{this.cleanup(e,r)}}prefetchNextScript(){this.hasWarmupError||this.tryWarmup().catch(()=>{})}async waitForGetToken(){return new Promise(t=>{let e=setInterval(()=>{typeof window<"u"&&typeof window.Deflect?.getToken=="function"&&(clearInterval(e),t())},10);setTimeout(()=>{clearInterval(e),t()},1e4)})}createScriptBlob(t){let e=new Blob([t],{type:"text/javascript"});return URL.createObjectURL(e)}async loadScriptElement(t){return new Promise((e,r)=>{let i=document.createElement("script");i.type="module",i.src=t,i.onload=()=>e(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(t){throw new Error(`Script execution failed: ${t}`)}}cleanup(t,e){URL.revokeObjectURL(t),e.remove(),typeof window<"u"&&window.Deflect?.getToken&&delete window.Deflect.getToken}configure(t){if(!t.actionId?.trim())throw new Error("actionId is required and cannot be empty");this.config?.actionId!==t.actionId&&(this.hasWarmupError=!1,this.scriptCache=null,this.config={...t},typeof window<"u"&&(window.Deflect.actionId=t.actionId),this.isTestMode()||this.tryWarmup())}isTestMode(){return this.config?.actionId==="t/FFFFFFFFFFFFF/111111111"||this.config?.actionId==="t/FFFFFFFFFFFFF/000000000"}async solveChallenge(){return this.getToken()}async getToken(){if(!this.config?.actionId)throw new Error("Must call configure() before solveChallenge()");if(this.isTestMode())return"TESTTOKEN";let t;return this.scriptCache&&!this.isWarmupInProgress?(t=this.scriptCache,this.scriptCache=null):t=await this.fetchScript(),this.executeScript(t)}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(t){if(!t||!t.target||!(t.target instanceof HTMLFormElement))throw new Error("injectToken: must be called from a form submit event");t.preventDefault();let e=t.target,r=await this.getToken();Array.from(e.querySelectorAll('input[name="deflect_token"]')).forEach(s=>s.remove());let i=document.createElement("input");return i.type="hidden",i.name="deflect_token",i.value=r,e.appendChild(i),e.submit(),!1}},o=new n;typeof window<"u"&&(window.Deflect=o);var a=o;})();
|
package/package.json
CHANGED
|
@@ -1,17 +1,24 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@deflectbot/deflect-sdk",
|
|
3
|
-
"version": "1.3.
|
|
3
|
+
"version": "1.3.7",
|
|
4
4
|
"description": "SDK for deflect.bot - Use it for seamless captcha integration on any website.",
|
|
5
5
|
"main": "dist/index.min.js",
|
|
6
6
|
"module": "dist/index.esm.js",
|
|
7
7
|
"types": "dist/index.d.ts",
|
|
8
8
|
"unpkg": "dist/index.min.js",
|
|
9
9
|
"jsdelivr": "dist/index.min.js",
|
|
10
|
+
"exports": {
|
|
11
|
+
".": {
|
|
12
|
+
"types": "./dist/index.d.ts",
|
|
13
|
+
"import": "./dist/index.esm.js",
|
|
14
|
+
"require": "./dist/index.min.js"
|
|
15
|
+
}
|
|
16
|
+
},
|
|
10
17
|
"files": [
|
|
11
18
|
"dist/**/*"
|
|
12
19
|
],
|
|
13
20
|
"scripts": {
|
|
14
|
-
"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 && esbuild src/index.ts --
|
|
21
|
+
"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 && esbuild src/index.ts --format=esm --outfile=dist/index.esm.js && tsc --declaration --emitDeclarationOnly --outDir dist"
|
|
15
22
|
},
|
|
16
23
|
"author": "Deflect",
|
|
17
24
|
"license": "MIT",
|