@mochabug/adapt-web 1.0.1-rc.30 → 1.0.1-rc.31

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/README.md CHANGED
@@ -6,7 +6,7 @@ Embed Adapt automations in any website.
6
6
  npm install @mochabug/adapt-web
7
7
  ```
8
8
 
9
- **CDN base:** `https://cdn.mochabug.com/adapt/web/1.0.1-rc.30/`
9
+ **CDN base:** `https://cdn.mochabug.com/adapt/web/1.0.1-rc.31/`
10
10
 
11
11
  | Bundle | File | Includes |
12
12
  |--------|------|----------|
@@ -20,8 +20,8 @@ npm install @mochabug/adapt-web
20
20
  Bundles merge into a single `MbAdapt` global, so you can combine them. For example, headless + Cap for automations that need proof-of-work but no UI:
21
21
 
22
22
  ```html
23
- <script src="https://cdn.mochabug.com/adapt/web/1.0.1-rc.30/adapt-core.min.js"></script>
24
- <script src="https://cdn.mochabug.com/adapt/web/1.0.1-rc.30/adapt-web.cap.min.js"></script>
23
+ <script src="https://cdn.mochabug.com/adapt/web/1.0.1-rc.31/adapt-core.min.js"></script>
24
+ <script src="https://cdn.mochabug.com/adapt/web/1.0.1-rc.31/adapt-web.cap.min.js"></script>
25
25
  <script>
26
26
  // MbAdapt has exports from both scripts
27
27
  var client = MbAdapt.createAdaptClient(
@@ -43,12 +43,12 @@ Preload the script and load the stylesheet in `<head>` to eliminate flash of uns
43
43
 
44
44
  ```html
45
45
  <head>
46
- <link rel="preload" href="https://cdn.mochabug.com/adapt/web/1.0.1-rc.30/adapt-web.min.js" as="script">
47
- <link rel="stylesheet" href="https://cdn.mochabug.com/adapt/web/1.0.1-rc.30/styles.css">
46
+ <link rel="preload" href="https://cdn.mochabug.com/adapt/web/1.0.1-rc.31/adapt-web.min.js" as="script">
47
+ <link rel="stylesheet" href="https://cdn.mochabug.com/adapt/web/1.0.1-rc.31/styles.css">
48
48
  </head>
49
49
  <body>
50
50
  <adapt-automation automation-id="YOUR_ID" requires-challenge style="height: 600px"></adapt-automation>
51
- <script src="https://cdn.mochabug.com/adapt/web/1.0.1-rc.30/adapt-web.min.js"></script>
51
+ <script src="https://cdn.mochabug.com/adapt/web/1.0.1-rc.31/adapt-web.min.js"></script>
52
52
  </body>
53
53
  ```
54
54
 
@@ -56,12 +56,12 @@ No challenges? Use the core bundle and drop `requires-challenge`:
56
56
 
57
57
  ```html
58
58
  <head>
59
- <link rel="preload" href="https://cdn.mochabug.com/adapt/web/1.0.1-rc.30/adapt-web.core.min.js" as="script">
60
- <link rel="stylesheet" href="https://cdn.mochabug.com/adapt/web/1.0.1-rc.30/styles.css">
59
+ <link rel="preload" href="https://cdn.mochabug.com/adapt/web/1.0.1-rc.31/adapt-web.core.min.js" as="script">
60
+ <link rel="stylesheet" href="https://cdn.mochabug.com/adapt/web/1.0.1-rc.31/styles.css">
61
61
  </head>
62
62
  <body>
63
63
  <adapt-automation automation-id="YOUR_ID" style="height: 600px"></adapt-automation>
64
- <script src="https://cdn.mochabug.com/adapt/web/1.0.1-rc.30/adapt-web.core.min.js"></script>
64
+ <script src="https://cdn.mochabug.com/adapt/web/1.0.1-rc.31/adapt-web.core.min.js"></script>
65
65
  </body>
66
66
  ```
67
67
 
@@ -71,14 +71,14 @@ Just the element and script. CSS is auto-injected at runtime.
71
71
 
72
72
  ```html
73
73
  <adapt-automation automation-id="YOUR_ID" requires-challenge style="height: 600px"></adapt-automation>
74
- <script src="https://cdn.mochabug.com/adapt/web/1.0.1-rc.30/adapt-web.min.js"></script>
74
+ <script src="https://cdn.mochabug.com/adapt/web/1.0.1-rc.31/adapt-web.min.js"></script>
75
75
  ```
76
76
 
77
77
  Without challenges:
78
78
 
79
79
  ```html
80
80
  <adapt-automation automation-id="YOUR_ID" style="height: 600px"></adapt-automation>
81
- <script src="https://cdn.mochabug.com/adapt/web/1.0.1-rc.30/adapt-web.core.min.js"></script>
81
+ <script src="https://cdn.mochabug.com/adapt/web/1.0.1-rc.31/adapt-web.core.min.js"></script>
82
82
  ```
83
83
 
84
84
  ### ESM
@@ -130,7 +130,7 @@ Initial JSON options can be written directly on the element:
130
130
  signals='{"key":"value"}'
131
131
  style="height: 600px"
132
132
  ></adapt-automation>
133
- <script src="https://cdn.mochabug.com/adapt/web/1.0.1-rc.30/adapt-web.core.min.js"></script>
133
+ <script src="https://cdn.mochabug.com/adapt/web/1.0.1-rc.31/adapt-web.core.min.js"></script>
134
134
  ```
135
135
 
136
136
  For complex values that are easier to build in JavaScript, set properties before loading the bundle:
@@ -142,7 +142,7 @@ For complex values that are easier to build in JavaScript, set properties before
142
142
  el.inheritFrom = { hash: 'mb_session' };
143
143
  el.signals = { key: 'value' };
144
144
  </script>
145
- <script src="https://cdn.mochabug.com/adapt/web/1.0.1-rc.30/adapt-web.core.min.js"></script>
145
+ <script src="https://cdn.mochabug.com/adapt/web/1.0.1-rc.31/adapt-web.core.min.js"></script>
146
146
  ```
147
147
 
148
148
  ### JS-only properties
@@ -186,12 +186,12 @@ Requires a `client` JS property — set it after the element is in the DOM.
186
186
 
187
187
  ```html
188
188
  <head>
189
- <link rel="preload" href="https://cdn.mochabug.com/adapt/web/1.0.1-rc.30/adapt-web.cap.min.js" as="script">
190
- <link rel="stylesheet" href="https://cdn.mochabug.com/adapt/web/1.0.1-rc.30/styles.css">
189
+ <link rel="preload" href="https://cdn.mochabug.com/adapt/web/1.0.1-rc.31/adapt-web.cap.min.js" as="script">
190
+ <link rel="stylesheet" href="https://cdn.mochabug.com/adapt/web/1.0.1-rc.31/styles.css">
191
191
  </head>
192
192
  <body>
193
193
  <adapt-cap automation-id="YOUR_ID"></adapt-cap>
194
- <script src="https://cdn.mochabug.com/adapt/web/1.0.1-rc.30/adapt-web.cap.min.js"></script>
194
+ <script src="https://cdn.mochabug.com/adapt/web/1.0.1-rc.31/adapt-web.cap.min.js"></script>
195
195
  <script>
196
196
  var el = document.querySelector('adapt-cap');
197
197
  el.client = MbAdapt.createConnectClient({ id: 'YOUR_ID' });
@@ -206,7 +206,7 @@ Requires a `client` JS property — set it after the element is in the DOM.
206
206
 
207
207
  ```html
208
208
  <adapt-cap automation-id="YOUR_ID"></adapt-cap>
209
- <script src="https://cdn.mochabug.com/adapt/web/1.0.1-rc.30/adapt-web.cap.min.js"></script>
209
+ <script src="https://cdn.mochabug.com/adapt/web/1.0.1-rc.31/adapt-web.cap.min.js"></script>
210
210
  <script>
211
211
  var el = document.querySelector('adapt-cap');
212
212
  el.client = MbAdapt.createConnectClient({ id: 'YOUR_ID' });
@@ -1 +1 @@
1
- import{setupCapAdapter,cleanupCapAdapter,takeRedeemedChallengeExpiration}from"./cap-adapter.js";import{CAP_WIDGET_CSS}from"./css-cap.js";import"@cap.js/widget";class AdaptCapWidget{constructor(options){this.widgetContainer=null;this.widgetElement=null;this.destroyed=!1;if(!options.automationId)throw new Error('[adapt] AdaptCapWidget requires "automationId".');if(!options.client)throw new Error('[adapt] AdaptCapWidget requires "client". Create one with: createConnectClient({ id: "..." })');if(!options.onSolve)throw new Error('[adapt] AdaptCapWidget requires "onSolve" callback.');this.options=options;const container=typeof options.container=="string"?document.getElementById(options.container):options.container;if(!container)throw new Error(`Container ${typeof options.container=="string"?`with id '${options.container}'`:""} not found`);this.containerElement=container,this.injectStyles(),setupCapAdapter(options.client,options.automationId),this.mountWidget()}injectStyles(){if(getComputedStyle(document.documentElement).getPropertyValue("--mb-adapt-styles-loaded").trim()||document.getElementById("mb-adapt-cap-styles"))return;const style=document.createElement("style");style.id="mb-adapt-cap-styles",style.textContent=CAP_WIDGET_CSS,document.head.appendChild(style)}mountWidget(){this.widgetContainer=document.createElement("div"),this.widgetContainer.className="mb-adapt-cap";const innerContainer=document.createElement("div");if(innerContainer.className="mb-adapt-cap__container",this.widgetElement=document.createElement("cap-widget"),this.widgetElement.setAttribute("data-cap-api-endpoint",`/adapt-cap-${this.options.automationId}/`),this.options.workerCount&&this.widgetElement.setAttribute("data-cap-worker-count",String(this.options.workerCount)),this.options.hiddenFieldName&&this.widgetElement.setAttribute("data-cap-hidden-field-name",this.options.hiddenFieldName),this.options.troubleshootingUrl&&this.widgetElement.setAttribute("data-cap-troubleshooting-url",this.options.troubleshootingUrl),this.options.disableHaptics&&this.widgetElement.setAttribute("data-cap-disable-haptics",""),this.options.i18n){const i18nAttributes=[["initialState","data-cap-i18n-initial-state"],["verifyingLabel","data-cap-i18n-verifying-label"],["solvedLabel","data-cap-i18n-solved-label"],["errorLabel","data-cap-i18n-error-label"],["troubleshootingLabel","data-cap-i18n-troubleshooting-label"],["wasmDisabled","data-cap-i18n-wasm-disabled"],["verifyAriaLabel","data-cap-i18n-verify-aria-label"],["verifyingAriaLabel","data-cap-i18n-verifying-aria-label"],["verifiedAriaLabel","data-cap-i18n-verified-aria-label"],["requiredLabel","data-cap-i18n-required-label"],["errorAriaLabel","data-cap-i18n-error-aria-label"]];for(const[key,attribute]of i18nAttributes){const value=this.options.i18n[key];value&&this.widgetElement.setAttribute(attribute,value)}}this.widgetElement.addEventListener("solve",(e=>{if(this.destroyed)return;const token=e.detail?.token,expiresStr=e.detail?.expires,expires=takeRedeemedChallengeExpiration(this.options.automationId)??(expiresStr?new Date(expiresStr):new Date);setTimeout(()=>this.destroy(),0),token?this.options.onSolve(token,expires):this.options.onError?.(new Error("No token received from Cap.js"))})),this.widgetElement.addEventListener("error",(e=>{this.destroyed||(console.error("[AdaptCapWidget] Cap.js error:",e.detail),setTimeout(()=>this.destroy(),0),this.options.onError?.(new Error(e.detail?.message||"Cap.js error")))})),innerContainer.appendChild(this.widgetElement),this.widgetContainer.appendChild(innerContainer),this.containerElement.appendChild(this.widgetContainer),this.hideCapAttribution()}hideCapAttribution(){const hide=()=>{if(this.destroyed||!this.widgetElement)return;const attribution=this.widgetElement.shadowRoot?.querySelector('[part="attribution"], .credits');attribution&&(attribution.style.setProperty("display","none","important"),attribution.style.setProperty("visibility","hidden","important"),attribution.style.setProperty("pointer-events","none","important"),attribution.setAttribute("aria-hidden","true"),attribution.setAttribute("tabindex","-1"))};hide(),queueMicrotask(hide),setTimeout(hide,0)}setDarkMode(dark){this.widgetContainer&&(dark?this.widgetContainer.classList.add("mb-adapt-cap--dark"):this.widgetContainer.classList.remove("mb-adapt-cap--dark"))}destroy(){this.destroyed||(this.destroyed=!0,cleanupCapAdapter(),this.widgetContainer&&this.widgetContainer.parentNode&&this.widgetContainer.parentNode.removeChild(this.widgetContainer),this.widgetContainer=null,this.widgetElement=null)}}export{AdaptCapWidget};
1
+ import{setupCapAdapter,cleanupCapAdapter,takeRedeemedChallengeExpiration}from"./cap-adapter.js";import{CAP_WIDGET_CSS}from"./css-cap.js";import"@cap.js/widget";class AdaptCapWidget{constructor(options){this.widgetContainer=null;this.widgetElement=null;this.attributionObserver=null;this.destroyed=!1;if(!options.automationId)throw new Error('[adapt] AdaptCapWidget requires "automationId".');if(!options.client)throw new Error('[adapt] AdaptCapWidget requires "client". Create one with: createConnectClient({ id: "..." })');if(!options.onSolve)throw new Error('[adapt] AdaptCapWidget requires "onSolve" callback.');this.options=options;const container=typeof options.container=="string"?document.getElementById(options.container):options.container;if(!container)throw new Error(`Container ${typeof options.container=="string"?`with id '${options.container}'`:""} not found`);this.containerElement=container,this.injectStyles(),setupCapAdapter(options.client,options.automationId),this.mountWidget()}injectStyles(){if(getComputedStyle(document.documentElement).getPropertyValue("--mb-adapt-styles-loaded").trim()||document.getElementById("mb-adapt-cap-styles"))return;const style=document.createElement("style");style.id="mb-adapt-cap-styles",style.textContent=CAP_WIDGET_CSS,document.head.appendChild(style)}mountWidget(){this.widgetContainer=document.createElement("div"),this.widgetContainer.className="mb-adapt-cap";const innerContainer=document.createElement("div");if(innerContainer.className="mb-adapt-cap__container",this.widgetElement=document.createElement("cap-widget"),this.widgetElement.setAttribute("data-cap-api-endpoint",`/adapt-cap-${encodeURIComponent(this.options.automationId)}/`),this.options.workerCount&&this.widgetElement.setAttribute("data-cap-worker-count",String(this.options.workerCount)),this.options.hiddenFieldName&&this.widgetElement.setAttribute("data-cap-hidden-field-name",this.options.hiddenFieldName),this.options.troubleshootingUrl&&this.widgetElement.setAttribute("data-cap-troubleshooting-url",this.options.troubleshootingUrl),this.options.disableHaptics&&this.widgetElement.setAttribute("data-cap-disable-haptics",""),this.options.i18n){const i18nAttributes=[["initialState","data-cap-i18n-initial-state"],["verifyingLabel","data-cap-i18n-verifying-label"],["solvedLabel","data-cap-i18n-solved-label"],["errorLabel","data-cap-i18n-error-label"],["troubleshootingLabel","data-cap-i18n-troubleshooting-label"],["wasmDisabled","data-cap-i18n-wasm-disabled"],["verifyAriaLabel","data-cap-i18n-verify-aria-label"],["verifyingAriaLabel","data-cap-i18n-verifying-aria-label"],["verifiedAriaLabel","data-cap-i18n-verified-aria-label"],["requiredLabel","data-cap-i18n-required-label"],["errorAriaLabel","data-cap-i18n-error-aria-label"]];for(const[key,attribute]of i18nAttributes){const value=this.options.i18n[key];value&&this.widgetElement.setAttribute(attribute,value)}}this.widgetElement.addEventListener("solve",(e=>{if(this.destroyed)return;const token=e.detail?.token,expiresStr=e.detail?.expires,expires=takeRedeemedChallengeExpiration(this.options.automationId)??(expiresStr?new Date(expiresStr):new Date);setTimeout(()=>this.destroy(),0),token?this.options.onSolve(token,expires):this.options.onError?.(new Error("No token received from Cap.js"))})),this.widgetElement.addEventListener("error",(e=>{this.destroyed||(console.error("[AdaptCapWidget] Cap.js error:",e.detail),setTimeout(()=>this.destroy(),0),this.options.onError?.(new Error(e.detail?.message||"Cap.js error")))})),innerContainer.appendChild(this.widgetElement),this.widgetContainer.appendChild(innerContainer),this.containerElement.appendChild(this.widgetContainer),this.hideCapAttribution()}hideCapAttribution(){const hide=()=>{if(this.destroyed||!this.widgetElement)return;const attribution=this.widgetElement.shadowRoot?.querySelector('[part="attribution"], .credits');attribution&&((attribution.style.getPropertyValue("display")!=="none"||attribution.style.getPropertyPriority("display")!=="important")&&attribution.style.setProperty("display","none","important"),(attribution.style.getPropertyValue("visibility")!=="hidden"||attribution.style.getPropertyPriority("visibility")!=="important")&&attribution.style.setProperty("visibility","hidden","important"),(attribution.style.getPropertyValue("pointer-events")!=="none"||attribution.style.getPropertyPriority("pointer-events")!=="important")&&attribution.style.setProperty("pointer-events","none","important"),attribution.getAttribute("aria-hidden")!=="true"&&attribution.setAttribute("aria-hidden","true"),attribution.getAttribute("tabindex")!=="-1"&&attribution.setAttribute("tabindex","-1"))},observe=()=>{this.destroyed||!this.widgetElement?.shadowRoot||(hide(),!(this.attributionObserver||typeof MutationObserver>"u")&&(this.attributionObserver=new MutationObserver(hide),this.attributionObserver.observe(this.widgetElement.shadowRoot,{subtree:!0,childList:!0,attributes:!0,attributeFilter:["style","class","aria-hidden","tabindex"]})))};observe(),queueMicrotask(observe),setTimeout(observe,0),setTimeout(hide,150)}setDarkMode(dark){this.widgetContainer&&(dark?this.widgetContainer.classList.add("mb-adapt-cap--dark"):this.widgetContainer.classList.remove("mb-adapt-cap--dark"))}destroy(){this.destroyed||(this.destroyed=!0,cleanupCapAdapter(this.options.automationId),this.attributionObserver?.disconnect(),this.attributionObserver=null,this.widgetContainer&&this.widgetContainer.parentNode&&this.widgetContainer.parentNode.removeChild(this.widgetContainer),this.widgetContainer=null,this.widgetElement=null)}}export{AdaptCapWidget};
@@ -1 +1 @@
1
- typeof window<"u"&&!window.CAP_CUSTOM_WASM_URL&&(window.CAP_CUSTOM_WASM_URL=new URL("https://cdn.mochabug.com/adapt/web/1.0.1-rc.30/cap_wasm_bg.wasm",window.location.href).href);import{timestampDate}from"@bufbuild/protobuf/wkt";let currentClient=null,currentAutomationId=null;const verificationTokens=new Map,redeemedChallengeExpirations=new Map;async function createChallenge(client,id){const response=await client.createChallenge({id}),instrumentation=response.instrumentation;return{count:response.count,size:response.size,difficulty:response.difficulty,expires:response.expires?timestampDate(response.expires):new Date,token:response.token,verificationToken:response.verificationToken,...instrumentation?{instrumentation}:{}}}async function redeemChallenge(client,id,verificationToken,solutions,options={}){const request={id,verificationToken,solutions,...options.instrumentation?{instrumentation:options.instrumentation}:{},...options.instrumentationBlocked?{instrumentationBlocked:!0}:{},...options.instrumentationTimeout?{instrumentationTimeout:!0}:{}},response=await client.redeemChallenge(request);return{token:response.token,expires:response.expires?timestampDate(response.expires):new Date}}function takeRedeemedChallengeExpiration(automationId){const expires=redeemedChallengeExpirations.get(automationId)??null;return expires&&redeemedChallengeExpirations.delete(automationId),expires}typeof window<"u"&&(window.CAP_CUSTOM_FETCH=async(url,options)=>{const urlStr=url.toString();if(urlStr.endsWith("/challenge")){if(!currentClient||!currentAutomationId)return new Response(JSON.stringify({error:"Cap adapter not initialized"}),{status:500,headers:{"Content-Type":"application/json"}});try{const challengeInfo=await createChallenge(currentClient,currentAutomationId);return verificationTokens.set(currentAutomationId,challengeInfo.verificationToken),redeemedChallengeExpirations.delete(currentAutomationId),new Response(JSON.stringify({challenge:{c:challengeInfo.count,s:challengeInfo.size,d:challengeInfo.difficulty},token:challengeInfo.token,expires:challengeInfo.expires.toISOString(),...challengeInfo.instrumentation?{instrumentation:challengeInfo.instrumentation}:{}}),{status:200,headers:{"Content-Type":"application/json"}})}catch(error){return new Response(JSON.stringify({error:String(error)}),{status:500,headers:{"Content-Type":"application/json"}})}}if(urlStr.endsWith("/redeem")){if(!currentClient||!currentAutomationId)return new Response(JSON.stringify({error:"Cap adapter not initialized"}),{status:500,headers:{"Content-Type":"application/json"}});const verificationToken=verificationTokens.get(currentAutomationId);if(!verificationToken)return new Response(JSON.stringify({error:"No verification token found - challenge must be created first"}),{status:400,headers:{"Content-Type":"application/json"}});try{const body=options?.body?JSON.parse(options.body):{},solutions=(body.solutions||[]).map(s=>BigInt(s)),instrumentationBlocked=body.instr_blocked===!0||body.instr?.__blocked===!0,instrumentationTimeout=body.instr_timeout===!0||body.instr?.__timeout===!0,instrumentation=body.instr&&!instrumentationBlocked&&!instrumentationTimeout?body.instr:void 0,redeemed=await redeemChallenge(currentClient,currentAutomationId,verificationToken,solutions,{...instrumentation?{instrumentation}:{},...instrumentationBlocked?{instrumentationBlocked}:{},...instrumentationTimeout?{instrumentationTimeout}:{}});return redeemedChallengeExpirations.set(currentAutomationId,redeemed.expires),verificationTokens.delete(currentAutomationId),new Response(JSON.stringify({success:!0,token:redeemed.token,expires:redeemed.expires.toISOString()}),{status:200,headers:{"Content-Type":"application/json"}})}catch(error){return new Response(JSON.stringify({error:String(error)}),{status:500,headers:{"Content-Type":"application/json"}})}}return fetch(url,options)});function setupCapAdapter(client,automationId){currentAutomationId&&currentAutomationId!==automationId&&(verificationTokens.delete(currentAutomationId),redeemedChallengeExpirations.delete(currentAutomationId)),currentClient=client,currentAutomationId=automationId,redeemedChallengeExpirations.delete(automationId)}function cleanupCapAdapter(){currentAutomationId&&(verificationTokens.delete(currentAutomationId),redeemedChallengeExpirations.delete(currentAutomationId)),currentClient=null,currentAutomationId=null}export{cleanupCapAdapter,createChallenge,redeemChallenge,setupCapAdapter,takeRedeemedChallengeExpiration};
1
+ typeof window<"u"&&!window.CAP_CUSTOM_WASM_URL&&(window.CAP_CUSTOM_WASM_URL=new URL("https://cdn.mochabug.com/adapt/web/1.0.1-rc.31/cap_wasm_bg.wasm",window.location.href).href);import{timestampDate}from"@bufbuild/protobuf/wkt";const adapterRegistrations=new Map,verificationTokens=new Map,redeemedChallengeExpirations=new Map;function automationIdFromCapUrl(url){const urlStr=url.toString();let pathname=urlStr;try{pathname=new URL(urlStr,typeof window<"u"?window.location.href:void 0).pathname}catch{}const match=pathname.match(/(?:^|\/)adapt-cap-([^/]+)\/(?:challenge|redeem)$/);if(!match?.[1])return null;try{return decodeURIComponent(match[1])}catch{return match[1]}}function adapterForRequest(url){const automationId=automationIdFromCapUrl(url);if(automationId){const registration=adapterRegistrations.get(automationId);return registration?{automationId,client:registration.client}:null}if(adapterRegistrations.size===1){const first=adapterRegistrations.entries().next();if(!first.done){const[singleAutomationId,registration]=first.value;return{automationId:singleAutomationId,client:registration.client}}}return null}async function createChallenge(client,id){const response=await client.createChallenge({id}),instrumentation=response.instrumentation;return{count:response.count,size:response.size,difficulty:response.difficulty,expires:response.expires?timestampDate(response.expires):new Date,token:response.token,verificationToken:response.verificationToken,...instrumentation?{instrumentation}:{}}}async function redeemChallenge(client,id,verificationToken,solutions,options={}){const request={id,verificationToken,solutions,...options.instrumentation?{instrumentation:options.instrumentation}:{},...options.instrumentationBlocked?{instrumentationBlocked:!0}:{},...options.instrumentationTimeout?{instrumentationTimeout:!0}:{}},response=await client.redeemChallenge(request);return{token:response.token,expires:response.expires?timestampDate(response.expires):new Date}}function takeRedeemedChallengeExpiration(automationId){const expires=redeemedChallengeExpirations.get(automationId)??null;return expires&&redeemedChallengeExpirations.delete(automationId),expires}typeof window<"u"&&(window.CAP_CUSTOM_FETCH=async(url,options)=>{const urlStr=url.toString();if(urlStr.endsWith("/challenge")){const adapter=adapterForRequest(url);if(!adapter)return new Response(JSON.stringify({error:"Cap adapter not initialized"}),{status:500,headers:{"Content-Type":"application/json"}});try{const challengeInfo=await createChallenge(adapter.client,adapter.automationId);return verificationTokens.set(adapter.automationId,challengeInfo.verificationToken),redeemedChallengeExpirations.delete(adapter.automationId),new Response(JSON.stringify({challenge:{c:challengeInfo.count,s:challengeInfo.size,d:challengeInfo.difficulty},token:challengeInfo.token,expires:challengeInfo.expires.toISOString(),...challengeInfo.instrumentation?{instrumentation:challengeInfo.instrumentation}:{}}),{status:200,headers:{"Content-Type":"application/json"}})}catch(error){return new Response(JSON.stringify({error:String(error)}),{status:500,headers:{"Content-Type":"application/json"}})}}if(urlStr.endsWith("/redeem")){const adapter=adapterForRequest(url);if(!adapter)return new Response(JSON.stringify({error:"Cap adapter not initialized"}),{status:500,headers:{"Content-Type":"application/json"}});const verificationToken=verificationTokens.get(adapter.automationId);if(!verificationToken)return new Response(JSON.stringify({error:"No verification token found - challenge must be created first"}),{status:400,headers:{"Content-Type":"application/json"}});try{const body=options?.body?JSON.parse(options.body):{},solutions=(body.solutions||[]).map(s=>BigInt(s)),instrumentationBlocked=body.instr_blocked===!0||body.instr?.__blocked===!0,instrumentationTimeout=body.instr_timeout===!0||body.instr?.__timeout===!0,instrumentation=body.instr&&!instrumentationBlocked&&!instrumentationTimeout?body.instr:void 0,redeemed=await redeemChallenge(adapter.client,adapter.automationId,verificationToken,solutions,{...instrumentation?{instrumentation}:{},...instrumentationBlocked?{instrumentationBlocked}:{},...instrumentationTimeout?{instrumentationTimeout}:{}});return redeemedChallengeExpirations.set(adapter.automationId,redeemed.expires),verificationTokens.delete(adapter.automationId),new Response(JSON.stringify({success:!0,token:redeemed.token,expires:redeemed.expires.toISOString()}),{status:200,headers:{"Content-Type":"application/json"}})}catch(error){return new Response(JSON.stringify({error:String(error)}),{status:500,headers:{"Content-Type":"application/json"}})}}return fetch(url,options)});function setupCapAdapter(client,automationId){const registration=adapterRegistrations.get(automationId);registration?(registration.client=client,registration.references+=1):adapterRegistrations.set(automationId,{client,references:1}),redeemedChallengeExpirations.delete(automationId)}function cleanupCapAdapter(automationId){if(!automationId){adapterRegistrations.clear(),verificationTokens.clear(),redeemedChallengeExpirations.clear();return}const registration=adapterRegistrations.get(automationId);if(registration&&registration.references>1){registration.references-=1;return}adapterRegistrations.delete(automationId),verificationTokens.delete(automationId),redeemedChallengeExpirations.delete(automationId)}export{cleanupCapAdapter,createChallenge,redeemChallenge,setupCapAdapter,takeRedeemedChallengeExpiration};
@@ -5,8 +5,8 @@ import type { CapWidgetI18n } from "./types.js";
5
5
  *
6
6
  * Renders a Cap.js widget that handles challenge creation, solving, and redemption.
7
7
  * The widget is styled through CSS custom properties. Avoid styling Cap.js
8
- * internals directly; this package only uses Cap's public attribution part to
9
- * remove the attribution required by Adapt embeds.
8
+ * internals directly; this package only touches Cap's attribution node so
9
+ * Adapt embeds do not show Cap branding.
10
10
  *
11
11
  * The widget initializes when both `automation-id` (attribute) and `client` (JS property)
12
12
  * are set. It auto-destroys after a successful solve.
@@ -8,9 +8,8 @@
8
8
  *
9
9
  * **Styling:** The widget is themed through CSS custom properties
10
10
  * (`--mb-cap-*` on the `.mb-adapt-cap` wrapper -> mapped to Cap.js `--cap-*`
11
- * variables). Avoid styling Cap.js internals directly; the only supported
12
- * exception here is hiding Cap's attribution via its public `part="attribution"`
13
- * hook, which is also reinforced at runtime because Cap marks it `display:block!important`.
11
+ * variables). Avoid styling Cap.js internals directly; this wrapper only
12
+ * touches Cap's attribution node so Adapt embeds do not show Cap branding.
14
13
  *
15
14
  * @example
16
15
  * ```typescript
@@ -102,6 +101,7 @@ export declare class AdaptCapWidget {
102
101
  private containerElement;
103
102
  private widgetContainer;
104
103
  private widgetElement;
104
+ private attributionObserver;
105
105
  private destroyed;
106
106
  private options;
107
107
  constructor(options: AdaptCapWidgetOptions);
@@ -43,4 +43,4 @@ export declare function setupCapAdapter(client: AutomationClient, automationId:
43
43
  * The CAP_CUSTOM_FETCH handler remains in place but will error if called
44
44
  * without being set up again via setupCapAdapter().
45
45
  */
46
- export declare function cleanupCapAdapter(): void;
46
+ export declare function cleanupCapAdapter(automationId?: string): void;