@reevit/core 0.9.0 → 0.9.1
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/README.md +66 -2
- package/dist/index.d.mts +70 -8
- package/dist/index.d.ts +70 -8
- package/dist/index.js +192 -37
- package/dist/index.js.map +1 -1
- package/dist/index.mjs +187 -37
- package/dist/index.mjs.map +1 -1
- package/package.json +5 -2
package/dist/index.js
CHANGED
|
@@ -21,14 +21,17 @@ var __toCommonJS = (mod) => __copyProps(__defProp({}, "__esModule", { value: tru
|
|
|
21
21
|
var index_exports = {};
|
|
22
22
|
__export(index_exports, {
|
|
23
23
|
ReevitAPIClient: () => ReevitAPIClient,
|
|
24
|
+
attemptIdempotencyKey: () => attemptIdempotencyKey,
|
|
24
25
|
cacheIntentPromise: () => cacheIntentPromise,
|
|
25
26
|
cacheIntentResponse: () => cacheIntentResponse,
|
|
27
|
+
clearIdempotencyAttemptKeys: () => clearIdempotencyAttemptKeys,
|
|
26
28
|
clearIntentCacheEntry: () => clearIntentCacheEntry,
|
|
27
29
|
cn: () => cn,
|
|
28
30
|
createInitialState: () => createInitialState,
|
|
29
31
|
createPaymentError: () => createPaymentError,
|
|
30
32
|
createReevitClient: () => createReevitClient,
|
|
31
33
|
createThemeVariables: () => createThemeVariables,
|
|
34
|
+
currencyExponent: () => currencyExponent,
|
|
32
35
|
detectCountryFromCurrency: () => detectCountryFromCurrency,
|
|
33
36
|
detectNetwork: () => detectNetwork,
|
|
34
37
|
formatAmount: () => formatAmount,
|
|
@@ -37,8 +40,10 @@ __export(index_exports, {
|
|
|
37
40
|
generateReference: () => generateReference,
|
|
38
41
|
getIntentCacheEntry: () => getIntentCacheEntry,
|
|
39
42
|
isPaymentError: () => isPaymentError,
|
|
43
|
+
newIdempotencyKey: () => newIdempotencyKey,
|
|
40
44
|
reevitReducer: () => reevitReducer,
|
|
41
45
|
resolveIntentIdentity: () => resolveIntentIdentity,
|
|
46
|
+
toMinorUnits: () => toMinorUnits,
|
|
42
47
|
validatePhone: () => validatePhone
|
|
43
48
|
});
|
|
44
49
|
module.exports = __toCommonJS(index_exports);
|
|
@@ -77,6 +82,95 @@ function generateIdempotencyKey(params) {
|
|
|
77
82
|
const timeBucket = Math.floor(Date.now() / (5 * 60 * 1e3));
|
|
78
83
|
return `reevit_${timeBucket}_${hashHex}`;
|
|
79
84
|
}
|
|
85
|
+
var IDEMPOTENCY_STORE_PREFIX = "reevit:idem:";
|
|
86
|
+
var memoryAttemptKeys = /* @__PURE__ */ new Map();
|
|
87
|
+
function getSessionStore() {
|
|
88
|
+
try {
|
|
89
|
+
const storage = globalThis.sessionStorage;
|
|
90
|
+
if (!storage) {
|
|
91
|
+
return null;
|
|
92
|
+
}
|
|
93
|
+
const probe = `${IDEMPOTENCY_STORE_PREFIX}probe`;
|
|
94
|
+
storage.setItem(probe, "1");
|
|
95
|
+
storage.removeItem(probe);
|
|
96
|
+
return storage;
|
|
97
|
+
} catch {
|
|
98
|
+
return null;
|
|
99
|
+
}
|
|
100
|
+
}
|
|
101
|
+
function newIdempotencyKey() {
|
|
102
|
+
const cryptoObj = globalThis.crypto;
|
|
103
|
+
if (cryptoObj && typeof cryptoObj.randomUUID === "function") {
|
|
104
|
+
try {
|
|
105
|
+
return cryptoObj.randomUUID();
|
|
106
|
+
} catch {
|
|
107
|
+
}
|
|
108
|
+
}
|
|
109
|
+
const bytes = new Uint8Array(16);
|
|
110
|
+
if (cryptoObj && typeof cryptoObj.getRandomValues === "function") {
|
|
111
|
+
cryptoObj.getRandomValues(bytes);
|
|
112
|
+
} else {
|
|
113
|
+
for (let i = 0; i < bytes.length; i++) {
|
|
114
|
+
bytes[i] = Math.floor(Math.random() * 256);
|
|
115
|
+
}
|
|
116
|
+
}
|
|
117
|
+
bytes[6] = bytes[6] & 15 | 64;
|
|
118
|
+
bytes[8] = bytes[8] & 63 | 128;
|
|
119
|
+
const hex = [];
|
|
120
|
+
for (let i = 0; i < bytes.length; i++) {
|
|
121
|
+
hex.push(bytes[i].toString(16).padStart(2, "0"));
|
|
122
|
+
}
|
|
123
|
+
return [
|
|
124
|
+
hex.slice(0, 4).join(""),
|
|
125
|
+
hex.slice(4, 6).join(""),
|
|
126
|
+
hex.slice(6, 8).join(""),
|
|
127
|
+
hex.slice(8, 10).join(""),
|
|
128
|
+
hex.slice(10, 16).join("")
|
|
129
|
+
].join("-");
|
|
130
|
+
}
|
|
131
|
+
function attemptIdempotencyKey(lookupKey) {
|
|
132
|
+
const storageKey = `${IDEMPOTENCY_STORE_PREFIX}${lookupKey}`;
|
|
133
|
+
const store = getSessionStore();
|
|
134
|
+
if (store) {
|
|
135
|
+
try {
|
|
136
|
+
const existing2 = store.getItem(storageKey);
|
|
137
|
+
if (existing2) {
|
|
138
|
+
return existing2;
|
|
139
|
+
}
|
|
140
|
+
const created2 = newIdempotencyKey();
|
|
141
|
+
store.setItem(storageKey, created2);
|
|
142
|
+
return created2;
|
|
143
|
+
} catch {
|
|
144
|
+
}
|
|
145
|
+
}
|
|
146
|
+
const existing = memoryAttemptKeys.get(storageKey);
|
|
147
|
+
if (existing) {
|
|
148
|
+
return existing;
|
|
149
|
+
}
|
|
150
|
+
const created = newIdempotencyKey();
|
|
151
|
+
memoryAttemptKeys.set(storageKey, created);
|
|
152
|
+
return created;
|
|
153
|
+
}
|
|
154
|
+
function clearIdempotencyAttemptKeys() {
|
|
155
|
+
memoryAttemptKeys.clear();
|
|
156
|
+
const store = getSessionStore();
|
|
157
|
+
if (!store) {
|
|
158
|
+
return;
|
|
159
|
+
}
|
|
160
|
+
try {
|
|
161
|
+
const keys = [];
|
|
162
|
+
for (let i = 0; i < store.length; i++) {
|
|
163
|
+
const key = store.key(i);
|
|
164
|
+
if (key && key.startsWith(IDEMPOTENCY_STORE_PREFIX)) {
|
|
165
|
+
keys.push(key);
|
|
166
|
+
}
|
|
167
|
+
}
|
|
168
|
+
for (const key of keys) {
|
|
169
|
+
store.removeItem(key);
|
|
170
|
+
}
|
|
171
|
+
} catch {
|
|
172
|
+
}
|
|
173
|
+
}
|
|
80
174
|
var ReevitAPIClient = class {
|
|
81
175
|
constructor(config) {
|
|
82
176
|
this.publicKey = config.publicKey || "";
|
|
@@ -93,13 +187,13 @@ var ReevitAPIClient = class {
|
|
|
93
187
|
const headers = {
|
|
94
188
|
"Content-Type": "application/json",
|
|
95
189
|
"X-Reevit-Client": "@reevit/core",
|
|
96
|
-
"X-Reevit-Client-Version": "0.9.
|
|
190
|
+
"X-Reevit-Client-Version": "0.9.1"
|
|
97
191
|
};
|
|
98
192
|
if (this.publicKey) {
|
|
99
193
|
headers["X-Reevit-Key"] = this.publicKey;
|
|
100
194
|
}
|
|
101
195
|
if (method === "POST" || method === "PATCH" || method === "PUT") {
|
|
102
|
-
headers["Idempotency-Key"] = idempotencyKey || (
|
|
196
|
+
headers["Idempotency-Key"] = idempotencyKey || newIdempotencyKey();
|
|
103
197
|
}
|
|
104
198
|
try {
|
|
105
199
|
const response = await fetch(`${this.baseUrl}${path}`, {
|
|
@@ -189,7 +283,7 @@ var ReevitAPIClient = class {
|
|
|
189
283
|
allowed_providers: options?.allowedProviders
|
|
190
284
|
};
|
|
191
285
|
}
|
|
192
|
-
const idempotencyKey = config.idempotencyKey || generateIdempotencyKey({
|
|
286
|
+
const idempotencyKey = config.idempotencyKey || attemptIdempotencyKey(generateIdempotencyKey({
|
|
193
287
|
amount: config.amount,
|
|
194
288
|
currency: config.currency,
|
|
195
289
|
customer: config.email || config.metadata?.customerId || "",
|
|
@@ -197,7 +291,7 @@ var ReevitAPIClient = class {
|
|
|
197
291
|
method: method || "",
|
|
198
292
|
provider: options?.preferredProviders?.[0] || options?.allowedProviders?.[0] || "",
|
|
199
293
|
publicKey: this.publicKey
|
|
200
|
-
});
|
|
294
|
+
}));
|
|
201
295
|
return this.request("POST", "/v1/payments/intents", request, idempotencyKey);
|
|
202
296
|
}
|
|
203
297
|
/**
|
|
@@ -266,25 +360,62 @@ function createReevitClient(config) {
|
|
|
266
360
|
}
|
|
267
361
|
|
|
268
362
|
// src/utils.ts
|
|
363
|
+
var CURRENCY_LOCALES = {
|
|
364
|
+
GHS: "en-GH",
|
|
365
|
+
NGN: "en-NG",
|
|
366
|
+
KES: "en-KE",
|
|
367
|
+
USD: "en-US",
|
|
368
|
+
EUR: "de-DE",
|
|
369
|
+
GBP: "en-GB"
|
|
370
|
+
};
|
|
371
|
+
var ZERO_DECIMAL_CURRENCIES = /* @__PURE__ */ new Set([
|
|
372
|
+
"XOF",
|
|
373
|
+
"XAF",
|
|
374
|
+
"RWF",
|
|
375
|
+
"UGX",
|
|
376
|
+
"JPY",
|
|
377
|
+
"KRW",
|
|
378
|
+
"BIF",
|
|
379
|
+
"GNF",
|
|
380
|
+
"VND",
|
|
381
|
+
"CLP",
|
|
382
|
+
"ISK",
|
|
383
|
+
"KMF",
|
|
384
|
+
"DJF",
|
|
385
|
+
"PYG",
|
|
386
|
+
"MGA"
|
|
387
|
+
]);
|
|
388
|
+
function currencyExponent(currency) {
|
|
389
|
+
const code = (currency || "").toUpperCase();
|
|
390
|
+
try {
|
|
391
|
+
const digits = new Intl.NumberFormat("en", {
|
|
392
|
+
style: "currency",
|
|
393
|
+
currency: code
|
|
394
|
+
}).resolvedOptions().maximumFractionDigits;
|
|
395
|
+
if (typeof digits === "number" && Number.isFinite(digits)) {
|
|
396
|
+
return digits;
|
|
397
|
+
}
|
|
398
|
+
} catch {
|
|
399
|
+
}
|
|
400
|
+
return ZERO_DECIMAL_CURRENCIES.has(code) ? 0 : 2;
|
|
401
|
+
}
|
|
402
|
+
function toMinorUnits(major, currency) {
|
|
403
|
+
return Math.round(major * 10 ** currencyExponent(currency));
|
|
404
|
+
}
|
|
269
405
|
function formatAmount(amount, currency) {
|
|
270
|
-
const
|
|
271
|
-
const
|
|
272
|
-
|
|
273
|
-
|
|
274
|
-
KES: { locale: "en-KE", minimumFractionDigits: 2 },
|
|
275
|
-
USD: { locale: "en-US", minimumFractionDigits: 2 },
|
|
276
|
-
EUR: { locale: "de-DE", minimumFractionDigits: 2 },
|
|
277
|
-
GBP: { locale: "en-GB", minimumFractionDigits: 2 }
|
|
278
|
-
};
|
|
279
|
-
const format = currencyFormats[currency.toUpperCase()] || { locale: "en-US", minimumFractionDigits: 2 };
|
|
406
|
+
const code = (currency || "").toUpperCase();
|
|
407
|
+
const exponent = currencyExponent(code);
|
|
408
|
+
const majorUnit = amount / 10 ** exponent;
|
|
409
|
+
const locale = CURRENCY_LOCALES[code] || "en-US";
|
|
280
410
|
try {
|
|
281
|
-
return new Intl.NumberFormat(
|
|
411
|
+
return new Intl.NumberFormat(locale, {
|
|
282
412
|
style: "currency",
|
|
283
|
-
currency:
|
|
284
|
-
minimumFractionDigits:
|
|
413
|
+
currency: code,
|
|
414
|
+
minimumFractionDigits: exponent,
|
|
415
|
+
maximumFractionDigits: exponent
|
|
285
416
|
}).format(majorUnit);
|
|
286
417
|
} catch {
|
|
287
|
-
return `${
|
|
418
|
+
return `${code} ${majorUnit.toFixed(exponent)}`;
|
|
288
419
|
}
|
|
289
420
|
}
|
|
290
421
|
function generateReference(prefix = "reevit") {
|
|
@@ -402,33 +533,50 @@ function detectCountryFromCurrency(currency) {
|
|
|
402
533
|
// src/intent.ts
|
|
403
534
|
var INTENT_CACHE_TTL_MS = 10 * 60 * 1e3;
|
|
404
535
|
var intentCache = /* @__PURE__ */ new Map();
|
|
536
|
+
var lookupKeyByWireKey = /* @__PURE__ */ new Map();
|
|
537
|
+
function forgetKey(lookupKey) {
|
|
538
|
+
const entry = intentCache.get(lookupKey);
|
|
539
|
+
if (entry?.idempotencyKey) {
|
|
540
|
+
lookupKeyByWireKey.delete(entry.idempotencyKey);
|
|
541
|
+
}
|
|
542
|
+
intentCache.delete(lookupKey);
|
|
543
|
+
}
|
|
544
|
+
function toLookupKey(key) {
|
|
545
|
+
return lookupKeyByWireKey.get(key) ?? key;
|
|
546
|
+
}
|
|
405
547
|
function pruneIntentCache(now = Date.now()) {
|
|
406
548
|
for (const [key, entry] of intentCache) {
|
|
407
549
|
if (entry.expiresAt <= now) {
|
|
408
|
-
|
|
550
|
+
forgetKey(key);
|
|
409
551
|
}
|
|
410
552
|
}
|
|
411
553
|
}
|
|
412
|
-
function getIntentCacheEntryInternal(
|
|
413
|
-
const entry = intentCache.get(
|
|
554
|
+
function getIntentCacheEntryInternal(lookupKey) {
|
|
555
|
+
const entry = intentCache.get(lookupKey);
|
|
414
556
|
if (!entry) {
|
|
415
557
|
return void 0;
|
|
416
558
|
}
|
|
417
559
|
if (entry.expiresAt <= Date.now()) {
|
|
418
|
-
|
|
560
|
+
forgetKey(lookupKey);
|
|
419
561
|
return void 0;
|
|
420
562
|
}
|
|
421
563
|
return entry;
|
|
422
564
|
}
|
|
423
|
-
function setIntentCacheEntryInternal(
|
|
565
|
+
function setIntentCacheEntryInternal(lookupKey, update) {
|
|
424
566
|
const now = Date.now();
|
|
425
|
-
const existing = getIntentCacheEntryInternal(
|
|
567
|
+
const existing = getIntentCacheEntryInternal(lookupKey);
|
|
426
568
|
const next = {
|
|
427
569
|
...existing,
|
|
428
570
|
...update,
|
|
429
571
|
expiresAt: now + INTENT_CACHE_TTL_MS
|
|
430
572
|
};
|
|
431
|
-
|
|
573
|
+
if (existing?.idempotencyKey && existing.idempotencyKey !== next.idempotencyKey) {
|
|
574
|
+
lookupKeyByWireKey.delete(existing.idempotencyKey);
|
|
575
|
+
}
|
|
576
|
+
intentCache.set(lookupKey, next);
|
|
577
|
+
if (next.idempotencyKey && next.idempotencyKey !== lookupKey) {
|
|
578
|
+
lookupKeyByWireKey.set(next.idempotencyKey, lookupKey);
|
|
579
|
+
}
|
|
432
580
|
return next;
|
|
433
581
|
}
|
|
434
582
|
function buildIdempotencyPayload(options) {
|
|
@@ -461,24 +609,26 @@ function buildIdempotencyPayload(options) {
|
|
|
461
609
|
}
|
|
462
610
|
function resolveIntentIdentity(options) {
|
|
463
611
|
pruneIntentCache();
|
|
464
|
-
const
|
|
465
|
-
const
|
|
612
|
+
const explicitKey = options.config.idempotencyKey;
|
|
613
|
+
const lookupKey = explicitKey || generateIdempotencyKey(buildIdempotencyPayload(options));
|
|
614
|
+
const idempotencyKey = explicitKey || attemptIdempotencyKey(lookupKey);
|
|
615
|
+
const existing = getIntentCacheEntryInternal(lookupKey);
|
|
466
616
|
const reference = options.config.reference || existing?.reference || generateReference();
|
|
467
|
-
const cacheEntry = setIntentCacheEntryInternal(
|
|
468
|
-
return { idempotencyKey, reference, cacheEntry };
|
|
617
|
+
const cacheEntry = setIntentCacheEntryInternal(lookupKey, { reference, idempotencyKey });
|
|
618
|
+
return { idempotencyKey, lookupKey, reference, cacheEntry };
|
|
469
619
|
}
|
|
470
|
-
function getIntentCacheEntry(
|
|
620
|
+
function getIntentCacheEntry(key) {
|
|
471
621
|
pruneIntentCache();
|
|
472
|
-
return getIntentCacheEntryInternal(
|
|
622
|
+
return getIntentCacheEntryInternal(toLookupKey(key));
|
|
473
623
|
}
|
|
474
|
-
function cacheIntentPromise(
|
|
475
|
-
return setIntentCacheEntryInternal(
|
|
624
|
+
function cacheIntentPromise(key, promise) {
|
|
625
|
+
return setIntentCacheEntryInternal(toLookupKey(key), { promise });
|
|
476
626
|
}
|
|
477
|
-
function cacheIntentResponse(
|
|
478
|
-
return setIntentCacheEntryInternal(
|
|
627
|
+
function cacheIntentResponse(key, response) {
|
|
628
|
+
return setIntentCacheEntryInternal(toLookupKey(key), { response, promise: void 0 });
|
|
479
629
|
}
|
|
480
|
-
function clearIntentCacheEntry(
|
|
481
|
-
|
|
630
|
+
function clearIntentCacheEntry(key) {
|
|
631
|
+
forgetKey(toLookupKey(key));
|
|
482
632
|
}
|
|
483
633
|
|
|
484
634
|
// src/state.ts
|
|
@@ -523,14 +673,17 @@ function reevitReducer(state, action) {
|
|
|
523
673
|
// Annotate the CommonJS export names for ESM import in node:
|
|
524
674
|
0 && (module.exports = {
|
|
525
675
|
ReevitAPIClient,
|
|
676
|
+
attemptIdempotencyKey,
|
|
526
677
|
cacheIntentPromise,
|
|
527
678
|
cacheIntentResponse,
|
|
679
|
+
clearIdempotencyAttemptKeys,
|
|
528
680
|
clearIntentCacheEntry,
|
|
529
681
|
cn,
|
|
530
682
|
createInitialState,
|
|
531
683
|
createPaymentError,
|
|
532
684
|
createReevitClient,
|
|
533
685
|
createThemeVariables,
|
|
686
|
+
currencyExponent,
|
|
534
687
|
detectCountryFromCurrency,
|
|
535
688
|
detectNetwork,
|
|
536
689
|
formatAmount,
|
|
@@ -539,8 +692,10 @@ function reevitReducer(state, action) {
|
|
|
539
692
|
generateReference,
|
|
540
693
|
getIntentCacheEntry,
|
|
541
694
|
isPaymentError,
|
|
695
|
+
newIdempotencyKey,
|
|
542
696
|
reevitReducer,
|
|
543
697
|
resolveIntentIdentity,
|
|
698
|
+
toMinorUnits,
|
|
544
699
|
validatePhone
|
|
545
700
|
});
|
|
546
701
|
//# sourceMappingURL=index.js.map
|
package/dist/index.js.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"sources":["../src/index.ts","../src/api/client.ts","../src/utils.ts","../src/intent.ts","../src/state.ts"],"sourcesContent":["/**\n * @reevit/core\n * Shared utilities and API client for Reevit payment SDKs\n */\n\n// API Client\nexport {\n ReevitAPIClient,\n createReevitClient,\n createPaymentError,\n generateIdempotencyKey,\n isPaymentError,\n type ReevitAPIClientConfig,\n type CreatePaymentIntentRequest,\n type PaymentIntentResponse,\n type CheckoutSessionResponse,\n type PaymentDetailResponse,\n type ConfirmPaymentRequest,\n type APIErrorResponse,\n type ReevitAPIResult,\n} from './api/client';\n\n// Types\nexport type {\n PaymentMethod,\n MobileMoneyNetwork,\n ReevitCheckoutConfig,\n ReevitCheckoutCallbacks,\n CheckoutState,\n PaymentResult,\n PaymentError,\n ReevitTheme,\n CheckoutProviderOption,\n MobileMoneyFormData,\n CardFormData,\n PaymentIntent,\n PSPConfig,\n PSPType,\n PaymentSource,\n HubtelSessionResponse,\n} from './types';\n\n// Utilities\nexport {\n formatAmount,\n generateReference,\n validatePhone,\n formatPhone,\n detectNetwork,\n detectCountryFromCurrency,\n createThemeVariables,\n cn,\n} from './utils';\n\n// Intent identity + cache helpers\nexport {\n resolveIntentIdentity,\n getIntentCacheEntry,\n cacheIntentPromise,\n cacheIntentResponse,\n clearIntentCacheEntry,\n type IntentCacheEntry,\n} from './intent';\n\n// State machine helpers\nexport {\n createInitialState,\n reevitReducer,\n type ReevitState,\n type ReevitAction,\n} from './state';\n","/**\n * Reevit API Client\n * \n * Handles communication with the Reevit backend for payment operations.\n */\n\nimport type { PaymentMethod, ReevitCheckoutConfig, PaymentError, HubtelSessionResponse } from '../types';\n\n// API Response Types (matching backend handlers_payments.go)\nexport interface CreatePaymentIntentRequest {\n amount: number;\n currency: string;\n method?: string;\n country: string;\n customer_id?: string;\n metadata?: Record<string, unknown>;\n description?: string;\n policy?: {\n prefer?: string[];\n allowed_providers?: string[];\n max_amount?: number;\n blocked_bins?: string[];\n allowed_bins?: string[];\n velocity_max_per_minute?: number;\n };\n}\n\nexport interface PaymentIntentResponse {\n id: string;\n org_id?: string;\n connection_id: string;\n provider: string;\n provider_ref_id?: string;\n status: string;\n client_secret: string;\n session_secret?: string;\n psp_public_key: string;\n psp_credentials?: {\n merchantAccount?: string | number;\n basicAuth?: string;\n [key: string]: unknown;\n };\n amount: number;\n currency: string;\n fee_amount: number;\n fee_currency: string;\n net_amount: number;\n reference?: string;\n available_psps?: Array<{\n provider: string;\n name: string;\n methods: string[];\n countries?: string[];\n }>;\n branding?: Record<string, unknown>;\n}\n\nexport interface CheckoutSessionResponse {\n id: string;\n client_secret: string;\n session_secret: string;\n payment_intent: PaymentIntentResponse;\n expires_at?: string;\n}\n\nexport interface ConfirmPaymentRequest {\n provider_ref_id: string;\n provider_data?: Record<string, unknown>;\n}\n\nexport interface PaymentDetailResponse {\n id: string;\n connection_id: string;\n provider: string;\n method: string;\n status: string;\n amount: number;\n currency: string;\n fee_amount: number;\n fee_currency: string;\n net_amount: number;\n customer_id?: string;\n client_secret: string;\n provider_ref_id?: string;\n metadata?: Record<string, unknown>;\n created_at: string;\n updated_at: string;\n /** Payment source type (payment_link, api, subscription) */\n source?: 'payment_link' | 'api' | 'subscription';\n /** ID of the source (payment link ID, subscription ID, etc.) */\n source_id?: string;\n /** Human-readable description of the source (e.g., payment link name) */\n source_description?: string;\n}\n\nexport interface APIErrorResponse {\n code: string;\n message: string;\n details?: Record<string, unknown>;\n}\n\nexport type ReevitAPIResult<T> = { data: T; error?: never } | { data?: never; error: PaymentError };\n\n// API Client configuration\nexport interface ReevitAPIClientConfig {\n /** Your Reevit public key */\n publicKey?: string;\n /** Base URL for the Reevit API (defaults to production) */\n baseUrl?: string;\n /** Request timeout in milliseconds */\n timeout?: number;\n}\n\n// Default API base URLs\nconst API_BASE_URL_PRODUCTION = 'https://api.reevit.io';\nconst DEFAULT_TIMEOUT = 30000; // 30 seconds\nlet hasWarnedAboutLiveBrowserIntents = false;\n\n/**\n * Determines if a public key is for sandbox mode\n */\nexport function isSandboxKey(publicKey: string): boolean {\n return publicKey.startsWith('pfk_test_');\n}\n\n/**\n * Creates a PaymentError from an API error response\n */\nexport function createPaymentError(response: Response, errorData: APIErrorResponse): PaymentError {\n return {\n code: errorData.code || 'api_error',\n message: errorData.message || 'An unexpected error occurred',\n recoverable: isRecoverableStatus(response.status),\n details: {\n httpStatus: response.status,\n requestId: response.headers.get('x-request-id') || response.headers.get('x-reevit-request-id') || undefined,\n ...errorData.details,\n },\n };\n}\n\nexport function isPaymentError(error: unknown): error is PaymentError {\n return typeof error === 'object' && error !== null && 'code' in error && 'message' in error;\n}\n\nfunction isRecoverableStatus(status: number): boolean {\n return status === 408 || status === 409 || status === 425 || status === 429 || status >= 500;\n}\n\n/**\n * Generates a deterministic idempotency key based on input parameters\n * Uses a simple hash function suitable for browser environments\n * Exported for use by SDK hooks (e.g., payment link flows)\n */\nexport function generateIdempotencyKey(params: Record<string, unknown>): string {\n // Create a stable string representation of the parameters\n const sortedKeys = Object.keys(params).sort();\n const stableString = sortedKeys\n .map(key => `${key}:${JSON.stringify(params[key])}`)\n .join('|');\n\n // Simple hash function (djb2 algorithm)\n let hash = 5381;\n for (let i = 0; i < stableString.length; i++) {\n hash = ((hash << 5) + hash) + stableString.charCodeAt(i);\n hash = hash & hash; // Convert to 32-bit integer\n }\n\n // Convert to positive hex string\n const hashHex = (hash >>> 0).toString(16);\n\n // Add a time bucket (5-minute windows) to allow retries within a reasonable window\n // but prevent keys from being reused across completely different sessions\n const timeBucket = Math.floor(Date.now() / (5 * 60 * 1000));\n\n return `reevit_${timeBucket}_${hashHex}`;\n}\n\n/**\n * Reevit API Client\n */\nexport class ReevitAPIClient {\n private readonly publicKey: string;\n private readonly baseUrl: string;\n private readonly timeout: number;\n\n constructor(config: ReevitAPIClientConfig) {\n this.publicKey = config.publicKey || '';\n this.baseUrl = config.baseUrl || API_BASE_URL_PRODUCTION;\n this.timeout = config.timeout || DEFAULT_TIMEOUT;\n }\n\n /**\n * Makes an authenticated API request\n * @param idempotencyKey Optional deterministic idempotency key for the request\n */\n private async request<T>(\n method: string,\n path: string,\n body?: unknown,\n idempotencyKey?: string\n ): Promise<ReevitAPIResult<T>> {\n const controller = new AbortController();\n const timeoutId = setTimeout(() => controller.abort(), this.timeout);\n\n // Generate headers with idempotency key for mutating requests\n const headers: Record<string, string> = {\n 'Content-Type': 'application/json',\n 'X-Reevit-Client': '@reevit/core',\n 'X-Reevit-Client-Version': '0.9.0',\n };\n if (this.publicKey) {\n headers['X-Reevit-Key'] = this.publicKey;\n }\n\n if (method === 'POST' || method === 'PATCH' || method === 'PUT') {\n // Use provided deterministic key, or generate one based on request body\n headers['Idempotency-Key'] = idempotencyKey ||\n (body ? generateIdempotencyKey(body as Record<string, unknown>) : `${Date.now()}-${Math.random().toString(36).substring(2, 15)}`);\n }\n\n try {\n const response = await fetch(`${this.baseUrl}${path}`, {\n method,\n headers,\n body: body ? JSON.stringify(body) : undefined,\n signal: controller.signal,\n });\n\n clearTimeout(timeoutId);\n\n const responseData = await response.json().catch(() => ({}));\n\n if (!response.ok) {\n return {\n error: createPaymentError(response, responseData as APIErrorResponse),\n };\n }\n\n return { data: responseData as T };\n } catch (err) {\n clearTimeout(timeoutId);\n\n if (err instanceof Error) {\n if (err.name === 'AbortError') {\n return {\n error: {\n code: 'request_timeout',\n message: 'The request timed out. Please try again.',\n recoverable: true,\n },\n };\n }\n\n if (err.message.includes('Failed to fetch') || err.message.includes('NetworkError')) {\n return {\n error: {\n code: 'network_error',\n message: 'Unable to connect to Reevit. Please check your internet connection.',\n recoverable: true,\n },\n };\n }\n }\n\n return {\n error: {\n code: 'unknown_error',\n message: 'An unexpected error occurred. Please try again.',\n recoverable: true,\n },\n };\n }\n }\n\n /**\n * Creates a payment intent\n */\n async createPaymentIntent(\n config: ReevitCheckoutConfig,\n method?: PaymentMethod,\n country: string = 'GH',\n options?: { preferredProviders?: string[]; allowedProviders?: string[] }\n ): Promise<{ data?: PaymentIntentResponse; error?: PaymentError }> {\n if (\n this.publicKey.startsWith('pfk_live_') &&\n !hasWarnedAboutLiveBrowserIntents &&\n typeof console !== 'undefined'\n ) {\n hasWarnedAboutLiveBrowserIntents = true;\n console.warn(\n 'Creating live payment intents from the browser is deprecated. Create a checkout session on your server and pass sessionSecret to the browser SDK instead.'\n );\n }\n\n if (typeof config.amount !== 'number' || !config.currency) {\n return {\n error: {\n code: 'invalid_checkout_config',\n message: 'amount and currency are required when creating a payment intent in the browser.',\n recoverable: false,\n },\n };\n }\n\n // Build metadata with customer_email for PSP providers that require it\n const metadata: Record<string, unknown> = { ...config.metadata };\n if (config.email) {\n metadata.customer_email = config.email;\n }\n if (config.phone) {\n metadata.customer_phone = config.phone;\n }\n\n const request: CreatePaymentIntentRequest = {\n amount: config.amount,\n currency: config.currency,\n country,\n customer_id: config.email || (config.metadata?.customerId as string | undefined),\n metadata,\n };\n\n if (method) {\n request.method = this.mapPaymentMethod(method);\n }\n\n if (options?.preferredProviders?.length || options?.allowedProviders?.length) {\n request.policy = {\n prefer: options?.preferredProviders,\n allowed_providers: options?.allowedProviders,\n };\n }\n\n // Generate a deterministic idempotency key based on payment parameters\n // This ensures that duplicate requests for the same payment return the same intent\n const idempotencyKey = config.idempotencyKey || generateIdempotencyKey({\n amount: config.amount,\n currency: config.currency,\n customer: config.email || config.metadata?.customerId || '',\n reference: config.reference || '',\n method: method || '',\n provider: options?.preferredProviders?.[0] || options?.allowedProviders?.[0] || '',\n publicKey: this.publicKey,\n });\n\n return this.request<PaymentIntentResponse>('POST', '/v1/payments/intents', request, idempotencyKey);\n }\n\n /**\n * Retrieves a payment intent by ID\n */\n async getPaymentIntent(paymentId: string): Promise<{ data?: PaymentDetailResponse; error?: PaymentError }> {\n return this.request<PaymentDetailResponse>('GET', `/v1/payments/${paymentId}`);\n }\n\n /**\n * Retrieves a server-created checkout session using its public session secret.\n */\n async getCheckoutSession(sessionSecret: string): Promise<{ data?: CheckoutSessionResponse; error?: PaymentError }> {\n return this.request<CheckoutSessionResponse>(\n 'GET',\n `/v1/checkout/sessions/${encodeURIComponent(sessionSecret)}`\n );\n }\n\n /**\n * Confirms a payment after PSP callback\n */\n async confirmPayment(paymentId: string): Promise<{ data?: PaymentDetailResponse; error?: PaymentError }> {\n return this.request<PaymentDetailResponse>('POST', `/v1/payments/${paymentId}/confirm`);\n }\n\n /**\n * Confirms a payment intent using client secret (public endpoint)\n */\n async confirmPaymentIntent(paymentId: string, clientSecret: string): Promise<{ data?: PaymentDetailResponse; error?: PaymentError }> {\n return this.request<PaymentDetailResponse>(\n 'POST',\n `/v1/payments/${paymentId}/confirm-intent?client_secret=${encodeURIComponent(clientSecret)}`\n );\n }\n\n /**\n * Cancels a payment intent\n */\n async cancelPaymentIntent(paymentId: string): Promise<{ data?: PaymentDetailResponse; error?: PaymentError }> {\n return this.request<PaymentDetailResponse>('POST', `/v1/payments/${paymentId}/cancel`);\n }\n\n /**\n * Creates a Hubtel session token for secure checkout\n * Returns a short-lived token that contains Hubtel credentials\n * Credentials are never exposed to the client directly\n */\n async createHubtelSession(\n paymentId: string,\n clientSecret?: string\n ): Promise<{ data?: HubtelSessionResponse; error?: PaymentError }> {\n const query = clientSecret ? `?client_secret=${encodeURIComponent(clientSecret)}` : '';\n return this.request<HubtelSessionResponse>('POST', `/v1/payments/hubtel/sessions/${paymentId}${query}`);\n }\n\n /**\n * Maps SDK payment method to backend format\n */\n private mapPaymentMethod(method: PaymentMethod): string {\n switch (method) {\n case 'card':\n return 'card';\n case 'mobile_money':\n return 'mobile_money';\n case 'bank_transfer':\n return 'bank_transfer';\n default:\n return method;\n }\n }\n}\n\n/**\n * Creates a new Reevit API client instance\n */\nexport function createReevitClient(config: ReevitAPIClientConfig): ReevitAPIClient {\n return new ReevitAPIClient(config);\n}\n","/**\n * Utility Functions\n * Shared utilities for Reevit SDKs\n */\n\nimport type { MobileMoneyNetwork, ReevitTheme } from './types';\n\n/**\n * Formats an amount from smallest currency unit to display format\n */\nexport function formatAmount(amount: number, currency: string): string {\n const majorUnit = amount / 100;\n\n const currencyFormats: Record<string, { locale: string; minimumFractionDigits: number }> = {\n GHS: { locale: 'en-GH', minimumFractionDigits: 2 },\n NGN: { locale: 'en-NG', minimumFractionDigits: 2 },\n KES: { locale: 'en-KE', minimumFractionDigits: 2 },\n USD: { locale: 'en-US', minimumFractionDigits: 2 },\n EUR: { locale: 'de-DE', minimumFractionDigits: 2 },\n GBP: { locale: 'en-GB', minimumFractionDigits: 2 },\n };\n\n const format = currencyFormats[currency.toUpperCase()] || { locale: 'en-US', minimumFractionDigits: 2 };\n\n try {\n return new Intl.NumberFormat(format.locale, {\n style: 'currency',\n currency: currency.toUpperCase(),\n minimumFractionDigits: format.minimumFractionDigits,\n }).format(majorUnit);\n } catch {\n // Fallback for unsupported currencies\n return `${currency} ${majorUnit.toFixed(2)}`;\n }\n}\n\n/**\n * Generates a unique payment reference\n */\nexport function generateReference(prefix: string = 'reevit'): string {\n const timestamp = Date.now().toString(36);\n const random = Math.random().toString(36).substring(2, 8);\n return `${prefix}_${timestamp}_${random}`;\n}\n\n/**\n * Validates a phone number for mobile money\n */\nexport function validatePhone(phone: string, country: string = 'GH'): boolean {\n // Remove non-digit characters\n const digits = phone.replace(/\\D/g, '');\n\n const patterns: Record<string, RegExp> = {\n GH: /^(?:233|0)?[235][0-9]{8}$/, // Ghana\n NG: /^(?:234|0)?[789][01][0-9]{8}$/, // Nigeria\n KE: /^(?:254|0)?[17][0-9]{8}$/, // Kenya\n };\n\n const pattern = patterns[country.toUpperCase()];\n if (!pattern) return digits.length >= 10;\n\n return pattern.test(digits);\n}\n\n/**\n * Formats a phone number for display\n */\nexport function formatPhone(phone: string, country: string = 'GH'): string {\n const digits = phone.replace(/\\D/g, '');\n\n if (country === 'GH') {\n // Format as 0XX XXX XXXX\n if (digits.startsWith('233') && digits.length === 12) {\n const local = '0' + digits.slice(3);\n return `${local.slice(0, 3)} ${local.slice(3, 6)} ${local.slice(6)}`;\n }\n if (digits.length === 10 && digits.startsWith('0')) {\n return `${digits.slice(0, 3)} ${digits.slice(3, 6)} ${digits.slice(6)}`;\n }\n }\n\n return phone;\n}\n\n/**\n * Detects mobile money network from phone number (Ghana)\n */\nexport function detectNetwork(phone: string): MobileMoneyNetwork | null {\n const digits = phone.replace(/\\D/g, '');\n\n // Get the network prefix (first 3 digits after country code or 0)\n let prefix: string;\n if (digits.startsWith('233')) {\n prefix = digits.slice(3, 5);\n } else if (digits.startsWith('0')) {\n prefix = digits.slice(1, 3);\n } else {\n prefix = digits.slice(0, 2);\n }\n\n // Ghana network prefixes\n const mtnPrefixes = ['24', '25', '53', '54', '55', '59'];\n const telecelPrefixes = ['20', '50'];\n const airteltigoPrefixes = ['26', '27', '56', '57'];\n\n if (mtnPrefixes.includes(prefix)) return 'mtn';\n if (telecelPrefixes.includes(prefix)) return 'telecel';\n if (airteltigoPrefixes.includes(prefix)) return 'airteltigo';\n\n return null;\n}\n\n/**\n * Creates CSS custom property variables from theme\n */\nexport function createThemeVariables(theme: ReevitTheme): Record<string, string> {\n const variables: Record<string, string> = {};\n\n // Primary color = main text color\n if (theme.primaryColor) {\n variables['--reevit-text'] = theme.primaryColor;\n }\n\n // Primary foreground = description/secondary text color\n if (theme.primaryForegroundColor) {\n variables['--reevit-text-secondary'] = theme.primaryForegroundColor;\n variables['--reevit-muted'] = theme.primaryForegroundColor;\n }\n\n // Button colors\n if (theme.buttonBackgroundColor) {\n variables['--reevit-primary'] = theme.buttonBackgroundColor;\n variables['--reevit-primary-hover'] = theme.buttonBackgroundColor;\n }\n if (theme.buttonTextColor) {\n variables['--reevit-primary-foreground'] = theme.buttonTextColor;\n }\n\n // Background and surface colors\n if (theme.backgroundColor) {\n variables['--reevit-background'] = theme.backgroundColor;\n variables['--reevit-surface'] = theme.backgroundColor;\n }\n if (theme.surfaceColor) {\n variables['--reevit-surface'] = theme.surfaceColor;\n }\n\n // Border color\n if (theme.borderColor) {\n variables['--reevit-border'] = theme.borderColor;\n }\n\n // Legacy text color support\n if (theme.textColor) {\n variables['--reevit-text'] = theme.textColor;\n }\n if (theme.mutedTextColor) {\n variables['--reevit-text-secondary'] = theme.mutedTextColor;\n }\n\n // Border radius\n if (theme.borderRadius) {\n variables['--reevit-radius'] = theme.borderRadius;\n variables['--reevit-radius-sm'] = theme.borderRadius;\n variables['--reevit-radius-lg'] = theme.borderRadius;\n }\n\n // Font family\n if (theme.fontFamily) {\n variables['--reevit-font'] = theme.fontFamily;\n }\n\n return variables;\n}\n\nfunction getContrastingColor(color: string): string | null {\n const hex = color.trim();\n if (!hex.startsWith('#')) {\n return null;\n }\n\n const normalized = hex.length === 4\n ? `#${hex[1]}${hex[1]}${hex[2]}${hex[2]}${hex[3]}${hex[3]}`\n : hex;\n\n if (normalized.length !== 7) {\n return null;\n }\n\n const r = parseInt(normalized.slice(1, 3), 16);\n const g = parseInt(normalized.slice(3, 5), 16);\n const b = parseInt(normalized.slice(5, 7), 16);\n\n if (Number.isNaN(r) || Number.isNaN(g) || Number.isNaN(b)) {\n return null;\n }\n\n const brightness = (r * 299 + g * 587 + b * 114) / 1000;\n return brightness >= 140 ? '#0b1120' : '#ffffff';\n}\n\n/**\n * Simple class name concatenation utility\n */\nexport function cn(...classes: (string | boolean | undefined | null)[]): string {\n return classes.filter(Boolean).join(' ');\n}\n\n/**\n * Detects country code from currency\n */\nexport function detectCountryFromCurrency(currency: string): string {\n const currencyToCountry: Record<string, string> = {\n GHS: 'GH',\n NGN: 'NG',\n KES: 'KE',\n UGX: 'UG',\n TZS: 'TZ',\n ZAR: 'ZA',\n XOF: 'CI',\n XAF: 'CM',\n USD: 'US',\n EUR: 'DE',\n GBP: 'GB',\n };\n\n return currencyToCountry[currency.toUpperCase()] || 'GH';\n}\n","/**\n * Intent identity + cache helpers\n */\n\nimport type { PaymentIntentResponse } from './api/client';\nimport { generateIdempotencyKey } from './api/client';\nimport type { PaymentMethod, ReevitCheckoutConfig } from './types';\nimport { generateReference } from './utils';\n\nconst INTENT_CACHE_TTL_MS = 10 * 60 * 1000; // 10 minutes\n\nexport interface IntentIdentityOptions {\n config: ReevitCheckoutConfig;\n method?: PaymentMethod;\n preferredProvider?: string;\n allowedProviders?: string[];\n publicKey?: string;\n}\n\nexport interface IntentCacheEntry {\n promise?: Promise<PaymentIntentResponse>;\n response?: PaymentIntentResponse;\n expiresAt: number;\n reference?: string;\n}\n\nconst intentCache = new Map<string, IntentCacheEntry>();\n\nfunction pruneIntentCache(now: number = Date.now()): void {\n for (const [key, entry] of intentCache) {\n if (entry.expiresAt <= now) {\n intentCache.delete(key);\n }\n }\n}\n\nfunction getIntentCacheEntryInternal(key: string): IntentCacheEntry | undefined {\n const entry = intentCache.get(key);\n if (!entry) {\n return undefined;\n }\n if (entry.expiresAt <= Date.now()) {\n intentCache.delete(key);\n return undefined;\n }\n return entry;\n}\n\nfunction setIntentCacheEntryInternal(key: string, update: Partial<IntentCacheEntry>): IntentCacheEntry {\n const now = Date.now();\n const existing = getIntentCacheEntryInternal(key);\n const next: IntentCacheEntry = {\n ...existing,\n ...update,\n expiresAt: now + INTENT_CACHE_TTL_MS,\n };\n intentCache.set(key, next);\n return next;\n}\n\nfunction buildIdempotencyPayload(options: IntentIdentityOptions): Record<string, unknown> {\n const { config, method, preferredProvider, allowedProviders, publicKey } = options;\n if (config.sessionSecret) {\n return {\n sessionSecret: config.sessionSecret,\n publicKey: publicKey || config.publicKey || '',\n };\n }\n\n const payload: Record<string, unknown> = {\n amount: config.amount,\n currency: config.currency,\n email: config.email || '',\n phone: config.phone || '',\n customerName: config.customerName || '',\n paymentLinkCode: config.paymentLinkCode || '',\n paymentMethods: config.paymentMethods || [],\n metadata: config.metadata || {},\n customFields: config.customFields || {},\n method: method || '',\n preferredProvider: preferredProvider || '',\n allowedProviders: allowedProviders || [],\n publicKey: publicKey || config.publicKey || '',\n };\n\n if (config.reference) {\n payload.reference = config.reference;\n }\n\n return payload;\n}\n\nexport function resolveIntentIdentity(options: IntentIdentityOptions): {\n idempotencyKey: string;\n reference: string;\n cacheEntry?: IntentCacheEntry;\n} {\n pruneIntentCache();\n\n const idempotencyKey =\n options.config.idempotencyKey || generateIdempotencyKey(buildIdempotencyPayload(options));\n const existing = getIntentCacheEntryInternal(idempotencyKey);\n const reference = options.config.reference || existing?.reference || generateReference();\n\n const cacheEntry = setIntentCacheEntryInternal(idempotencyKey, { reference });\n\n return { idempotencyKey, reference, cacheEntry };\n}\n\nexport function getIntentCacheEntry(idempotencyKey: string): IntentCacheEntry | undefined {\n pruneIntentCache();\n return getIntentCacheEntryInternal(idempotencyKey);\n}\n\nexport function cacheIntentPromise(\n idempotencyKey: string,\n promise: Promise<PaymentIntentResponse>\n): IntentCacheEntry {\n return setIntentCacheEntryInternal(idempotencyKey, { promise });\n}\n\nexport function cacheIntentResponse(\n idempotencyKey: string,\n response: PaymentIntentResponse\n): IntentCacheEntry {\n return setIntentCacheEntryInternal(idempotencyKey, { response, promise: undefined });\n}\n\nexport function clearIntentCacheEntry(idempotencyKey: string): void {\n intentCache.delete(idempotencyKey);\n}\n","/**\n * Reevit State Machine\n * Shared state management logic for all SDKs\n */\n\nimport type { CheckoutState, PaymentIntent, PaymentMethod, PaymentResult, PaymentError } from './types';\n\n// State shape\nexport interface ReevitState {\n status: CheckoutState;\n paymentIntent: PaymentIntent | null;\n selectedMethod: PaymentMethod | null;\n error: PaymentError | null;\n result: PaymentResult | null;\n}\n\n// Actions\nexport type ReevitAction =\n | { type: 'INIT_START' }\n | { type: 'INIT_SUCCESS'; payload: PaymentIntent }\n | { type: 'INIT_ERROR'; payload: PaymentError }\n | { type: 'SELECT_METHOD'; payload: PaymentMethod }\n | { type: 'PROCESS_START' }\n | { type: 'PROCESS_SUCCESS'; payload: PaymentResult }\n | { type: 'PROCESS_ERROR'; payload: PaymentError }\n | { type: 'RESET' }\n | { type: 'CLOSE' };\n\n/**\n * Creates the initial state for the checkout\n */\nexport function createInitialState(): ReevitState {\n return {\n status: 'idle',\n paymentIntent: null,\n selectedMethod: null,\n error: null,\n result: null,\n };\n}\n\n/**\n * State reducer for checkout flow\n */\nexport function reevitReducer(state: ReevitState, action: ReevitAction): ReevitState {\n switch (action.type) {\n case 'INIT_START':\n return { ...state, status: 'loading', error: null };\n case 'INIT_SUCCESS':\n return {\n ...state,\n status: 'ready',\n paymentIntent: action.payload,\n selectedMethod:\n action.payload.availableMethods?.length === 1 ? action.payload.availableMethods[0] : null,\n };\n case 'INIT_ERROR':\n return { ...state, status: 'failed', error: action.payload };\n case 'SELECT_METHOD':\n return { ...state, status: 'method_selected', selectedMethod: action.payload };\n case 'PROCESS_START':\n return { ...state, status: 'processing', error: null };\n case 'PROCESS_SUCCESS':\n return { ...state, status: 'success', result: action.payload };\n case 'PROCESS_ERROR':\n return { ...state, status: 'failed', error: action.payload };\n case 'RESET':\n return { ...createInitialState(), status: 'ready', paymentIntent: state.paymentIntent };\n case 'CLOSE':\n return { ...state, status: 'closed' };\n default:\n return state;\n }\n}\n"],"mappings":"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","names":[]}
|
|
1
|
+
{"version":3,"sources":["../src/index.ts","../src/api/client.ts","../src/utils.ts","../src/intent.ts","../src/state.ts"],"sourcesContent":["/**\n * @reevit/core\n * Shared utilities and API client for Reevit payment SDKs\n */\n\n// API Client\nexport {\n ReevitAPIClient,\n createReevitClient,\n createPaymentError,\n generateIdempotencyKey,\n newIdempotencyKey,\n attemptIdempotencyKey,\n clearIdempotencyAttemptKeys,\n isPaymentError,\n type ReevitAPIClientConfig,\n type CreatePaymentIntentRequest,\n type PaymentIntentResponse,\n type CheckoutSessionResponse,\n type PaymentDetailResponse,\n type ConfirmPaymentRequest,\n type APIErrorResponse,\n type ReevitAPIResult,\n} from './api/client';\n\n// Types\nexport type {\n PaymentMethod,\n MobileMoneyNetwork,\n ReevitCheckoutConfig,\n ReevitCheckoutCallbacks,\n CheckoutState,\n PaymentResult,\n PaymentError,\n ReevitTheme,\n CheckoutProviderOption,\n MobileMoneyFormData,\n CardFormData,\n PaymentIntent,\n PSPConfig,\n PSPType,\n PaymentSource,\n HubtelSessionResponse,\n} from './types';\n\n// Utilities\nexport {\n formatAmount,\n currencyExponent,\n toMinorUnits,\n generateReference,\n validatePhone,\n formatPhone,\n detectNetwork,\n detectCountryFromCurrency,\n createThemeVariables,\n cn,\n} from './utils';\n\n// Intent identity + cache helpers\nexport {\n resolveIntentIdentity,\n getIntentCacheEntry,\n cacheIntentPromise,\n cacheIntentResponse,\n clearIntentCacheEntry,\n type IntentCacheEntry,\n} from './intent';\n\n// State machine helpers\nexport {\n createInitialState,\n reevitReducer,\n type ReevitState,\n type ReevitAction,\n} from './state';\n","/**\n * Reevit API Client\n * \n * Handles communication with the Reevit backend for payment operations.\n */\n\nimport type { PaymentMethod, ReevitCheckoutConfig, PaymentError, HubtelSessionResponse } from '../types';\n\n// API Response Types (matching backend handlers_payments.go)\nexport interface CreatePaymentIntentRequest {\n amount: number;\n currency: string;\n method?: string;\n country: string;\n customer_id?: string;\n metadata?: Record<string, unknown>;\n description?: string;\n policy?: {\n prefer?: string[];\n allowed_providers?: string[];\n max_amount?: number;\n blocked_bins?: string[];\n allowed_bins?: string[];\n velocity_max_per_minute?: number;\n };\n}\n\nexport interface PaymentIntentResponse {\n id: string;\n org_id?: string;\n connection_id: string;\n provider: string;\n provider_ref_id?: string;\n status: string;\n client_secret: string;\n session_secret?: string;\n psp_public_key: string;\n psp_credentials?: {\n merchantAccount?: string | number;\n basicAuth?: string;\n [key: string]: unknown;\n };\n amount: number;\n currency: string;\n fee_amount: number;\n fee_currency: string;\n net_amount: number;\n reference?: string;\n available_psps?: Array<{\n provider: string;\n name: string;\n methods: string[];\n countries?: string[];\n }>;\n branding?: Record<string, unknown>;\n}\n\nexport interface CheckoutSessionResponse {\n id: string;\n client_secret: string;\n session_secret: string;\n payment_intent: PaymentIntentResponse;\n expires_at?: string;\n}\n\nexport interface ConfirmPaymentRequest {\n provider_ref_id: string;\n provider_data?: Record<string, unknown>;\n}\n\nexport interface PaymentDetailResponse {\n id: string;\n connection_id: string;\n provider: string;\n method: string;\n status: string;\n amount: number;\n currency: string;\n fee_amount: number;\n fee_currency: string;\n net_amount: number;\n customer_id?: string;\n client_secret: string;\n provider_ref_id?: string;\n metadata?: Record<string, unknown>;\n created_at: string;\n updated_at: string;\n /** Payment source type (payment_link, api, subscription) */\n source?: 'payment_link' | 'api' | 'subscription';\n /** ID of the source (payment link ID, subscription ID, etc.) */\n source_id?: string;\n /** Human-readable description of the source (e.g., payment link name) */\n source_description?: string;\n}\n\nexport interface APIErrorResponse {\n code: string;\n message: string;\n details?: Record<string, unknown>;\n}\n\nexport type ReevitAPIResult<T> = { data: T; error?: never } | { data?: never; error: PaymentError };\n\n// API Client configuration\nexport interface ReevitAPIClientConfig {\n /** Your Reevit public key */\n publicKey?: string;\n /** Base URL for the Reevit API (defaults to production) */\n baseUrl?: string;\n /** Request timeout in milliseconds */\n timeout?: number;\n}\n\n// Default API base URLs\nconst API_BASE_URL_PRODUCTION = 'https://api.reevit.io';\nconst DEFAULT_TIMEOUT = 30000; // 30 seconds\nlet hasWarnedAboutLiveBrowserIntents = false;\n\n/**\n * Determines if a public key is for sandbox mode\n */\nexport function isSandboxKey(publicKey: string): boolean {\n return publicKey.startsWith('pfk_test_');\n}\n\n/**\n * Creates a PaymentError from an API error response\n */\nexport function createPaymentError(response: Response, errorData: APIErrorResponse): PaymentError {\n return {\n code: errorData.code || 'api_error',\n message: errorData.message || 'An unexpected error occurred',\n recoverable: isRecoverableStatus(response.status),\n details: {\n httpStatus: response.status,\n requestId: response.headers.get('x-request-id') || response.headers.get('x-reevit-request-id') || undefined,\n ...errorData.details,\n },\n };\n}\n\nexport function isPaymentError(error: unknown): error is PaymentError {\n return typeof error === 'object' && error !== null && 'code' in error && 'message' in error;\n}\n\nexport function isRecoverableStatus(status: number): boolean {\n return status === 408 || status === 409 || status === 425 || status === 429 || status >= 500;\n}\n\n/**\n * Generates a deterministic **cache/lookup** key from input parameters.\n *\n * NEVER SEND THIS ON THE WIRE. It is a 32-bit djb2 hash bucketed into\n * 5-minute windows, so two unrelated shoppers can collide and be handed each\n * other's payment intent (and therefore each other's `client_secret`), and a\n * shopper legitimately buying the same item twice inside one window would be\n * charged once. Its only job is to identify \"the same checkout attempt\" inside\n * a single browser tab so the in-flight intent cache can dedupe a repeated\n * \"Continue\" click.\n *\n * The value actually sent as `Idempotency-Key` is produced by\n * {@link newIdempotencyKey} / {@link attemptIdempotencyKey}.\n *\n * Exported for use by SDK hooks (e.g. payment link flows).\n */\nexport function generateIdempotencyKey(params: Record<string, unknown>): string {\n // Create a stable string representation of the parameters\n const sortedKeys = Object.keys(params).sort();\n const stableString = sortedKeys\n .map(key => `${key}:${JSON.stringify(params[key])}`)\n .join('|');\n\n // Simple hash function (djb2 algorithm)\n let hash = 5381;\n for (let i = 0; i < stableString.length; i++) {\n hash = ((hash << 5) + hash) + stableString.charCodeAt(i);\n hash = hash & hash; // Convert to 32-bit integer\n }\n\n // Convert to positive hex string\n const hashHex = (hash >>> 0).toString(16);\n\n // Add a time bucket (5-minute windows) to allow retries within a reasonable window\n // but prevent keys from being reused across completely different sessions\n const timeBucket = Math.floor(Date.now() / (5 * 60 * 1000));\n\n return `reevit_${timeBucket}_${hashHex}`;\n}\n\nconst IDEMPOTENCY_STORE_PREFIX = 'reevit:idem:';\n\n/** Fallback store for SSR / privacy mode, where `sessionStorage` is unusable. */\nconst memoryAttemptKeys = new Map<string, string>();\n\nfunction getSessionStore(): Storage | null {\n try {\n const storage = (globalThis as { sessionStorage?: Storage }).sessionStorage;\n if (!storage) {\n return null;\n }\n // Safari private mode and some embedded webviews throw on write.\n const probe = `${IDEMPOTENCY_STORE_PREFIX}probe`;\n storage.setItem(probe, '1');\n storage.removeItem(probe);\n return storage;\n } catch {\n return null;\n }\n}\n\n/**\n * Generates a fresh, globally unique `Idempotency-Key` (RFC 4122 v4 UUID).\n * This is the only value that should ever be sent on the wire.\n */\nexport function newIdempotencyKey(): string {\n const cryptoObj = (globalThis as { crypto?: Crypto }).crypto;\n\n if (cryptoObj && typeof cryptoObj.randomUUID === 'function') {\n try {\n return cryptoObj.randomUUID();\n } catch {\n // fall through to the manual generator\n }\n }\n\n const bytes = new Uint8Array(16);\n if (cryptoObj && typeof cryptoObj.getRandomValues === 'function') {\n cryptoObj.getRandomValues(bytes);\n } else {\n for (let i = 0; i < bytes.length; i++) {\n bytes[i] = Math.floor(Math.random() * 256);\n }\n }\n\n bytes[6] = (bytes[6] & 0x0f) | 0x40; // version 4\n bytes[8] = (bytes[8] & 0x3f) | 0x80; // variant 10\n\n const hex: string[] = [];\n for (let i = 0; i < bytes.length; i++) {\n hex.push(bytes[i].toString(16).padStart(2, '0'));\n }\n\n return [\n hex.slice(0, 4).join(''),\n hex.slice(4, 6).join(''),\n hex.slice(6, 8).join(''),\n hex.slice(8, 10).join(''),\n hex.slice(10, 16).join(''),\n ].join('-');\n}\n\n/**\n * Resolves the stable per-checkout-attempt wire key for a deterministic\n * lookup key (see {@link generateIdempotencyKey}).\n *\n * The first call for a lookup key mints a UUID and stores it in\n * `sessionStorage` (falling back to a module-level map when storage is\n * unavailable); every later call in the same tab returns that same UUID, so a\n * repeated \"Continue\" click is still deduped by the backend. A different tab,\n * a different shopper or a cleared store yields a different UUID.\n */\nexport function attemptIdempotencyKey(lookupKey: string): string {\n const storageKey = `${IDEMPOTENCY_STORE_PREFIX}${lookupKey}`;\n const store = getSessionStore();\n\n if (store) {\n try {\n const existing = store.getItem(storageKey);\n if (existing) {\n return existing;\n }\n const created = newIdempotencyKey();\n store.setItem(storageKey, created);\n return created;\n } catch {\n // fall through to the in-memory store\n }\n }\n\n const existing = memoryAttemptKeys.get(storageKey);\n if (existing) {\n return existing;\n }\n const created = newIdempotencyKey();\n memoryAttemptKeys.set(storageKey, created);\n return created;\n}\n\n/**\n * Forgets every stored per-attempt key, so the next checkout attempt gets a\n * fresh `Idempotency-Key`. Call it after a completed checkout (and in tests).\n */\nexport function clearIdempotencyAttemptKeys(): void {\n memoryAttemptKeys.clear();\n\n const store = getSessionStore();\n if (!store) {\n return;\n }\n\n try {\n const keys: string[] = [];\n for (let i = 0; i < store.length; i++) {\n const key = store.key(i);\n if (key && key.startsWith(IDEMPOTENCY_STORE_PREFIX)) {\n keys.push(key);\n }\n }\n for (const key of keys) {\n store.removeItem(key);\n }\n } catch {\n // nothing else we can do\n }\n}\n\n/**\n * Reevit API Client\n */\nexport class ReevitAPIClient {\n private readonly publicKey: string;\n private readonly baseUrl: string;\n private readonly timeout: number;\n\n constructor(config: ReevitAPIClientConfig) {\n this.publicKey = config.publicKey || '';\n this.baseUrl = config.baseUrl || API_BASE_URL_PRODUCTION;\n this.timeout = config.timeout || DEFAULT_TIMEOUT;\n }\n\n /**\n * Makes an authenticated API request\n * @param idempotencyKey Optional deterministic idempotency key for the request\n */\n private async request<T>(\n method: string,\n path: string,\n body?: unknown,\n idempotencyKey?: string\n ): Promise<ReevitAPIResult<T>> {\n const controller = new AbortController();\n const timeoutId = setTimeout(() => controller.abort(), this.timeout);\n\n // Generate headers with idempotency key for mutating requests\n const headers: Record<string, string> = {\n 'Content-Type': 'application/json',\n 'X-Reevit-Client': '@reevit/core',\n 'X-Reevit-Client-Version': '0.9.1',\n };\n if (this.publicKey) {\n headers['X-Reevit-Key'] = this.publicKey;\n }\n\n if (method === 'POST' || method === 'PATCH' || method === 'PUT') {\n // Never derive the wire key from the request body: a body hash collides\n // across unrelated shoppers. Fall back to a fresh UUID instead.\n headers['Idempotency-Key'] = idempotencyKey || newIdempotencyKey();\n }\n\n try {\n const response = await fetch(`${this.baseUrl}${path}`, {\n method,\n headers,\n body: body ? JSON.stringify(body) : undefined,\n signal: controller.signal,\n });\n\n clearTimeout(timeoutId);\n\n const responseData = await response.json().catch(() => ({}));\n\n if (!response.ok) {\n return {\n error: createPaymentError(response, responseData as APIErrorResponse),\n };\n }\n\n return { data: responseData as T };\n } catch (err) {\n clearTimeout(timeoutId);\n\n if (err instanceof Error) {\n if (err.name === 'AbortError') {\n return {\n error: {\n code: 'request_timeout',\n message: 'The request timed out. Please try again.',\n recoverable: true,\n },\n };\n }\n\n if (err.message.includes('Failed to fetch') || err.message.includes('NetworkError')) {\n return {\n error: {\n code: 'network_error',\n message: 'Unable to connect to Reevit. Please check your internet connection.',\n recoverable: true,\n },\n };\n }\n }\n\n return {\n error: {\n code: 'unknown_error',\n message: 'An unexpected error occurred. Please try again.',\n recoverable: true,\n },\n };\n }\n }\n\n /**\n * Creates a payment intent\n */\n async createPaymentIntent(\n config: ReevitCheckoutConfig,\n method?: PaymentMethod,\n country: string = 'GH',\n options?: { preferredProviders?: string[]; allowedProviders?: string[] }\n ): Promise<{ data?: PaymentIntentResponse; error?: PaymentError }> {\n if (\n this.publicKey.startsWith('pfk_live_') &&\n !hasWarnedAboutLiveBrowserIntents &&\n typeof console !== 'undefined'\n ) {\n hasWarnedAboutLiveBrowserIntents = true;\n console.warn(\n 'Creating live payment intents from the browser is deprecated. Create a checkout session on your server and pass sessionSecret to the browser SDK instead.'\n );\n }\n\n if (typeof config.amount !== 'number' || !config.currency) {\n return {\n error: {\n code: 'invalid_checkout_config',\n message: 'amount and currency are required when creating a payment intent in the browser.',\n recoverable: false,\n },\n };\n }\n\n // Build metadata with customer_email for PSP providers that require it\n const metadata: Record<string, unknown> = { ...config.metadata };\n if (config.email) {\n metadata.customer_email = config.email;\n }\n if (config.phone) {\n metadata.customer_phone = config.phone;\n }\n\n const request: CreatePaymentIntentRequest = {\n amount: config.amount,\n currency: config.currency,\n country,\n customer_id: config.email || (config.metadata?.customerId as string | undefined),\n metadata,\n };\n\n if (method) {\n request.method = this.mapPaymentMethod(method);\n }\n\n if (options?.preferredProviders?.length || options?.allowedProviders?.length) {\n request.policy = {\n prefer: options?.preferredProviders,\n allowed_providers: options?.allowedProviders,\n };\n }\n\n // The deterministic hash identifies this checkout attempt *locally*; the\n // key we put on the wire is a UUID minted once per attempt and reused for\n // the life of the tab, so a repeated \"Continue\" click still dedupes while\n // two unrelated shoppers can never share a key.\n const idempotencyKey = config.idempotencyKey || attemptIdempotencyKey(generateIdempotencyKey({\n amount: config.amount,\n currency: config.currency,\n customer: config.email || config.metadata?.customerId || '',\n reference: config.reference || '',\n method: method || '',\n provider: options?.preferredProviders?.[0] || options?.allowedProviders?.[0] || '',\n publicKey: this.publicKey,\n }));\n\n return this.request<PaymentIntentResponse>('POST', '/v1/payments/intents', request, idempotencyKey);\n }\n\n /**\n * Retrieves a payment intent by ID\n */\n async getPaymentIntent(paymentId: string): Promise<{ data?: PaymentDetailResponse; error?: PaymentError }> {\n return this.request<PaymentDetailResponse>('GET', `/v1/payments/${paymentId}`);\n }\n\n /**\n * Retrieves a server-created checkout session using its public session secret.\n */\n async getCheckoutSession(sessionSecret: string): Promise<{ data?: CheckoutSessionResponse; error?: PaymentError }> {\n return this.request<CheckoutSessionResponse>(\n 'GET',\n `/v1/checkout/sessions/${encodeURIComponent(sessionSecret)}`\n );\n }\n\n /**\n * Confirms a payment after PSP callback\n */\n async confirmPayment(paymentId: string): Promise<{ data?: PaymentDetailResponse; error?: PaymentError }> {\n return this.request<PaymentDetailResponse>('POST', `/v1/payments/${paymentId}/confirm`);\n }\n\n /**\n * Confirms a payment intent using client secret (public endpoint)\n */\n async confirmPaymentIntent(paymentId: string, clientSecret: string): Promise<{ data?: PaymentDetailResponse; error?: PaymentError }> {\n return this.request<PaymentDetailResponse>(\n 'POST',\n `/v1/payments/${paymentId}/confirm-intent?client_secret=${encodeURIComponent(clientSecret)}`\n );\n }\n\n /**\n * Cancels a payment intent\n */\n async cancelPaymentIntent(paymentId: string): Promise<{ data?: PaymentDetailResponse; error?: PaymentError }> {\n return this.request<PaymentDetailResponse>('POST', `/v1/payments/${paymentId}/cancel`);\n }\n\n /**\n * Creates a Hubtel session token for secure checkout\n * Returns a short-lived token that contains Hubtel credentials\n * Credentials are never exposed to the client directly\n */\n async createHubtelSession(\n paymentId: string,\n clientSecret?: string\n ): Promise<{ data?: HubtelSessionResponse; error?: PaymentError }> {\n const query = clientSecret ? `?client_secret=${encodeURIComponent(clientSecret)}` : '';\n return this.request<HubtelSessionResponse>('POST', `/v1/payments/hubtel/sessions/${paymentId}${query}`);\n }\n\n /**\n * Maps SDK payment method to backend format\n */\n private mapPaymentMethod(method: PaymentMethod): string {\n switch (method) {\n case 'card':\n return 'card';\n case 'mobile_money':\n return 'mobile_money';\n case 'bank_transfer':\n return 'bank_transfer';\n default:\n return method;\n }\n }\n}\n\n/**\n * Creates a new Reevit API client instance\n */\nexport function createReevitClient(config: ReevitAPIClientConfig): ReevitAPIClient {\n return new ReevitAPIClient(config);\n}\n","/**\n * Utility Functions\n * Shared utilities for Reevit SDKs\n */\n\nimport type { MobileMoneyNetwork, ReevitTheme } from './types';\n\nconst CURRENCY_LOCALES: Record<string, string> = {\n GHS: 'en-GH',\n NGN: 'en-NG',\n KES: 'en-KE',\n USD: 'en-US',\n EUR: 'de-DE',\n GBP: 'en-GB',\n};\n\n/**\n * Currencies with no minor unit — the API's integer amount *is* the amount.\n * Used only when `Intl` cannot tell us (old or trimmed ICU builds).\n * Keep in sync with the reevit CLI's copy of this table.\n */\nconst ZERO_DECIMAL_CURRENCIES = new Set([\n 'XOF', 'XAF', 'RWF', 'UGX', 'JPY', 'KRW', 'BIF', 'GNF',\n 'VND', 'CLP', 'ISK', 'KMF', 'DJF', 'PYG', 'MGA',\n]);\n\n/**\n * Returns how many decimal places a currency's minor unit uses: 2 for GHS and\n * NGN, 0 for XOF, XAF, RWF, UGX, JPY and friends.\n *\n * Dividing every amount by 100 renders a 5,000 XOF charge as \"XOF 50.00\" while\n * the shopper is actually charged 5,000 — which is why this exists.\n */\nexport function currencyExponent(currency: string): number {\n const code = (currency || '').toUpperCase();\n\n try {\n const digits = new Intl.NumberFormat('en', {\n style: 'currency',\n currency: code,\n }).resolvedOptions().maximumFractionDigits;\n\n if (typeof digits === 'number' && Number.isFinite(digits)) {\n return digits;\n }\n } catch {\n // Unsupported currency code, or an ICU build without currency data.\n }\n\n return ZERO_DECIMAL_CURRENCIES.has(code) ? 0 : 2;\n}\n\n/**\n * Converts a major-unit amount (what a shopper types) into the minor units the\n * API expects: `toMinorUnits(45, 'GHS') === 4500`, `toMinorUnits(5000, 'XOF') === 5000`.\n */\nexport function toMinorUnits(major: number, currency: string): number {\n return Math.round(major * 10 ** currencyExponent(currency));\n}\n\n/**\n * Formats an amount from smallest currency unit to display format\n */\nexport function formatAmount(amount: number, currency: string): string {\n const code = (currency || '').toUpperCase();\n const exponent = currencyExponent(code);\n const majorUnit = amount / 10 ** exponent;\n const locale = CURRENCY_LOCALES[code] || 'en-US';\n\n try {\n return new Intl.NumberFormat(locale, {\n style: 'currency',\n currency: code,\n minimumFractionDigits: exponent,\n maximumFractionDigits: exponent,\n }).format(majorUnit);\n } catch {\n // Fallback for unsupported currencies\n return `${code} ${majorUnit.toFixed(exponent)}`;\n }\n}\n\n/**\n * Generates a unique payment reference\n */\nexport function generateReference(prefix: string = 'reevit'): string {\n const timestamp = Date.now().toString(36);\n const random = Math.random().toString(36).substring(2, 8);\n return `${prefix}_${timestamp}_${random}`;\n}\n\n/**\n * Validates a phone number for mobile money\n */\nexport function validatePhone(phone: string, country: string = 'GH'): boolean {\n // Remove non-digit characters\n const digits = phone.replace(/\\D/g, '');\n\n const patterns: Record<string, RegExp> = {\n GH: /^(?:233|0)?[235][0-9]{8}$/, // Ghana\n NG: /^(?:234|0)?[789][01][0-9]{8}$/, // Nigeria\n KE: /^(?:254|0)?[17][0-9]{8}$/, // Kenya\n };\n\n const pattern = patterns[country.toUpperCase()];\n if (!pattern) return digits.length >= 10;\n\n return pattern.test(digits);\n}\n\n/**\n * Formats a phone number for display\n */\nexport function formatPhone(phone: string, country: string = 'GH'): string {\n const digits = phone.replace(/\\D/g, '');\n\n if (country === 'GH') {\n // Format as 0XX XXX XXXX\n if (digits.startsWith('233') && digits.length === 12) {\n const local = '0' + digits.slice(3);\n return `${local.slice(0, 3)} ${local.slice(3, 6)} ${local.slice(6)}`;\n }\n if (digits.length === 10 && digits.startsWith('0')) {\n return `${digits.slice(0, 3)} ${digits.slice(3, 6)} ${digits.slice(6)}`;\n }\n }\n\n return phone;\n}\n\n/**\n * Detects mobile money network from phone number (Ghana)\n */\nexport function detectNetwork(phone: string): MobileMoneyNetwork | null {\n const digits = phone.replace(/\\D/g, '');\n\n // Get the network prefix (first 3 digits after country code or 0)\n let prefix: string;\n if (digits.startsWith('233')) {\n prefix = digits.slice(3, 5);\n } else if (digits.startsWith('0')) {\n prefix = digits.slice(1, 3);\n } else {\n prefix = digits.slice(0, 2);\n }\n\n // Ghana network prefixes\n const mtnPrefixes = ['24', '25', '53', '54', '55', '59'];\n const telecelPrefixes = ['20', '50'];\n const airteltigoPrefixes = ['26', '27', '56', '57'];\n\n if (mtnPrefixes.includes(prefix)) return 'mtn';\n if (telecelPrefixes.includes(prefix)) return 'telecel';\n if (airteltigoPrefixes.includes(prefix)) return 'airteltigo';\n\n return null;\n}\n\n/**\n * Creates CSS custom property variables from theme\n */\nexport function createThemeVariables(theme: ReevitTheme): Record<string, string> {\n const variables: Record<string, string> = {};\n\n // Primary color = main text color\n if (theme.primaryColor) {\n variables['--reevit-text'] = theme.primaryColor;\n }\n\n // Primary foreground = description/secondary text color\n if (theme.primaryForegroundColor) {\n variables['--reevit-text-secondary'] = theme.primaryForegroundColor;\n variables['--reevit-muted'] = theme.primaryForegroundColor;\n }\n\n // Button colors\n if (theme.buttonBackgroundColor) {\n variables['--reevit-primary'] = theme.buttonBackgroundColor;\n variables['--reevit-primary-hover'] = theme.buttonBackgroundColor;\n }\n if (theme.buttonTextColor) {\n variables['--reevit-primary-foreground'] = theme.buttonTextColor;\n }\n\n // Background and surface colors\n if (theme.backgroundColor) {\n variables['--reevit-background'] = theme.backgroundColor;\n variables['--reevit-surface'] = theme.backgroundColor;\n }\n if (theme.surfaceColor) {\n variables['--reevit-surface'] = theme.surfaceColor;\n }\n\n // Border color\n if (theme.borderColor) {\n variables['--reevit-border'] = theme.borderColor;\n }\n\n // Legacy text color support\n if (theme.textColor) {\n variables['--reevit-text'] = theme.textColor;\n }\n if (theme.mutedTextColor) {\n variables['--reevit-text-secondary'] = theme.mutedTextColor;\n }\n\n // Border radius\n if (theme.borderRadius) {\n variables['--reevit-radius'] = theme.borderRadius;\n variables['--reevit-radius-sm'] = theme.borderRadius;\n variables['--reevit-radius-lg'] = theme.borderRadius;\n }\n\n // Font family\n if (theme.fontFamily) {\n variables['--reevit-font'] = theme.fontFamily;\n }\n\n return variables;\n}\n\nfunction getContrastingColor(color: string): string | null {\n const hex = color.trim();\n if (!hex.startsWith('#')) {\n return null;\n }\n\n const normalized = hex.length === 4\n ? `#${hex[1]}${hex[1]}${hex[2]}${hex[2]}${hex[3]}${hex[3]}`\n : hex;\n\n if (normalized.length !== 7) {\n return null;\n }\n\n const r = parseInt(normalized.slice(1, 3), 16);\n const g = parseInt(normalized.slice(3, 5), 16);\n const b = parseInt(normalized.slice(5, 7), 16);\n\n if (Number.isNaN(r) || Number.isNaN(g) || Number.isNaN(b)) {\n return null;\n }\n\n const brightness = (r * 299 + g * 587 + b * 114) / 1000;\n return brightness >= 140 ? '#0b1120' : '#ffffff';\n}\n\n/**\n * Simple class name concatenation utility\n */\nexport function cn(...classes: (string | boolean | undefined | null)[]): string {\n return classes.filter(Boolean).join(' ');\n}\n\n/**\n * Detects country code from currency\n */\nexport function detectCountryFromCurrency(currency: string): string {\n const currencyToCountry: Record<string, string> = {\n GHS: 'GH',\n NGN: 'NG',\n KES: 'KE',\n UGX: 'UG',\n TZS: 'TZ',\n ZAR: 'ZA',\n XOF: 'CI',\n XAF: 'CM',\n USD: 'US',\n EUR: 'DE',\n GBP: 'GB',\n };\n\n return currencyToCountry[currency.toUpperCase()] || 'GH';\n}\n","/**\n * Intent identity + cache helpers\n *\n * Two different keys are in play here and mixing them up is a money bug:\n *\n * - the **lookup key** is the deterministic djb2 hash of the checkout\n * parameters (`generateIdempotencyKey`). It identifies \"the same checkout\n * attempt\" for the in-flight cache and is never sent to the API.\n * - the **wire key** is the per-attempt UUID (`attemptIdempotencyKey`) that\n * goes out as the `Idempotency-Key` header.\n *\n * The cache is keyed by the lookup key and remembers the wire key it minted.\n * The public helpers accept either key so callers that only ever saw the\n * `idempotencyKey` field keep working unchanged.\n */\n\nimport type { PaymentIntentResponse } from './api/client';\nimport { attemptIdempotencyKey, generateIdempotencyKey } from './api/client';\nimport type { PaymentMethod, ReevitCheckoutConfig } from './types';\nimport { generateReference } from './utils';\n\nconst INTENT_CACHE_TTL_MS = 10 * 60 * 1000; // 10 minutes\n\nexport interface IntentIdentityOptions {\n config: ReevitCheckoutConfig;\n method?: PaymentMethod;\n preferredProvider?: string;\n allowedProviders?: string[];\n publicKey?: string;\n}\n\nexport interface IntentCacheEntry {\n promise?: Promise<PaymentIntentResponse>;\n response?: PaymentIntentResponse;\n expiresAt: number;\n reference?: string;\n /** The `Idempotency-Key` sent on the wire for this attempt. */\n idempotencyKey?: string;\n}\n\nconst intentCache = new Map<string, IntentCacheEntry>();\n/** wire key -> lookup key, so callers can pass either one. */\nconst lookupKeyByWireKey = new Map<string, string>();\n\nfunction forgetKey(lookupKey: string): void {\n const entry = intentCache.get(lookupKey);\n if (entry?.idempotencyKey) {\n lookupKeyByWireKey.delete(entry.idempotencyKey);\n }\n intentCache.delete(lookupKey);\n}\n\n/** Accepts either the lookup key or the wire key. */\nfunction toLookupKey(key: string): string {\n return lookupKeyByWireKey.get(key) ?? key;\n}\n\nfunction pruneIntentCache(now: number = Date.now()): void {\n for (const [key, entry] of intentCache) {\n if (entry.expiresAt <= now) {\n forgetKey(key);\n }\n }\n}\n\nfunction getIntentCacheEntryInternal(lookupKey: string): IntentCacheEntry | undefined {\n const entry = intentCache.get(lookupKey);\n if (!entry) {\n return undefined;\n }\n if (entry.expiresAt <= Date.now()) {\n forgetKey(lookupKey);\n return undefined;\n }\n return entry;\n}\n\nfunction setIntentCacheEntryInternal(lookupKey: string, update: Partial<IntentCacheEntry>): IntentCacheEntry {\n const now = Date.now();\n const existing = getIntentCacheEntryInternal(lookupKey);\n const next: IntentCacheEntry = {\n ...existing,\n ...update,\n expiresAt: now + INTENT_CACHE_TTL_MS,\n };\n if (existing?.idempotencyKey && existing.idempotencyKey !== next.idempotencyKey) {\n lookupKeyByWireKey.delete(existing.idempotencyKey);\n }\n intentCache.set(lookupKey, next);\n if (next.idempotencyKey && next.idempotencyKey !== lookupKey) {\n lookupKeyByWireKey.set(next.idempotencyKey, lookupKey);\n }\n return next;\n}\n\nfunction buildIdempotencyPayload(options: IntentIdentityOptions): Record<string, unknown> {\n const { config, method, preferredProvider, allowedProviders, publicKey } = options;\n if (config.sessionSecret) {\n return {\n sessionSecret: config.sessionSecret,\n publicKey: publicKey || config.publicKey || '',\n };\n }\n\n const payload: Record<string, unknown> = {\n amount: config.amount,\n currency: config.currency,\n email: config.email || '',\n phone: config.phone || '',\n customerName: config.customerName || '',\n paymentLinkCode: config.paymentLinkCode || '',\n paymentMethods: config.paymentMethods || [],\n metadata: config.metadata || {},\n customFields: config.customFields || {},\n method: method || '',\n preferredProvider: preferredProvider || '',\n allowedProviders: allowedProviders || [],\n publicKey: publicKey || config.publicKey || '',\n };\n\n if (config.reference) {\n payload.reference = config.reference;\n }\n\n return payload;\n}\n\nexport function resolveIntentIdentity(options: IntentIdentityOptions): {\n /** The value to send as `Idempotency-Key`. */\n idempotencyKey: string;\n /** The local cache key. Never send this on the wire. */\n lookupKey: string;\n reference: string;\n cacheEntry?: IntentCacheEntry;\n} {\n pruneIntentCache();\n\n // A caller-supplied key is authoritative for both roles: the merchant owns\n // its retry semantics and we must send exactly what they asked for.\n const explicitKey = options.config.idempotencyKey;\n const lookupKey = explicitKey || generateIdempotencyKey(buildIdempotencyPayload(options));\n const idempotencyKey = explicitKey || attemptIdempotencyKey(lookupKey);\n\n const existing = getIntentCacheEntryInternal(lookupKey);\n const reference = options.config.reference || existing?.reference || generateReference();\n\n const cacheEntry = setIntentCacheEntryInternal(lookupKey, { reference, idempotencyKey });\n\n return { idempotencyKey, lookupKey, reference, cacheEntry };\n}\n\nexport function getIntentCacheEntry(key: string): IntentCacheEntry | undefined {\n pruneIntentCache();\n return getIntentCacheEntryInternal(toLookupKey(key));\n}\n\nexport function cacheIntentPromise(\n key: string,\n promise: Promise<PaymentIntentResponse>\n): IntentCacheEntry {\n return setIntentCacheEntryInternal(toLookupKey(key), { promise });\n}\n\nexport function cacheIntentResponse(\n key: string,\n response: PaymentIntentResponse\n): IntentCacheEntry {\n return setIntentCacheEntryInternal(toLookupKey(key), { response, promise: undefined });\n}\n\nexport function clearIntentCacheEntry(key: string): void {\n forgetKey(toLookupKey(key));\n}\n","/**\n * Reevit State Machine\n * Shared state management logic for all SDKs\n */\n\nimport type { CheckoutState, PaymentIntent, PaymentMethod, PaymentResult, PaymentError } from './types';\n\n// State shape\nexport interface ReevitState {\n status: CheckoutState;\n paymentIntent: PaymentIntent | null;\n selectedMethod: PaymentMethod | null;\n error: PaymentError | null;\n result: PaymentResult | null;\n}\n\n// Actions\nexport type ReevitAction =\n | { type: 'INIT_START' }\n | { type: 'INIT_SUCCESS'; payload: PaymentIntent }\n | { type: 'INIT_ERROR'; payload: PaymentError }\n | { type: 'SELECT_METHOD'; payload: PaymentMethod }\n | { type: 'PROCESS_START' }\n | { type: 'PROCESS_SUCCESS'; payload: PaymentResult }\n | { type: 'PROCESS_ERROR'; payload: PaymentError }\n | { type: 'RESET' }\n | { type: 'CLOSE' };\n\n/**\n * Creates the initial state for the checkout\n */\nexport function createInitialState(): ReevitState {\n return {\n status: 'idle',\n paymentIntent: null,\n selectedMethod: null,\n error: null,\n result: null,\n };\n}\n\n/**\n * State reducer for checkout flow\n */\nexport function reevitReducer(state: ReevitState, action: ReevitAction): ReevitState {\n switch (action.type) {\n case 'INIT_START':\n return { ...state, status: 'loading', error: null };\n case 'INIT_SUCCESS':\n return {\n ...state,\n status: 'ready',\n paymentIntent: action.payload,\n selectedMethod:\n action.payload.availableMethods?.length === 1 ? action.payload.availableMethods[0] : null,\n };\n case 'INIT_ERROR':\n return { ...state, status: 'failed', error: action.payload };\n case 'SELECT_METHOD':\n return { ...state, status: 'method_selected', selectedMethod: action.payload };\n case 'PROCESS_START':\n return { ...state, status: 'processing', error: null };\n case 'PROCESS_SUCCESS':\n return { ...state, status: 'success', result: action.payload };\n case 'PROCESS_ERROR':\n return { ...state, status: 'failed', error: action.payload };\n case 'RESET':\n return { ...createInitialState(), status: 'ready', paymentIntent: state.paymentIntent };\n case 'CLOSE':\n return { ...state, status: 'closed' };\n default:\n return state;\n }\n}\n"],"mappings":"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","names":["existing","created"]}
|