@mochabug/adapt-web 1.0.0-rc34 → 1.0.0-rc37

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.
@@ -0,0 +1,286 @@
1
+ /**
2
+ * Standalone Cap.js widget component for proof-of-work challenges.
3
+ * Can be used independently of AdaptWebClient and iframes.
4
+ *
5
+ * @example
6
+ * ```typescript
7
+ * import { AdaptCapWidget } from "@mochabug/adapt-web";
8
+ * import { createConnectClient } from "@mochabug/adapt-core/connect";
9
+ *
10
+ * const rawClient = createConnectClient({ id: "my-automation" });
11
+ * const widget = new AdaptCapWidget({
12
+ * container: "cap-container",
13
+ * automationId: "my-automation",
14
+ * client: rawClient,
15
+ * onSolve: async (challengeToken, expires) => {
16
+ * const client = createAdaptClient(rawClient, "my-automation");
17
+ * const session = await client.run({ challengeToken });
18
+ * }
19
+ * });
20
+ * ```
21
+ */
22
+ import { setupCapAdapter, cleanupCapAdapter } from "./cap-adapter.js";
23
+ // Import Cap.js widget (registers <cap-widget> custom element)
24
+ import "@cap.js/widget";
25
+ /**
26
+ * Standalone Cap.js widget for proof-of-work challenges.
27
+ *
28
+ * This component can be used independently of AdaptWebClient to handle
29
+ * PoW challenges. After solving, the token can be used with any session
30
+ * starting method in @mochabug/adapt-core.
31
+ */
32
+ export class AdaptCapWidget {
33
+ constructor(options) {
34
+ this.widgetContainer = null;
35
+ this.widgetElement = null;
36
+ this.destroyed = false;
37
+ this.options = options;
38
+ // Resolve container
39
+ const container = typeof options.container === "string"
40
+ ? document.getElementById(options.container)
41
+ : options.container;
42
+ if (!container) {
43
+ throw new Error(`Container ${typeof options.container === "string"
44
+ ? `with id '${options.container}'`
45
+ : ""} not found`);
46
+ }
47
+ this.containerElement = container;
48
+ // Inject default styles if not already present
49
+ this.injectStyles();
50
+ // Set up Cap.js adapter to intercept fetch calls using the provided client
51
+ setupCapAdapter(options.client, options.automationId);
52
+ // Create and mount widget
53
+ this.mountWidget();
54
+ }
55
+ injectStyles() {
56
+ if (document.getElementById("mb-adapt-cap-styles"))
57
+ return;
58
+ const style = document.createElement("style");
59
+ style.id = "mb-adapt-cap-styles";
60
+ style.textContent = `
61
+ /* ============================================
62
+ Mochabug Adapt Cap Widget - Premium Design
63
+ ============================================ */
64
+
65
+ .mb-adapt-cap {
66
+ /* Sizing */
67
+ --mb-cap-border-radius: 16px;
68
+ --mb-cap-height: 72px;
69
+ --mb-cap-width: 320px;
70
+ --mb-cap-padding: 18px 22px;
71
+ --mb-cap-gap: 16px;
72
+
73
+ /* Light Mode Colors */
74
+ --mb-cap-bg: #ffffff;
75
+ --mb-cap-border-color: #e5e7eb;
76
+ --mb-cap-text-color: #111827;
77
+
78
+ /* Checkbox */
79
+ --mb-cap-checkbox-size: 30px;
80
+ --mb-cap-checkbox-radius: 8px;
81
+ --mb-cap-checkbox-border-color: #d1d5db;
82
+ --mb-cap-checkbox-bg: #f9fafb;
83
+
84
+ /* Spinner */
85
+ --mb-cap-spinner-color: #6366f1;
86
+ --mb-cap-spinner-bg: #e5e7eb;
87
+
88
+ /* Typography */
89
+ --mb-cap-font: system-ui, -apple-system, BlinkMacSystemFont, "Segoe UI", Roboto, sans-serif;
90
+ --mb-cap-font-size: 15px;
91
+ --mb-cap-font-weight: 500;
92
+
93
+ /* Shadows */
94
+ --mb-cap-shadow:
95
+ 0 1px 3px rgba(0, 0, 0, 0.08),
96
+ 0 4px 12px rgba(0, 0, 0, 0.05);
97
+ --mb-cap-shadow-hover:
98
+ 0 4px 12px rgba(0, 0, 0, 0.1),
99
+ 0 8px 24px rgba(0, 0, 0, 0.08);
100
+ }
101
+
102
+ /* Dark Mode */
103
+ .mb-adapt-cap--dark {
104
+ --mb-cap-bg: #1f2937;
105
+ --mb-cap-border-color: #374151;
106
+ --mb-cap-text-color: #f9fafb;
107
+ --mb-cap-checkbox-border-color: #4b5563;
108
+ --mb-cap-checkbox-bg: #374151;
109
+ --mb-cap-spinner-color: #818cf8;
110
+ --mb-cap-spinner-bg: #4b5563;
111
+ --mb-cap-shadow:
112
+ 0 1px 3px rgba(0, 0, 0, 0.3),
113
+ 0 4px 12px rgba(0, 0, 0, 0.2);
114
+ --mb-cap-shadow-hover:
115
+ 0 4px 12px rgba(0, 0, 0, 0.4),
116
+ 0 8px 24px rgba(0, 0, 0, 0.3);
117
+ }
118
+
119
+ /* Container */
120
+ .mb-adapt-cap__container {
121
+ display: flex;
122
+ align-items: center;
123
+ justify-content: center;
124
+ padding: 16px;
125
+ }
126
+
127
+ /* Cap Widget */
128
+ .mb-adapt-cap cap-widget {
129
+ --cap-background: var(--mb-cap-bg);
130
+ --cap-border-color: var(--mb-cap-border-color);
131
+ --cap-border-radius: var(--mb-cap-border-radius);
132
+ --cap-widget-height: var(--mb-cap-height);
133
+ --cap-widget-width: var(--mb-cap-width);
134
+ --cap-widget-padding: var(--mb-cap-padding);
135
+ --cap-gap: var(--mb-cap-gap);
136
+ --cap-color: var(--mb-cap-text-color);
137
+ --cap-checkbox-size: var(--mb-cap-checkbox-size);
138
+ --cap-checkbox-border: 2px solid var(--mb-cap-checkbox-border-color);
139
+ --cap-checkbox-border-radius: var(--mb-cap-checkbox-radius);
140
+ --cap-checkbox-background: var(--mb-cap-checkbox-bg);
141
+ --cap-checkbox-margin: 0;
142
+ --cap-font: var(--mb-cap-font);
143
+ --cap-spinner-color: var(--mb-cap-spinner-color);
144
+ --cap-spinner-background-color: var(--mb-cap-spinner-bg);
145
+ --cap-spinner-thickness: 3px;
146
+
147
+ display: block;
148
+ box-shadow: var(--mb-cap-shadow);
149
+ border-radius: var(--mb-cap-border-radius);
150
+ transition:
151
+ transform 0.2s ease,
152
+ box-shadow 0.2s ease;
153
+ }
154
+
155
+ .mb-adapt-cap cap-widget:hover {
156
+ transform: translateY(-2px);
157
+ box-shadow: var(--mb-cap-shadow-hover);
158
+ }
159
+
160
+ .mb-adapt-cap cap-widget:active {
161
+ transform: translateY(0);
162
+ transition-duration: 0.1s;
163
+ }
164
+
165
+ /* Checkbox styling */
166
+ .mb-adapt-cap cap-widget::part(checkbox) {
167
+ transition: transform 0.15s ease;
168
+ }
169
+
170
+ .mb-adapt-cap cap-widget:hover::part(checkbox) {
171
+ transform: scale(1.05);
172
+ }
173
+
174
+ /* Label styling */
175
+ .mb-adapt-cap cap-widget::part(label) {
176
+ font-size: var(--mb-cap-font-size);
177
+ font-weight: var(--mb-cap-font-weight);
178
+ }
179
+
180
+ /* Hide attribution */
181
+ .mb-adapt-cap cap-widget::part(attribution) {
182
+ display: none;
183
+ }
184
+
185
+ /* Responsive */
186
+ @media (max-width: 380px) {
187
+ .mb-adapt-cap {
188
+ --mb-cap-width: 280px;
189
+ --mb-cap-height: 64px;
190
+ --mb-cap-padding: 14px 18px;
191
+ --mb-cap-checkbox-size: 26px;
192
+ --mb-cap-font-size: 14px;
193
+ }
194
+ }
195
+ `;
196
+ document.head.appendChild(style);
197
+ }
198
+ mountWidget() {
199
+ // Create container wrapper with styling class
200
+ this.widgetContainer = document.createElement("div");
201
+ this.widgetContainer.className = "mb-adapt-cap";
202
+ const innerContainer = document.createElement("div");
203
+ innerContainer.className = "mb-adapt-cap__container";
204
+ // Create the Cap widget element
205
+ this.widgetElement = document.createElement("cap-widget");
206
+ this.widgetElement.setAttribute("data-cap-api-endpoint", `/adapt-cap-${this.options.automationId}/`);
207
+ // Apply widget options
208
+ if (this.options.workerCount) {
209
+ this.widgetElement.setAttribute("data-cap-worker-count", String(this.options.workerCount));
210
+ }
211
+ if (this.options.i18n) {
212
+ const { i18n } = this.options;
213
+ if (i18n.verifyingLabel) {
214
+ this.widgetElement.setAttribute("data-cap-i18n-verifying-label", i18n.verifyingLabel);
215
+ }
216
+ if (i18n.initialState) {
217
+ this.widgetElement.setAttribute("data-cap-i18n-initial-state", i18n.initialState);
218
+ }
219
+ if (i18n.solvedLabel) {
220
+ this.widgetElement.setAttribute("data-cap-i18n-solved-label", i18n.solvedLabel);
221
+ }
222
+ if (i18n.errorLabel) {
223
+ this.widgetElement.setAttribute("data-cap-i18n-error-label", i18n.errorLabel);
224
+ }
225
+ }
226
+ // Listen for solve event
227
+ this.widgetElement.addEventListener("solve", ((e) => {
228
+ if (this.destroyed)
229
+ return;
230
+ const token = e.detail?.token;
231
+ const expiresStr = e.detail?.expires;
232
+ const expires = expiresStr ? new Date(expiresStr) : new Date();
233
+ // Auto-destroy after successful solve
234
+ this.destroy();
235
+ if (token) {
236
+ this.options.onSolve(token, expires);
237
+ }
238
+ else {
239
+ this.options.onError?.(new Error("No token received from Cap.js"));
240
+ }
241
+ }));
242
+ // Listen for error event
243
+ this.widgetElement.addEventListener("error", ((e) => {
244
+ if (this.destroyed)
245
+ return;
246
+ console.error("[AdaptCapWidget] Cap.js error:", e.detail);
247
+ this.destroy();
248
+ this.options.onError?.(new Error(e.detail?.message || "Cap.js error"));
249
+ }));
250
+ // Mount to DOM
251
+ innerContainer.appendChild(this.widgetElement);
252
+ this.widgetContainer.appendChild(innerContainer);
253
+ this.containerElement.appendChild(this.widgetContainer);
254
+ }
255
+ /**
256
+ * Enable or disable dark mode styling.
257
+ */
258
+ setDarkMode(dark) {
259
+ if (!this.widgetContainer)
260
+ return;
261
+ if (dark) {
262
+ this.widgetContainer.classList.add("mb-adapt-cap--dark");
263
+ }
264
+ else {
265
+ this.widgetContainer.classList.remove("mb-adapt-cap--dark");
266
+ }
267
+ }
268
+ /**
269
+ * Clean up and remove the widget from DOM.
270
+ * Called automatically after successful solve.
271
+ */
272
+ destroy() {
273
+ if (this.destroyed)
274
+ return;
275
+ this.destroyed = true;
276
+ // Cleanup Cap adapter
277
+ cleanupCapAdapter();
278
+ // Remove from DOM
279
+ if (this.widgetContainer && this.widgetContainer.parentNode) {
280
+ this.widgetContainer.parentNode.removeChild(this.widgetContainer);
281
+ }
282
+ this.widgetContainer = null;
283
+ this.widgetElement = null;
284
+ }
285
+ }
286
+ //# sourceMappingURL=AdaptCapWidget.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"AdaptCapWidget.js","sourceRoot":"","sources":["../../src/AdaptCapWidget.ts"],"names":[],"mappings":"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"}
@@ -0,0 +1,147 @@
1
+ import { timestampDate } from "@bufbuild/protobuf/wkt";
2
+ // Module-level state for the Cap.js adapter
3
+ let currentClient = null;
4
+ let currentAutomationId = null;
5
+ // Store verification tokens per automation for the redeem step
6
+ const verificationTokens = new Map();
7
+ /**
8
+ * Create a challenge for an automation that requires proof-of-work.
9
+ *
10
+ * @param client - The automation client
11
+ * @param id - The automation ID
12
+ * @returns Challenge information including the token to solve
13
+ */
14
+ export async function createChallenge(client, id) {
15
+ const response = await client.createChallenge({ id });
16
+ return {
17
+ count: response.count,
18
+ size: response.size,
19
+ difficulty: response.difficulty,
20
+ expires: response.expires ? timestampDate(response.expires) : new Date(),
21
+ token: response.token,
22
+ verificationToken: response.verificationToken,
23
+ };
24
+ }
25
+ /**
26
+ * Redeem solved challenge solutions for a token that can be used to start a session.
27
+ *
28
+ * @param client - The automation client
29
+ * @param id - The automation ID
30
+ * @param verificationToken - The encrypted verification token from createChallenge
31
+ * @param solutions - Array of nonce solutions found by Cap.js solver
32
+ * @returns Redeemed challenge with token to use for session start
33
+ */
34
+ export async function redeemChallenge(client, id, verificationToken, solutions) {
35
+ const response = await client.redeemChallenge({
36
+ id,
37
+ verificationToken,
38
+ solutions,
39
+ });
40
+ return {
41
+ token: response.token,
42
+ expires: response.expires ? timestampDate(response.expires) : new Date(),
43
+ };
44
+ }
45
+ // Set up CAP_CUSTOM_FETCH immediately at module load time.
46
+ // Cap.js checks for this global when its module loads, so we must set it
47
+ // BEFORE @cap.js/widget is imported. The actual client/id are set later
48
+ // via setupCapAdapter().
49
+ if (typeof window !== "undefined") {
50
+ window.CAP_CUSTOM_FETCH = async (url, options) => {
51
+ const urlStr = url.toString();
52
+ // Check if this is a challenge endpoint call from Cap.js
53
+ if (urlStr.endsWith("/challenge")) {
54
+ if (!currentClient || !currentAutomationId) {
55
+ return new Response(JSON.stringify({ error: "Cap adapter not initialized" }), { status: 500, headers: { "Content-Type": "application/json" } });
56
+ }
57
+ try {
58
+ const challengeInfo = await createChallenge(currentClient, currentAutomationId);
59
+ // Store verification token for the redeem step
60
+ verificationTokens.set(currentAutomationId, challengeInfo.verificationToken);
61
+ // Transform response to Cap.js expected format
62
+ // Cap.js expects: { challenge: { c, s, d }, token } where it generates
63
+ // challenges using prng(token + index, size) for salt and prng(token + index + 'd', difficulty) for target
64
+ // We pass the hex seed as 'token' for Cap.js PRNG derivation
65
+ return new Response(JSON.stringify({
66
+ challenge: {
67
+ c: challengeInfo.count,
68
+ s: challengeInfo.size,
69
+ d: challengeInfo.difficulty,
70
+ },
71
+ token: challengeInfo.token, // hex seed for Cap.js PRNG
72
+ expires: challengeInfo.expires.toISOString(),
73
+ }), {
74
+ status: 200,
75
+ headers: { "Content-Type": "application/json" },
76
+ });
77
+ }
78
+ catch (error) {
79
+ return new Response(JSON.stringify({ error: String(error) }), {
80
+ status: 500,
81
+ headers: { "Content-Type": "application/json" },
82
+ });
83
+ }
84
+ }
85
+ if (urlStr.endsWith("/redeem")) {
86
+ if (!currentClient || !currentAutomationId) {
87
+ return new Response(JSON.stringify({ error: "Cap adapter not initialized" }), { status: 500, headers: { "Content-Type": "application/json" } });
88
+ }
89
+ // Get the stored verification token
90
+ const verificationToken = verificationTokens.get(currentAutomationId);
91
+ if (!verificationToken) {
92
+ return new Response(JSON.stringify({ error: "No verification token found - challenge must be created first" }), { status: 400, headers: { "Content-Type": "application/json" } });
93
+ }
94
+ try {
95
+ const body = options?.body ? JSON.parse(options.body) : {};
96
+ // Cap.js sends solutions as numbers or strings, convert to bigint
97
+ const solutions = (body.solutions || []).map((s) => BigInt(s));
98
+ const redeemed = await redeemChallenge(currentClient, currentAutomationId, verificationToken, // Use stored verification token, not Cap.js token
99
+ solutions);
100
+ // Clean up stored verification token after successful redeem
101
+ verificationTokens.delete(currentAutomationId);
102
+ // Transform response to Cap.js expected format
103
+ // Cap.js expects: { success: true, token, expires }
104
+ return new Response(JSON.stringify({
105
+ success: true,
106
+ token: redeemed.token,
107
+ expires: redeemed.expires.toISOString(),
108
+ }), {
109
+ status: 200,
110
+ headers: { "Content-Type": "application/json" },
111
+ });
112
+ }
113
+ catch (error) {
114
+ return new Response(JSON.stringify({ error: String(error) }), {
115
+ status: 500,
116
+ headers: { "Content-Type": "application/json" },
117
+ });
118
+ }
119
+ }
120
+ // Fall through to regular fetch for any other requests
121
+ return fetch(url, options);
122
+ };
123
+ }
124
+ /**
125
+ * Set up the Cap.js adapter with the client and automation ID.
126
+ * Must be called before the Cap.js widget is activated.
127
+ *
128
+ * @param client - The automation client to use for API calls
129
+ * @param automationId - The automation ID to use for challenge endpoints
130
+ */
131
+ export function setupCapAdapter(client, automationId) {
132
+ currentClient = client;
133
+ currentAutomationId = automationId;
134
+ }
135
+ /**
136
+ * Clean up the Cap.js adapter state.
137
+ * The CAP_CUSTOM_FETCH handler remains in place but will error if called
138
+ * without being set up again via setupCapAdapter().
139
+ */
140
+ export function cleanupCapAdapter() {
141
+ if (currentAutomationId) {
142
+ verificationTokens.delete(currentAutomationId);
143
+ }
144
+ currentClient = null;
145
+ currentAutomationId = null;
146
+ }
147
+ //# sourceMappingURL=cap-adapter.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"cap-adapter.js","sourceRoot":"","sources":["../../src/cap-adapter.ts"],"names":[],"mappings":"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"}