@thavguard/arc-pay 0.1.0 → 0.1.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/LICENSE ADDED
@@ -0,0 +1,21 @@
1
+ MIT License
2
+
3
+ Copyright (c) 2026 Finext
4
+
5
+ Permission is hereby granted, free of charge, to any person obtaining a copy
6
+ of this software and associated documentation files (the "Software"), to deal
7
+ in the Software without restriction, including without limitation the rights
8
+ to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
9
+ copies of the Software, and to permit persons to whom the Software is
10
+ furnished to do so, subject to the following conditions:
11
+
12
+ The above copyright notice and this permission notice shall be included in all
13
+ copies or substantial portions of the Software.
14
+
15
+ THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
16
+ IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
17
+ FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
18
+ AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
19
+ LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
20
+ OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
21
+ SOFTWARE.
package/README.md CHANGED
@@ -11,14 +11,17 @@ npm install @thavguard/arc-pay
11
11
  ## Browser SDK
12
12
 
13
13
  ```ts
14
- import { ArcPay } from "@thavguard/arc-pay";
14
+ import { ArcPay } from "@thavguard/arc-pay/js";
15
15
 
16
- const arcpay = await ArcPay.load({
17
- publishableKey: "pk_test_...",
18
- environment: "sandbox",
19
- });
16
+ const arcpay = await ArcPay.load("pk_test_...");
17
+ const elements = arcpay.elements();
20
18
  ```
21
19
 
20
+ `ArcPay.load()` takes the publishable key as the first argument. Sandbox/live is
21
+ inferred from the key prefix (`pk_test_` or `pk_live_`). Hosted Fields are served
22
+ from `https://sdk.arcpay.space` and tokenize against the Arc Pay public API
23
+ configured for that iframe app.
24
+
22
25
  ## React Bindings
23
26
 
24
27
  ```ts
@@ -36,3 +39,33 @@ const client = createArcPayClient({
36
39
  ```
37
40
 
38
41
  Amounts are integer minor units. Never pass card PAN or CVV to server APIs; use Hosted Fields for browser card entry.
42
+
43
+ Browser pages using Hosted Fields must allow frames from `https://sdk.arcpay.space`
44
+ and API connections to `https://api.arcpay.space`. If your Content Security
45
+ Policy also governs telemetry, allow connections to your configured Sentry ingest
46
+ host or disable browser telemetry at your application layer.
47
+
48
+ Hosted Fields performs a browser settings check against Arc Pay API before
49
+ mounting fields. That check is internal to the SDK; merchants should configure
50
+ CSP for the public origins above, not call the settings endpoint directly.
51
+ Tokenization requests are sent from `https://sdk.arcpay.space` to the public API
52
+ with `Authorization: Bearer <pk_...>`, `Content-Type`, optional
53
+ `Idempotency-Key`, `sentry-trace`, and `baggage` headers. Direct REST callers
54
+ may use either `Authorization: Bearer <pk_...>` or `X-Api-Key: pk_...` for
55
+ `/payments/{id}/tokenize`.
56
+
57
+ `@thavguard/arc-pay/server` intentionally does not expose `tokenizeCard()`.
58
+ Tokenization belongs to Hosted Fields. Direct browser calls with a publishable
59
+ key are only for explicitly approved raw-card forms; those forms handle
60
+ cardholder data in the merchant environment and require the applicable PCI DSS
61
+ controls before live traffic. Keep `sk_*` keys on your backend for payment
62
+ creation, execution, capture, void, refund, saved-card charges, payment links,
63
+ and checkout sessions.
64
+
65
+ The server client accepts an optional `apiBase` only for local or isolated test
66
+ environments. Production integrations should use the default
67
+ `https://api.arcpay.space/v1`; sandbox/live is selected by the key prefix.
68
+
69
+ ## License
70
+
71
+ MIT.
@@ -18,40 +18,11 @@ type ParentToIframe = {
18
18
  paymentId: string;
19
19
  idempotencyKey: string;
20
20
  };
21
- type IframeToParent = {
22
- type: "arcpay:ready";
23
- } | {
24
- type: "arcpay:rejected";
25
- reason: string;
26
- } | {
27
- type: "arcpay:change";
28
- field: FieldType;
29
- isValid: boolean;
30
- brand?: string;
31
- lastFour?: string;
32
- } | {
33
- type: "arcpay:tokenize-result";
34
- cardTokenId: string;
35
- cardMask: string;
36
- cardScheme: string;
37
- cardBin: string;
38
- expiresAt: string;
39
- } | {
40
- type: "arcpay:tokenize-error";
41
- errorType: string;
42
- code?: string;
43
- message: string;
44
- };
45
21
  interface StyleSubset {
46
22
  base: Record<string, string>;
47
23
  invalid?: Record<string, string>;
48
24
  focus?: Record<string, string>;
49
25
  }
50
- declare const postToIframe: (iframe: HTMLIFrameElement, message: ParentToIframe, targetOrigin: string) => void;
51
- declare const postToParent: (message: IframeToParent, targetOrigin: string) => void;
52
- declare const parseIncoming: <T extends {
53
- type: string;
54
- }>(event: MessageEvent, expectedOrigin: string) => T | null;
55
26
 
56
27
  interface ElementOptions {
57
28
  /** StyleSubset applied via arcpay:style postMessage. */
@@ -105,27 +76,16 @@ declare class Element {
105
76
  private emit;
106
77
  }
107
78
 
108
- interface TokenizeRequestInput {
109
- pan: string;
110
- cvv: string;
111
- expiryMonth: string;
112
- expiryYear: string;
113
- }
114
-
115
79
  interface TokenizeResult {
116
80
  cardTokenId: string;
117
81
  cardMask: string;
118
82
  cardScheme: string;
119
83
  cardBin: string;
84
+ expiresIn: number;
120
85
  expiresAt: string;
121
86
  }
122
- interface TokenizeRequest extends TokenizeRequestInput {
123
- paymentId: string;
124
- }
125
87
 
126
- interface ElementsOptions {
127
- iframeBase?: string;
128
- }
88
+ type ElementsOptions = Record<string, never>;
129
89
  declare class Elements {
130
90
  private readonly elementMap;
131
91
  private readonly iframeBase;
@@ -143,18 +103,17 @@ declare class Elements {
143
103
  }
144
104
 
145
105
  interface ArcPayLoadOptions {
146
- apiBase?: string;
106
+ readonly _reserved?: never;
147
107
  }
148
108
  interface ArcPayInstance {
149
109
  readonly publishableKey: string;
150
- readonly apiBase: string;
151
110
  readonly environment: Environment;
152
111
  elements: (opts?: ElementsOptions) => Elements;
153
112
  }
154
- declare function load(publishableKey: string, opts?: ArcPayLoadOptions): Promise<ArcPayInstance>;
113
+ declare function load(publishableKey: string): Promise<ArcPayInstance>;
155
114
  declare const ArcPay: {
156
115
  load: typeof load;
157
116
  __resetForTests: () => void;
158
117
  };
159
118
 
160
- export { ArcPay as A, Element as E, type FieldType as F, type IframeToParent as I, type ParentToIframe as P, type StyleSubset as S, type TokenizeRequest as T, type ArcPayInstance as a, type ArcPayLoadOptions as b, type ElementContext as c, type ElementEvent as d, type ElementOptions as e, Elements as f, type ElementsOptions as g, type Environment as h, type TokenizeResult as i, postToIframe as j, postToParent as k, parseIncoming as p };
119
+ export { ArcPay as A, type ElementEvent as E, type FieldType as F, type TokenizeResult as T, type ArcPayInstance as a, type ArcPayLoadOptions as b, type ElementOptions as c, Elements as d, type ElementsOptions as e, type Environment as f };
@@ -18,40 +18,11 @@ type ParentToIframe = {
18
18
  paymentId: string;
19
19
  idempotencyKey: string;
20
20
  };
21
- type IframeToParent = {
22
- type: "arcpay:ready";
23
- } | {
24
- type: "arcpay:rejected";
25
- reason: string;
26
- } | {
27
- type: "arcpay:change";
28
- field: FieldType;
29
- isValid: boolean;
30
- brand?: string;
31
- lastFour?: string;
32
- } | {
33
- type: "arcpay:tokenize-result";
34
- cardTokenId: string;
35
- cardMask: string;
36
- cardScheme: string;
37
- cardBin: string;
38
- expiresAt: string;
39
- } | {
40
- type: "arcpay:tokenize-error";
41
- errorType: string;
42
- code?: string;
43
- message: string;
44
- };
45
21
  interface StyleSubset {
46
22
  base: Record<string, string>;
47
23
  invalid?: Record<string, string>;
48
24
  focus?: Record<string, string>;
49
25
  }
50
- declare const postToIframe: (iframe: HTMLIFrameElement, message: ParentToIframe, targetOrigin: string) => void;
51
- declare const postToParent: (message: IframeToParent, targetOrigin: string) => void;
52
- declare const parseIncoming: <T extends {
53
- type: string;
54
- }>(event: MessageEvent, expectedOrigin: string) => T | null;
55
26
 
56
27
  interface ElementOptions {
57
28
  /** StyleSubset applied via arcpay:style postMessage. */
@@ -105,27 +76,16 @@ declare class Element {
105
76
  private emit;
106
77
  }
107
78
 
108
- interface TokenizeRequestInput {
109
- pan: string;
110
- cvv: string;
111
- expiryMonth: string;
112
- expiryYear: string;
113
- }
114
-
115
79
  interface TokenizeResult {
116
80
  cardTokenId: string;
117
81
  cardMask: string;
118
82
  cardScheme: string;
119
83
  cardBin: string;
84
+ expiresIn: number;
120
85
  expiresAt: string;
121
86
  }
122
- interface TokenizeRequest extends TokenizeRequestInput {
123
- paymentId: string;
124
- }
125
87
 
126
- interface ElementsOptions {
127
- iframeBase?: string;
128
- }
88
+ type ElementsOptions = Record<string, never>;
129
89
  declare class Elements {
130
90
  private readonly elementMap;
131
91
  private readonly iframeBase;
@@ -143,18 +103,17 @@ declare class Elements {
143
103
  }
144
104
 
145
105
  interface ArcPayLoadOptions {
146
- apiBase?: string;
106
+ readonly _reserved?: never;
147
107
  }
148
108
  interface ArcPayInstance {
149
109
  readonly publishableKey: string;
150
- readonly apiBase: string;
151
110
  readonly environment: Environment;
152
111
  elements: (opts?: ElementsOptions) => Elements;
153
112
  }
154
- declare function load(publishableKey: string, opts?: ArcPayLoadOptions): Promise<ArcPayInstance>;
113
+ declare function load(publishableKey: string): Promise<ArcPayInstance>;
155
114
  declare const ArcPay: {
156
115
  load: typeof load;
157
116
  __resetForTests: () => void;
158
117
  };
159
118
 
160
- export { ArcPay as A, Element as E, type FieldType as F, type IframeToParent as I, type ParentToIframe as P, type StyleSubset as S, type TokenizeRequest as T, type ArcPayInstance as a, type ArcPayLoadOptions as b, type ElementContext as c, type ElementEvent as d, type ElementOptions as e, Elements as f, type ElementsOptions as g, type Environment as h, type TokenizeResult as i, postToIframe as j, postToParent as k, parseIncoming as p };
119
+ export { ArcPay as A, type ElementEvent as E, type FieldType as F, type TokenizeResult as T, type ArcPayInstance as a, type ArcPayLoadOptions as b, type ElementOptions as c, Elements as d, type ElementsOptions as e, type Environment as f };
@@ -1,3 +1,3 @@
1
- var ArcPay=(function(exports){'use strict';var o=class extends Error{constructor(t){super(t.message),this.name="ArcPayError",this.type=t.type,this.code=t.code,this.param=t.param,this.paymentId=t.paymentId,this.declineCode=t.declineCode,this.retryable=t.retryable,this.requestId=t.requestId;}},A=e=>e instanceof o&&e.type==="validation_error",I=e=>e instanceof o&&e.type==="authentication_error",S=e=>e instanceof o&&e.type==="authorization_error",z=e=>e instanceof o&&e.type==="state_error",C=e=>e instanceof o&&e.type==="rate_limit_error",R=e=>e instanceof o&&e.type==="api_error",B=e=>e instanceof o&&e.type==="network_error",M=e=>e instanceof o&&e.type==="challenge_aborted";var L=()=>{var t;if(typeof document=="undefined")return null;let e=document.head.querySelector('meta[http-equiv="Content-Security-Policy"]');return (t=e==null?void 0:e.getAttribute("content"))!=null?t:null},F=(e,t)=>{let n=e.toLowerCase().indexOf(`${t} `);if(n===-1)return null;let s=e.slice(n+t.length+1),i=s.indexOf(";");return (i===-1?s:s.slice(0,i)).trim()},O=(e,t)=>{let r=e.split(/\s+/).filter(Boolean);return r.includes("*")?true:r.some(n=>{if(n===t)return true;if(n.startsWith("https://*")){let s=n.slice(9);return t.endsWith(s)}return false})},x=e=>{let t=L();if(!t)return;let r=F(t,"connect-src");if(r&&!O(r,e))throw new o({type:"validation_error",code:"csp_blocks_api",message:`CSP connect-src directive does not allow ${e}. Add it to your Content-Security-Policy header.`,retryable:false})};var g=e=>e.startsWith("pk_test_")?"sandbox":"live",w=e=>{if(typeof e!="string"||e.length===0)throw new o({type:"validation_error",code:"invalid_publishable_key",message:"Publishable key must be a non-empty string",retryable:false});if(!e.startsWith("pk_test_")&&!e.startsWith("pk_live_"))throw new o({type:"validation_error",code:"invalid_publishable_key",message:"Publishable key must start with pk_test_ or pk_live_. Secret keys (sk_*) cannot be used in browser.",retryable:false})};var _="data-arcpay-sandbox-banner",T=()=>{if(typeof document=="undefined"||document.querySelector(`[${_}]`))return;let e=document.createElement("div");e.setAttribute(_,""),e.style.cssText="position:fixed;top:0;left:0;right:0;z-index:2147483647;background:#ffd166;color:#222;font:13px/1.4 system-ui,sans-serif;padding:6px 12px;display:flex;align-items:center;justify-content:center;box-shadow:0 1px 3px rgba(0,0,0,0.1);";let t=document.createElement("span");t.textContent="ARC PAY TEST MODE \u2014 payments are simulated",e.appendChild(t);let r=document.createElement("button");r.type="button",r.setAttribute("data-arcpay-banner-dismiss",""),r.textContent="\xD7",r.setAttribute("aria-label","Dismiss test mode banner"),r.style.cssText="margin-left:12px;background:transparent;border:0;font-size:18px;cursor:pointer;color:inherit;",r.addEventListener("click",()=>e.remove()),e.appendChild(r),document.body.appendChild(e);};var W="arcpay:",H=e=>typeof e=="object"&&e!==null&&"type"in e&&typeof e.type=="string"&&e.type.startsWith(W),f=(e,t,r)=>{if(r==="*")throw new o({type:"validation_error",code:"wildcard_origin_forbidden",message:"postToIframe: targetOrigin cannot be '*'",retryable:false});if(!e.contentWindow)throw new o({type:"validation_error",code:"iframe_not_loaded",message:"postToIframe: iframe.contentWindow is null (iframe not mounted)",retryable:false});e.contentWindow.postMessage(t,r);},K=(e,t)=>{if(t==="*")throw new Error("postToParent: targetOrigin cannot be '*'");window.parent.postMessage(e,t);},p=(e,t)=>e.origin!==t||!H(e.data)?null:e.data;var $=new Set(["position","transform","pointer-events","z-index","top","left","right","bottom","inset"]),h=e=>{let t={};for(let[r,n]of Object.entries(e)){let s=r.toLowerCase();$.has(s)||(t[r]=n);}return t},u=e=>{let t={base:h(e.base)};return e.invalid!==void 0&&(t.invalid=h(e.invalid)),e.focus!==void 0&&(t.focus=h(e.focus)),t};var d=class{constructor(t,r,n){this.field=t;this.options=r;this.context=n;this.iframe=null;this.listeners=new Set;this.status="pending";this.messageHandler=null;}mount(t){if(this.iframe)throw new o({type:"validation_error",code:"already_mounted",message:`Element ${this.field} is already mounted`,retryable:false});let r=typeof t=="string"?document.querySelector(t):t;if(!(r instanceof HTMLElement))throw new o({type:"validation_error",code:"mount_target_not_found",message:`mount target not found: ${String(t)}`,retryable:false});let n=document.createElement("iframe");n.src=`${this.context.iframeBase}/iframe/${this.field}`,n.style.cssText="border:0;width:100%;height:100%;display:block;",n.setAttribute("allow","payment"),n.setAttribute("data-arcpay-element",this.field),r.appendChild(n),this.iframe=n;let s=new URL(this.context.iframeBase).origin;this.messageHandler=i=>{var c;if(i.source!==((c=this.iframe)==null?void 0:c.contentWindow))return;let l=p(i,s);l&&this.handleMessage(l);},window.addEventListener("message",this.messageHandler),n.addEventListener("load",()=>{if(!this.iframe)return;let i={type:"arcpay:hello",origin:window.location.origin,publishableKey:this.context.publishableKey,channelId:this.context.channelId};f(this.iframe,i,s);},{once:true});}handleMessage(t){t.type==="arcpay:ready"?(this.status="ready",this.options.style&&this.send({type:"arcpay:style",payload:u(this.options.style)}),this.emit({type:"ready"})):t.type==="arcpay:rejected"?(this.status="error",this.emit({type:"error",reason:t.reason})):t.type==="arcpay:change"&&t.field===this.field&&this.emit({type:"change",isValid:t.isValid,brand:t.brand,lastFour:t.lastFour});}update(t){t.style&&this.send({type:"arcpay:style",payload:u(t.style)});}destroy(){this.iframe&&(this.iframe.remove(),this.iframe=null),this.messageHandler&&(window.removeEventListener("message",this.messageHandler),this.messageHandler=null),this.listeners.clear(),this.status="pending";}on(t,r){return this.listeners.add(r),()=>this.listeners.delete(r)}focus(){this.send({type:"arcpay:focus"});}clear(){this.send({type:"arcpay:clear"});}isReady(){return this.status==="ready"}getIframeContentWindow(){var t,r;return (r=(t=this.iframe)==null?void 0:t.contentWindow)!=null?r:null}send(t){if(!this.iframe)throw new o({type:"validation_error",code:"not_mounted",message:`Element ${this.field} is not mounted`,retryable:false});f(this.iframe,t,new URL(this.context.iframeBase).origin);}emit(t){for(let r of this.listeners)r(t);}};var D="https://sdk.arcpay.space",U=()=>{var e;if(!((e=globalThis.crypto)!=null&&e.randomUUID))throw new o({type:"validation_error",code:"crypto_unavailable",message:"crypto.randomUUID is required for Hosted Fields",retryable:false});return globalThis.crypto.randomUUID()},y=class{constructor(t){this.elementMap=new Map;this.tokenizeInFlight=false;var r;this.publishableKey=t.publishableKey,this.iframeBase=(r=t.iframeBase)!=null?r:D,this.channelId=U();}create(t,r={}){if(this.elementMap.has(t))throw new o({type:"validation_error",code:"duplicate_element",message:`Element for ${t} already created`,retryable:false});let n={iframeBase:this.iframeBase,publishableKey:this.publishableKey,channelId:this.channelId},s=new d(t,r,n);return this.elementMap.set(t,s),s}async tokenize(t,r){if(this.tokenizeInFlight)throw new o({type:"validation_error",code:"tokenize_in_progress",message:"A tokenize() call is already in progress for this Elements instance",retryable:false});let n=this.elementMap.get("cardNumber"),s=this.elementMap.get("cardExpiry"),i=this.elementMap.get("cardCvv");if(!n||!s||!i)throw new o({type:"validation_error",code:"incomplete_elements",message:"All three elements (cardNumber, cardExpiry, cardCvv) must be created and mounted before tokenize()",retryable:false});if(!n.isReady()||!s.isReady()||!i.isReady())throw new o({type:"validation_error",code:"elements_not_ready",message:"Wait for all elements to fire 'ready' event before tokenize()",retryable:false});this.tokenizeInFlight=true;try{return await this.doTokenize(n,t,r)}finally{this.tokenizeInFlight=false;}}doTokenize(t,r,n){let s=new URL(this.iframeBase).origin,i=t.getIframeContentWindow();return new Promise((l,c)=>{let E=window.setTimeout(()=>{window.removeEventListener("message",m),c(new o({type:"network_error",code:"tokenize_timeout",message:"tokenize() timed out after 30 seconds",retryable:true,paymentId:r}));},3e4),m=v=>{if(i!==null&&v.source!==i)return;let a=p(v,s);if(a){if(a.type==="arcpay:tokenize-result")clearTimeout(E),window.removeEventListener("message",m),l({cardTokenId:a.cardTokenId,cardMask:a.cardMask,cardScheme:a.cardScheme,cardBin:a.cardBin,expiresAt:a.expiresAt});else if(a.type==="arcpay:tokenize-error"){clearTimeout(E),window.removeEventListener("message",m);let P=a.errorType==="validation_error"||a.errorType==="api_error"?a.errorType:"api_error";c(new o({type:P,code:a.code,message:a.message,retryable:false,paymentId:r}));}}};window.addEventListener("message",m),t.send({type:"arcpay:tokenize",paymentId:r,idempotencyKey:n});})}destroy(){for(let t of this.elementMap.values())t.destroy();this.elementMap.clear();}};var q=w,k="https://api.arcpay.space",b=new Map,N=(e,t)=>{var n;let r=(n=t.apiBase)!=null?n:k;return x(r),g(e)==="sandbox"&&T(),{publishableKey:e,apiBase:r,environment:g(e),elements:s=>new y({publishableKey:e,iframeBase:s==null?void 0:s.iframeBase})}};function V(e,t={}){var i;try{q(e);}catch(l){return Promise.reject(l)}let r=`${e}|${(i=t.apiBase)!=null?i:k}`,n=b.get(r);if(n)return n;let s=Promise.resolve(N(e,t));return b.set(r,s),s}var j=()=>{b.clear();},Y={load:V,__resetForTests:j};var X=e=>{if(!/^\d+$/.test(e)||/^0+$/.test(e))return false;let t=0,r=false;for(let n=e.length-1;n>=0;n--){let s=e.charCodeAt(n)-48;r&&(s*=2,s>9&&(s-=9)),t+=s,r=!r;}return t%10===0};var Ee="0.1.0";
2
- exports.ArcPay=Y;exports.ArcPayError=o;exports.Element=d;exports.Elements=y;exports.SDK_VERSION=Ee;exports.isApiError=R;exports.isAuthenticationError=I;exports.isAuthorizationError=S;exports.isChallengeAborted=M;exports.isNetworkError=B;exports.isRateLimitError=C;exports.isStateError=z;exports.isValidationError=A;exports.luhnCheck=X;exports.parseIncoming=p;exports.postToIframe=f;exports.postToParent=K;exports.sanitizeStyle=u;return exports;})({});//# sourceMappingURL=arcpay.global.js.map
1
+ var ArcPay=(function(exports){'use strict';var n=class extends Error{constructor(t){super(t.message),this.name="ArcPayError",this.type=t.type,this.code=t.code,this.param=t.param,this.paymentId=t.paymentId,this.declineCode=t.declineCode,this.retryable=t.retryable,this.requestId=t.requestId;}},T=e=>e instanceof n&&e.type==="validation_error",I=e=>e instanceof n&&e.type==="authentication_error",P=e=>e instanceof n&&e.type==="authorization_error",A=e=>e instanceof n&&e.type==="state_error",z=e=>e instanceof n&&e.type==="rate_limit_error",S=e=>e instanceof n&&e.type==="api_error",R=e=>e instanceof n&&e.type==="network_error",M=e=>e instanceof n&&e.type==="challenge_aborted";var f=e=>e.startsWith("pk_test_")?"sandbox":"live",x=e=>{if(typeof e!="string"||e.length===0)throw new n({type:"validation_error",code:"invalid_publishable_key",message:"Publishable key must be a non-empty string",retryable:false});if(!e.startsWith("pk_test_")&&!e.startsWith("pk_live_"))throw new n({type:"validation_error",code:"invalid_publishable_key",message:"Publishable key must start with pk_test_ or pk_live_. Secret keys (sk_*) cannot be used in browser.",retryable:false})};var w="data-arcpay-sandbox-banner",_=()=>{if(typeof document=="undefined"||document.querySelector(`[${w}]`))return;let e=document.createElement("div");e.setAttribute(w,""),e.style.cssText="position:fixed;top:0;left:0;right:0;z-index:2147483647;background:#ffd166;color:#222;font:13px/1.4 system-ui,sans-serif;padding:6px 12px;display:flex;align-items:center;justify-content:center;box-shadow:0 1px 3px rgba(0,0,0,0.1);";let t=document.createElement("span");t.textContent="ARC PAY TEST MODE \u2014 payments are simulated",e.appendChild(t);let r=document.createElement("button");r.type="button",r.setAttribute("data-arcpay-banner-dismiss",""),r.textContent="\xD7",r.setAttribute("aria-label","Dismiss test mode banner"),r.style.cssText="margin-left:12px;background:transparent;border:0;font-size:18px;cursor:pointer;color:inherit;",r.addEventListener("click",()=>e.remove()),e.appendChild(r),document.body.appendChild(e);};var C="arcpay:",F=e=>typeof e=="object"&&e!==null&&"type"in e&&typeof e.type=="string"&&e.type.startsWith(C),u=(e,t,r)=>{if(r==="*")throw new n({type:"validation_error",code:"wildcard_origin_forbidden",message:"postToIframe: targetOrigin cannot be '*'",retryable:false});if(!e.contentWindow)throw new n({type:"validation_error",code:"iframe_not_loaded",message:"postToIframe: iframe.contentWindow is null (iframe not mounted)",retryable:false});e.contentWindow.postMessage(t,r);};var y=(e,t)=>e.origin!==t||!F(e.data)?null:e.data;var L=new Set(["position","transform","pointer-events","z-index","top","left","right","bottom","inset"]),g=e=>{let t={};for(let[r,o]of Object.entries(e)){let s=r.toLowerCase();L.has(s)||(t[r]=o);}return t},h=e=>{let t={base:g(e.base)};return e.invalid!==void 0&&(t.invalid=g(e.invalid)),e.focus!==void 0&&(t.focus=g(e.focus)),t};var m=class{constructor(t,r,o){this.field=t;this.options=r;this.context=o;this.iframe=null;this.listeners=new Set;this.status="pending";this.messageHandler=null;}mount(t){if(this.iframe)throw new n({type:"validation_error",code:"already_mounted",message:`Element ${this.field} is already mounted`,retryable:false});let r=typeof t=="string"?document.querySelector(t):t;if(!(r instanceof HTMLElement))throw new n({type:"validation_error",code:"mount_target_not_found",message:`mount target not found: ${String(t)}`,retryable:false});let o=document.createElement("iframe");o.src=`${this.context.iframeBase}/iframe/${this.field}`,o.style.cssText="border:0;width:100%;height:100%;display:block;",o.setAttribute("allow","payment"),o.setAttribute("data-arcpay-element",this.field),r.appendChild(o),this.iframe=o;let s=new URL(this.context.iframeBase).origin;this.messageHandler=a=>{var l;if(a.source!==((l=this.iframe)==null?void 0:l.contentWindow))return;let d=y(a,s);d&&this.handleMessage(d);},window.addEventListener("message",this.messageHandler),o.addEventListener("load",()=>{if(!this.iframe)return;let a={type:"arcpay:hello",origin:window.location.origin,publishableKey:this.context.publishableKey,channelId:this.context.channelId};u(this.iframe,a,s);},{once:true});}handleMessage(t){t.type==="arcpay:ready"?(this.status="ready",this.options.style&&this.send({type:"arcpay:style",payload:h(this.options.style)}),this.emit({type:"ready"})):t.type==="arcpay:rejected"?(this.status="error",this.emit({type:"error",reason:t.reason})):t.type==="arcpay:change"&&t.field===this.field&&this.emit({type:"change",isValid:t.isValid,brand:t.brand,lastFour:t.lastFour});}update(t){t.style&&this.send({type:"arcpay:style",payload:h(t.style)});}destroy(){this.iframe&&(this.iframe.remove(),this.iframe=null),this.messageHandler&&(window.removeEventListener("message",this.messageHandler),this.messageHandler=null),this.listeners.clear(),this.status="pending";}on(t,r){return this.listeners.add(r),()=>this.listeners.delete(r)}focus(){this.send({type:"arcpay:focus"});}clear(){this.send({type:"arcpay:clear"});}isReady(){return this.status==="ready"}getIframeContentWindow(){var t,r;return (r=(t=this.iframe)==null?void 0:t.contentWindow)!=null?r:null}send(t){if(!this.iframe)throw new n({type:"validation_error",code:"not_mounted",message:`Element ${this.field} is not mounted`,retryable:false});u(this.iframe,t,new URL(this.context.iframeBase).origin);}emit(t){for(let r of this.listeners)r(t);}};var B="https://sdk.arcpay.space",O=()=>{var e;if(!((e=globalThis.crypto)!=null&&e.randomUUID))throw new n({type:"validation_error",code:"crypto_unavailable",message:"crypto.randomUUID is required for Hosted Fields",retryable:false});return globalThis.crypto.randomUUID()},p=class{constructor(t){this.elementMap=new Map;this.tokenizeInFlight=false;var r;this.publishableKey=t.publishableKey,this.iframeBase=(r=t.iframeBase)!=null?r:B,this.channelId=O();}create(t,r={}){if(this.elementMap.has(t))throw new n({type:"validation_error",code:"duplicate_element",message:`Element for ${t} already created`,retryable:false});let o={iframeBase:this.iframeBase,publishableKey:this.publishableKey,channelId:this.channelId},s=new m(t,r,o);return this.elementMap.set(t,s),s}async tokenize(t,r){if(this.tokenizeInFlight)throw new n({type:"validation_error",code:"tokenize_in_progress",message:"A tokenize() call is already in progress for this Elements instance",retryable:false});let o=this.elementMap.get("cardNumber"),s=this.elementMap.get("cardExpiry"),a=this.elementMap.get("cardCvv");if(!o||!s||!a)throw new n({type:"validation_error",code:"incomplete_elements",message:"All three elements (cardNumber, cardExpiry, cardCvv) must be created and mounted before tokenize()",retryable:false});if(!o.isReady()||!s.isReady()||!a.isReady())throw new n({type:"validation_error",code:"elements_not_ready",message:"Wait for all elements to fire 'ready' event before tokenize()",retryable:false});this.tokenizeInFlight=true;try{return await this.doTokenize(o,t,r)}finally{this.tokenizeInFlight=false;}}doTokenize(t,r,o){let s=new URL(this.iframeBase).origin,a=t.getIframeContentWindow();return new Promise((d,l)=>{let E=window.setTimeout(()=>{window.removeEventListener("message",c),l(new n({type:"network_error",code:"tokenize_timeout",message:"tokenize() timed out after 30 seconds",retryable:true,paymentId:r}));},3e4),c=v=>{if(a!==null&&v.source!==a)return;let i=y(v,s);if(i){if(i.type==="arcpay:tokenize-result")clearTimeout(E),window.removeEventListener("message",c),d({cardTokenId:i.cardTokenId,cardMask:i.cardMask,cardScheme:i.cardScheme,cardBin:i.cardBin,expiresIn:i.expiresIn,expiresAt:i.expiresAt});else if(i.type==="arcpay:tokenize-error"){clearTimeout(E),window.removeEventListener("message",c);let k=i.errorType==="validation_error"||i.errorType==="api_error"?i.errorType:"api_error";l(new n({type:k,code:i.code,message:i.message,retryable:false,paymentId:r}));}}};window.addEventListener("message",c),t.send({type:"arcpay:tokenize",paymentId:r,idempotencyKey:o});})}destroy(){for(let t of this.elementMap.values())t.destroy();this.elementMap.clear();}};var W=x,b=new Map,K=e=>(f(e)==="sandbox"&&_(),{publishableKey:e,environment:f(e),elements:()=>new p({publishableKey:e})});function H(e){try{W(e);}catch(s){return Promise.reject(s)}let t=e,r=b.get(t);if(r)return r;let o=Promise.resolve(K(e));return b.set(t,o),o}var U=()=>{b.clear();},D={load:H,__resetForTests:U};var le="0.1.2";
2
+ exports.ArcPay=D;exports.ArcPayError=n;exports.Elements=p;exports.SDK_VERSION=le;exports.isApiError=S;exports.isAuthenticationError=I;exports.isAuthorizationError=P;exports.isChallengeAborted=M;exports.isNetworkError=R;exports.isRateLimitError=z;exports.isStateError=A;exports.isValidationError=T;return exports;})({});//# sourceMappingURL=arcpay.global.js.map
3
3
  //# sourceMappingURL=arcpay.global.js.map
@@ -1 +1 @@
1
- {"version":3,"sources":["../../src/core/errors.ts","../../src/core/csp.ts","../../src/core/env.ts","../../src/core/sandbox-banner.ts","../../src/elements/postmessage.ts","../../src/elements/style.ts","../../src/elements/element.ts","../../src/elements/elements.ts","../../src/core/arcpay.ts","../../src/tokenize/luhn.ts","../../src/index.ts"],"names":["ArcPayError","init","isValidationError","isAuthenticationError","isAuthorizationError","isStateError","isRateLimitError","isApiError","isNetworkError","isChallengeAborted","readCspContent","_a","meta","extractDirective","csp","name","idx","rest","end","directiveAllowsHost","directive","host","tokens","t","suffix","verifyCspAllowsApiBase","apiBase","detectEnvironment","publishableKey","validatePublishableKey","key","BANNER_ATTR","showSandboxBanner","bar","text","dismiss","ARCPAY_TYPE_PREFIX","isArcpayMessage","data","postToIframe","iframe","message","targetOrigin","postToParent","parseIncoming","event","expectedOrigin","FORBIDDEN_PROPERTIES","sanitizeBlock","block","out","value","normalizedKey","sanitizeStyle","style","result","Element","field","options","context","target","container","hello","_event","callback","_b","listener","DEFAULT_IFRAME_BASE","createChannelId","Elements","opts","ctx","element","paymentId","idempotencyKey","cardNumber","cardExpiry","cardCvv","iframeOrigin","cardIframeWindow","resolve","reject","timer","onMessage","errType","el","DEFAULT_API_BASE","cache","buildInstance","elemOpts","load","err","existing","promise","resetForTests","ArcPay","luhnCheck","pan","sum","alternate","i","n","SDK_VERSION"],"mappings":"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","file":"arcpay.global.js","sourcesContent":["export type ArcPayErrorType =\n | \"validation_error\"\n | \"authentication_error\"\n | \"authorization_error\"\n | \"state_error\"\n | \"rate_limit_error\"\n | \"api_error\"\n | \"network_error\"\n | \"challenge_aborted\";\n\nexport interface ArcPayErrorInit {\n type: ArcPayErrorType;\n message: string;\n code?: string;\n param?: string;\n paymentId?: string;\n declineCode?: string;\n retryable: boolean;\n requestId?: string;\n}\n\nexport class ArcPayError extends Error {\n readonly type: ArcPayErrorType;\n readonly code?: string;\n readonly param?: string;\n readonly paymentId?: string;\n readonly declineCode?: string;\n readonly retryable: boolean;\n readonly requestId?: string;\n\n constructor(init: ArcPayErrorInit) {\n super(init.message);\n this.name = \"ArcPayError\";\n this.type = init.type;\n this.code = init.code;\n this.param = init.param;\n this.paymentId = init.paymentId;\n this.declineCode = init.declineCode;\n this.retryable = init.retryable;\n this.requestId = init.requestId;\n }\n}\n\nexport const isValidationError = (e: unknown): e is ArcPayError =>\n e instanceof ArcPayError && e.type === \"validation_error\";\nexport const isAuthenticationError = (e: unknown): e is ArcPayError =>\n e instanceof ArcPayError && e.type === \"authentication_error\";\nexport const isAuthorizationError = (e: unknown): e is ArcPayError =>\n e instanceof ArcPayError && e.type === \"authorization_error\";\nexport const isStateError = (e: unknown): e is ArcPayError =>\n e instanceof ArcPayError && e.type === \"state_error\";\nexport const isRateLimitError = (e: unknown): e is ArcPayError =>\n e instanceof ArcPayError && e.type === \"rate_limit_error\";\nexport const isApiError = (e: unknown): e is ArcPayError =>\n e instanceof ArcPayError && e.type === \"api_error\";\nexport const isNetworkError = (e: unknown): e is ArcPayError =>\n e instanceof ArcPayError && e.type === \"network_error\";\nexport const isChallengeAborted = (e: unknown): e is ArcPayError =>\n e instanceof ArcPayError && e.type === \"challenge_aborted\";\n","import { ArcPayError } from \"./errors\";\n\nconst readCspContent = (): string | null => {\n if (typeof document === \"undefined\") return null;\n const meta = document.head.querySelector<HTMLMetaElement>(\n 'meta[http-equiv=\"Content-Security-Policy\"]',\n );\n return meta?.getAttribute(\"content\") ?? null;\n};\n\nconst extractDirective = (csp: string, name: string): string | null => {\n const lower = csp.toLowerCase();\n const idx = lower.indexOf(`${name} `);\n if (idx === -1) return null;\n const rest = csp.slice(idx + name.length + 1);\n const end = rest.indexOf(\";\");\n return (end === -1 ? rest : rest.slice(0, end)).trim();\n};\n\nconst directiveAllowsHost = (directive: string, host: string): boolean => {\n const tokens = directive.split(/\\s+/).filter(Boolean);\n if (tokens.includes(\"*\")) return true;\n return tokens.some((t) => {\n if (t === host) return true;\n if (t.startsWith(\"https://*\")) {\n const suffix = t.slice(\"https://*\".length);\n return host.endsWith(suffix);\n }\n return false;\n });\n};\n\nexport const verifyCspAllowsApiBase = (apiBase: string): void => {\n const csp = readCspContent();\n if (!csp) return;\n const directive = extractDirective(csp, \"connect-src\");\n if (!directive) return;\n if (directiveAllowsHost(directive, apiBase)) return;\n throw new ArcPayError({\n type: \"validation_error\",\n code: \"csp_blocks_api\",\n message: `CSP connect-src directive does not allow ${apiBase}. Add it to your Content-Security-Policy header.`,\n retryable: false,\n });\n};\n","import { ArcPayError } from \"./errors\";\n\nexport type Environment = \"sandbox\" | \"live\";\n\nexport const detectEnvironment = (publishableKey: string): Environment =>\n publishableKey.startsWith(\"pk_test_\") ? \"sandbox\" : \"live\";\n\nexport const validatePublishableKey = (key: unknown): asserts key is string => {\n if (typeof key !== \"string\" || key.length === 0) {\n throw new ArcPayError({\n type: \"validation_error\",\n code: \"invalid_publishable_key\",\n message: \"Publishable key must be a non-empty string\",\n retryable: false,\n });\n }\n if (!key.startsWith(\"pk_test_\") && !key.startsWith(\"pk_live_\")) {\n throw new ArcPayError({\n type: \"validation_error\",\n code: \"invalid_publishable_key\",\n message:\n \"Publishable key must start with pk_test_ or pk_live_. Secret keys (sk_*) cannot be used in browser.\",\n retryable: false,\n });\n }\n};\n","const BANNER_ATTR = \"data-arcpay-sandbox-banner\";\n\nexport const showSandboxBanner = (): void => {\n if (typeof document === \"undefined\") return;\n if (document.querySelector(`[${BANNER_ATTR}]`)) return;\n\n const bar = document.createElement(\"div\");\n bar.setAttribute(BANNER_ATTR, \"\");\n bar.style.cssText =\n \"position:fixed;top:0;left:0;right:0;z-index:2147483647;background:#ffd166;color:#222;font:13px/1.4 system-ui,sans-serif;padding:6px 12px;display:flex;align-items:center;justify-content:center;box-shadow:0 1px 3px rgba(0,0,0,0.1);\";\n\n const text = document.createElement(\"span\");\n text.textContent = \"ARC PAY TEST MODE — payments are simulated\";\n bar.appendChild(text);\n\n const dismiss = document.createElement(\"button\");\n dismiss.type = \"button\";\n dismiss.setAttribute(\"data-arcpay-banner-dismiss\", \"\");\n dismiss.textContent = \"×\";\n dismiss.setAttribute(\"aria-label\", \"Dismiss test mode banner\");\n dismiss.style.cssText =\n \"margin-left:12px;background:transparent;border:0;font-size:18px;cursor:pointer;color:inherit;\";\n dismiss.addEventListener(\"click\", () => bar.remove());\n bar.appendChild(dismiss);\n\n document.body.appendChild(bar);\n};\n","import { ArcPayError } from \"../core/errors\";\n\nexport type FieldType = \"cardNumber\" | \"cardExpiry\" | \"cardCvv\";\n\n// Parent → iframe\nexport type ParentToIframe =\n | { type: \"arcpay:hello\"; origin: string; publishableKey: string; channelId: string }\n | { type: \"arcpay:style\"; payload: StyleSubset }\n | { type: \"arcpay:focus\" }\n | { type: \"arcpay:clear\" }\n | { type: \"arcpay:tokenize\"; paymentId: string; idempotencyKey: string };\n\n// iframe → parent\nexport type IframeToParent =\n | { type: \"arcpay:ready\" }\n | { type: \"arcpay:rejected\"; reason: string }\n | {\n type: \"arcpay:change\";\n field: FieldType;\n isValid: boolean;\n brand?: string;\n lastFour?: string;\n }\n | {\n type: \"arcpay:tokenize-result\";\n cardTokenId: string;\n cardMask: string;\n cardScheme: string;\n cardBin: string;\n expiresAt: string;\n }\n | { type: \"arcpay:tokenize-error\"; errorType: string; code?: string; message: string };\n\nexport interface StyleSubset {\n base: Record<string, string>;\n invalid?: Record<string, string>;\n focus?: Record<string, string>;\n}\n\nconst ARCPAY_TYPE_PREFIX = \"arcpay:\";\n\nconst isArcpayMessage = (data: unknown): data is { type: string } =>\n typeof data === \"object\" &&\n data !== null &&\n \"type\" in data &&\n typeof (data as { type: unknown }).type === \"string\" &&\n (data as { type: string }).type.startsWith(ARCPAY_TYPE_PREFIX);\n\nexport const postToIframe = (\n iframe: HTMLIFrameElement,\n message: ParentToIframe,\n targetOrigin: string,\n): void => {\n if (targetOrigin === \"*\") {\n throw new ArcPayError({\n type: \"validation_error\",\n code: \"wildcard_origin_forbidden\",\n message: \"postToIframe: targetOrigin cannot be '*'\",\n retryable: false,\n });\n }\n if (!iframe.contentWindow) {\n throw new ArcPayError({\n type: \"validation_error\",\n code: \"iframe_not_loaded\",\n message: \"postToIframe: iframe.contentWindow is null (iframe not mounted)\",\n retryable: false,\n });\n }\n iframe.contentWindow.postMessage(message, targetOrigin);\n};\n\nexport const postToParent = (message: IframeToParent, targetOrigin: string): void => {\n if (targetOrigin === \"*\") {\n throw new Error(\"postToParent: targetOrigin cannot be '*'\");\n }\n window.parent.postMessage(message, targetOrigin);\n};\n\nexport const parseIncoming = <T extends { type: string }>(\n event: MessageEvent,\n expectedOrigin: string,\n): T | null => {\n if (event.origin !== expectedOrigin) return null;\n if (!isArcpayMessage(event.data)) return null;\n return event.data as T;\n};\n","import type { StyleSubset } from \"./postmessage\";\n\n// Spec calls out position:fixed, transform, pointer-events:none as forbidden.\n// We extend to cover the full clickjacking attack surface: any positioning\n// (fixed/absolute/sticky), transform, all pointer-events values, z-index, and\n// inset properties (top/left/right/bottom/inset). The legitimate use cases\n// for these in a 1-line input field are zero, so blanket drop.\nconst FORBIDDEN_PROPERTIES = new Set([\n \"position\",\n \"transform\",\n \"pointer-events\",\n \"z-index\",\n \"top\",\n \"left\",\n \"right\",\n \"bottom\",\n \"inset\",\n]);\n\nconst sanitizeBlock = (block: Record<string, string>): Record<string, string> => {\n const out: Record<string, string> = {};\n for (const [key, value] of Object.entries(block)) {\n const normalizedKey = key.toLowerCase();\n if (FORBIDDEN_PROPERTIES.has(normalizedKey)) {\n // Defense against position/transform-based clickjacking. Silently drop.\n continue;\n }\n out[key] = value;\n }\n return out;\n};\n\nexport const sanitizeStyle = (style: StyleSubset): StyleSubset => {\n const result: StyleSubset = { base: sanitizeBlock(style.base) };\n if (style.invalid !== undefined) result.invalid = sanitizeBlock(style.invalid);\n if (style.focus !== undefined) result.focus = sanitizeBlock(style.focus);\n return result;\n};\n","import { ArcPayError } from \"../core/errors\";\nimport {\n type FieldType,\n type ParentToIframe,\n type IframeToParent,\n type StyleSubset,\n postToIframe,\n parseIncoming,\n} from \"./postmessage\";\nimport { sanitizeStyle } from \"./style\";\n\nexport interface ElementOptions {\n /** StyleSubset applied via arcpay:style postMessage. */\n style?: StyleSubset;\n placeholder?: string;\n}\n\nexport type ElementEvent =\n | { type: \"ready\" }\n | { type: \"change\"; isValid: boolean; brand?: string; lastFour?: string }\n | { type: \"error\"; reason: string };\n\ntype Listener = (event: ElementEvent) => void;\n\nexport interface ElementContext {\n iframeBase: string;\n publishableKey: string;\n channelId: string;\n}\n\nexport class Element {\n private iframe: HTMLIFrameElement | null = null;\n private readonly listeners = new Set<Listener>();\n private status: \"pending\" | \"ready\" | \"error\" = \"pending\";\n private messageHandler: ((e: MessageEvent) => void) | null = null;\n\n constructor(\n public readonly field: FieldType,\n private readonly options: ElementOptions,\n private readonly context: ElementContext,\n ) {}\n\n mount(target: string | HTMLElement): void {\n if (this.iframe) {\n throw new ArcPayError({\n type: \"validation_error\",\n code: \"already_mounted\",\n message: `Element ${this.field} is already mounted`,\n retryable: false,\n });\n }\n const container = typeof target === \"string\" ? document.querySelector(target) : target;\n if (!(container instanceof HTMLElement)) {\n throw new ArcPayError({\n type: \"validation_error\",\n code: \"mount_target_not_found\",\n message: `mount target not found: ${String(target)}`,\n retryable: false,\n });\n }\n\n const iframe = document.createElement(\"iframe\");\n iframe.src = `${this.context.iframeBase}/iframe/${this.field}`;\n iframe.style.cssText = \"border:0;width:100%;height:100%;display:block;\";\n iframe.setAttribute(\"allow\", \"payment\");\n iframe.setAttribute(\"data-arcpay-element\", this.field);\n container.appendChild(iframe);\n this.iframe = iframe;\n\n const expectedOrigin = new URL(this.context.iframeBase).origin;\n\n this.messageHandler = (event: MessageEvent) => {\n // C1: source guard — only accept messages from this element's own iframe.\n // Without this, any iframe at the same origin (e.g. cardExpiry, cardCvv)\n // could trigger handlers on cardNumber and vice-versa.\n if (event.source !== this.iframe?.contentWindow) return;\n // C4: use parseIncoming for origin + arcpay: prefix guard.\n const data = parseIncoming<IframeToParent>(event, expectedOrigin);\n if (!data) return;\n this.handleMessage(data);\n };\n window.addEventListener(\"message\", this.messageHandler);\n\n iframe.addEventListener(\n \"load\",\n () => {\n if (!this.iframe) return;\n const hello: ParentToIframe = {\n type: \"arcpay:hello\",\n origin: window.location.origin,\n publishableKey: this.context.publishableKey,\n channelId: this.context.channelId,\n };\n postToIframe(this.iframe, hello, expectedOrigin);\n },\n { once: true },\n );\n }\n\n private handleMessage(data: IframeToParent): void {\n if (data.type === \"arcpay:ready\") {\n this.status = \"ready\";\n // Apply initial style if provided at construction time.\n if (this.options.style) {\n this.send({ type: \"arcpay:style\", payload: sanitizeStyle(this.options.style) });\n }\n this.emit({ type: \"ready\" });\n } else if (data.type === \"arcpay:rejected\") {\n this.status = \"error\";\n this.emit({ type: \"error\", reason: data.reason });\n } else if (data.type === \"arcpay:change\" && data.field === this.field) {\n this.emit({\n type: \"change\",\n isValid: data.isValid,\n brand: data.brand,\n lastFour: data.lastFour,\n });\n }\n // arcpay:tokenize-result / arcpay:tokenize-error handled by Elements factory (Task 9).\n }\n\n update(options: { style?: StyleSubset }): void {\n if (options.style) {\n this.send({ type: \"arcpay:style\", payload: sanitizeStyle(options.style) });\n }\n }\n\n destroy(): void {\n if (this.iframe) {\n this.iframe.remove();\n this.iframe = null;\n }\n if (this.messageHandler) {\n window.removeEventListener(\"message\", this.messageHandler);\n this.messageHandler = null;\n }\n this.listeners.clear();\n this.status = \"pending\";\n }\n\n on(_event: \"ready\" | \"change\" | \"error\", callback: Listener): () => void {\n this.listeners.add(callback);\n return () => this.listeners.delete(callback);\n }\n\n focus(): void {\n this.send({ type: \"arcpay:focus\" });\n }\n\n clear(): void {\n this.send({ type: \"arcpay:clear\" });\n }\n\n isReady(): boolean {\n return this.status === \"ready\";\n }\n\n /**\n * Internal: returns the iframe's contentWindow for source-filtering in\n * Elements.doTokenize(). Returns null when the iframe is not yet mounted\n * or when jsdom has not yet populated contentWindow (test environment).\n */\n getIframeContentWindow(): Window | null {\n return this.iframe?.contentWindow ?? null;\n }\n\n /** Internal: used by Elements factory to send tokenize commands. */\n send(message: ParentToIframe): void {\n if (!this.iframe) {\n throw new ArcPayError({\n type: \"validation_error\",\n code: \"not_mounted\",\n message: `Element ${this.field} is not mounted`,\n retryable: false,\n });\n }\n postToIframe(this.iframe, message, new URL(this.context.iframeBase).origin);\n }\n\n private emit(event: ElementEvent): void {\n for (const listener of this.listeners) {\n listener(event);\n }\n }\n}\n","import { ArcPayError } from \"../core/errors\";\nimport { Element, type ElementContext, type ElementOptions } from \"./element\";\nimport type { FieldType, IframeToParent } from \"./postmessage\";\nimport { parseIncoming } from \"./postmessage\";\nimport type { TokenizeResult } from \"../tokenize/tokenize\";\n\nexport type { TokenizeResult };\n\nexport interface ElementsOptions {\n iframeBase?: string;\n}\n\nconst DEFAULT_IFRAME_BASE = \"https://sdk.arcpay.space\";\n\nconst createChannelId = (): string => {\n if (!globalThis.crypto?.randomUUID) {\n throw new ArcPayError({\n type: \"validation_error\",\n code: \"crypto_unavailable\",\n message: \"crypto.randomUUID is required for Hosted Fields\",\n retryable: false,\n });\n }\n return globalThis.crypto.randomUUID();\n};\n\nexport class Elements {\n private readonly elementMap = new Map<FieldType, Element>();\n private readonly iframeBase: string;\n private readonly publishableKey: string;\n private readonly channelId: string;\n private tokenizeInFlight = false;\n\n constructor(opts: { publishableKey: string; iframeBase?: string }) {\n this.publishableKey = opts.publishableKey;\n this.iframeBase = opts.iframeBase ?? DEFAULT_IFRAME_BASE;\n this.channelId = createChannelId();\n }\n\n create(field: FieldType, options: ElementOptions = {}): Element {\n if (this.elementMap.has(field)) {\n throw new ArcPayError({\n type: \"validation_error\",\n code: \"duplicate_element\",\n message: `Element for ${field} already created`,\n retryable: false,\n });\n }\n const ctx: ElementContext = {\n iframeBase: this.iframeBase,\n publishableKey: this.publishableKey,\n channelId: this.channelId,\n };\n const element = new Element(field, options, ctx);\n this.elementMap.set(field, element);\n return element;\n }\n\n async tokenize(paymentId: string, idempotencyKey: string): Promise<TokenizeResult> {\n // C2: concurrent-call guard — only one tokenize() may be in-flight at a time.\n if (this.tokenizeInFlight) {\n throw new ArcPayError({\n type: \"validation_error\",\n code: \"tokenize_in_progress\",\n message: \"A tokenize() call is already in progress for this Elements instance\",\n retryable: false,\n });\n }\n\n const cardNumber = this.elementMap.get(\"cardNumber\");\n const cardExpiry = this.elementMap.get(\"cardExpiry\");\n const cardCvv = this.elementMap.get(\"cardCvv\");\n\n if (!cardNumber || !cardExpiry || !cardCvv) {\n throw new ArcPayError({\n type: \"validation_error\",\n code: \"incomplete_elements\",\n message:\n \"All three elements (cardNumber, cardExpiry, cardCvv) must be created and mounted before tokenize()\",\n retryable: false,\n });\n }\n if (!cardNumber.isReady() || !cardExpiry.isReady() || !cardCvv.isReady()) {\n throw new ArcPayError({\n type: \"validation_error\",\n code: \"elements_not_ready\",\n message: \"Wait for all elements to fire 'ready' event before tokenize()\",\n retryable: false,\n });\n }\n\n this.tokenizeInFlight = true;\n try {\n return await this.doTokenize(cardNumber, paymentId, idempotencyKey);\n } finally {\n this.tokenizeInFlight = false;\n }\n }\n\n private doTokenize(\n cardNumber: Element,\n paymentId: string,\n idempotencyKey: string,\n ): Promise<TokenizeResult> {\n const iframeOrigin = new URL(this.iframeBase).origin;\n // C1: obtain reference to the cardNumber iframe's contentWindow before\n // registering the listener so we can filter by source.\n const cardIframeWindow = cardNumber.getIframeContentWindow();\n\n return new Promise<TokenizeResult>((resolve, reject) => {\n // C3: 30-second timeout — rejects and cleans up if no result arrives.\n const timer = window.setTimeout(() => {\n window.removeEventListener(\"message\", onMessage);\n reject(\n new ArcPayError({\n type: \"network_error\",\n code: \"tokenize_timeout\",\n message: \"tokenize() timed out after 30 seconds\",\n retryable: true,\n paymentId,\n }),\n );\n }, 30_000);\n\n const onMessage = (event: MessageEvent) => {\n // C1: source guard — only accept messages from the cardNumber iframe.\n if (cardIframeWindow !== null && event.source !== cardIframeWindow) return;\n // C4: use parseIncoming for origin + arcpay: prefix guard.\n const data = parseIncoming<IframeToParent>(event, iframeOrigin);\n if (!data) return;\n\n if (data.type === \"arcpay:tokenize-result\") {\n clearTimeout(timer);\n window.removeEventListener(\"message\", onMessage);\n resolve({\n cardTokenId: data.cardTokenId,\n cardMask: data.cardMask,\n cardScheme: data.cardScheme,\n cardBin: data.cardBin,\n expiresAt: data.expiresAt,\n });\n } else if (data.type === \"arcpay:tokenize-error\") {\n clearTimeout(timer);\n window.removeEventListener(\"message\", onMessage);\n const errType =\n data.errorType === \"validation_error\" || data.errorType === \"api_error\"\n ? data.errorType\n : \"api_error\";\n reject(\n new ArcPayError({\n type: errType,\n code: data.code,\n message: data.message,\n retryable: false,\n paymentId,\n }),\n );\n }\n };\n\n window.addEventListener(\"message\", onMessage);\n cardNumber.send({ type: \"arcpay:tokenize\", paymentId, idempotencyKey });\n });\n }\n\n destroy(): void {\n for (const el of this.elementMap.values()) {\n el.destroy();\n }\n this.elementMap.clear();\n }\n}\n","import { verifyCspAllowsApiBase } from \"./csp\";\nimport { detectEnvironment, type Environment, validatePublishableKey as _validatePublishableKey } from \"./env\";\nimport { showSandboxBanner } from \"./sandbox-banner\";\nimport { Elements, type ElementsOptions } from \"../elements/elements\";\n\nconst validatePublishableKey: (key: unknown) => asserts key is string = _validatePublishableKey;\n\nexport interface ArcPayLoadOptions {\n apiBase?: string;\n}\n\nconst DEFAULT_API_BASE = \"https://api.arcpay.space\";\n\nexport interface ArcPayInstance {\n readonly publishableKey: string;\n readonly apiBase: string;\n readonly environment: Environment;\n elements: (opts?: ElementsOptions) => Elements;\n}\n\nconst cache = new Map<string, Promise<ArcPayInstance>>();\n\nconst buildInstance = (publishableKey: string, opts: ArcPayLoadOptions): ArcPayInstance => {\n const apiBase = opts.apiBase ?? DEFAULT_API_BASE;\n verifyCspAllowsApiBase(apiBase);\n if (detectEnvironment(publishableKey) === \"sandbox\") {\n showSandboxBanner();\n }\n return {\n publishableKey,\n apiBase,\n environment: detectEnvironment(publishableKey),\n elements: (elemOpts) => new Elements({ publishableKey, iframeBase: elemOpts?.iframeBase }),\n };\n};\n\nfunction load(publishableKey: string, opts: ArcPayLoadOptions = {}): Promise<ArcPayInstance> {\n try {\n validatePublishableKey(publishableKey);\n } catch (err) {\n return Promise.reject(err);\n }\n const key = `${publishableKey}|${opts.apiBase ?? DEFAULT_API_BASE}`;\n const existing = cache.get(key);\n if (existing) return existing;\n const promise = Promise.resolve(buildInstance(publishableKey, opts));\n cache.set(key, promise);\n return promise;\n}\n\nconst resetForTests = (): void => {\n cache.clear();\n};\n\nexport const ArcPay = {\n load,\n __resetForTests: resetForTests,\n};\n","export const luhnCheck = (pan: string): boolean => {\n if (!/^\\d+$/.test(pan)) return false;\n if (/^0+$/.test(pan)) return false;\n let sum = 0;\n let alternate = false;\n for (let i = pan.length - 1; i >= 0; i--) {\n let n = pan.charCodeAt(i) - 48;\n if (alternate) {\n n *= 2;\n if (n > 9) n -= 9;\n }\n sum += n;\n alternate = !alternate;\n }\n return sum % 10 === 0;\n};\n","export { ArcPay } from \"./core/arcpay\";\nexport type { ArcPayInstance, ArcPayLoadOptions } from \"./core/arcpay\";\nexport {\n ArcPayError,\n isValidationError,\n isAuthenticationError,\n isAuthorizationError,\n isStateError,\n isRateLimitError,\n isApiError,\n isNetworkError,\n isChallengeAborted,\n} from \"./core/errors\";\nexport type { ArcPayErrorType } from \"./core/errors\";\nexport type { Environment } from \"./core/env\";\nexport type { TokenizeRequest, TokenizeResult } from \"./tokenize/tokenize\";\nexport type { CardScheme } from \"./tokenize/scheme\";\nexport const SDK_VERSION = \"0.1.0\";\n\n// Hosted Fields postMessage protocol\nexport type {\n FieldType,\n ParentToIframe,\n IframeToParent,\n StyleSubset,\n} from \"./elements/postmessage\";\nexport { postToIframe, postToParent, parseIncoming } from \"./elements/postmessage\";\n\n// Style sanitizer — also used by elements iframe app (defense-in-depth on receipt)\nexport { sanitizeStyle } from \"./elements/style\";\n\n// Hosted Fields — Element class + Elements factory\nexport { Element } from \"./elements/element\";\nexport type { ElementOptions, ElementEvent, ElementContext } from \"./elements/element\";\nexport { Elements } from \"./elements/elements\";\nexport type { ElementsOptions } from \"./elements/elements\";\n\n// Luhn check (used by elements app for card-number validation)\nexport { luhnCheck } from \"./tokenize/luhn\";\n"]}
1
+ {"version":3,"sources":["../../src/core/errors.ts","../../src/core/env.ts","../../src/core/sandbox-banner.ts","../../src/elements/postmessage.ts","../../src/elements/style.ts","../../src/elements/element.ts","../../src/elements/elements.ts","../../src/core/arcpay.ts","../../src/index.ts"],"names":["ArcPayError","init","isValidationError","isAuthenticationError","isAuthorizationError","isStateError","isRateLimitError","isApiError","isNetworkError","isChallengeAborted","detectEnvironment","publishableKey","validatePublishableKey","key","BANNER_ATTR","showSandboxBanner","bar","text","dismiss","ARCPAY_TYPE_PREFIX","isArcpayMessage","data","postToIframe","iframe","message","targetOrigin","parseIncoming","event","expectedOrigin","FORBIDDEN_PROPERTIES","sanitizeBlock","block","out","value","normalizedKey","sanitizeStyle","style","result","Element","field","options","context","target","container","_a","hello","_event","callback","_b","listener","DEFAULT_IFRAME_BASE","createChannelId","Elements","opts","ctx","element","paymentId","idempotencyKey","cardNumber","cardExpiry","cardCvv","iframeOrigin","cardIframeWindow","resolve","reject","timer","onMessage","errType","el","cache","buildInstance","load","err","existing","promise","resetForTests","ArcPay","SDK_VERSION"],"mappings":"2CAqBO,IAAMA,EAAN,cAA0B,KAAM,CASrC,WAAA,CAAYC,EAAuB,CACjC,KAAA,CAAMA,CAAAA,CAAK,OAAO,EAClB,IAAA,CAAK,IAAA,CAAO,cACZ,IAAA,CAAK,IAAA,CAAOA,EAAK,IAAA,CACjB,IAAA,CAAK,IAAA,CAAOA,CAAAA,CAAK,KACjB,IAAA,CAAK,KAAA,CAAQA,CAAAA,CAAK,KAAA,CAClB,KAAK,SAAA,CAAYA,CAAAA,CAAK,SAAA,CACtB,IAAA,CAAK,YAAcA,CAAAA,CAAK,WAAA,CACxB,KAAK,SAAA,CAAYA,CAAAA,CAAK,UACtB,IAAA,CAAK,SAAA,CAAYA,CAAAA,CAAK,UACxB,CACF,CAAA,CAEaC,CAAAA,CAAqB,CAAA,EAChC,CAAA,YAAaF,GAAe,CAAA,CAAE,IAAA,GAAS,kBAAA,CAC5BG,CAAAA,CAAyB,GACpC,CAAA,YAAaH,CAAAA,EAAe,EAAE,IAAA,GAAS,sBAAA,CAC5BI,EAAwB,CAAA,EACnC,CAAA,YAAaJ,CAAAA,EAAe,CAAA,CAAE,OAAS,qBAAA,CAC5BK,CAAAA,CAAgB,GAC3B,CAAA,YAAaL,CAAAA,EAAe,EAAE,IAAA,GAAS,aAAA,CAC5BM,CAAAA,CAAoB,CAAA,EAC/B,aAAaN,CAAAA,EAAe,CAAA,CAAE,OAAS,kBAAA,CAC5BO,CAAAA,CAAc,GACzB,CAAA,YAAaP,CAAAA,EAAe,CAAA,CAAE,IAAA,GAAS,YAC5BQ,CAAAA,CAAkB,CAAA,EAC7B,CAAA,YAAaR,CAAAA,EAAe,EAAE,IAAA,GAAS,eAAA,CAC5BS,CAAAA,CAAsB,CAAA,EACjC,aAAaT,CAAAA,EAAe,CAAA,CAAE,OAAS,oBCtDlC,IAAMU,EAAqBC,CAAAA,EAChCA,CAAAA,CAAe,UAAA,CAAW,UAAU,EAAI,SAAA,CAAY,MAAA,CAEzCC,EAA0BC,CAAAA,EAAwC,CAC7E,GAAI,OAAOA,CAAAA,EAAQ,QAAA,EAAYA,CAAAA,CAAI,SAAW,CAAA,CAC5C,MAAM,IAAIb,CAAAA,CAAY,CACpB,KAAM,kBAAA,CACN,IAAA,CAAM,yBAAA,CACN,OAAA,CAAS,6CACT,SAAA,CAAW,KACb,CAAC,CAAA,CAEH,GAAI,CAACa,CAAAA,CAAI,UAAA,CAAW,UAAU,GAAK,CAACA,CAAAA,CAAI,WAAW,UAAU,CAAA,CAC3D,MAAM,IAAIb,CAAAA,CAAY,CACpB,IAAA,CAAM,mBACN,IAAA,CAAM,yBAAA,CACN,QACE,qGAAA,CACF,SAAA,CAAW,KACb,CAAC,CAEL,CAAA,CCzBA,IAAMc,EAAc,4BAAA,CAEPC,CAAAA,CAAoB,IAAY,CAE3C,GADI,OAAO,QAAA,EAAa,WAAA,EACpB,QAAA,CAAS,aAAA,CAAc,IAAID,CAAW,CAAA,CAAA,CAAG,CAAA,CAAG,OAEhD,IAAME,CAAAA,CAAM,QAAA,CAAS,aAAA,CAAc,KAAK,EACxCA,CAAAA,CAAI,YAAA,CAAaF,EAAa,EAAE,CAAA,CAChCE,EAAI,KAAA,CAAM,OAAA,CACR,uOAAA,CAEF,IAAMC,EAAO,QAAA,CAAS,aAAA,CAAc,MAAM,CAAA,CAC1CA,EAAK,WAAA,CAAc,iDAAA,CACnBD,CAAAA,CAAI,WAAA,CAAYC,CAAI,CAAA,CAEpB,IAAMC,EAAU,QAAA,CAAS,aAAA,CAAc,QAAQ,CAAA,CAC/CA,CAAAA,CAAQ,IAAA,CAAO,QAAA,CACfA,EAAQ,YAAA,CAAa,4BAAA,CAA8B,EAAE,CAAA,CACrDA,EAAQ,WAAA,CAAc,MAAA,CACtBA,CAAAA,CAAQ,YAAA,CAAa,aAAc,0BAA0B,CAAA,CAC7DA,EAAQ,KAAA,CAAM,OAAA,CACZ,gGACFA,CAAAA,CAAQ,gBAAA,CAAiB,OAAA,CAAS,IAAMF,EAAI,MAAA,EAAQ,EACpDA,CAAAA,CAAI,WAAA,CAAYE,CAAO,CAAA,CAEvB,QAAA,CAAS,IAAA,CAAK,WAAA,CAAYF,CAAG,EAC/B,CAAA,CCcA,IAAMG,CAAAA,CAAqB,SAAA,CAErBC,EAAmBC,CAAAA,EACvB,OAAOA,CAAAA,EAAS,QAAA,EAChBA,IAAS,IAAA,EACT,MAAA,GAAUA,CAAAA,EACV,OAAQA,EAA2B,IAAA,EAAS,QAAA,EAC3CA,CAAAA,CAA0B,IAAA,CAAK,WAAWF,CAAkB,CAAA,CAElDG,EAAe,CAC1BC,CAAAA,CACAC,EACAC,CAAAA,GACS,CACT,GAAIA,CAAAA,GAAiB,IACnB,MAAM,IAAIzB,EAAY,CACpB,IAAA,CAAM,mBACN,IAAA,CAAM,2BAAA,CACN,OAAA,CAAS,0CAAA,CACT,UAAW,KACb,CAAC,EAEH,GAAI,CAACuB,EAAO,aAAA,CACV,MAAM,IAAIvB,CAAAA,CAAY,CACpB,IAAA,CAAM,kBAAA,CACN,IAAA,CAAM,mBAAA,CACN,QAAS,iEAAA,CACT,SAAA,CAAW,KACb,CAAC,EAEHuB,CAAAA,CAAO,aAAA,CAAc,YAAYC,CAAAA,CAASC,CAAY,EACxD,CAAA,CASO,IAAMC,CAAAA,CAAgB,CAC3BC,EACAC,CAAAA,GAEID,CAAAA,CAAM,SAAWC,CAAAA,EACjB,CAACR,EAAgBO,CAAAA,CAAM,IAAI,CAAA,CAAU,IAAA,CAClCA,EAAM,IAAA,CC/Ef,IAAME,EAAuB,IAAI,GAAA,CAAI,CACnC,UAAA,CACA,WAAA,CACA,gBAAA,CACA,SAAA,CACA,MACA,MAAA,CACA,OAAA,CACA,QAAA,CACA,OACF,CAAC,CAAA,CAEKC,CAAAA,CAAiBC,CAAAA,EAA0D,CAC/E,IAAMC,CAAAA,CAA8B,GACpC,IAAA,GAAW,CAACnB,EAAKoB,CAAK,CAAA,GAAK,MAAA,CAAO,OAAA,CAAQF,CAAK,CAAA,CAAG,CAChD,IAAMG,CAAAA,CAAgBrB,EAAI,WAAA,EAAY,CAClCgB,CAAAA,CAAqB,GAAA,CAAIK,CAAa,CAAA,GAI1CF,CAAAA,CAAInB,CAAG,CAAA,CAAIoB,CAAAA,EACb,CACA,OAAOD,CACT,CAAA,CAEaG,CAAAA,CAAiBC,GAAoC,CAChE,IAAMC,CAAAA,CAAsB,CAAE,KAAMP,CAAAA,CAAcM,CAAAA,CAAM,IAAI,CAAE,EAC9D,OAAIA,CAAAA,CAAM,UAAY,MAAA,GAAWC,CAAAA,CAAO,QAAUP,CAAAA,CAAcM,CAAAA,CAAM,OAAO,CAAA,CAAA,CACzEA,EAAM,KAAA,GAAU,MAAA,GAAWC,EAAO,KAAA,CAAQP,CAAAA,CAAcM,EAAM,KAAK,CAAA,CAAA,CAChEC,CACT,CAAA,CCPO,IAAMC,CAAAA,CAAN,KAAc,CAMnB,WAAA,CACkBC,CAAAA,CACCC,EACAC,CAAAA,CACjB,CAHgB,IAAA,CAAA,KAAA,CAAAF,CAAAA,CACC,aAAAC,CAAAA,CACA,IAAA,CAAA,OAAA,CAAAC,CAAAA,CARnB,IAAA,CAAQ,OAAmC,IAAA,CAC3C,IAAA,CAAiB,SAAA,CAAY,IAAI,IACjC,IAAA,CAAQ,MAAA,CAAwC,UAChD,IAAA,CAAQ,cAAA,CAAqD,KAM1D,CAEH,KAAA,CAAMC,CAAAA,CAAoC,CACxC,GAAI,IAAA,CAAK,MAAA,CACP,MAAM,IAAI1C,CAAAA,CAAY,CACpB,IAAA,CAAM,kBAAA,CACN,IAAA,CAAM,iBAAA,CACN,QAAS,CAAA,QAAA,EAAW,IAAA,CAAK,KAAK,CAAA,mBAAA,CAAA,CAC9B,SAAA,CAAW,KACb,CAAC,CAAA,CAEH,IAAM2C,CAAAA,CAAY,OAAOD,CAAAA,EAAW,QAAA,CAAW,QAAA,CAAS,aAAA,CAAcA,CAAM,CAAA,CAAIA,CAAAA,CAChF,GAAI,EAAEC,aAAqB,WAAA,CAAA,CACzB,MAAM,IAAI3C,CAAAA,CAAY,CACpB,KAAM,kBAAA,CACN,IAAA,CAAM,wBAAA,CACN,OAAA,CAAS,2BAA2B,MAAA,CAAO0C,CAAM,CAAC,CAAA,CAAA,CAClD,SAAA,CAAW,KACb,CAAC,CAAA,CAGH,IAAMnB,CAAAA,CAAS,SAAS,aAAA,CAAc,QAAQ,EAC9CA,CAAAA,CAAO,GAAA,CAAM,GAAG,IAAA,CAAK,OAAA,CAAQ,UAAU,CAAA,QAAA,EAAW,KAAK,KAAK,CAAA,CAAA,CAC5DA,CAAAA,CAAO,KAAA,CAAM,QAAU,gDAAA,CACvBA,CAAAA,CAAO,YAAA,CAAa,OAAA,CAAS,SAAS,CAAA,CACtCA,CAAAA,CAAO,aAAa,qBAAA,CAAuB,IAAA,CAAK,KAAK,CAAA,CACrDoB,CAAAA,CAAU,WAAA,CAAYpB,CAAM,EAC5B,IAAA,CAAK,MAAA,CAASA,CAAAA,CAEd,IAAMK,EAAiB,IAAI,GAAA,CAAI,IAAA,CAAK,OAAA,CAAQ,UAAU,CAAA,CAAE,MAAA,CAExD,KAAK,cAAA,CAAkBD,CAAAA,EAAwB,CAvEnD,IAAAiB,CAAAA,CA2EM,GAAIjB,CAAAA,CAAM,WAAWiB,CAAAA,CAAA,IAAA,CAAK,MAAA,GAAL,IAAA,CAAA,MAAA,CAAAA,EAAa,aAAA,CAAA,CAAe,OAEjD,IAAMvB,CAAAA,CAAOK,EAA8BC,CAAAA,CAAOC,CAAc,EAC3DP,CAAAA,EACL,IAAA,CAAK,cAAcA,CAAI,EACzB,CAAA,CACA,MAAA,CAAO,iBAAiB,SAAA,CAAW,IAAA,CAAK,cAAc,CAAA,CAEtDE,CAAAA,CAAO,iBACL,MAAA,CACA,IAAM,CACJ,GAAI,CAAC,IAAA,CAAK,MAAA,CAAQ,OAClB,IAAMsB,CAAAA,CAAwB,CAC5B,IAAA,CAAM,cAAA,CACN,MAAA,CAAQ,MAAA,CAAO,SAAS,MAAA,CACxB,cAAA,CAAgB,IAAA,CAAK,OAAA,CAAQ,eAC7B,SAAA,CAAW,IAAA,CAAK,OAAA,CAAQ,SAC1B,EACAvB,CAAAA,CAAa,IAAA,CAAK,OAAQuB,CAAAA,CAAOjB,CAAc,EACjD,CAAA,CACA,CAAE,IAAA,CAAM,IAAK,CACf,EACF,CAEQ,cAAcP,CAAAA,CAA4B,CAC5CA,EAAK,IAAA,GAAS,cAAA,EAChB,IAAA,CAAK,MAAA,CAAS,QAEV,IAAA,CAAK,OAAA,CAAQ,OACf,IAAA,CAAK,IAAA,CAAK,CAAE,IAAA,CAAM,cAAA,CAAgB,OAAA,CAASc,CAAAA,CAAc,KAAK,OAAA,CAAQ,KAAK,CAAE,CAAC,EAEhF,IAAA,CAAK,IAAA,CAAK,CAAE,IAAA,CAAM,OAAQ,CAAC,CAAA,EAClBd,EAAK,IAAA,GAAS,iBAAA,EACvB,KAAK,MAAA,CAAS,OAAA,CACd,IAAA,CAAK,IAAA,CAAK,CAAE,IAAA,CAAM,OAAA,CAAS,OAAQA,CAAAA,CAAK,MAAO,CAAC,CAAA,EACvCA,CAAAA,CAAK,IAAA,GAAS,eAAA,EAAmBA,EAAK,KAAA,GAAU,IAAA,CAAK,OAC9D,IAAA,CAAK,IAAA,CAAK,CACR,IAAA,CAAM,QAAA,CACN,OAAA,CAASA,CAAAA,CAAK,QACd,KAAA,CAAOA,CAAAA,CAAK,KAAA,CACZ,QAAA,CAAUA,EAAK,QACjB,CAAC,EAGL,CAEA,OAAOmB,CAAAA,CAAwC,CACzCA,EAAQ,KAAA,EACV,IAAA,CAAK,KAAK,CAAE,IAAA,CAAM,cAAA,CAAgB,OAAA,CAASL,EAAcK,CAAAA,CAAQ,KAAK,CAAE,CAAC,EAE7E,CAEA,OAAA,EAAgB,CACV,IAAA,CAAK,SACP,IAAA,CAAK,MAAA,CAAO,QAAO,CACnB,IAAA,CAAK,OAAS,IAAA,CAAA,CAEZ,IAAA,CAAK,cAAA,GACP,MAAA,CAAO,oBAAoB,SAAA,CAAW,IAAA,CAAK,cAAc,CAAA,CACzD,KAAK,cAAA,CAAiB,IAAA,CAAA,CAExB,IAAA,CAAK,SAAA,CAAU,OAAM,CACrB,IAAA,CAAK,OAAS,UAChB,CAEA,GAAGM,CAAAA,CAAsCC,CAAAA,CAAgC,CACvE,OAAA,IAAA,CAAK,UAAU,GAAA,CAAIA,CAAQ,EACpB,IAAM,IAAA,CAAK,UAAU,MAAA,CAAOA,CAAQ,CAC7C,CAEA,OAAc,CACZ,IAAA,CAAK,KAAK,CAAE,IAAA,CAAM,cAAe,CAAC,EACpC,CAEA,KAAA,EAAc,CACZ,IAAA,CAAK,IAAA,CAAK,CAAE,IAAA,CAAM,cAAe,CAAC,EACpC,CAEA,OAAA,EAAmB,CACjB,OAAO,IAAA,CAAK,SAAW,OACzB,CAOA,wBAAwC,CAlK1C,IAAAH,CAAAA,CAAAI,CAAAA,CAmKI,QAAOA,CAAAA,CAAAA,CAAAJ,CAAAA,CAAA,KAAK,MAAA,GAAL,IAAA,CAAA,MAAA,CAAAA,EAAa,aAAA,GAAb,IAAA,CAAAI,CAAAA,CAA8B,IACvC,CAGA,IAAA,CAAKxB,CAAAA,CAA+B,CAClC,GAAI,CAAC,KAAK,MAAA,CACR,MAAM,IAAIxB,CAAAA,CAAY,CACpB,IAAA,CAAM,kBAAA,CACN,IAAA,CAAM,aAAA,CACN,QAAS,CAAA,QAAA,EAAW,IAAA,CAAK,KAAK,CAAA,eAAA,CAAA,CAC9B,UAAW,KACb,CAAC,EAEHsB,CAAAA,CAAa,IAAA,CAAK,OAAQE,CAAAA,CAAS,IAAI,GAAA,CAAI,IAAA,CAAK,QAAQ,UAAU,CAAA,CAAE,MAAM,EAC5E,CAEQ,KAAKG,CAAAA,CAA2B,CACtC,IAAA,IAAWsB,CAAAA,IAAY,KAAK,SAAA,CAC1BA,CAAAA,CAAStB,CAAK,EAElB,CACF,EC9KA,IAAMuB,CAAAA,CAAsB,0BAAA,CAEtBC,CAAAA,CAAkB,IAAc,CAZtC,IAAAP,CAAAA,CAaE,GAAI,GAACA,CAAAA,CAAA,UAAA,CAAW,MAAA,GAAX,IAAA,EAAAA,EAAmB,UAAA,CAAA,CACtB,MAAM,IAAI5C,CAAAA,CAAY,CACpB,KAAM,kBAAA,CACN,IAAA,CAAM,oBAAA,CACN,OAAA,CAAS,kDACT,SAAA,CAAW,KACb,CAAC,CAAA,CAEH,OAAO,UAAA,CAAW,MAAA,CAAO,UAAA,EAC3B,EAEaoD,CAAAA,CAAN,KAAe,CAOpB,WAAA,CAAYC,CAAAA,CAAuD,CANnE,IAAA,CAAiB,UAAA,CAAa,IAAI,GAAA,CAIlC,KAAQ,gBAAA,CAAmB,KAAA,CA7B7B,IAAAT,CAAAA,CAgCI,KAAK,cAAA,CAAiBS,CAAAA,CAAK,cAAA,CAC3B,IAAA,CAAK,YAAaT,CAAAA,CAAAS,CAAAA,CAAK,aAAL,IAAA,CAAAT,CAAAA,CAAmBM,EACrC,IAAA,CAAK,SAAA,CAAYC,CAAAA,GACnB,CAEA,MAAA,CAAOZ,CAAAA,CAAkBC,EAA0B,EAAC,CAAY,CAC9D,GAAI,IAAA,CAAK,UAAA,CAAW,GAAA,CAAID,CAAK,CAAA,CAC3B,MAAM,IAAIvC,CAAAA,CAAY,CACpB,KAAM,kBAAA,CACN,IAAA,CAAM,mBAAA,CACN,OAAA,CAAS,eAAeuC,CAAK,CAAA,gBAAA,CAAA,CAC7B,SAAA,CAAW,KACb,CAAC,CAAA,CAEH,IAAMe,CAAAA,CAAsB,CAC1B,WAAY,IAAA,CAAK,UAAA,CACjB,eAAgB,IAAA,CAAK,cAAA,CACrB,UAAW,IAAA,CAAK,SAClB,CAAA,CACMC,CAAAA,CAAU,IAAIjB,CAAAA,CAAQC,CAAAA,CAAOC,EAASc,CAAG,CAAA,CAC/C,YAAK,UAAA,CAAW,GAAA,CAAIf,CAAAA,CAAOgB,CAAO,EAC3BA,CACT,CAEA,MAAM,QAAA,CAASC,CAAAA,CAAmBC,EAAiD,CAEjF,GAAI,IAAA,CAAK,gBAAA,CACP,MAAM,IAAIzD,CAAAA,CAAY,CACpB,IAAA,CAAM,mBACN,IAAA,CAAM,sBAAA,CACN,OAAA,CAAS,qEAAA,CACT,UAAW,KACb,CAAC,EAGH,IAAM0D,CAAAA,CAAa,KAAK,UAAA,CAAW,GAAA,CAAI,YAAY,CAAA,CAC7CC,EAAa,IAAA,CAAK,UAAA,CAAW,IAAI,YAAY,CAAA,CAC7CC,EAAU,IAAA,CAAK,UAAA,CAAW,GAAA,CAAI,SAAS,EAE7C,GAAI,CAACF,GAAc,CAACC,CAAAA,EAAc,CAACC,CAAAA,CACjC,MAAM,IAAI5D,CAAAA,CAAY,CACpB,IAAA,CAAM,kBAAA,CACN,IAAA,CAAM,qBAAA,CACN,QACE,oGAAA,CACF,SAAA,CAAW,KACb,CAAC,EAEH,GAAI,CAAC0D,EAAW,OAAA,EAAQ,EAAK,CAACC,CAAAA,CAAW,OAAA,EAAQ,EAAK,CAACC,EAAQ,OAAA,EAAQ,CACrE,MAAM,IAAI5D,EAAY,CACpB,IAAA,CAAM,kBAAA,CACN,IAAA,CAAM,qBACN,OAAA,CAAS,+DAAA,CACT,UAAW,KACb,CAAC,EAGH,IAAA,CAAK,gBAAA,CAAmB,IAAA,CACxB,GAAI,CACF,OAAO,MAAM,IAAA,CAAK,UAAA,CAAW0D,EAAYF,CAAAA,CAAWC,CAAc,CACpE,CAAA,OAAE,CACA,IAAA,CAAK,gBAAA,CAAmB,MAC1B,CACF,CAEQ,WACNC,CAAAA,CACAF,CAAAA,CACAC,CAAAA,CACyB,CACzB,IAAMI,CAAAA,CAAe,IAAI,IAAI,IAAA,CAAK,UAAU,EAAE,MAAA,CAGxCC,CAAAA,CAAmBJ,CAAAA,CAAW,sBAAA,GAEpC,OAAO,IAAI,QAAwB,CAACK,CAAAA,CAASC,IAAW,CAEtD,IAAMC,CAAAA,CAAQ,MAAA,CAAO,WAAW,IAAM,CACpC,MAAA,CAAO,mBAAA,CAAoB,UAAWC,CAAS,CAAA,CAC/CF,CAAAA,CACE,IAAIhE,EAAY,CACd,IAAA,CAAM,gBACN,IAAA,CAAM,kBAAA,CACN,QAAS,uCAAA,CACT,SAAA,CAAW,IAAA,CACX,SAAA,CAAAwD,CACF,CAAC,CACH,EACF,CAAA,CAAG,GAAM,EAEHU,CAAAA,CAAavC,CAAAA,EAAwB,CAEzC,GAAImC,IAAqB,IAAA,EAAQnC,CAAAA,CAAM,SAAWmC,CAAAA,CAAkB,OAEpE,IAAMzC,CAAAA,CAAOK,CAAAA,CAA8BC,CAAAA,CAAOkC,CAAY,EAC9D,GAAKxC,CAAAA,CAAAA,CAEL,GAAIA,CAAAA,CAAK,OAAS,wBAAA,CAChB,YAAA,CAAa4C,CAAK,CAAA,CAClB,OAAO,mBAAA,CAAoB,SAAA,CAAWC,CAAS,CAAA,CAC/CH,CAAAA,CAAQ,CACN,WAAA,CAAa1C,CAAAA,CAAK,WAAA,CAClB,QAAA,CAAUA,EAAK,QAAA,CACf,UAAA,CAAYA,EAAK,UAAA,CACjB,OAAA,CAASA,EAAK,OAAA,CACd,SAAA,CAAWA,CAAAA,CAAK,SAAA,CAChB,UAAWA,CAAAA,CAAK,SAClB,CAAC,CAAA,CAAA,KAAA,GACQA,CAAAA,CAAK,OAAS,uBAAA,CAAyB,CAChD,YAAA,CAAa4C,CAAK,EAClB,MAAA,CAAO,mBAAA,CAAoB,SAAA,CAAWC,CAAS,EAC/C,IAAMC,CAAAA,CACJ9C,CAAAA,CAAK,SAAA,GAAc,oBAAsBA,CAAAA,CAAK,SAAA,GAAc,YACxDA,CAAAA,CAAK,SAAA,CACL,YACN2C,CAAAA,CACE,IAAIhE,CAAAA,CAAY,CACd,KAAMmE,CAAAA,CACN,IAAA,CAAM9C,CAAAA,CAAK,IAAA,CACX,QAASA,CAAAA,CAAK,OAAA,CACd,SAAA,CAAW,KAAA,CACX,UAAAmC,CACF,CAAC,CACH,EACF,CAAA,CACF,EAEA,MAAA,CAAO,gBAAA,CAAiB,SAAA,CAAWU,CAAS,EAC5CR,CAAAA,CAAW,IAAA,CAAK,CAAE,IAAA,CAAM,kBAAmB,SAAA,CAAAF,CAAAA,CAAW,cAAA,CAAAC,CAAe,CAAC,EACxE,CAAC,CACH,CAEA,OAAA,EAAgB,CACd,IAAA,IAAWW,CAAAA,IAAM,IAAA,CAAK,UAAA,CAAW,QAAO,CACtCA,CAAAA,CAAG,SAAQ,CAEb,IAAA,CAAK,WAAW,KAAA,GAClB,CACF,EClKA,IAAMxD,CAAAA,CAAkEA,CAAAA,CAYlEyD,EAAQ,IAAI,GAAA,CAEZC,EAAiB3D,CAAAA,GACjBD,CAAAA,CAAkBC,CAAc,CAAA,GAAM,WACxCI,CAAAA,EAAkB,CAEb,CACL,cAAA,CAAAJ,EACA,WAAA,CAAaD,CAAAA,CAAkBC,CAAc,CAAA,CAC7C,SAAU,IAAM,IAAIyC,EAAS,CAAE,cAAA,CAAAzC,CAAe,CAAC,CACjD,CAAA,CAAA,CAGF,SAAS4D,EAAK5D,CAAAA,CAAiD,CAC7D,GAAI,CACFC,CAAAA,CAAuBD,CAAc,EACvC,CAAA,MAAS6D,CAAAA,CAAK,CACZ,OAAO,OAAA,CAAQ,MAAA,CAAOA,CAAG,CAC3B,CACA,IAAM3D,CAAAA,CAAMF,CAAAA,CACN8D,CAAAA,CAAWJ,CAAAA,CAAM,IAAIxD,CAAG,CAAA,CAC9B,GAAI4D,CAAAA,CAAU,OAAOA,CAAAA,CACrB,IAAMC,CAAAA,CAAU,OAAA,CAAQ,QAAQJ,CAAAA,CAAc3D,CAAc,CAAC,CAAA,CAC7D,OAAA0D,EAAM,GAAA,CAAIxD,CAAAA,CAAK6D,CAAO,CAAA,CACfA,CACT,CAEA,IAAMC,EAAgB,IAAY,CAChCN,EAAM,KAAA,GACR,CAAA,CAEaO,CAAAA,CAAS,CACpB,IAAA,CAAAL,CAAAA,CACA,gBAAiBI,CACnB,MCrCaE,EAAAA,CAAc","file":"arcpay.global.js","sourcesContent":["export type ArcPayErrorType =\n | \"validation_error\"\n | \"authentication_error\"\n | \"authorization_error\"\n | \"state_error\"\n | \"rate_limit_error\"\n | \"api_error\"\n | \"network_error\"\n | \"challenge_aborted\";\n\nexport interface ArcPayErrorInit {\n type: ArcPayErrorType;\n message: string;\n code?: string;\n param?: string;\n paymentId?: string;\n declineCode?: string;\n retryable: boolean;\n requestId?: string;\n}\n\nexport class ArcPayError extends Error {\n readonly type: ArcPayErrorType;\n readonly code?: string;\n readonly param?: string;\n readonly paymentId?: string;\n readonly declineCode?: string;\n readonly retryable: boolean;\n readonly requestId?: string;\n\n constructor(init: ArcPayErrorInit) {\n super(init.message);\n this.name = \"ArcPayError\";\n this.type = init.type;\n this.code = init.code;\n this.param = init.param;\n this.paymentId = init.paymentId;\n this.declineCode = init.declineCode;\n this.retryable = init.retryable;\n this.requestId = init.requestId;\n }\n}\n\nexport const isValidationError = (e: unknown): e is ArcPayError =>\n e instanceof ArcPayError && e.type === \"validation_error\";\nexport const isAuthenticationError = (e: unknown): e is ArcPayError =>\n e instanceof ArcPayError && e.type === \"authentication_error\";\nexport const isAuthorizationError = (e: unknown): e is ArcPayError =>\n e instanceof ArcPayError && e.type === \"authorization_error\";\nexport const isStateError = (e: unknown): e is ArcPayError =>\n e instanceof ArcPayError && e.type === \"state_error\";\nexport const isRateLimitError = (e: unknown): e is ArcPayError =>\n e instanceof ArcPayError && e.type === \"rate_limit_error\";\nexport const isApiError = (e: unknown): e is ArcPayError =>\n e instanceof ArcPayError && e.type === \"api_error\";\nexport const isNetworkError = (e: unknown): e is ArcPayError =>\n e instanceof ArcPayError && e.type === \"network_error\";\nexport const isChallengeAborted = (e: unknown): e is ArcPayError =>\n e instanceof ArcPayError && e.type === \"challenge_aborted\";\n","import { ArcPayError } from \"./errors\";\n\nexport type Environment = \"sandbox\" | \"live\";\n\nexport const detectEnvironment = (publishableKey: string): Environment =>\n publishableKey.startsWith(\"pk_test_\") ? \"sandbox\" : \"live\";\n\nexport const validatePublishableKey = (key: unknown): asserts key is string => {\n if (typeof key !== \"string\" || key.length === 0) {\n throw new ArcPayError({\n type: \"validation_error\",\n code: \"invalid_publishable_key\",\n message: \"Publishable key must be a non-empty string\",\n retryable: false,\n });\n }\n if (!key.startsWith(\"pk_test_\") && !key.startsWith(\"pk_live_\")) {\n throw new ArcPayError({\n type: \"validation_error\",\n code: \"invalid_publishable_key\",\n message:\n \"Publishable key must start with pk_test_ or pk_live_. Secret keys (sk_*) cannot be used in browser.\",\n retryable: false,\n });\n }\n};\n","const BANNER_ATTR = \"data-arcpay-sandbox-banner\";\n\nexport const showSandboxBanner = (): void => {\n if (typeof document === \"undefined\") return;\n if (document.querySelector(`[${BANNER_ATTR}]`)) return;\n\n const bar = document.createElement(\"div\");\n bar.setAttribute(BANNER_ATTR, \"\");\n bar.style.cssText =\n \"position:fixed;top:0;left:0;right:0;z-index:2147483647;background:#ffd166;color:#222;font:13px/1.4 system-ui,sans-serif;padding:6px 12px;display:flex;align-items:center;justify-content:center;box-shadow:0 1px 3px rgba(0,0,0,0.1);\";\n\n const text = document.createElement(\"span\");\n text.textContent = \"ARC PAY TEST MODE — payments are simulated\";\n bar.appendChild(text);\n\n const dismiss = document.createElement(\"button\");\n dismiss.type = \"button\";\n dismiss.setAttribute(\"data-arcpay-banner-dismiss\", \"\");\n dismiss.textContent = \"×\";\n dismiss.setAttribute(\"aria-label\", \"Dismiss test mode banner\");\n dismiss.style.cssText =\n \"margin-left:12px;background:transparent;border:0;font-size:18px;cursor:pointer;color:inherit;\";\n dismiss.addEventListener(\"click\", () => bar.remove());\n bar.appendChild(dismiss);\n\n document.body.appendChild(bar);\n};\n","import { ArcPayError } from \"../core/errors\";\n\nexport type FieldType = \"cardNumber\" | \"cardExpiry\" | \"cardCvv\";\n\n// Parent → iframe\nexport type ParentToIframe =\n | { type: \"arcpay:hello\"; origin: string; publishableKey: string; channelId: string }\n | { type: \"arcpay:style\"; payload: StyleSubset }\n | { type: \"arcpay:focus\" }\n | { type: \"arcpay:clear\" }\n | { type: \"arcpay:tokenize\"; paymentId: string; idempotencyKey: string };\n\n// iframe → parent\nexport type IframeToParent =\n | { type: \"arcpay:ready\" }\n | { type: \"arcpay:rejected\"; reason: string }\n | {\n type: \"arcpay:change\";\n field: FieldType;\n isValid: boolean;\n brand?: string;\n lastFour?: string;\n }\n | {\n type: \"arcpay:tokenize-result\";\n cardTokenId: string;\n cardMask: string;\n cardScheme: string;\n cardBin: string;\n expiresIn: number;\n expiresAt: string;\n }\n | { type: \"arcpay:tokenize-error\"; errorType: string; code?: string; message: string };\n\nexport interface StyleSubset {\n base: Record<string, string>;\n invalid?: Record<string, string>;\n focus?: Record<string, string>;\n}\n\nconst ARCPAY_TYPE_PREFIX = \"arcpay:\";\n\nconst isArcpayMessage = (data: unknown): data is { type: string } =>\n typeof data === \"object\" &&\n data !== null &&\n \"type\" in data &&\n typeof (data as { type: unknown }).type === \"string\" &&\n (data as { type: string }).type.startsWith(ARCPAY_TYPE_PREFIX);\n\nexport const postToIframe = (\n iframe: HTMLIFrameElement,\n message: ParentToIframe,\n targetOrigin: string,\n): void => {\n if (targetOrigin === \"*\") {\n throw new ArcPayError({\n type: \"validation_error\",\n code: \"wildcard_origin_forbidden\",\n message: \"postToIframe: targetOrigin cannot be '*'\",\n retryable: false,\n });\n }\n if (!iframe.contentWindow) {\n throw new ArcPayError({\n type: \"validation_error\",\n code: \"iframe_not_loaded\",\n message: \"postToIframe: iframe.contentWindow is null (iframe not mounted)\",\n retryable: false,\n });\n }\n iframe.contentWindow.postMessage(message, targetOrigin);\n};\n\nexport const postToParent = (message: IframeToParent, targetOrigin: string): void => {\n if (targetOrigin === \"*\") {\n throw new Error(\"postToParent: targetOrigin cannot be '*'\");\n }\n window.parent.postMessage(message, targetOrigin);\n};\n\nexport const parseIncoming = <T extends { type: string }>(\n event: MessageEvent,\n expectedOrigin: string,\n): T | null => {\n if (event.origin !== expectedOrigin) return null;\n if (!isArcpayMessage(event.data)) return null;\n return event.data as T;\n};\n","import type { StyleSubset } from \"./postmessage\";\n\n// Spec calls out position:fixed, transform, pointer-events:none as forbidden.\n// We extend to cover the full clickjacking attack surface: any positioning\n// (fixed/absolute/sticky), transform, all pointer-events values, z-index, and\n// inset properties (top/left/right/bottom/inset). The legitimate use cases\n// for these in a 1-line input field are zero, so blanket drop.\nconst FORBIDDEN_PROPERTIES = new Set([\n \"position\",\n \"transform\",\n \"pointer-events\",\n \"z-index\",\n \"top\",\n \"left\",\n \"right\",\n \"bottom\",\n \"inset\",\n]);\n\nconst sanitizeBlock = (block: Record<string, string>): Record<string, string> => {\n const out: Record<string, string> = {};\n for (const [key, value] of Object.entries(block)) {\n const normalizedKey = key.toLowerCase();\n if (FORBIDDEN_PROPERTIES.has(normalizedKey)) {\n // Defense against position/transform-based clickjacking. Silently drop.\n continue;\n }\n out[key] = value;\n }\n return out;\n};\n\nexport const sanitizeStyle = (style: StyleSubset): StyleSubset => {\n const result: StyleSubset = { base: sanitizeBlock(style.base) };\n if (style.invalid !== undefined) result.invalid = sanitizeBlock(style.invalid);\n if (style.focus !== undefined) result.focus = sanitizeBlock(style.focus);\n return result;\n};\n","import { ArcPayError } from \"../core/errors\";\nimport {\n type FieldType,\n type ParentToIframe,\n type IframeToParent,\n type StyleSubset,\n postToIframe,\n parseIncoming,\n} from \"./postmessage\";\nimport { sanitizeStyle } from \"./style\";\n\nexport interface ElementOptions {\n /** StyleSubset applied via arcpay:style postMessage. */\n style?: StyleSubset;\n placeholder?: string;\n}\n\nexport type ElementEvent =\n | { type: \"ready\" }\n | { type: \"change\"; isValid: boolean; brand?: string; lastFour?: string }\n | { type: \"error\"; reason: string };\n\ntype Listener = (event: ElementEvent) => void;\n\nexport interface ElementContext {\n iframeBase: string;\n publishableKey: string;\n channelId: string;\n}\n\nexport class Element {\n private iframe: HTMLIFrameElement | null = null;\n private readonly listeners = new Set<Listener>();\n private status: \"pending\" | \"ready\" | \"error\" = \"pending\";\n private messageHandler: ((e: MessageEvent) => void) | null = null;\n\n constructor(\n public readonly field: FieldType,\n private readonly options: ElementOptions,\n private readonly context: ElementContext,\n ) {}\n\n mount(target: string | HTMLElement): void {\n if (this.iframe) {\n throw new ArcPayError({\n type: \"validation_error\",\n code: \"already_mounted\",\n message: `Element ${this.field} is already mounted`,\n retryable: false,\n });\n }\n const container = typeof target === \"string\" ? document.querySelector(target) : target;\n if (!(container instanceof HTMLElement)) {\n throw new ArcPayError({\n type: \"validation_error\",\n code: \"mount_target_not_found\",\n message: `mount target not found: ${String(target)}`,\n retryable: false,\n });\n }\n\n const iframe = document.createElement(\"iframe\");\n iframe.src = `${this.context.iframeBase}/iframe/${this.field}`;\n iframe.style.cssText = \"border:0;width:100%;height:100%;display:block;\";\n iframe.setAttribute(\"allow\", \"payment\");\n iframe.setAttribute(\"data-arcpay-element\", this.field);\n container.appendChild(iframe);\n this.iframe = iframe;\n\n const expectedOrigin = new URL(this.context.iframeBase).origin;\n\n this.messageHandler = (event: MessageEvent) => {\n // C1: source guard — only accept messages from this element's own iframe.\n // Without this, any iframe at the same origin (e.g. cardExpiry, cardCvv)\n // could trigger handlers on cardNumber and vice-versa.\n if (event.source !== this.iframe?.contentWindow) return;\n // C4: use parseIncoming for origin + arcpay: prefix guard.\n const data = parseIncoming<IframeToParent>(event, expectedOrigin);\n if (!data) return;\n this.handleMessage(data);\n };\n window.addEventListener(\"message\", this.messageHandler);\n\n iframe.addEventListener(\n \"load\",\n () => {\n if (!this.iframe) return;\n const hello: ParentToIframe = {\n type: \"arcpay:hello\",\n origin: window.location.origin,\n publishableKey: this.context.publishableKey,\n channelId: this.context.channelId,\n };\n postToIframe(this.iframe, hello, expectedOrigin);\n },\n { once: true },\n );\n }\n\n private handleMessage(data: IframeToParent): void {\n if (data.type === \"arcpay:ready\") {\n this.status = \"ready\";\n // Apply initial style if provided at construction time.\n if (this.options.style) {\n this.send({ type: \"arcpay:style\", payload: sanitizeStyle(this.options.style) });\n }\n this.emit({ type: \"ready\" });\n } else if (data.type === \"arcpay:rejected\") {\n this.status = \"error\";\n this.emit({ type: \"error\", reason: data.reason });\n } else if (data.type === \"arcpay:change\" && data.field === this.field) {\n this.emit({\n type: \"change\",\n isValid: data.isValid,\n brand: data.brand,\n lastFour: data.lastFour,\n });\n }\n // arcpay:tokenize-result / arcpay:tokenize-error handled by Elements factory (Task 9).\n }\n\n update(options: { style?: StyleSubset }): void {\n if (options.style) {\n this.send({ type: \"arcpay:style\", payload: sanitizeStyle(options.style) });\n }\n }\n\n destroy(): void {\n if (this.iframe) {\n this.iframe.remove();\n this.iframe = null;\n }\n if (this.messageHandler) {\n window.removeEventListener(\"message\", this.messageHandler);\n this.messageHandler = null;\n }\n this.listeners.clear();\n this.status = \"pending\";\n }\n\n on(_event: \"ready\" | \"change\" | \"error\", callback: Listener): () => void {\n this.listeners.add(callback);\n return () => this.listeners.delete(callback);\n }\n\n focus(): void {\n this.send({ type: \"arcpay:focus\" });\n }\n\n clear(): void {\n this.send({ type: \"arcpay:clear\" });\n }\n\n isReady(): boolean {\n return this.status === \"ready\";\n }\n\n /**\n * Internal: returns the iframe's contentWindow for source-filtering in\n * Elements.doTokenize(). Returns null when the iframe is not yet mounted\n * or when jsdom has not yet populated contentWindow (test environment).\n */\n getIframeContentWindow(): Window | null {\n return this.iframe?.contentWindow ?? null;\n }\n\n /** Internal: used by Elements factory to send tokenize commands. */\n send(message: ParentToIframe): void {\n if (!this.iframe) {\n throw new ArcPayError({\n type: \"validation_error\",\n code: \"not_mounted\",\n message: `Element ${this.field} is not mounted`,\n retryable: false,\n });\n }\n postToIframe(this.iframe, message, new URL(this.context.iframeBase).origin);\n }\n\n private emit(event: ElementEvent): void {\n for (const listener of this.listeners) {\n listener(event);\n }\n }\n}\n","import { ArcPayError } from \"../core/errors\";\nimport { Element, type ElementContext, type ElementOptions } from \"./element\";\nimport type { FieldType, IframeToParent } from \"./postmessage\";\nimport { parseIncoming } from \"./postmessage\";\nimport type { TokenizeResult } from \"../tokenize/tokenize\";\n\nexport type { TokenizeResult };\n\nexport type ElementsOptions = Record<string, never>;\n\nconst DEFAULT_IFRAME_BASE = \"https://sdk.arcpay.space\";\n\nconst createChannelId = (): string => {\n if (!globalThis.crypto?.randomUUID) {\n throw new ArcPayError({\n type: \"validation_error\",\n code: \"crypto_unavailable\",\n message: \"crypto.randomUUID is required for Hosted Fields\",\n retryable: false,\n });\n }\n return globalThis.crypto.randomUUID();\n};\n\nexport class Elements {\n private readonly elementMap = new Map<FieldType, Element>();\n private readonly iframeBase: string;\n private readonly publishableKey: string;\n private readonly channelId: string;\n private tokenizeInFlight = false;\n\n constructor(opts: { publishableKey: string; iframeBase?: string }) {\n this.publishableKey = opts.publishableKey;\n this.iframeBase = opts.iframeBase ?? DEFAULT_IFRAME_BASE;\n this.channelId = createChannelId();\n }\n\n create(field: FieldType, options: ElementOptions = {}): Element {\n if (this.elementMap.has(field)) {\n throw new ArcPayError({\n type: \"validation_error\",\n code: \"duplicate_element\",\n message: `Element for ${field} already created`,\n retryable: false,\n });\n }\n const ctx: ElementContext = {\n iframeBase: this.iframeBase,\n publishableKey: this.publishableKey,\n channelId: this.channelId,\n };\n const element = new Element(field, options, ctx);\n this.elementMap.set(field, element);\n return element;\n }\n\n async tokenize(paymentId: string, idempotencyKey: string): Promise<TokenizeResult> {\n // C2: concurrent-call guard — only one tokenize() may be in-flight at a time.\n if (this.tokenizeInFlight) {\n throw new ArcPayError({\n type: \"validation_error\",\n code: \"tokenize_in_progress\",\n message: \"A tokenize() call is already in progress for this Elements instance\",\n retryable: false,\n });\n }\n\n const cardNumber = this.elementMap.get(\"cardNumber\");\n const cardExpiry = this.elementMap.get(\"cardExpiry\");\n const cardCvv = this.elementMap.get(\"cardCvv\");\n\n if (!cardNumber || !cardExpiry || !cardCvv) {\n throw new ArcPayError({\n type: \"validation_error\",\n code: \"incomplete_elements\",\n message:\n \"All three elements (cardNumber, cardExpiry, cardCvv) must be created and mounted before tokenize()\",\n retryable: false,\n });\n }\n if (!cardNumber.isReady() || !cardExpiry.isReady() || !cardCvv.isReady()) {\n throw new ArcPayError({\n type: \"validation_error\",\n code: \"elements_not_ready\",\n message: \"Wait for all elements to fire 'ready' event before tokenize()\",\n retryable: false,\n });\n }\n\n this.tokenizeInFlight = true;\n try {\n return await this.doTokenize(cardNumber, paymentId, idempotencyKey);\n } finally {\n this.tokenizeInFlight = false;\n }\n }\n\n private doTokenize(\n cardNumber: Element,\n paymentId: string,\n idempotencyKey: string,\n ): Promise<TokenizeResult> {\n const iframeOrigin = new URL(this.iframeBase).origin;\n // C1: obtain reference to the cardNumber iframe's contentWindow before\n // registering the listener so we can filter by source.\n const cardIframeWindow = cardNumber.getIframeContentWindow();\n\n return new Promise<TokenizeResult>((resolve, reject) => {\n // C3: 30-second timeout — rejects and cleans up if no result arrives.\n const timer = window.setTimeout(() => {\n window.removeEventListener(\"message\", onMessage);\n reject(\n new ArcPayError({\n type: \"network_error\",\n code: \"tokenize_timeout\",\n message: \"tokenize() timed out after 30 seconds\",\n retryable: true,\n paymentId,\n }),\n );\n }, 30_000);\n\n const onMessage = (event: MessageEvent) => {\n // C1: source guard — only accept messages from the cardNumber iframe.\n if (cardIframeWindow !== null && event.source !== cardIframeWindow) return;\n // C4: use parseIncoming for origin + arcpay: prefix guard.\n const data = parseIncoming<IframeToParent>(event, iframeOrigin);\n if (!data) return;\n\n if (data.type === \"arcpay:tokenize-result\") {\n clearTimeout(timer);\n window.removeEventListener(\"message\", onMessage);\n resolve({\n cardTokenId: data.cardTokenId,\n cardMask: data.cardMask,\n cardScheme: data.cardScheme,\n cardBin: data.cardBin,\n expiresIn: data.expiresIn,\n expiresAt: data.expiresAt,\n });\n } else if (data.type === \"arcpay:tokenize-error\") {\n clearTimeout(timer);\n window.removeEventListener(\"message\", onMessage);\n const errType =\n data.errorType === \"validation_error\" || data.errorType === \"api_error\"\n ? data.errorType\n : \"api_error\";\n reject(\n new ArcPayError({\n type: errType,\n code: data.code,\n message: data.message,\n retryable: false,\n paymentId,\n }),\n );\n }\n };\n\n window.addEventListener(\"message\", onMessage);\n cardNumber.send({ type: \"arcpay:tokenize\", paymentId, idempotencyKey });\n });\n }\n\n destroy(): void {\n for (const el of this.elementMap.values()) {\n el.destroy();\n }\n this.elementMap.clear();\n }\n}\n","import {\n detectEnvironment,\n type Environment,\n validatePublishableKey as _validatePublishableKey,\n} from \"./env\";\nimport { showSandboxBanner } from \"./sandbox-banner\";\nimport { Elements, type ElementsOptions } from \"../elements/elements\";\n\nconst validatePublishableKey: (key: unknown) => asserts key is string = _validatePublishableKey;\n\nexport interface ArcPayLoadOptions {\n readonly _reserved?: never;\n}\n\nexport interface ArcPayInstance {\n readonly publishableKey: string;\n readonly environment: Environment;\n elements: (opts?: ElementsOptions) => Elements;\n}\n\nconst cache = new Map<string, Promise<ArcPayInstance>>();\n\nconst buildInstance = (publishableKey: string): ArcPayInstance => {\n if (detectEnvironment(publishableKey) === \"sandbox\") {\n showSandboxBanner();\n }\n return {\n publishableKey,\n environment: detectEnvironment(publishableKey),\n elements: () => new Elements({ publishableKey }),\n };\n};\n\nfunction load(publishableKey: string): Promise<ArcPayInstance> {\n try {\n validatePublishableKey(publishableKey);\n } catch (err) {\n return Promise.reject(err);\n }\n const key = publishableKey;\n const existing = cache.get(key);\n if (existing) return existing;\n const promise = Promise.resolve(buildInstance(publishableKey));\n cache.set(key, promise);\n return promise;\n}\n\nconst resetForTests = (): void => {\n cache.clear();\n};\n\nexport const ArcPay = {\n load,\n __resetForTests: resetForTests,\n};\n","export { ArcPay } from \"./core/arcpay\";\nexport type { ArcPayInstance, ArcPayLoadOptions } from \"./core/arcpay\";\nexport {\n ArcPayError,\n isValidationError,\n isAuthenticationError,\n isAuthorizationError,\n isStateError,\n isRateLimitError,\n isApiError,\n isNetworkError,\n isChallengeAborted,\n} from \"./core/errors\";\nexport type { ArcPayErrorType } from \"./core/errors\";\nexport type { Environment } from \"./core/env\";\nexport type { TokenizeResult } from \"./tokenize/tokenize\";\nexport type { CardScheme } from \"./tokenize/scheme\";\nexport const SDK_VERSION = \"0.1.2\";\n\nexport type { FieldType } from \"./elements/postmessage\";\nexport type { ElementOptions, ElementEvent } from \"./elements/element\";\nexport { Elements } from \"./elements/elements\";\nexport type { ElementsOptions } from \"./elements/elements\";\n"]}