@reevit/core 0.2.5 → 0.3.3

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.d.mts CHANGED
@@ -5,6 +5,8 @@
5
5
  type PaymentMethod = 'card' | 'mobile_money' | 'bank_transfer';
6
6
  type MobileMoneyNetwork = 'mtn' | 'vodafone' | 'airteltigo';
7
7
  type PSPType = 'paystack' | 'hubtel' | 'flutterwave' | 'stripe' | 'monnify' | 'mpesa';
8
+ /** Payment source type - indicates where the payment originated from */
9
+ type PaymentSource = 'payment_link' | 'api' | 'subscription';
8
10
  interface ReevitCheckoutConfig {
9
11
  /** Your Reevit public key (pk_live_xxx or pk_test_xxx) */
10
12
  publicKey: string;
@@ -22,6 +24,8 @@ interface ReevitCheckoutConfig {
22
24
  metadata?: Record<string, unknown>;
23
25
  /** Payment methods to display */
24
26
  paymentMethods?: PaymentMethod[];
27
+ /** Pre-created payment intent to use */
28
+ initialPaymentIntent?: PaymentIntent | any;
25
29
  }
26
30
  interface ReevitCheckoutCallbacks {
27
31
  /** Called when payment is successful */
@@ -53,6 +57,12 @@ interface PaymentResult {
53
57
  status: 'success' | 'pending';
54
58
  /** Any additional data from the PSP */
55
59
  metadata?: Record<string, unknown>;
60
+ /** Payment source type (payment_link, api, subscription) */
61
+ source?: PaymentSource;
62
+ /** ID of the source (payment link ID, subscription ID, etc.) */
63
+ sourceId?: string;
64
+ /** Human-readable description of the source (e.g., payment link name) */
65
+ sourceDescription?: string;
56
66
  }
57
67
  interface PaymentError {
58
68
  /** Error code */
@@ -103,6 +113,8 @@ interface PaymentIntent {
103
113
  id: string;
104
114
  /** Client secret for authenticating client-side operations */
105
115
  clientSecret: string;
116
+ /** PSP public key if available */
117
+ pspPublicKey?: string;
106
118
  /** Amount in smallest currency unit */
107
119
  amount: number;
108
120
  /** Currency code */
@@ -113,6 +125,8 @@ interface PaymentIntent {
113
125
  recommendedPsp: PSPType;
114
126
  /** Available payment methods for this intent */
115
127
  availableMethods: PaymentMethod[];
128
+ /** Reference provided or generated */
129
+ reference?: string;
116
130
  /** Connection ID (from Reevit backend) */
117
131
  connectionId?: string;
118
132
  /** Provider name (from backend) */
@@ -155,11 +169,13 @@ interface PaymentIntentResponse {
155
169
  provider: string;
156
170
  status: string;
157
171
  client_secret: string;
172
+ psp_public_key: string;
158
173
  amount: number;
159
174
  currency: string;
160
175
  fee_amount: number;
161
176
  fee_currency: string;
162
177
  net_amount: number;
178
+ reference?: string;
163
179
  }
164
180
  interface ConfirmPaymentRequest {
165
181
  provider_ref_id: string;
@@ -182,6 +198,12 @@ interface PaymentDetailResponse {
182
198
  metadata?: Record<string, unknown>;
183
199
  created_at: string;
184
200
  updated_at: string;
201
+ /** Payment source type (payment_link, api, subscription) */
202
+ source?: 'payment_link' | 'api' | 'subscription';
203
+ /** ID of the source (payment link ID, subscription ID, etc.) */
204
+ source_id?: string;
205
+ /** Human-readable description of the source (e.g., payment link name) */
206
+ source_description?: string;
185
207
  }
186
208
  interface APIErrorResponse {
187
209
  code: string;
@@ -229,6 +251,13 @@ declare class ReevitAPIClient {
229
251
  data?: PaymentDetailResponse;
230
252
  error?: PaymentError;
231
253
  }>;
254
+ /**
255
+ * Confirms a payment intent using client secret (public endpoint)
256
+ */
257
+ confirmPaymentIntent(paymentId: string, clientSecret: string): Promise<{
258
+ data?: PaymentDetailResponse;
259
+ error?: PaymentError;
260
+ }>;
232
261
  /**
233
262
  * Cancels a payment intent
234
263
  */
@@ -329,4 +358,4 @@ declare function createInitialState(): ReevitState;
329
358
  */
330
359
  declare function reevitReducer(state: ReevitState, action: ReevitAction): ReevitState;
331
360
 
332
- export { type APIErrorResponse, type CardFormData, type CheckoutState, type ConfirmPaymentRequest, type CreatePaymentIntentRequest, type MobileMoneyFormData, type MobileMoneyNetwork, type PSPConfig, type PSPType, type PaymentDetailResponse, type PaymentError, type PaymentIntent, type PaymentIntentResponse, type PaymentMethod, type PaymentResult, ReevitAPIClient, type ReevitAPIClientConfig, type ReevitAction, type ReevitCheckoutCallbacks, type ReevitCheckoutConfig, type ReevitState, type ReevitTheme, cn, createInitialState, createReevitClient, createThemeVariables, detectCountryFromCurrency, detectNetwork, formatAmount, formatPhone, generateReference, reevitReducer, validatePhone };
361
+ export { type APIErrorResponse, type CardFormData, type CheckoutState, type ConfirmPaymentRequest, type CreatePaymentIntentRequest, type MobileMoneyFormData, type MobileMoneyNetwork, type PSPConfig, type PSPType, type PaymentDetailResponse, type PaymentError, type PaymentIntent, type PaymentIntentResponse, type PaymentMethod, type PaymentResult, type PaymentSource, ReevitAPIClient, type ReevitAPIClientConfig, type ReevitAction, type ReevitCheckoutCallbacks, type ReevitCheckoutConfig, type ReevitState, type ReevitTheme, cn, createInitialState, createReevitClient, createThemeVariables, detectCountryFromCurrency, detectNetwork, formatAmount, formatPhone, generateReference, reevitReducer, validatePhone };
package/dist/index.d.ts CHANGED
@@ -5,6 +5,8 @@
5
5
  type PaymentMethod = 'card' | 'mobile_money' | 'bank_transfer';
6
6
  type MobileMoneyNetwork = 'mtn' | 'vodafone' | 'airteltigo';
7
7
  type PSPType = 'paystack' | 'hubtel' | 'flutterwave' | 'stripe' | 'monnify' | 'mpesa';
8
+ /** Payment source type - indicates where the payment originated from */
9
+ type PaymentSource = 'payment_link' | 'api' | 'subscription';
8
10
  interface ReevitCheckoutConfig {
9
11
  /** Your Reevit public key (pk_live_xxx or pk_test_xxx) */
10
12
  publicKey: string;
@@ -22,6 +24,8 @@ interface ReevitCheckoutConfig {
22
24
  metadata?: Record<string, unknown>;
23
25
  /** Payment methods to display */
24
26
  paymentMethods?: PaymentMethod[];
27
+ /** Pre-created payment intent to use */
28
+ initialPaymentIntent?: PaymentIntent | any;
25
29
  }
26
30
  interface ReevitCheckoutCallbacks {
27
31
  /** Called when payment is successful */
@@ -53,6 +57,12 @@ interface PaymentResult {
53
57
  status: 'success' | 'pending';
54
58
  /** Any additional data from the PSP */
55
59
  metadata?: Record<string, unknown>;
60
+ /** Payment source type (payment_link, api, subscription) */
61
+ source?: PaymentSource;
62
+ /** ID of the source (payment link ID, subscription ID, etc.) */
63
+ sourceId?: string;
64
+ /** Human-readable description of the source (e.g., payment link name) */
65
+ sourceDescription?: string;
56
66
  }
57
67
  interface PaymentError {
58
68
  /** Error code */
@@ -103,6 +113,8 @@ interface PaymentIntent {
103
113
  id: string;
104
114
  /** Client secret for authenticating client-side operations */
105
115
  clientSecret: string;
116
+ /** PSP public key if available */
117
+ pspPublicKey?: string;
106
118
  /** Amount in smallest currency unit */
107
119
  amount: number;
108
120
  /** Currency code */
@@ -113,6 +125,8 @@ interface PaymentIntent {
113
125
  recommendedPsp: PSPType;
114
126
  /** Available payment methods for this intent */
115
127
  availableMethods: PaymentMethod[];
128
+ /** Reference provided or generated */
129
+ reference?: string;
116
130
  /** Connection ID (from Reevit backend) */
117
131
  connectionId?: string;
118
132
  /** Provider name (from backend) */
@@ -155,11 +169,13 @@ interface PaymentIntentResponse {
155
169
  provider: string;
156
170
  status: string;
157
171
  client_secret: string;
172
+ psp_public_key: string;
158
173
  amount: number;
159
174
  currency: string;
160
175
  fee_amount: number;
161
176
  fee_currency: string;
162
177
  net_amount: number;
178
+ reference?: string;
163
179
  }
164
180
  interface ConfirmPaymentRequest {
165
181
  provider_ref_id: string;
@@ -182,6 +198,12 @@ interface PaymentDetailResponse {
182
198
  metadata?: Record<string, unknown>;
183
199
  created_at: string;
184
200
  updated_at: string;
201
+ /** Payment source type (payment_link, api, subscription) */
202
+ source?: 'payment_link' | 'api' | 'subscription';
203
+ /** ID of the source (payment link ID, subscription ID, etc.) */
204
+ source_id?: string;
205
+ /** Human-readable description of the source (e.g., payment link name) */
206
+ source_description?: string;
185
207
  }
186
208
  interface APIErrorResponse {
187
209
  code: string;
@@ -229,6 +251,13 @@ declare class ReevitAPIClient {
229
251
  data?: PaymentDetailResponse;
230
252
  error?: PaymentError;
231
253
  }>;
254
+ /**
255
+ * Confirms a payment intent using client secret (public endpoint)
256
+ */
257
+ confirmPaymentIntent(paymentId: string, clientSecret: string): Promise<{
258
+ data?: PaymentDetailResponse;
259
+ error?: PaymentError;
260
+ }>;
232
261
  /**
233
262
  * Cancels a payment intent
234
263
  */
@@ -329,4 +358,4 @@ declare function createInitialState(): ReevitState;
329
358
  */
330
359
  declare function reevitReducer(state: ReevitState, action: ReevitAction): ReevitState;
331
360
 
332
- export { type APIErrorResponse, type CardFormData, type CheckoutState, type ConfirmPaymentRequest, type CreatePaymentIntentRequest, type MobileMoneyFormData, type MobileMoneyNetwork, type PSPConfig, type PSPType, type PaymentDetailResponse, type PaymentError, type PaymentIntent, type PaymentIntentResponse, type PaymentMethod, type PaymentResult, ReevitAPIClient, type ReevitAPIClientConfig, type ReevitAction, type ReevitCheckoutCallbacks, type ReevitCheckoutConfig, type ReevitState, type ReevitTheme, cn, createInitialState, createReevitClient, createThemeVariables, detectCountryFromCurrency, detectNetwork, formatAmount, formatPhone, generateReference, reevitReducer, validatePhone };
361
+ export { type APIErrorResponse, type CardFormData, type CheckoutState, type ConfirmPaymentRequest, type CreatePaymentIntentRequest, type MobileMoneyFormData, type MobileMoneyNetwork, type PSPConfig, type PSPType, type PaymentDetailResponse, type PaymentError, type PaymentIntent, type PaymentIntentResponse, type PaymentMethod, type PaymentResult, type PaymentSource, ReevitAPIClient, type ReevitAPIClientConfig, type ReevitAction, type ReevitCheckoutCallbacks, type ReevitCheckoutConfig, type ReevitState, type ReevitTheme, cn, createInitialState, createReevitClient, createThemeVariables, detectCountryFromCurrency, detectNetwork, formatAmount, formatPhone, generateReference, reevitReducer, validatePhone };
package/dist/index.js CHANGED
@@ -68,7 +68,7 @@ var ReevitAPIClient = class {
68
68
  "Content-Type": "application/json",
69
69
  "X-Reevit-Key": this.publicKey,
70
70
  "X-Reevit-Client": "@reevit/core",
71
- "X-Reevit-Client-Version": "0.2.3"
71
+ "X-Reevit-Client-Version": "0.3.2"
72
72
  };
73
73
  if (method === "POST" || method === "PATCH" || method === "PUT") {
74
74
  headers["Idempotency-Key"] = `${Date.now()}-${Math.random().toString(36).substring(2, 15)}`;
@@ -149,6 +149,12 @@ var ReevitAPIClient = class {
149
149
  async confirmPayment(paymentId) {
150
150
  return this.request("POST", `/v1/payments/${paymentId}/confirm`);
151
151
  }
152
+ /**
153
+ * Confirms a payment intent using client secret (public endpoint)
154
+ */
155
+ async confirmPaymentIntent(paymentId, clientSecret) {
156
+ return this.request("POST", `/v1/payments/${paymentId}/confirm-intent?client_secret=${clientSecret}`);
157
+ }
152
158
  /**
153
159
  * Cancels a payment intent
154
160
  */
@@ -301,7 +307,12 @@ function reevitReducer(state, action) {
301
307
  case "INIT_START":
302
308
  return { ...state, status: "loading", error: null };
303
309
  case "INIT_SUCCESS":
304
- return { ...state, status: "ready", paymentIntent: action.payload };
310
+ return {
311
+ ...state,
312
+ status: "ready",
313
+ paymentIntent: action.payload,
314
+ selectedMethod: action.payload.availableMethods?.length === 1 ? action.payload.availableMethods[0] : null
315
+ };
305
316
  case "INIT_ERROR":
306
317
  return { ...state, status: "failed", error: action.payload };
307
318
  case "SELECT_METHOD":
package/dist/index.js.map CHANGED
@@ -1 +1 @@
1
- {"version":3,"sources":["../src/index.ts","../src/api/client.ts","../src/utils.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 type ReevitAPIClientConfig,\n type CreatePaymentIntentRequest,\n type PaymentIntentResponse,\n type PaymentDetailResponse,\n type ConfirmPaymentRequest,\n type APIErrorResponse,\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 MobileMoneyFormData,\n CardFormData,\n PaymentIntent,\n PSPConfig,\n PSPType,\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// 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 } 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 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 connection_id: string;\n provider: string;\n status: string;\n client_secret: string;\n amount: number;\n currency: string;\n fee_amount: number;\n fee_currency: string;\n net_amount: number;\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}\n\nexport interface APIErrorResponse {\n code: string;\n message: string;\n details?: Record<string, string>;\n}\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 API_BASE_URL_SANDBOX = 'https://sandbox-api.reevit.io';\nconst DEFAULT_TIMEOUT = 30000; // 30 seconds\n\n/**\n * Determines if a public key is for sandbox mode\n */\nexport function isSandboxKey(publicKey: string): boolean {\n return publicKey.startsWith('pk_test_') ||\n publicKey.startsWith('pk_sandbox_') ||\n publicKey.startsWith('pfk_test_') ||\n publicKey.startsWith('pfk_sandbox_');\n}\n\n/**\n * Creates a PaymentError from an API error response\n */\nfunction createPaymentError(response: Response, errorData: APIErrorResponse): PaymentError {\n return {\n code: errorData.code || 'api_error',\n message: errorData.message || 'An unexpected error occurred',\n details: {\n httpStatus: response.status,\n ...errorData.details,\n },\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 || (isSandboxKey(config.publicKey)\n ? API_BASE_URL_SANDBOX\n : API_BASE_URL_PRODUCTION);\n this.timeout = config.timeout || DEFAULT_TIMEOUT;\n }\n\n /**\n * Makes an authenticated API request\n */\n private async request<T>(\n method: string,\n path: string,\n body?: unknown\n ): Promise<{ data?: T; error?: PaymentError }> {\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-Key': this.publicKey,\n 'X-Reevit-Client': '@reevit/core',\n 'X-Reevit-Client-Version': '0.2.3',\n };\n\n if (method === 'POST' || method === 'PATCH' || method === 'PUT') {\n headers['Idempotency-Key'] = `${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 },\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 },\n };\n }\n }\n\n return {\n error: {\n code: 'unknown_error',\n message: 'An unexpected error occurred. Please try again.',\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 ): Promise<{ data?: PaymentIntentResponse; error?: PaymentError }> {\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 method: this.mapPaymentMethod(method),\n country,\n customer_id: config.email || (config.metadata?.customerId as string | undefined),\n metadata,\n };\n\n return this.request<PaymentIntentResponse>('POST', '/v1/payments/intents', request);\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 * 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 * 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 * 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 vodafonePrefixes = ['20', '50'];\n const airteltigoPrefixes = ['26', '27', '56', '57'];\n\n if (mtnPrefixes.includes(prefix)) return 'mtn';\n if (vodafonePrefixes.includes(prefix)) return 'vodafone';\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 if (theme.primaryColor) {\n variables['--reevit-primary'] = theme.primaryColor;\n }\n if (theme.backgroundColor) {\n variables['--reevit-bg'] = theme.backgroundColor;\n }\n if (theme.textColor) {\n variables['--reevit-text'] = theme.textColor;\n }\n if (theme.borderRadius) {\n variables['--reevit-radius'] = theme.borderRadius;\n }\n if (theme.fontFamily) {\n variables['--reevit-font'] = theme.fontFamily;\n }\n\n return variables;\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 * 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 { ...state, status: 'ready', paymentIntent: action.payload };\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/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 type ReevitAPIClientConfig,\n type CreatePaymentIntentRequest,\n type PaymentIntentResponse,\n type PaymentDetailResponse,\n type ConfirmPaymentRequest,\n type APIErrorResponse,\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 MobileMoneyFormData,\n CardFormData,\n PaymentIntent,\n PSPConfig,\n PSPType,\n PaymentSource,\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// 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 } 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 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 connection_id: string;\n provider: string;\n status: string;\n client_secret: string;\n psp_public_key: string;\n amount: number;\n currency: string;\n fee_amount: number;\n fee_currency: string;\n net_amount: number;\n reference?: 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, string>;\n}\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 API_BASE_URL_SANDBOX = 'https://sandbox-api.reevit.io';\nconst DEFAULT_TIMEOUT = 30000; // 30 seconds\n\n/**\n * Determines if a public key is for sandbox mode\n */\nexport function isSandboxKey(publicKey: string): boolean {\n return publicKey.startsWith('pk_test_') ||\n publicKey.startsWith('pk_sandbox_') ||\n publicKey.startsWith('pfk_test_') ||\n publicKey.startsWith('pfk_sandbox_');\n}\n\n/**\n * Creates a PaymentError from an API error response\n */\nfunction createPaymentError(response: Response, errorData: APIErrorResponse): PaymentError {\n return {\n code: errorData.code || 'api_error',\n message: errorData.message || 'An unexpected error occurred',\n details: {\n httpStatus: response.status,\n ...errorData.details,\n },\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 || (isSandboxKey(config.publicKey)\n ? API_BASE_URL_SANDBOX\n : API_BASE_URL_PRODUCTION);\n this.timeout = config.timeout || DEFAULT_TIMEOUT;\n }\n\n /**\n * Makes an authenticated API request\n */\n private async request<T>(\n method: string,\n path: string,\n body?: unknown\n ): Promise<{ data?: T; error?: PaymentError }> {\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-Key': this.publicKey,\n 'X-Reevit-Client': '@reevit/core',\n 'X-Reevit-Client-Version': '0.3.2',\n };\n\n if (method === 'POST' || method === 'PATCH' || method === 'PUT') {\n headers['Idempotency-Key'] = `${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 },\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 },\n };\n }\n }\n\n return {\n error: {\n code: 'unknown_error',\n message: 'An unexpected error occurred. Please try again.',\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 ): Promise<{ data?: PaymentIntentResponse; error?: PaymentError }> {\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 method: this.mapPaymentMethod(method),\n country,\n customer_id: config.email || (config.metadata?.customerId as string | undefined),\n metadata,\n };\n\n return this.request<PaymentIntentResponse>('POST', '/v1/payments/intents', request);\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 * 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>('POST', `/v1/payments/${paymentId}/confirm-intent?client_secret=${clientSecret}`);\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 * 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 vodafonePrefixes = ['20', '50'];\n const airteltigoPrefixes = ['26', '27', '56', '57'];\n\n if (mtnPrefixes.includes(prefix)) return 'mtn';\n if (vodafonePrefixes.includes(prefix)) return 'vodafone';\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 if (theme.primaryColor) {\n variables['--reevit-primary'] = theme.primaryColor;\n }\n if (theme.backgroundColor) {\n variables['--reevit-bg'] = theme.backgroundColor;\n }\n if (theme.textColor) {\n variables['--reevit-text'] = theme.textColor;\n }\n if (theme.borderRadius) {\n variables['--reevit-radius'] = theme.borderRadius;\n }\n if (theme.fontFamily) {\n variables['--reevit-font'] = theme.fontFamily;\n }\n\n return variables;\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 * 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":[]}
package/dist/index.mjs CHANGED
@@ -31,7 +31,7 @@ var ReevitAPIClient = class {
31
31
  "Content-Type": "application/json",
32
32
  "X-Reevit-Key": this.publicKey,
33
33
  "X-Reevit-Client": "@reevit/core",
34
- "X-Reevit-Client-Version": "0.2.3"
34
+ "X-Reevit-Client-Version": "0.3.2"
35
35
  };
36
36
  if (method === "POST" || method === "PATCH" || method === "PUT") {
37
37
  headers["Idempotency-Key"] = `${Date.now()}-${Math.random().toString(36).substring(2, 15)}`;
@@ -112,6 +112,12 @@ var ReevitAPIClient = class {
112
112
  async confirmPayment(paymentId) {
113
113
  return this.request("POST", `/v1/payments/${paymentId}/confirm`);
114
114
  }
115
+ /**
116
+ * Confirms a payment intent using client secret (public endpoint)
117
+ */
118
+ async confirmPaymentIntent(paymentId, clientSecret) {
119
+ return this.request("POST", `/v1/payments/${paymentId}/confirm-intent?client_secret=${clientSecret}`);
120
+ }
115
121
  /**
116
122
  * Cancels a payment intent
117
123
  */
@@ -264,7 +270,12 @@ function reevitReducer(state, action) {
264
270
  case "INIT_START":
265
271
  return { ...state, status: "loading", error: null };
266
272
  case "INIT_SUCCESS":
267
- return { ...state, status: "ready", paymentIntent: action.payload };
273
+ return {
274
+ ...state,
275
+ status: "ready",
276
+ paymentIntent: action.payload,
277
+ selectedMethod: action.payload.availableMethods?.length === 1 ? action.payload.availableMethods[0] : null
278
+ };
268
279
  case "INIT_ERROR":
269
280
  return { ...state, status: "failed", error: action.payload };
270
281
  case "SELECT_METHOD":
@@ -1 +1 @@
1
- {"version":3,"sources":["../src/api/client.ts","../src/utils.ts","../src/state.ts"],"sourcesContent":["/**\n * Reevit API Client\n * \n * Handles communication with the Reevit backend for payment operations.\n */\n\nimport type { PaymentMethod, ReevitCheckoutConfig, PaymentError } 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 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 connection_id: string;\n provider: string;\n status: string;\n client_secret: string;\n amount: number;\n currency: string;\n fee_amount: number;\n fee_currency: string;\n net_amount: number;\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}\n\nexport interface APIErrorResponse {\n code: string;\n message: string;\n details?: Record<string, string>;\n}\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 API_BASE_URL_SANDBOX = 'https://sandbox-api.reevit.io';\nconst DEFAULT_TIMEOUT = 30000; // 30 seconds\n\n/**\n * Determines if a public key is for sandbox mode\n */\nexport function isSandboxKey(publicKey: string): boolean {\n return publicKey.startsWith('pk_test_') ||\n publicKey.startsWith('pk_sandbox_') ||\n publicKey.startsWith('pfk_test_') ||\n publicKey.startsWith('pfk_sandbox_');\n}\n\n/**\n * Creates a PaymentError from an API error response\n */\nfunction createPaymentError(response: Response, errorData: APIErrorResponse): PaymentError {\n return {\n code: errorData.code || 'api_error',\n message: errorData.message || 'An unexpected error occurred',\n details: {\n httpStatus: response.status,\n ...errorData.details,\n },\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 || (isSandboxKey(config.publicKey)\n ? API_BASE_URL_SANDBOX\n : API_BASE_URL_PRODUCTION);\n this.timeout = config.timeout || DEFAULT_TIMEOUT;\n }\n\n /**\n * Makes an authenticated API request\n */\n private async request<T>(\n method: string,\n path: string,\n body?: unknown\n ): Promise<{ data?: T; error?: PaymentError }> {\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-Key': this.publicKey,\n 'X-Reevit-Client': '@reevit/core',\n 'X-Reevit-Client-Version': '0.2.3',\n };\n\n if (method === 'POST' || method === 'PATCH' || method === 'PUT') {\n headers['Idempotency-Key'] = `${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 },\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 },\n };\n }\n }\n\n return {\n error: {\n code: 'unknown_error',\n message: 'An unexpected error occurred. Please try again.',\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 ): Promise<{ data?: PaymentIntentResponse; error?: PaymentError }> {\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 method: this.mapPaymentMethod(method),\n country,\n customer_id: config.email || (config.metadata?.customerId as string | undefined),\n metadata,\n };\n\n return this.request<PaymentIntentResponse>('POST', '/v1/payments/intents', request);\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 * 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 * 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 * 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 vodafonePrefixes = ['20', '50'];\n const airteltigoPrefixes = ['26', '27', '56', '57'];\n\n if (mtnPrefixes.includes(prefix)) return 'mtn';\n if (vodafonePrefixes.includes(prefix)) return 'vodafone';\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 if (theme.primaryColor) {\n variables['--reevit-primary'] = theme.primaryColor;\n }\n if (theme.backgroundColor) {\n variables['--reevit-bg'] = theme.backgroundColor;\n }\n if (theme.textColor) {\n variables['--reevit-text'] = theme.textColor;\n }\n if (theme.borderRadius) {\n variables['--reevit-radius'] = theme.borderRadius;\n }\n if (theme.fontFamily) {\n variables['--reevit-font'] = theme.fontFamily;\n }\n\n return variables;\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 * 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 { ...state, status: 'ready', paymentIntent: action.payload };\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/api/client.ts","../src/utils.ts","../src/state.ts"],"sourcesContent":["/**\n * Reevit API Client\n * \n * Handles communication with the Reevit backend for payment operations.\n */\n\nimport type { PaymentMethod, ReevitCheckoutConfig, PaymentError } 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 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 connection_id: string;\n provider: string;\n status: string;\n client_secret: string;\n psp_public_key: string;\n amount: number;\n currency: string;\n fee_amount: number;\n fee_currency: string;\n net_amount: number;\n reference?: 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, string>;\n}\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 API_BASE_URL_SANDBOX = 'https://sandbox-api.reevit.io';\nconst DEFAULT_TIMEOUT = 30000; // 30 seconds\n\n/**\n * Determines if a public key is for sandbox mode\n */\nexport function isSandboxKey(publicKey: string): boolean {\n return publicKey.startsWith('pk_test_') ||\n publicKey.startsWith('pk_sandbox_') ||\n publicKey.startsWith('pfk_test_') ||\n publicKey.startsWith('pfk_sandbox_');\n}\n\n/**\n * Creates a PaymentError from an API error response\n */\nfunction createPaymentError(response: Response, errorData: APIErrorResponse): PaymentError {\n return {\n code: errorData.code || 'api_error',\n message: errorData.message || 'An unexpected error occurred',\n details: {\n httpStatus: response.status,\n ...errorData.details,\n },\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 || (isSandboxKey(config.publicKey)\n ? API_BASE_URL_SANDBOX\n : API_BASE_URL_PRODUCTION);\n this.timeout = config.timeout || DEFAULT_TIMEOUT;\n }\n\n /**\n * Makes an authenticated API request\n */\n private async request<T>(\n method: string,\n path: string,\n body?: unknown\n ): Promise<{ data?: T; error?: PaymentError }> {\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-Key': this.publicKey,\n 'X-Reevit-Client': '@reevit/core',\n 'X-Reevit-Client-Version': '0.3.2',\n };\n\n if (method === 'POST' || method === 'PATCH' || method === 'PUT') {\n headers['Idempotency-Key'] = `${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 },\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 },\n };\n }\n }\n\n return {\n error: {\n code: 'unknown_error',\n message: 'An unexpected error occurred. Please try again.',\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 ): Promise<{ data?: PaymentIntentResponse; error?: PaymentError }> {\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 method: this.mapPaymentMethod(method),\n country,\n customer_id: config.email || (config.metadata?.customerId as string | undefined),\n metadata,\n };\n\n return this.request<PaymentIntentResponse>('POST', '/v1/payments/intents', request);\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 * 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>('POST', `/v1/payments/${paymentId}/confirm-intent?client_secret=${clientSecret}`);\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 * 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 vodafonePrefixes = ['20', '50'];\n const airteltigoPrefixes = ['26', '27', '56', '57'];\n\n if (mtnPrefixes.includes(prefix)) return 'mtn';\n if (vodafonePrefixes.includes(prefix)) return 'vodafone';\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 if (theme.primaryColor) {\n variables['--reevit-primary'] = theme.primaryColor;\n }\n if (theme.backgroundColor) {\n variables['--reevit-bg'] = theme.backgroundColor;\n }\n if (theme.textColor) {\n variables['--reevit-text'] = theme.textColor;\n }\n if (theme.borderRadius) {\n variables['--reevit-radius'] = theme.borderRadius;\n }\n if (theme.fontFamily) {\n variables['--reevit-font'] = theme.fontFamily;\n }\n\n return variables;\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 * 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":[]}
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@reevit/core",
3
- "version": "0.2.5",
3
+ "version": "0.3.3",
4
4
  "description": "Core utilities and API client for Reevit payment SDKs",
5
5
  "main": "./dist/index.js",
6
6
  "module": "./dist/index.mjs",