@paypercut/checkout-js 1.0.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.
package/dist/index.cjs ADDED
@@ -0,0 +1,515 @@
1
+ 'use strict';
2
+
3
+ Object.defineProperty(exports, '__esModule', { value: true });
4
+
5
+ /**
6
+ * Simple event emitter for handling checkout events
7
+ * Supports subscribing, unsubscribing, and emitting events
8
+ */
9
+ class Emitter {
10
+ constructor() {
11
+ this.handlers = new Map();
12
+ }
13
+ /**
14
+ * Subscribe to an event
15
+ * @param event - Event name to listen to
16
+ * @param handler - Callback function to execute when event is emitted
17
+ * @returns Unsubscribe function
18
+ */
19
+ on(event, handler) {
20
+ if (!this.handlers.has(event)) {
21
+ this.handlers.set(event, new Set());
22
+ }
23
+ this.handlers.get(event).add(handler);
24
+ // Return unsubscribe function
25
+ return () => this.off(event, handler);
26
+ }
27
+ /**
28
+ * Subscribe to an event that auto-unsubscribes after first emission
29
+ *
30
+ * Common use case: waiting for 'loaded' event or handling first 'success'.
31
+ * Without this helper, developers would need to manually unsubscribe inside
32
+ * their handler, which is error-prone and leads to memory leaks if forgotten.
33
+ *
34
+ * @param event - Event name to listen to
35
+ * @param handler - Callback function to execute when event is emitted
36
+ * @returns Unsubscribe function
37
+ */
38
+ once(event, handler) {
39
+ const wrappedHandler = (...args) => {
40
+ handler(...args);
41
+ this.off(event, wrappedHandler);
42
+ };
43
+ return this.on(event, wrappedHandler);
44
+ }
45
+ /**
46
+ * Unsubscribe from an event
47
+ * @param event - Event name to stop listening to
48
+ * @param handler - Callback function to remove
49
+ */
50
+ off(event, handler) {
51
+ this.handlers.get(event)?.delete(handler);
52
+ }
53
+ /**
54
+ * Emit an event with optional arguments
55
+ * @param event - Event name to emit
56
+ * @param args - Arguments to pass to event handlers
57
+ */
58
+ emit(event, ...args) {
59
+ this.handlers.get(event)?.forEach(h => {
60
+ try {
61
+ h(...args);
62
+ }
63
+ catch (err) {
64
+ console.error(`[Emitter] Error in ${event} handler:`, err);
65
+ }
66
+ });
67
+ }
68
+ /**
69
+ * Clear all event handlers
70
+ */
71
+ clear() {
72
+ this.handlers.clear();
73
+ }
74
+ }
75
+
76
+ /**
77
+ * Build-time configuration
78
+ *
79
+ * This file is processed at build time with different values for:
80
+ * - Production build (for merchants)
81
+ * - Internal build (for team development)
82
+ */
83
+ /**
84
+ * Production configuration (for merchants)
85
+ */
86
+ /**
87
+ * Internal configuration (for team development)
88
+ */
89
+ const internalConfig = {
90
+ version: "1.0.0",
91
+ defaultCheckoutOrigin: 'https://buy.paypercut.io',
92
+ allowedOrigins: [
93
+ 'https://buy.paypercut.io',
94
+ 'http://localhost:3000',
95
+ 'http://localhost:3001',
96
+ 'http://127.0.0.1:3000',
97
+ 'http://127.0.0.1:3001'
98
+ ],
99
+ allowOriginOverride: true // ← Team CAN override for testing
100
+ };
101
+ /**
102
+ * Active configuration (selected at build time)
103
+ */
104
+ const config = internalConfig
105
+ ;
106
+ /**
107
+ * Helper to check if origin is allowed
108
+ */
109
+ function isOriginAllowed(origin) {
110
+ return config.allowedOrigins.includes(origin);
111
+ }
112
+ /**
113
+ * Get the checkout origin (with optional override for internal builds)
114
+ */
115
+ function getCheckoutOrigin(override) {
116
+ // Only allow override in internal builds
117
+ if (override && config.allowOriginOverride) {
118
+ return override;
119
+ }
120
+ return config.defaultCheckoutOrigin;
121
+ }
122
+
123
+ /**
124
+ * Supported locales for Paypercut Checkout
125
+ *
126
+ * @remarks
127
+ * Single source of truth for all supported locale codes.
128
+ *
129
+ * Supported languages:
130
+ * - Bulgarian: 'bg', 'bg-BG'
131
+ * - English: 'en', 'en-GB'
132
+ * - Greek: 'el', 'el-GR'
133
+ * - Romanian: 'ro', 'ro-RO'
134
+ * - Croatian: 'hr', 'hr-HR'
135
+ * - Polish: 'pl', 'pl-PL'
136
+ * - Czech: 'cs', 'cs-CZ'
137
+ * - Slovenian: 'sl', 'sl-SI'
138
+ * - Slovak: 'sk', 'sk-SK'
139
+ *
140
+ * @example
141
+ * ```typescript
142
+ * const checkout = PaypercutCheckout({
143
+ * locale: 'bg' // or 'bg-BG', 'en', 'en-GB', etc.
144
+ * });
145
+ * ```
146
+ */
147
+ const LOCALES = [
148
+ 'bg', 'bg-BG',
149
+ 'en', 'en-GB',
150
+ 'el', 'el-GR',
151
+ 'ro', 'ro-RO',
152
+ 'hr', 'hr-HR',
153
+ 'pl', 'pl-PL',
154
+ 'cs', 'cs-CZ',
155
+ 'sl', 'sl-SI',
156
+ 'sk', 'sk-SK',
157
+ ];
158
+ /**
159
+ * Fast runtime check using Set for O(1) lookup
160
+ * @internal
161
+ */
162
+ const LOCALE_SET = new Set(LOCALES);
163
+ /**
164
+ * Normalize and validate locale
165
+ *
166
+ * @param locale - Locale code to normalize
167
+ * @returns Normalized locale code or 'en' as fallback
168
+ *
169
+ * @remarks
170
+ * - 'auto' or empty → 'en'
171
+ * - Unsupported locale → 'en' with console warning
172
+ * - Supported locale → original value
173
+ *
174
+ * @example
175
+ * ```typescript
176
+ * normalizeLocale('auto') // → 'en'
177
+ * normalizeLocale('bg') // → 'bg'
178
+ * normalizeLocale('de') // → 'en' (with warning)
179
+ * ```
180
+ */
181
+ function normalizeLocale(locale) {
182
+ if (!locale || locale === 'auto')
183
+ return 'en';
184
+ if (LOCALE_SET.has(locale))
185
+ return locale;
186
+ console.warn(`[PaypercutCheckout] Locale "${locale}" is not supported. Falling back to "en".`);
187
+ return 'en';
188
+ }
189
+
190
+ /**
191
+ * UI mode for checkout
192
+ */
193
+ exports.UIMode = void 0;
194
+ (function (UIMode) {
195
+ /** Custom UI mode - merchant provides their own submit button */
196
+ UIMode["CUSTOM"] = "custom";
197
+ /** Embedded mode - checkout embedded in merchant page */
198
+ UIMode["EMBEDDED"] = "embedded";
199
+ /** Hosted mode - full-page checkout experience */
200
+ UIMode["HOSTED"] = "hosted";
201
+ })(exports.UIMode || (exports.UIMode = {}));
202
+ /**
203
+ * Type guard for UIMode
204
+ */
205
+ function isValidUIMode(value) {
206
+ return Object.values(exports.UIMode).includes(value);
207
+ }
208
+ /**
209
+ * Payment method types
210
+ */
211
+ exports.PaymentMethod = void 0;
212
+ (function (PaymentMethod) {
213
+ /** Card payment (credit/debit) */
214
+ PaymentMethod["CARD"] = "card";
215
+ })(exports.PaymentMethod || (exports.PaymentMethod = {}));
216
+ /**
217
+ * Type guard for PaymentMethod
218
+ */
219
+ function isValidPaymentMethod(value) {
220
+ return Object.values(exports.PaymentMethod).includes(value);
221
+ }
222
+ /**
223
+ * Wallet options for digital wallets
224
+ */
225
+ exports.WalletOption = void 0;
226
+ (function (WalletOption) {
227
+ /** Apple Pay */
228
+ WalletOption["APPLE_PAY"] = "apple_pay";
229
+ /** Google Pay */
230
+ WalletOption["GOOGLE_PAY"] = "google_pay";
231
+ })(exports.WalletOption || (exports.WalletOption = {}));
232
+ /**
233
+ * Type guard for WalletOption
234
+ */
235
+ function isValidWalletOption(value) {
236
+ return Object.values(exports.WalletOption).includes(value);
237
+ }
238
+ /**
239
+ * Validate payment methods array
240
+ */
241
+ function validatePaymentMethods(methods) {
242
+ const validated = [];
243
+ for (const method of methods) {
244
+ if (isValidPaymentMethod(method)) {
245
+ validated.push(method);
246
+ }
247
+ else {
248
+ console.warn(`[PaypercutCheckout] Invalid payment method: "${method}". Skipping.`);
249
+ }
250
+ }
251
+ // Default to card if no valid methods
252
+ if (validated.length === 0) {
253
+ console.warn('[PaypercutCheckout] No valid payment methods provided. Defaulting to "card".');
254
+ validated.push(exports.PaymentMethod.CARD);
255
+ }
256
+ return validated;
257
+ }
258
+ /**
259
+ * Validate wallet options array
260
+ */
261
+ function validateWalletOptions(options) {
262
+ const validated = [];
263
+ for (const option of options) {
264
+ if (isValidWalletOption(option)) {
265
+ validated.push(option);
266
+ }
267
+ else {
268
+ console.warn(`[PaypercutCheckout] Invalid wallet option: "${option}". Skipping.`);
269
+ }
270
+ }
271
+ return validated;
272
+ }
273
+ /**
274
+ * Validate UI mode
275
+ */
276
+ function validateUIMode(mode) {
277
+ if (!mode) {
278
+ return undefined;
279
+ }
280
+ if (isValidUIMode(mode)) {
281
+ return mode;
282
+ }
283
+ console.warn(`[PaypercutCheckout] Invalid ui_mode: "${mode}". Valid options: ${Object.values(exports.UIMode).join(', ')}`);
284
+ return undefined;
285
+ }
286
+
287
+ /**
288
+ * Internal implementation of CheckoutInstance
289
+ */
290
+ class CheckoutImpl {
291
+ constructor(options) {
292
+ this.options = options;
293
+ this.emitter = new Emitter();
294
+ this.mounted = false;
295
+ this.destroyed = false;
296
+ this.iframe = null;
297
+ // Bind message handler
298
+ this.messageHandler = this.onMessage.bind(this);
299
+ window.addEventListener('message', this.messageHandler);
300
+ }
301
+ /**
302
+ * Build the iframe source URL with query parameters
303
+ */
304
+ buildSrc() {
305
+ const baseUrl = getCheckoutOrigin(this.options.hostedCheckoutUrl);
306
+ const url = new URL(`/c/${this.options.id}`, baseUrl);
307
+ // Add locale parameter
308
+ if (this.options.locale) {
309
+ const normalizedLocale = normalizeLocale(this.options.locale);
310
+ url.searchParams.set('locale', normalizedLocale);
311
+ }
312
+ // Add ui_mode parameter
313
+ if (this.options.ui_mode) {
314
+ const validatedUIMode = validateUIMode(this.options.ui_mode);
315
+ if (validatedUIMode) {
316
+ url.searchParams.set('ui_mode', validatedUIMode);
317
+ }
318
+ }
319
+ // Add payment_methods parameters (repeated for each method)
320
+ if (this.options.payment_methods && this.options.payment_methods.length > 0) {
321
+ const validatedMethods = validatePaymentMethods(this.options.payment_methods);
322
+ validatedMethods.forEach(method => {
323
+ url.searchParams.append('payment_methods', method);
324
+ });
325
+ }
326
+ // Add wallet_options parameters (repeated for each wallet)
327
+ if (this.options.wallet_options && this.options.wallet_options.length > 0) {
328
+ const validatedWallets = validateWalletOptions(this.options.wallet_options);
329
+ validatedWallets.forEach(wallet => {
330
+ url.searchParams.append('wallet_options', wallet);
331
+ });
332
+ }
333
+ console.log('this.options', this.options);
334
+ if (this.options.form_only !== undefined) {
335
+ url.searchParams.set('form_only', String(this.options.form_only));
336
+ }
337
+ return url.toString();
338
+ }
339
+ /**
340
+ * Get the container element from selector or HTMLElement
341
+ */
342
+ getContainer() {
343
+ const container = typeof this.options.containerId === 'string'
344
+ ? document.querySelector(this.options.containerId)
345
+ : this.options.containerId;
346
+ if (!container) {
347
+ throw new Error(`Container not found: ${this.options.containerId}`);
348
+ }
349
+ return container;
350
+ }
351
+ /**
352
+ * Handle incoming postMessage events from iframe
353
+ */
354
+ onMessage(evt) {
355
+ // Validate origin against allowed origins (build-time whitelist)
356
+ if (!isOriginAllowed(evt.origin)) {
357
+ console.warn('[PaypercutCheckout] Rejected message from unauthorized origin:', evt.origin, 'Allowed:', config.allowedOrigins);
358
+ return;
359
+ }
360
+ // Validate structure
361
+ const data = evt.data;
362
+ if (!data || typeof data !== 'object' || !('type' in data)) {
363
+ return;
364
+ }
365
+ // Filter messages by checkout session ID to prevent cross-instance message handling
366
+ // This ensures each checkout instance only processes its own messages
367
+ if (data.checkoutId && data.checkoutId !== this.options.id) {
368
+ return; // Message is for a different checkout instance
369
+ }
370
+ // Handle specific events
371
+ switch (data.type) {
372
+ case 'CHECKOUT_LOADED':
373
+ this.emitter.emit('loaded');
374
+ break;
375
+ case 'CHECKOUT_SUCCESS':
376
+ this.emitter.emit('success');
377
+ break;
378
+ case 'CHECKOUT_ERROR':
379
+ this.emitter.emit('error');
380
+ break;
381
+ }
382
+ }
383
+ /**
384
+ * Render the checkout iframe into the container
385
+ */
386
+ render() {
387
+ if (this.mounted) {
388
+ console.warn('[PaypercutCheckout] Already mounted');
389
+ return;
390
+ }
391
+ try {
392
+ const container = this.getContainer();
393
+ // Create iframe
394
+ this.iframe = document.createElement('iframe');
395
+ this.iframe.id = 'paypercut-checkout-iframe';
396
+ this.iframe.src = this.buildSrc();
397
+ this.iframe.allow = 'payment *; clipboard-write';
398
+ this.iframe.setAttribute('frameborder', '0');
399
+ // Apply default styles - just construct URL and assign to iframe
400
+ Object.assign(this.iframe.style, {
401
+ width: '100%',
402
+ height: '100%',
403
+ border: 'none',
404
+ display: 'block'
405
+ });
406
+ // Listen for iframe load event (fallback)
407
+ // This ensures 'loaded' event is always emitted even if hosted checkout
408
+ // doesn't send CHECKOUT_LOADED message
409
+ /*this.iframe.addEventListener('load', () => {
410
+ this.emitter.emit('loaded');
411
+ });*/
412
+ container.appendChild(this.iframe);
413
+ this.mounted = true;
414
+ }
415
+ catch (err) {
416
+ console.error('[PaypercutCheckout] Failed to render:', err);
417
+ throw err;
418
+ }
419
+ }
420
+ /**
421
+ * Submit payment - sends message to hosted checkout to confirm payment
422
+ */
423
+ submit() {
424
+ if (!this.mounted) {
425
+ console.warn('[PaypercutCheckout] Cannot submit: checkout not mounted');
426
+ return;
427
+ }
428
+ try {
429
+ this.postToIframe({
430
+ type: 'START_PROCESSING',
431
+ checkoutId: this.options.id,
432
+ });
433
+ console.log('[PaypercutCheckout] Submit payment message sent');
434
+ }
435
+ catch (err) {
436
+ console.error('[PaypercutCheckout] Failed to submit payment:', err);
437
+ throw err;
438
+ }
439
+ }
440
+ /**
441
+ * Send message to iframe - used for submit and other commands
442
+ */
443
+ postToIframe(message) {
444
+ if (!this.iframe?.contentWindow) {
445
+ console.error('[PaypercutCheckout] Cannot post message: iframe not mounted');
446
+ return;
447
+ }
448
+ const checkoutOrigin = getCheckoutOrigin(this.options.hostedCheckoutUrl);
449
+ this.iframe.contentWindow.postMessage(message, checkoutOrigin);
450
+ }
451
+ /**
452
+ * Destroy the checkout instance and cleanup (idempotent)
453
+ */
454
+ destroy() {
455
+ // Early return if already destroyed
456
+ if (this.destroyed) {
457
+ return;
458
+ }
459
+ // Remove iframe from DOM
460
+ if (this.iframe) {
461
+ try {
462
+ this.iframe.remove();
463
+ this.iframe = null;
464
+ }
465
+ catch (err) {
466
+ console.error('[PaypercutCheckout] Error removing iframe:', err);
467
+ }
468
+ }
469
+ // Only set mounted = false after successful DOM removal
470
+ this.mounted = false;
471
+ this.destroyed = true;
472
+ // Cleanup event listeners
473
+ window.removeEventListener('message', this.messageHandler);
474
+ this.emitter.clear();
475
+ }
476
+ /**
477
+ * Subscribe to an event
478
+ */
479
+ on(event, handler) {
480
+ return this.emitter.on(event, handler);
481
+ }
482
+ /**
483
+ * Subscribe to event that auto-unsubscribes after first emission
484
+ */
485
+ once(event, handler) {
486
+ return this.emitter.once(event, handler);
487
+ }
488
+ /**
489
+ * Unsubscribe from an event
490
+ */
491
+ off(event, handler) {
492
+ this.emitter.off(event, handler);
493
+ }
494
+ /**
495
+ * Check if checkout is currently mounted
496
+ */
497
+ isMounted() {
498
+ return this.mounted;
499
+ }
500
+ }
501
+ /**
502
+ * Factory function that works both as callable and constructable.
503
+ * Always returns a new CheckoutImpl instance - no prototype manipulation needed.
504
+ */
505
+ const PaypercutCheckout = function (options) {
506
+ // Always return a new instance, regardless of how it's called
507
+ return new CheckoutImpl(options);
508
+ };
509
+ // Add static version property
510
+ PaypercutCheckout.version = config.version;
511
+
512
+ exports.LOCALES = LOCALES;
513
+ exports.PaypercutCheckout = PaypercutCheckout;
514
+ exports.default = PaypercutCheckout;
515
+ //# sourceMappingURL=index.cjs.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"index.cjs","sources":["../src/utils/emitter.ts","../src/config.ts","../src/types/locales.ts","../src/types/checkout.ts","../src/index.ts"],"sourcesContent":["/**\n * Simple event emitter for handling checkout events\n * Supports subscribing, unsubscribing, and emitting events\n */\nexport class Emitter<T extends string = string> {\n private handlers = new Map<T, Set<Function>>();\n\n /**\n * Subscribe to an event\n * @param event - Event name to listen to\n * @param handler - Callback function to execute when event is emitted\n * @returns Unsubscribe function\n */\n on(event: T, handler: Function): () => void {\n if (!this.handlers.has(event)) {\n this.handlers.set(event, new Set());\n }\n this.handlers.get(event)!.add(handler);\n\n // Return unsubscribe function\n return () => this.off(event, handler);\n }\n\n /**\n * Subscribe to an event that auto-unsubscribes after first emission\n *\n * Common use case: waiting for 'loaded' event or handling first 'success'.\n * Without this helper, developers would need to manually unsubscribe inside\n * their handler, which is error-prone and leads to memory leaks if forgotten.\n *\n * @param event - Event name to listen to\n * @param handler - Callback function to execute when event is emitted\n * @returns Unsubscribe function\n */\n once(event: T, handler: Function): () => void {\n const wrappedHandler = (...args: any[]) => {\n handler(...args);\n this.off(event, wrappedHandler);\n };\n return this.on(event, wrappedHandler);\n }\n\n /**\n * Unsubscribe from an event\n * @param event - Event name to stop listening to\n * @param handler - Callback function to remove\n */\n off(event: T, handler: Function): void {\n this.handlers.get(event)?.delete(handler);\n }\n\n /**\n * Emit an event with optional arguments\n * @param event - Event name to emit\n * @param args - Arguments to pass to event handlers\n */\n emit(event: T, ...args: any[]): void {\n this.handlers.get(event)?.forEach(h => {\n try {\n h(...args);\n } catch (err) {\n console.error(`[Emitter] Error in ${event} handler:`, err);\n }\n });\n }\n\n /**\n * Clear all event handlers\n */\n clear(): void {\n this.handlers.clear();\n }\n}\n\n","/**\n * Build-time configuration\n * \n * This file is processed at build time with different values for:\n * - Production build (for merchants)\n * - Internal build (for team development)\n */\n\n/**\n * Build mode - replaced at build time\n */\ndeclare const __BUILD_MODE__: 'production' | 'internal';\n\n/**\n * SDK version - replaced at build time\n */\ndeclare const __VERSION__: string;\n\n/**\n * Configuration interface\n */\nexport interface BuildConfig {\n /** SDK version */\n version: string;\n \n /** Build mode */\n mode: 'production' | 'internal';\n \n /** Default checkout origin (production URL) */\n defaultCheckoutOrigin: string;\n \n /** Allowed origins for postMessage validation */\n allowedOrigins: string[];\n \n /** Whether hostedCheckoutUrl override is allowed */\n allowOriginOverride: boolean;\n}\n\n/**\n * Production configuration (for merchants)\n */\nconst productionConfig: BuildConfig = {\n version: __VERSION__,\n mode: 'production',\n defaultCheckoutOrigin: 'https://buy.paypercut.io',\n allowedOrigins: [\n 'https://buy.paypercut.io'\n ],\n allowOriginOverride: false // ← Merchants CANNOT override\n};\n\n/**\n * Internal configuration (for team development)\n */\nconst internalConfig: BuildConfig = {\n version: __VERSION__,\n mode: 'internal',\n defaultCheckoutOrigin: 'https://buy.paypercut.io',\n allowedOrigins: [\n 'https://buy.paypercut.io',\n 'http://localhost:3000',\n 'http://localhost:3001',\n 'http://127.0.0.1:3000',\n 'http://127.0.0.1:3001'\n ],\n allowOriginOverride: true // ← Team CAN override for testing\n};\n\n/**\n * Active configuration (selected at build time)\n */\nexport const config: BuildConfig = __BUILD_MODE__ === 'internal' \n ? internalConfig \n : productionConfig;\n\n/**\n * Helper to check if origin is allowed\n */\nexport function isOriginAllowed(origin: string): boolean {\n return config.allowedOrigins.includes(origin);\n}\n\n/**\n * Get the checkout origin (with optional override for internal builds)\n */\nexport function getCheckoutOrigin(override?: string): string {\n // Only allow override in internal builds\n if (override && config.allowOriginOverride) {\n return override;\n }\n \n return config.defaultCheckoutOrigin;\n}\n\n","/**\n * Supported locales for Paypercut Checkout\n * \n * @remarks\n * Single source of truth for all supported locale codes.\n * \n * Supported languages:\n * - Bulgarian: 'bg', 'bg-BG'\n * - English: 'en', 'en-GB'\n * - Greek: 'el', 'el-GR'\n * - Romanian: 'ro', 'ro-RO'\n * - Croatian: 'hr', 'hr-HR'\n * - Polish: 'pl', 'pl-PL'\n * - Czech: 'cs', 'cs-CZ'\n * - Slovenian: 'sl', 'sl-SI'\n * - Slovak: 'sk', 'sk-SK'\n * \n * @example\n * ```typescript\n * const checkout = PaypercutCheckout({\n * locale: 'bg' // or 'bg-BG', 'en', 'en-GB', etc.\n * });\n * ```\n */\nexport const LOCALES = [\n 'bg', 'bg-BG',\n 'en', 'en-GB',\n 'el', 'el-GR',\n 'ro', 'ro-RO',\n 'hr', 'hr-HR',\n 'pl', 'pl-PL',\n 'cs', 'cs-CZ',\n 'sl', 'sl-SI',\n 'sk', 'sk-SK',\n] as const;\n\n/**\n * Locale type - union of all supported locale codes plus 'auto'\n * @example\n * ```typescript\n * const locale: Locale = 'bg';\n * const autoLocale: Locale = 'auto';\n * ```\n */\nexport type Locale = typeof LOCALES[number] | 'auto';\n\n/**\n * Fast runtime check using Set for O(1) lookup\n * @internal\n */\nconst LOCALE_SET: ReadonlySet<string> = new Set(LOCALES);\n\n/**\n * Normalize and validate locale\n * \n * @param locale - Locale code to normalize\n * @returns Normalized locale code or 'en' as fallback\n * \n * @remarks\n * - 'auto' or empty → 'en'\n * - Unsupported locale → 'en' with console warning\n * - Supported locale → original value\n * \n * @example\n * ```typescript\n * normalizeLocale('auto') // → 'en'\n * normalizeLocale('bg') // → 'bg'\n * normalizeLocale('de') // → 'en' (with warning)\n * ```\n */\nexport function normalizeLocale(locale: string | Locale): typeof LOCALES[number] | 'en' {\n if (!locale || locale === 'auto') return 'en';\n if (LOCALE_SET.has(locale)) return locale as typeof LOCALES[number];\n console.warn(`[PaypercutCheckout] Locale \"${locale}\" is not supported. Falling back to \"en\".`);\n return 'en';\n}\n\n","import { Locale } from './locales';\n\n/**\n * UI mode for checkout\n */\nexport enum UIMode {\n /** Custom UI mode - merchant provides their own submit button */\n CUSTOM = 'custom',\n /** Embedded mode - checkout embedded in merchant page */\n EMBEDDED = 'embedded',\n /** Hosted mode - full-page checkout experience */\n HOSTED = 'hosted',\n}\n\n/**\n * Type guard for UIMode\n */\nexport function isValidUIMode(value: string): value is UIMode {\n return Object.values(UIMode).includes(value as UIMode);\n}\n\n/**\n * Payment method types\n */\nexport enum PaymentMethod {\n /** Card payment (credit/debit) */\n CARD = 'card',\n}\n\n/**\n * Type guard for PaymentMethod\n */\nexport function isValidPaymentMethod(value: string): value is PaymentMethod {\n return Object.values(PaymentMethod).includes(value as PaymentMethod);\n}\n\n/**\n * Wallet options for digital wallets\n */\nexport enum WalletOption {\n /** Apple Pay */\n APPLE_PAY = 'apple_pay',\n /** Google Pay */\n GOOGLE_PAY = 'google_pay',\n}\n\n/**\n * Type guard for WalletOption\n */\nexport function isValidWalletOption(value: string): value is WalletOption {\n return Object.values(WalletOption).includes(value as WalletOption);\n}\n\n/**\n * Validate payment methods array\n */\nexport function validatePaymentMethods(methods: string[]): PaymentMethod[] {\n const validated: PaymentMethod[] = [];\n \n for (const method of methods) {\n if (isValidPaymentMethod(method)) {\n validated.push(method as PaymentMethod);\n } else {\n console.warn(`[PaypercutCheckout] Invalid payment method: \"${method}\". Skipping.`);\n }\n }\n \n // Default to card if no valid methods\n if (validated.length === 0) {\n console.warn('[PaypercutCheckout] No valid payment methods provided. Defaulting to \"card\".');\n validated.push(PaymentMethod.CARD);\n }\n \n return validated;\n}\n\n/**\n * Validate wallet options array\n */\nexport function validateWalletOptions(options: string[]): WalletOption[] {\n const validated: WalletOption[] = [];\n \n for (const option of options) {\n if (isValidWalletOption(option)) {\n validated.push(option as WalletOption);\n } else {\n console.warn(`[PaypercutCheckout] Invalid wallet option: \"${option}\". Skipping.`);\n }\n }\n \n return validated;\n}\n\n/**\n * Validate UI mode\n */\nexport function validateUIMode(mode: string | undefined): UIMode | undefined {\n if (!mode) {\n return undefined;\n }\n \n if (isValidUIMode(mode)) {\n return mode as UIMode;\n }\n \n console.warn(`[PaypercutCheckout] Invalid ui_mode: \"${mode}\". Valid options: ${Object.values(UIMode).join(', ')}`);\n return undefined;\n}\n\n/**\n * Configuration options for PaypercutCheckout\n */\nexport interface PaypercutCheckoutOptions {\n /** Checkout session identifier (e.g., 'CHK_12345') */\n id: string;\n\n /** CSS selector or HTMLElement where iframe mounts (required) */\n containerId: string | HTMLElement;\n\n /**\n * Optional: Custom hosted checkout URL (only available in internal builds)\n * Production builds will ignore this option for security\n */\n hostedCheckoutUrl?: string;\n\n /**\n * Optional: Locale for checkout UI\n * @default 'en'\n */\n locale?: Locale | string;\n\n /**\n * Optional: UI mode for checkout\n */\n ui_mode?: UIMode | `${UIMode}`;\n\n /**\n * Optional: Payment methods to enable\n * @default ['card']\n */\n payment_methods?: (PaymentMethod | `${PaymentMethod}`)[];\n\n /**\n * Optional: Digital wallet options\n * Can include both or just one\n */\n wallet_options?: (WalletOption | `${WalletOption}`)[];\n\n /**\n * Optional: Show only the payment form without header/footer\n * @default false\n */\n form_only?: boolean;\n}\n\n/**\n * Event names that can be emitted by the checkout\n */\nexport type EventName =\n | 'loaded' // iframe finished loading\n | 'success' // payment successful\n | 'error'; // payment or system error\n\n/**\n * Checkout instance interface\n */\nexport interface CheckoutInstance {\n /** Mount and render the iframe into the container */\n render(): void;\n\n /** Submit payment - sends message to hosted checkout to confirm payment */\n submit(): void;\n\n /** Destroy instance and cleanup all listeners */\n destroy(): void;\n\n /** Subscribe to events. Returns unsubscribe function */\n on(event: EventName, handler: (...args: any[]) => void): () => void;\n\n /** Subscribe to event that auto-unsubscribes after first emission */\n once(event: EventName, handler: (...args: any[]) => void): () => void;\n\n /** Unsubscribe from events */\n off(event: EventName, handler: (...args: any[]) => void): void;\n\n /** Check if checkout is currently mounted */\n isMounted(): boolean;\n}\n\n/**\n * PaypercutCheckout static interface (callable and constructable)\n */\nexport interface PaypercutCheckoutStatic {\n /** Callable factory function */\n (options: PaypercutCheckoutOptions): CheckoutInstance;\n\n /** Constructor support */\n new (options: PaypercutCheckoutOptions): CheckoutInstance;\n\n /** SDK version */\n version: string;\n}\n\n","import { Emitter } from './utils/emitter';\nimport { config, isOriginAllowed, getCheckoutOrigin } from './config';\n\nimport {\n PaypercutCheckoutOptions,\n CheckoutInstance,\n PaypercutCheckoutStatic,\n EventName,\n validatePaymentMethods,\n validateWalletOptions,\n validateUIMode,\n} from './types';\nimport {normalizeLocale} from \"./types\";\n\n// Re-export types and enums for consumers\nexport type {\n PaypercutCheckoutOptions,\n CheckoutInstance,\n PaypercutCheckoutStatic,\n EventName,\n};\n\nexport {\n UIMode,\n PaymentMethod,\n WalletOption,\n} from './types/checkout';\n\nexport type { Locale } from './types/locales';\nexport { LOCALES } from './types/locales';\n\n/**\n * Internal implementation of CheckoutInstance\n */\nclass CheckoutImpl implements CheckoutInstance {\n private emitter = new Emitter<EventName>();\n private mounted = false;\n private destroyed = false;\n private iframe: HTMLIFrameElement | null = null;\n private messageHandler: (evt: MessageEvent) => void;\n\n constructor(private options: PaypercutCheckoutOptions) {\n // Bind message handler\n this.messageHandler = this.onMessage.bind(this);\n window.addEventListener('message', this.messageHandler);\n }\n\n /**\n * Build the iframe source URL with query parameters\n */\n private buildSrc(): string {\n const baseUrl = getCheckoutOrigin(this.options.hostedCheckoutUrl);\n const url = new URL(`/c/${this.options.id}`, baseUrl);\n\n // Add locale parameter\n if (this.options.locale) {\n const normalizedLocale = normalizeLocale(this.options.locale);\n url.searchParams.set('locale', normalizedLocale);\n }\n\n // Add ui_mode parameter\n if (this.options.ui_mode) {\n const validatedUIMode = validateUIMode(this.options.ui_mode);\n if (validatedUIMode) {\n url.searchParams.set('ui_mode', validatedUIMode);\n }\n }\n\n // Add payment_methods parameters (repeated for each method)\n if (this.options.payment_methods && this.options.payment_methods.length > 0) {\n const validatedMethods = validatePaymentMethods(this.options.payment_methods as string[]);\n validatedMethods.forEach(method => {\n url.searchParams.append('payment_methods', method);\n });\n }\n\n // Add wallet_options parameters (repeated for each wallet)\n if (this.options.wallet_options && this.options.wallet_options.length > 0) {\n const validatedWallets = validateWalletOptions(this.options.wallet_options as string[]);\n validatedWallets.forEach(wallet => {\n url.searchParams.append('wallet_options', wallet);\n });\n }\n\n console.log('this.options', this.options);\n\n if (this.options.form_only !== undefined) {\n url.searchParams.set('form_only', String(this.options.form_only));\n }\n\n return url.toString();\n }\n\n /**\n * Get the container element from selector or HTMLElement\n */\n private getContainer(): HTMLElement {\n const container = typeof this.options.containerId === 'string'\n ? document.querySelector(this.options.containerId)\n : this.options.containerId;\n\n if (!container) {\n throw new Error(`Container not found: ${this.options.containerId}`);\n }\n\n return container as HTMLElement;\n }\n\n /**\n * Handle incoming postMessage events from iframe\n */\n private onMessage(evt: MessageEvent): void {\n // Validate origin against allowed origins (build-time whitelist)\n if (!isOriginAllowed(evt.origin)) {\n console.warn('[PaypercutCheckout] Rejected message from unauthorized origin:', evt.origin, 'Allowed:', config.allowedOrigins);\n return;\n }\n\n // Validate structure\n const data = evt.data;\n if (!data || typeof data !== 'object' || !('type' in data)) {\n return;\n }\n\n // Filter messages by checkout session ID to prevent cross-instance message handling\n // This ensures each checkout instance only processes its own messages\n if (data.checkoutId && data.checkoutId !== this.options.id) {\n return; // Message is for a different checkout instance\n }\n\n // Handle specific events\n switch (data.type) {\n case 'CHECKOUT_LOADED':\n this.emitter.emit('loaded');\n break;\n case 'CHECKOUT_SUCCESS':\n this.emitter.emit('success');\n break;\n case 'CHECKOUT_ERROR':\n this.emitter.emit('error');\n break;\n }\n }\n\n /**\n * Render the checkout iframe into the container\n */\n render(): void {\n if (this.mounted) {\n console.warn('[PaypercutCheckout] Already mounted');\n return;\n }\n\n try {\n const container = this.getContainer();\n\n // Create iframe\n this.iframe = document.createElement('iframe');\n this.iframe.id = 'paypercut-checkout-iframe';\n this.iframe.src = this.buildSrc();\n this.iframe.allow = 'payment *; clipboard-write';\n this.iframe.setAttribute('frameborder', '0');\n\n // Apply default styles - just construct URL and assign to iframe\n Object.assign(this.iframe.style, {\n width: '100%',\n height: '100%',\n border: 'none',\n display: 'block'\n });\n\n // Listen for iframe load event (fallback)\n // This ensures 'loaded' event is always emitted even if hosted checkout\n // doesn't send CHECKOUT_LOADED message\n /*this.iframe.addEventListener('load', () => {\n this.emitter.emit('loaded');\n });*/\n\n container.appendChild(this.iframe);\n this.mounted = true;\n } catch (err) {\n console.error('[PaypercutCheckout] Failed to render:', err);\n throw err;\n }\n }\n\n /**\n * Submit payment - sends message to hosted checkout to confirm payment\n */\n submit(): void {\n if (!this.mounted) {\n console.warn('[PaypercutCheckout] Cannot submit: checkout not mounted');\n return;\n }\n\n try {\n this.postToIframe({\n type: 'START_PROCESSING',\n checkoutId: this.options.id,\n });\n console.log('[PaypercutCheckout] Submit payment message sent');\n } catch (err) {\n console.error('[PaypercutCheckout] Failed to submit payment:', err);\n throw err;\n }\n }\n\n /**\n * Send message to iframe - used for submit and other commands\n */\n private postToIframe(message: any): void {\n if (!this.iframe?.contentWindow) {\n console.error('[PaypercutCheckout] Cannot post message: iframe not mounted');\n return;\n }\n\n const checkoutOrigin = getCheckoutOrigin(this.options.hostedCheckoutUrl);\n this.iframe.contentWindow.postMessage(message, checkoutOrigin);\n }\n\n /**\n * Destroy the checkout instance and cleanup (idempotent)\n */\n destroy(): void {\n // Early return if already destroyed\n if (this.destroyed) {\n return;\n }\n\n // Remove iframe from DOM\n if (this.iframe) {\n try {\n this.iframe.remove();\n this.iframe = null;\n } catch (err) {\n console.error('[PaypercutCheckout] Error removing iframe:', err);\n }\n }\n\n // Only set mounted = false after successful DOM removal\n this.mounted = false;\n this.destroyed = true;\n\n // Cleanup event listeners\n window.removeEventListener('message', this.messageHandler);\n this.emitter.clear();\n }\n\n /**\n * Subscribe to an event\n */\n on(event: EventName, handler: (...args: any[]) => void): () => void {\n return this.emitter.on(event, handler);\n }\n\n /**\n * Subscribe to event that auto-unsubscribes after first emission\n */\n once(event: EventName, handler: (...args: any[]) => void): () => void {\n return this.emitter.once(event, handler);\n }\n\n /**\n * Unsubscribe from an event\n */\n off(event: EventName, handler: (...args: any[]) => void): void {\n this.emitter.off(event, handler);\n }\n\n /**\n * Check if checkout is currently mounted\n */\n isMounted(): boolean {\n return this.mounted;\n }\n}\n\n/**\n * Factory function that works both as callable and constructable.\n * Always returns a new CheckoutImpl instance - no prototype manipulation needed.\n */\nconst PaypercutCheckout: PaypercutCheckoutStatic = function (\n this: unknown,\n options: PaypercutCheckoutOptions\n): CheckoutInstance {\n // Always return a new instance, regardless of how it's called\n return new CheckoutImpl(options);\n} as unknown as PaypercutCheckoutStatic;\n\n// Add static version property\n(PaypercutCheckout as any).version = config.version;\n\n// Export as default and named\nexport default PaypercutCheckout;\nexport { PaypercutCheckout };\n\n"],"names":["UIMode","PaymentMethod","WalletOption"],"mappings":"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"}