@ozura/elements 1.0.2 → 1.1.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
@@ -0,0 +1,12 @@
1
+ /**
2
+ * Shared postMessage protocol constants.
3
+ *
4
+ * PROTOCOL_VERSION must be incremented any time a breaking change is made to
5
+ * the postMessage message shape (new required fields, renamed types, removed
6
+ * fields, changed semantics). The SDK reads this value from OZ_FRAME_READY
7
+ * messages and warns when the frame and SDK are out of sync.
8
+ *
9
+ * Non-breaking additions (new optional fields, new message types that old
10
+ * frames can safely ignore) do NOT require a version bump.
11
+ */
12
+ export declare const PROTOCOL_VERSION = 1;
@@ -44,6 +44,8 @@ export declare class OzVault {
44
44
  private tokenizerReady;
45
45
  private _tokenizing;
46
46
  private _destroyed;
47
+ private _resetCount;
48
+ private _debug;
47
49
  private _tokenizeSuccessCount;
48
50
  private _maxTokenizeCalls;
49
51
  private boundHandleMessage;
@@ -155,6 +157,29 @@ export declare class OzVault {
155
157
  * Returns a token and cvcSession that can be passed to the Ozura Pay API.
156
158
  */
157
159
  createToken(options?: TokenizeOptions): Promise<TokenResponse>;
160
+ /**
161
+ * Clears all mounted element fields without tearing down the vault.
162
+ *
163
+ * Call this after a failed payment (e.g. card declined) to let the customer
164
+ * re-enter their details. The vault instance, tokenizer iframe, wax key, and
165
+ * tokenization budget counter are all preserved — no network calls are made.
166
+ *
167
+ * **Wax key session model:** by design, one wax key covers the full checkout
168
+ * session. The default `max_tokenize_calls: 3` supports two declined attempts
169
+ * and one final attempt on the same key. Do not call `vault.destroy()` and
170
+ * recreate the vault between declines — that unnecessarily re-mints the key
171
+ * and discards the remaining budget.
172
+ *
173
+ * @example
174
+ * try {
175
+ * const { token, cvcSession } = await vault.createToken({ billing });
176
+ * await chargeCard(token, cvcSession);
177
+ * } catch (err) {
178
+ * vault.reset(); // clear fields; let customer re-enter
179
+ * showError(err.message);
180
+ * }
181
+ */
182
+ reset(): void;
158
183
  /**
159
184
  * Tears down the vault: removes all element iframes, the tokenizer iframe,
160
185
  * and the global message listener. Call this when the checkout component
@@ -172,6 +197,30 @@ export declare class OzVault {
172
197
  * while avoiding spurious refreshes for brief tab-switches.
173
198
  */
174
199
  private handleVisibilityChange;
200
+ /**
201
+ * Emits a `[OzVault]`-prefixed entry to `console.log`. No-op when `debug` is
202
+ * not set. Never called with sensitive values — callers use presence flags only.
203
+ */
204
+ private log;
205
+ /**
206
+ * Returns a plain-object snapshot of the vault's current internal state.
207
+ * Safe to attach to bug reports — no wax keys, tokens, or billing data included.
208
+ *
209
+ * Available on all vault instances regardless of whether `debug` was enabled.
210
+ *
211
+ * @example
212
+ * console.log(vault.debugState());
213
+ * // {
214
+ * // vaultId: 'vault-abc123',
215
+ * // isReady: true,
216
+ * // tokenizing: null,
217
+ * // destroyed: false,
218
+ * // waxKeyPresent: true,
219
+ * // elements: ['cardNumber', 'expirationDate', 'cvv'],
220
+ * // ...
221
+ * // }
222
+ */
223
+ debugState(): Record<string, unknown>;
175
224
  private mountTokenizerFrame;
176
225
  private handleMessage;
177
226
  /**
@@ -256,6 +256,24 @@ export interface VaultOptions {
256
256
  * }
257
257
  */
258
258
  appearance?: Appearance;
259
+ /**
260
+ * Enables structured debug logging to the browser console.
261
+ *
262
+ * When `true`, the vault emits a `[OzVault]`-prefixed `console.log` entry at
263
+ * every meaningful lifecycle event: vault creation, tokenizer readiness, element
264
+ * readiness, field changes, tokenization start/result/error, wax key refresh,
265
+ * tab-visibility refreshes, `reset()`, and `destroy()`.
266
+ *
267
+ * **No sensitive data is ever logged.** Wax keys, tokens, CVC sessions, and
268
+ * billing fields are represented only as boolean presence flags. Frame IDs and
269
+ * request IDs are truncated. Output is safe to paste directly into bug reports.
270
+ *
271
+ * Use `vault.debugState()` to capture a full snapshot of internal state at any
272
+ * point, regardless of whether `debug` is enabled.
273
+ *
274
+ * @default false
275
+ */
276
+ debug?: boolean;
259
277
  }
260
278
  /** Billing address. All string fields are validated to 1–50 characters. */
261
279
  export interface BillingAddress {
@@ -593,6 +611,8 @@ export interface TransactionQueryResponse {
593
611
  export type OzMessageType = 'OZ_FRAME_READY' | 'OZ_INIT' | 'OZ_UPDATE' | 'OZ_CLEAR' | 'OZ_CHANGE' | 'OZ_FOCUS' | 'OZ_BLUR' | 'OZ_RESIZE' | 'OZ_BEGIN_COLLECT' | 'OZ_FIELD_VALUE' | 'OZ_TOKENIZE' | 'OZ_TOKEN_RESULT' | 'OZ_TOKEN_ERROR' | 'OZ_FOCUS_REQUEST' | 'OZ_BLUR_REQUEST' | 'OZ_SET_CVV_LENGTH' | 'OZ_BANK_TOKENIZE' | 'OZ_BANK_TOKEN_RESULT' | 'OZ_TOKENIZE_CANCEL';
594
612
  export interface OzMessage {
595
613
  __oz: true;
614
+ /** Protocol version stamped by the frame on OZ_FRAME_READY. Read by the SDK to detect stale CDN frames. */
615
+ __ozVersion?: number;
596
616
  vaultId: string;
597
617
  type: OzMessageType;
598
618
  [key: string]: unknown;
@@ -5,4 +5,73 @@
5
5
  * communicates with the host SDK via postMessage. Raw values NEVER leave this
6
6
  * file except when sent directly to the tokenizer frame (same-origin).
7
7
  */
8
- export {};
8
+ /**
9
+ * Validates a US ABA routing number using the standard checksum algorithm.
10
+ * The checksum is: (3*(d1+d4+d7) + 7*(d2+d5+d8) + 1*(d3+d6+d9)) mod 10 === 0
11
+ */
12
+ export declare function validateRoutingNumber(routing: string): boolean;
13
+ export declare const ALLOWED_STYLE_PROPERTIES: Set<string>;
14
+ export declare const BLOCKED_VALUE_PATTERNS: RegExp;
15
+ /** Matches `url('https://...')` or `url(https://...)` with optional `format('woff2')`. */
16
+ export declare const FONT_SRC_PATTERN: RegExp;
17
+ export declare const CSS_BREAKOUT: RegExp;
18
+ export declare function sanitizeCssString(value: string, maxLen: number): string;
19
+ export declare function sanitizeCssToken(value: string, maxLen?: number): string;
20
+ export declare class ElementFrame {
21
+ private elementType;
22
+ private vaultId;
23
+ private frameId;
24
+ private hostOrigin;
25
+ private rawValue;
26
+ private cardBrand;
27
+ private cvvMaxLength;
28
+ private _composing;
29
+ private _appliedBaseStyleKeys;
30
+ private _appliedStateStyleKeys;
31
+ private containerEl;
32
+ private inputEl;
33
+ private iconEl;
34
+ private liveRegion;
35
+ private options;
36
+ private _boundOnMessage;
37
+ constructor();
38
+ private buildDOM;
39
+ private getInputType;
40
+ private getAutocomplete;
41
+ private getDefaultPlaceholder;
42
+ private getAriaLabel;
43
+ private onInput;
44
+ private onKeydown;
45
+ private onFocus;
46
+ private onBlur;
47
+ private updateBrandIcon;
48
+ private isComplete;
49
+ private isValid;
50
+ private getError;
51
+ private emitChange;
52
+ private onMessage;
53
+ private placeholderStyleEl;
54
+ private applyOptions;
55
+ private applyStyles;
56
+ private static readonly PLACEHOLDER_INPUT_ID;
57
+ /** Clears all CSS properties that were applied from a state-style bucket
58
+ * (focus, complete, or invalid), then restores any that exist in the base
59
+ * style so that base values are not lost when transitioning between states. */
60
+ private clearStateStyles;
61
+ /** Clears stale state styles then re-applies the correct state bucket based
62
+ * on current focus and validity. Used after a base-style update so the
63
+ * on-screen state visual stays accurate without requiring user interaction. */
64
+ private reapplyStateStyles;
65
+ private applyPlaceholderStyles;
66
+ private fontsInjected;
67
+ private injectFonts;
68
+ /**
69
+ * Delivers this field's raw value to the tokenizer iframe via the MessagePort
70
+ * transferred in OZ_BEGIN_COLLECT. The port provides a direct channel that
71
+ * bypasses the merchant page entirely — no named-window lookup is needed.
72
+ */
73
+ private sendValueToTokenizer;
74
+ private sendResize;
75
+ private postToParent;
76
+ destroy(): void;
77
+ }
@@ -0,0 +1,12 @@
1
+ /**
2
+ * Shared postMessage protocol constants.
3
+ *
4
+ * PROTOCOL_VERSION must be incremented any time a breaking change is made to
5
+ * the postMessage message shape (new required fields, renamed types, removed
6
+ * fields, changed semantics). The SDK reads this value from OZ_FRAME_READY
7
+ * messages and warns when the frame and SDK are out of sync.
8
+ *
9
+ * Non-breaking additions (new optional fields, new message types that old
10
+ * frames can safely ignore) do NOT require a version bump.
11
+ */
12
+ export declare const PROTOCOL_VERSION = 1;
@@ -44,6 +44,8 @@ export declare class OzVault {
44
44
  private tokenizerReady;
45
45
  private _tokenizing;
46
46
  private _destroyed;
47
+ private _resetCount;
48
+ private _debug;
47
49
  private _tokenizeSuccessCount;
48
50
  private _maxTokenizeCalls;
49
51
  private boundHandleMessage;
@@ -155,6 +157,29 @@ export declare class OzVault {
155
157
  * Returns a token and cvcSession that can be passed to the Ozura Pay API.
156
158
  */
157
159
  createToken(options?: TokenizeOptions): Promise<TokenResponse>;
160
+ /**
161
+ * Clears all mounted element fields without tearing down the vault.
162
+ *
163
+ * Call this after a failed payment (e.g. card declined) to let the customer
164
+ * re-enter their details. The vault instance, tokenizer iframe, wax key, and
165
+ * tokenization budget counter are all preserved — no network calls are made.
166
+ *
167
+ * **Wax key session model:** by design, one wax key covers the full checkout
168
+ * session. The default `max_tokenize_calls: 3` supports two declined attempts
169
+ * and one final attempt on the same key. Do not call `vault.destroy()` and
170
+ * recreate the vault between declines — that unnecessarily re-mints the key
171
+ * and discards the remaining budget.
172
+ *
173
+ * @example
174
+ * try {
175
+ * const { token, cvcSession } = await vault.createToken({ billing });
176
+ * await chargeCard(token, cvcSession);
177
+ * } catch (err) {
178
+ * vault.reset(); // clear fields; let customer re-enter
179
+ * showError(err.message);
180
+ * }
181
+ */
182
+ reset(): void;
158
183
  /**
159
184
  * Tears down the vault: removes all element iframes, the tokenizer iframe,
160
185
  * and the global message listener. Call this when the checkout component
@@ -172,6 +197,30 @@ export declare class OzVault {
172
197
  * while avoiding spurious refreshes for brief tab-switches.
173
198
  */
174
199
  private handleVisibilityChange;
200
+ /**
201
+ * Emits a `[OzVault]`-prefixed entry to `console.log`. No-op when `debug` is
202
+ * not set. Never called with sensitive values — callers use presence flags only.
203
+ */
204
+ private log;
205
+ /**
206
+ * Returns a plain-object snapshot of the vault's current internal state.
207
+ * Safe to attach to bug reports — no wax keys, tokens, or billing data included.
208
+ *
209
+ * Available on all vault instances regardless of whether `debug` was enabled.
210
+ *
211
+ * @example
212
+ * console.log(vault.debugState());
213
+ * // {
214
+ * // vaultId: 'vault-abc123',
215
+ * // isReady: true,
216
+ * // tokenizing: null,
217
+ * // destroyed: false,
218
+ * // waxKeyPresent: true,
219
+ * // elements: ['cardNumber', 'expirationDate', 'cvv'],
220
+ * // ...
221
+ * // }
222
+ */
223
+ debugState(): Record<string, unknown>;
175
224
  private mountTokenizerFrame;
176
225
  private handleMessage;
177
226
  /**
@@ -256,6 +256,24 @@ export interface VaultOptions {
256
256
  * }
257
257
  */
258
258
  appearance?: Appearance;
259
+ /**
260
+ * Enables structured debug logging to the browser console.
261
+ *
262
+ * When `true`, the vault emits a `[OzVault]`-prefixed `console.log` entry at
263
+ * every meaningful lifecycle event: vault creation, tokenizer readiness, element
264
+ * readiness, field changes, tokenization start/result/error, wax key refresh,
265
+ * tab-visibility refreshes, `reset()`, and `destroy()`.
266
+ *
267
+ * **No sensitive data is ever logged.** Wax keys, tokens, CVC sessions, and
268
+ * billing fields are represented only as boolean presence flags. Frame IDs and
269
+ * request IDs are truncated. Output is safe to paste directly into bug reports.
270
+ *
271
+ * Use `vault.debugState()` to capture a full snapshot of internal state at any
272
+ * point, regardless of whether `debug` is enabled.
273
+ *
274
+ * @default false
275
+ */
276
+ debug?: boolean;
259
277
  }
260
278
  /** Billing address. All string fields are validated to 1–50 characters. */
261
279
  export interface BillingAddress {
@@ -593,6 +611,8 @@ export interface TransactionQueryResponse {
593
611
  export type OzMessageType = 'OZ_FRAME_READY' | 'OZ_INIT' | 'OZ_UPDATE' | 'OZ_CLEAR' | 'OZ_CHANGE' | 'OZ_FOCUS' | 'OZ_BLUR' | 'OZ_RESIZE' | 'OZ_BEGIN_COLLECT' | 'OZ_FIELD_VALUE' | 'OZ_TOKENIZE' | 'OZ_TOKEN_RESULT' | 'OZ_TOKEN_ERROR' | 'OZ_FOCUS_REQUEST' | 'OZ_BLUR_REQUEST' | 'OZ_SET_CVV_LENGTH' | 'OZ_BANK_TOKENIZE' | 'OZ_BANK_TOKEN_RESULT' | 'OZ_TOKENIZE_CANCEL';
594
612
  export interface OzMessage {
595
613
  __oz: true;
614
+ /** Protocol version stamped by the frame on OZ_FRAME_READY. Read by the SDK to detect stale CDN frames. */
615
+ __ozVersion?: number;
596
616
  vaultId: string;
597
617
  type: OzMessageType;
598
618
  [key: string]: unknown;
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@ozura/elements",
3
- "version": "1.0.2",
3
+ "version": "1.1.0",
4
4
  "description": "PCI-compliant card tokenization SDK for the Ozura Vault — collect card data in iframe-isolated fields and tokenize without PCI scope",
5
5
  "main": "dist/oz-elements.umd.js",
6
6
  "module": "dist/oz-elements.esm.js",