@nehorai/payments 0.1.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/LICENSE +21 -0
- package/dist/config/index.cjs +116 -0
- package/dist/config/index.cjs.map +1 -0
- package/dist/config/index.d.cts +125 -0
- package/dist/config/index.d.ts +125 -0
- package/dist/config/index.js +83 -0
- package/dist/config/index.js.map +1 -0
- package/dist/factory.cjs +807 -0
- package/dist/factory.cjs.map +1 -0
- package/dist/factory.d.cts +96 -0
- package/dist/factory.d.ts +96 -0
- package/dist/factory.js +777 -0
- package/dist/factory.js.map +1 -0
- package/dist/index.cjs +1341 -0
- package/dist/index.cjs.map +1 -0
- package/dist/index.d.cts +40 -0
- package/dist/index.d.ts +40 -0
- package/dist/index.js +1260 -0
- package/dist/index.js.map +1 -0
- package/dist/payment-orchestrator-CPaLmDM5.d.ts +404 -0
- package/dist/payment-orchestrator-Co_X6T_V.d.cts +404 -0
- package/dist/payment-types-68W-PlGg.d.cts +211 -0
- package/dist/payment-types-68W-PlGg.d.ts +211 -0
- package/dist/providers/interfaces/index.cjs +19 -0
- package/dist/providers/interfaces/index.cjs.map +1 -0
- package/dist/providers/interfaces/index.d.cts +80 -0
- package/dist/providers/interfaces/index.d.ts +80 -0
- package/dist/providers/interfaces/index.js +1 -0
- package/dist/providers/interfaces/index.js.map +1 -0
- package/dist/repository/interfaces/index.cjs +19 -0
- package/dist/repository/interfaces/index.cjs.map +1 -0
- package/dist/repository/interfaces/index.d.cts +556 -0
- package/dist/repository/interfaces/index.d.ts +556 -0
- package/dist/repository/interfaces/index.js +1 -0
- package/dist/repository/interfaces/index.js.map +1 -0
- package/dist/routing-engine.interface-DJzGXor9.d.cts +194 -0
- package/dist/routing-engine.interface-h9_GmQ4b.d.ts +194 -0
- package/dist/services/index.cjs +806 -0
- package/dist/services/index.cjs.map +1 -0
- package/dist/services/index.d.cts +75 -0
- package/dist/services/index.d.ts +75 -0
- package/dist/services/index.js +763 -0
- package/dist/services/index.js.map +1 -0
- package/dist/state-machine-Cu6_qKnv.d.cts +109 -0
- package/dist/state-machine-Cu6_qKnv.d.ts +109 -0
- package/dist/types/index.cjs +173 -0
- package/dist/types/index.cjs.map +1 -0
- package/dist/types/index.d.cts +127 -0
- package/dist/types/index.d.ts +127 -0
- package/dist/types/index.js +130 -0
- package/dist/types/index.js.map +1 -0
- package/dist/utils/index.cjs +167 -0
- package/dist/utils/index.cjs.map +1 -0
- package/dist/utils/index.d.cts +102 -0
- package/dist/utils/index.d.ts +102 -0
- package/dist/utils/index.js +127 -0
- package/dist/utils/index.js.map +1 -0
- package/package.json +68 -0
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"sources":["../src/factory.ts","../src/services/payment-orchestrator.ts","../src/config/payment-config.ts","../src/services/circuit-breaker-storage.interface.ts","../src/services/in-memory-storage.ts","../src/services/circuit-breaker.ts","../src/services/routing-engine.ts"],"sourcesContent":["/**\r\n * @nehorai/payments - Service Factory\r\n *\r\n * Factory functions for creating payment service instances.\r\n * Framework-agnostic - can be used in any TypeScript application.\r\n *\r\n * Unlike the Podcasto-specific factory, this does NOT import any\r\n * provider implementations. Providers are registered by the caller.\r\n *\r\n * Usage:\r\n * ```typescript\r\n * import { createPaymentServices } from '@nehorai/payments';\r\n * import { StripeProvider } from '@nehorai/payments-stripe';\r\n *\r\n * const providers = new Map();\r\n * providers.set('stripe', new StripeProvider(config));\r\n *\r\n * const services = createPaymentServices({\r\n * providers,\r\n * config: myConfig,\r\n * });\r\n * ```\r\n */\r\n\r\nimport type { PaymentProvider } from './types/index.js'\r\nimport type { IPaymentProvider, IWebhookHandler } from './providers/interfaces/index.js'\r\nimport type { IPaymentRepositories } from './repository/interfaces/index.js'\r\nimport { PaymentOrchestrator } from './services/payment-orchestrator.js'\r\nimport {\r\n RoutingEngine,\r\n createRoutingEngine,\r\n resetRoutingEngine,\r\n type RoutingRules,\r\n} from './services/routing-engine.js'\r\nimport {\r\n CircuitBreaker,\r\n createCircuitBreaker,\r\n resetCircuitBreaker,\r\n type CircuitBreakerConfig,\r\n} from './services/circuit-breaker.js'\r\nimport type { ICircuitBreakerStorage } from './services/circuit-breaker-storage.interface.js'\r\nimport { InMemoryCircuitBreakerStorage } from './services/in-memory-storage.js'\r\nimport {\r\n type PaymentConfig,\r\n createPartialConfig,\r\n} from './config/payment-config.js'\r\n\r\n// ============================================================================\r\n// Types\r\n// ============================================================================\r\n\r\n/**\r\n * Full configuration for creating payment services\r\n */\r\nexport interface PaymentServicesConfig {\r\n /** Provider instances - callers must create and pass these in */\r\n providers: Map<PaymentProvider, IPaymentProvider>\r\n /** Webhook handler instances (optional) */\r\n webhookHandlers?: Map<PaymentProvider, IWebhookHandler>\r\n /** Payment configuration */\r\n config?: PaymentConfig\r\n /** Circuit breaker configuration */\r\n circuitBreaker?: Partial<CircuitBreakerConfig>\r\n /** Circuit breaker storage implementation */\r\n circuitBreakerStorage?: ICircuitBreakerStorage\r\n /** Routing rules for intelligent provider selection */\r\n routingRules?: RoutingRules\r\n /** Repository implementations (for database operations) */\r\n repositories?: IPaymentRepositories\r\n}\r\n\r\n/**\r\n * Created payment services\r\n */\r\nexport interface PaymentServices {\r\n /** Main payment orchestrator */\r\n orchestrator: PaymentOrchestrator\r\n /** Provider routing engine */\r\n routingEngine: RoutingEngine\r\n /** Circuit breaker for resilience */\r\n circuitBreaker: CircuitBreaker\r\n /** Map of available providers */\r\n providers: Map<PaymentProvider, IPaymentProvider>\r\n /** Map of webhook handlers */\r\n webhookHandlers: Map<PaymentProvider, IWebhookHandler>\r\n /** Current configuration */\r\n config: PaymentConfig\r\n}\r\n\r\n// ============================================================================\r\n// Factory Functions\r\n// ============================================================================\r\n\r\n/**\r\n * Create all payment services.\r\n *\r\n * Providers are passed in by the caller (no auto-discovery).\r\n * This factory only wires up the core services.\r\n *\r\n * @param options - Configuration options including provider instances\r\n * @returns PaymentServices instance with all components\r\n */\r\nexport function createPaymentServices(options: PaymentServicesConfig): PaymentServices {\r\n const config = options.config ?? createPartialConfig({})\r\n const providers = options.providers\r\n const webhookHandlers = options.webhookHandlers ?? new Map<PaymentProvider, IWebhookHandler>()\r\n\r\n if (providers.size === 0) {\r\n throw new Error('No payment providers provided. Pass at least one provider instance.')\r\n }\r\n\r\n // Create circuit breaker storage (use injected or default to in-memory)\r\n const circuitBreakerStorage = options.circuitBreakerStorage ?? new InMemoryCircuitBreakerStorage()\r\n\r\n // Create circuit breaker with storage\r\n const circuitBreaker = createCircuitBreaker({\r\n storage: circuitBreakerStorage,\r\n config: options.circuitBreaker,\r\n })\r\n\r\n // Create routing engine with injected config, circuit breaker, and routing rules\r\n const routingEngine = createRoutingEngine({\r\n config,\r\n circuitBreaker,\r\n routingRules: options.routingRules,\r\n })\r\n\r\n // Create orchestrator with all dependencies\r\n const orchestrator = new PaymentOrchestrator({\r\n providers,\r\n routingEngine,\r\n circuitBreaker,\r\n })\r\n\r\n return {\r\n orchestrator,\r\n routingEngine,\r\n circuitBreaker,\r\n providers,\r\n webhookHandlers,\r\n config,\r\n }\r\n}\r\n\r\n/**\r\n * Register a provider and optional webhook handler to existing services.\r\n *\r\n * Returns a new PaymentServices with the provider added.\r\n * The original services object is not mutated.\r\n */\r\nexport function registerProvider(\r\n services: PaymentServices,\r\n name: PaymentProvider,\r\n provider: IPaymentProvider,\r\n webhookHandler?: IWebhookHandler\r\n): PaymentServices {\r\n const newProviders = new Map(services.providers)\r\n newProviders.set(name, provider)\r\n\r\n const newWebhookHandlers = new Map(services.webhookHandlers)\r\n if (webhookHandler) {\r\n newWebhookHandlers.set(name, webhookHandler)\r\n }\r\n\r\n // Re-create orchestrator with updated providers\r\n const orchestrator = new PaymentOrchestrator({\r\n providers: newProviders,\r\n routingEngine: services.routingEngine,\r\n circuitBreaker: services.circuitBreaker,\r\n })\r\n\r\n return {\r\n ...services,\r\n orchestrator,\r\n providers: newProviders,\r\n webhookHandlers: newWebhookHandlers,\r\n }\r\n}\r\n\r\n// ============================================================================\r\n// Singleton Pattern\r\n// ============================================================================\r\n\r\nlet servicesInstance: PaymentServices | null = null\r\n\r\n/**\r\n * Get or create singleton PaymentOS services instance\r\n */\r\nexport function getPaymentServices(config?: PaymentServicesConfig): PaymentServices {\r\n if (!servicesInstance) {\r\n if (!config) {\r\n throw new Error('PaymentServices not initialized. Call with config on first use.')\r\n }\r\n servicesInstance = createPaymentServices(config)\r\n }\r\n return servicesInstance\r\n}\r\n\r\n/**\r\n * Reset singleton instance (useful for testing)\r\n */\r\nexport function resetPaymentServices(): void {\r\n servicesInstance = null\r\n resetCircuitBreaker()\r\n resetRoutingEngine()\r\n}\r\n","/**\r\n * @nehorai/payments - Payment Orchestrator Service\r\n *\r\n * Main entry point for payment operations. Coordinates between:\r\n * - Routing Engine (provider selection)\r\n * - Payment Providers (actual processing)\r\n * - Circuit Breaker (resilience)\r\n *\r\n * Supports full dependency injection for:\r\n * - Provider instances\r\n * - Routing engine\r\n * - Circuit breaker\r\n */\r\n\r\nimport { randomUUID } from 'crypto'\r\nimport type { PaymentProvider, PaymentAmount, TransactionStatus, PaymentMetadata } from '../types/index.js'\r\nimport type { IPaymentProvider, RoutingDecision } from '../providers/interfaces/index.js'\r\nimport { RoutingEngine, getRoutingEngine } from './routing-engine.js'\r\nimport { CircuitBreaker, getCircuitBreaker } from './circuit-breaker.js'\r\n\r\n// ============================================================================\r\n// Types\r\n// ============================================================================\r\n\r\nexport interface InitiatePaymentParams {\r\n userId: string\r\n amount: PaymentAmount\r\n transactionType: 'one_time_purchase' | 'subscription_initial' | 'subscription_renewal'\r\n description?: string\r\n metadata?: PaymentMetadata\r\n preferredProvider?: PaymentProvider\r\n cardBin?: string\r\n returnUrl: string\r\n /** If true, auto-capture immediately (no J5 hold) */\r\n autoCapture?: boolean\r\n}\r\n\r\nexport interface PaymentInitiationResult {\r\n success: boolean\r\n transactionId: string\r\n internalPaymentId: string\r\n provider: PaymentProvider\r\n clientSecret?: string\r\n redirectUrl?: string\r\n error?: string\r\n}\r\n\r\nexport interface ConfirmPaymentParams {\r\n transactionId: string\r\n internalPaymentId: string\r\n providerIntentId: string\r\n provider: PaymentProvider\r\n}\r\n\r\nexport interface PaymentConfirmationResult {\r\n success: boolean\r\n transactionId: string\r\n status: TransactionStatus\r\n error?: string\r\n}\r\n\r\nexport interface CapturePaymentParams {\r\n transactionId: string\r\n providerIntentId: string\r\n provider: PaymentProvider\r\n amount?: PaymentAmount\r\n}\r\n\r\nexport interface PaymentCaptureResult {\r\n success: boolean\r\n status: TransactionStatus\r\n capturedAmount?: PaymentAmount\r\n error?: string\r\n}\r\n\r\n/**\r\n * Payment orchestrator dependencies (for dependency injection)\r\n */\r\nexport interface PaymentOrchestratorDeps {\r\n /** Provider instances - required */\r\n providers: Map<PaymentProvider, IPaymentProvider>\r\n /** Routing engine (optional, defaults to singleton) */\r\n routingEngine?: RoutingEngine\r\n /** Circuit breaker (optional, defaults to singleton) */\r\n circuitBreaker?: CircuitBreaker\r\n}\r\n\r\n// ============================================================================\r\n// Orchestrator Service\r\n// ============================================================================\r\n\r\n/**\r\n * Payment Orchestrator\r\n *\r\n * Standalone service for payment orchestration.\r\n * Supports full dependency injection for testing and customization.\r\n */\r\nexport class PaymentOrchestrator {\r\n private providers: Map<PaymentProvider, IPaymentProvider>\r\n private routingEngine: RoutingEngine\r\n private circuitBreaker: CircuitBreaker\r\n\r\n constructor(deps: PaymentOrchestratorDeps) {\r\n this.providers = deps.providers\r\n this.routingEngine = deps.routingEngine ?? getRoutingEngine()\r\n this.circuitBreaker = deps.circuitBreaker ?? getCircuitBreaker()\r\n }\r\n\r\n /**\r\n * Initiate a new payment\r\n */\r\n async initiatePayment(params: InitiatePaymentParams): Promise<PaymentInitiationResult> {\r\n const internalPaymentId = `pay_${randomUUID()}`\r\n const idempotencyKey = `idem_${randomUUID()}`\r\n\r\n try {\r\n const routing = await this.routingEngine.route({\r\n userId: params.userId,\r\n amount: params.amount,\r\n cardBin: params.cardBin,\r\n preferredProvider: params.preferredProvider,\r\n isRecurring: params.transactionType !== 'one_time_purchase',\r\n })\r\n\r\n const provider = this.getProvider(routing.provider)\r\n if (!provider) {\r\n return this.tryFailover(params, routing, internalPaymentId)\r\n }\r\n\r\n if (!(await this.circuitBreaker.canExecute(routing.provider))) {\r\n return this.tryFailover(params, routing, internalPaymentId)\r\n }\r\n\r\n const result = await provider.createPaymentIntent({\r\n amount: params.amount,\r\n userId: params.userId,\r\n idempotencyKey,\r\n description: params.description,\r\n metadata: params.metadata,\r\n returnUrl: params.returnUrl,\r\n captureMethod: params.autoCapture ? 'automatic' : 'manual',\r\n })\r\n\r\n if (!result.success) {\r\n await this.circuitBreaker.recordFailure(routing.provider)\r\n return this.tryFailover(params, routing, internalPaymentId)\r\n }\r\n\r\n await this.circuitBreaker.recordSuccess(routing.provider)\r\n\r\n return {\r\n success: true,\r\n transactionId: result.providerIntentId!,\r\n internalPaymentId,\r\n provider: routing.provider,\r\n clientSecret: result.clientSecret,\r\n redirectUrl: result.redirectUrl,\r\n }\r\n } catch (error) {\r\n return {\r\n success: false,\r\n transactionId: '',\r\n internalPaymentId,\r\n provider: 'unknown',\r\n error: error instanceof Error ? error.message : 'Unknown error',\r\n }\r\n }\r\n }\r\n\r\n /**\r\n * Confirm a payment after user authorization\r\n */\r\n async confirmPayment(params: ConfirmPaymentParams): Promise<PaymentConfirmationResult> {\r\n const provider = this.getProvider(params.provider)\r\n if (!provider) {\r\n return {\r\n success: false,\r\n transactionId: params.transactionId,\r\n status: 'failed',\r\n error: `Provider ${params.provider} not available`,\r\n }\r\n }\r\n\r\n const result = await provider.authorize({\r\n providerIntentId: params.providerIntentId,\r\n idempotencyKey: `auth_${params.internalPaymentId}`,\r\n })\r\n\r\n if (!result.success) {\r\n return {\r\n success: false,\r\n transactionId: params.transactionId,\r\n status: 'failed',\r\n error: result.error,\r\n }\r\n }\r\n\r\n return {\r\n success: true,\r\n transactionId: params.transactionId,\r\n status: (result.status as TransactionStatus) ?? 'authorized',\r\n }\r\n }\r\n\r\n /**\r\n * Capture an authorized payment (J5 completion)\r\n */\r\n async capturePayment(params: CapturePaymentParams): Promise<PaymentCaptureResult> {\r\n const provider = this.getProvider(params.provider)\r\n if (!provider) {\r\n return {\r\n success: false,\r\n status: 'failed',\r\n error: `Provider ${params.provider} not available`,\r\n }\r\n }\r\n\r\n const result = await provider.capture({\r\n providerIntentId: params.providerIntentId,\r\n authorizationCode: params.providerIntentId,\r\n amount: params.amount,\r\n idempotencyKey: `cap_${params.transactionId}`,\r\n })\r\n\r\n if (!result.success) {\r\n return {\r\n success: false,\r\n status: 'failed',\r\n error: result.error,\r\n }\r\n }\r\n\r\n return {\r\n success: true,\r\n status: 'captured',\r\n capturedAmount: result.capturedAmount,\r\n }\r\n }\r\n\r\n /**\r\n * Get the routing engine (for testing/debugging)\r\n */\r\n getRoutingEngine(): RoutingEngine {\r\n return this.routingEngine\r\n }\r\n\r\n /**\r\n * Get the circuit breaker (for testing/debugging)\r\n */\r\n getCircuitBreaker(): CircuitBreaker {\r\n return this.circuitBreaker\r\n }\r\n\r\n /**\r\n * Get available providers (for testing/debugging)\r\n */\r\n getProviders(): Map<PaymentProvider, IPaymentProvider> {\r\n return new Map(this.providers)\r\n }\r\n\r\n // ==========================================================================\r\n // Private Methods\r\n // ==========================================================================\r\n\r\n private getProvider(name: PaymentProvider): IPaymentProvider | undefined {\r\n return this.providers.get(name)\r\n }\r\n\r\n private async tryFailover(\r\n params: InitiatePaymentParams,\r\n routing: RoutingDecision,\r\n internalPaymentId: string\r\n ): Promise<PaymentInitiationResult> {\r\n for (const fallback of routing.fallbackProviders) {\r\n const provider = this.getProvider(fallback)\r\n if (!provider) continue\r\n\r\n if (!(await this.circuitBreaker.canExecute(fallback))) continue\r\n\r\n const result = await provider.createPaymentIntent({\r\n amount: params.amount,\r\n userId: params.userId,\r\n idempotencyKey: `idem_${randomUUID()}`,\r\n description: params.description,\r\n metadata: params.metadata,\r\n returnUrl: params.returnUrl,\r\n captureMethod: params.autoCapture ? 'automatic' : 'manual',\r\n })\r\n\r\n if (result.success) {\r\n await this.circuitBreaker.recordSuccess(fallback)\r\n return {\r\n success: true,\r\n transactionId: result.providerIntentId!,\r\n internalPaymentId,\r\n provider: fallback,\r\n clientSecret: result.clientSecret,\r\n }\r\n }\r\n\r\n await this.circuitBreaker.recordFailure(fallback)\r\n }\r\n\r\n return {\r\n success: false,\r\n transactionId: '',\r\n internalPaymentId,\r\n provider: routing.provider,\r\n error: 'All payment providers failed',\r\n }\r\n }\r\n}\r\n\r\n// ============================================================================\r\n// Factory Function\r\n// ============================================================================\r\n\r\n/**\r\n * Create a payment orchestrator with custom dependencies\r\n */\r\nexport function createPaymentOrchestrator(deps: PaymentOrchestratorDeps): PaymentOrchestrator {\r\n return new PaymentOrchestrator(deps)\r\n}\r\n","/**\r\n * @nehorai/payments - Injectable Configuration\r\n *\r\n * Provides a framework-agnostic configuration interface that can be\r\n * populated from any source (env vars, secrets manager, database, etc.).\r\n *\r\n * Usage:\r\n * ```typescript\r\n * // Option 1: Create from custom source\r\n * const config = createConfig({\r\n * providers: {\r\n * stripe: { secretKey: 'sk_test_...' },\r\n * },\r\n * environment: 'sandbox',\r\n * defaultCurrency: 'USD',\r\n * });\r\n *\r\n * // Option 2: Create from environment variables\r\n * const config = createConfigFromEnv({\r\n * stripeSecretKey: 'STRIPE_SECRET_KEY',\r\n * stripePublishableKey: 'STRIPE_PUBLISHABLE_KEY',\r\n * stripeWebhookSecret: 'STRIPE_WEBHOOK_SECRET',\r\n * environment: 'PAYMENT_ENVIRONMENT',\r\n * defaultCurrency: 'DEFAULT_CURRENCY',\r\n * });\r\n * ```\r\n */\r\n\r\n// ============================================================================\r\n// Provider Configuration Types\r\n// ============================================================================\r\n\r\n/**\r\n * Generic provider configuration - key-value pairs\r\n * Providers can have any config shape.\r\n */\r\nexport interface ProviderConfig {\r\n /** Provider-specific configuration values */\r\n [key: string]: unknown\r\n}\r\n\r\n/**\r\n * Provider configurations map.\r\n * Keys are provider names, values are provider-specific config.\r\n */\r\nexport interface ProvidersConfig {\r\n [providerName: string]: ProviderConfig | undefined\r\n}\r\n\r\n/**\r\n * Main payment configuration interface\r\n *\r\n * This is the injectable configuration that can be provided from any source.\r\n */\r\nexport interface PaymentConfig {\r\n /** Provider-specific configurations */\r\n providers: ProvidersConfig\r\n /** Environment mode */\r\n environment: 'sandbox' | 'production'\r\n /** Default currency for transactions */\r\n defaultCurrency: string\r\n}\r\n\r\n/**\r\n * Provider availability derived from configuration\r\n */\r\nexport interface ConfiguredProviderAvailability {\r\n [providerName: string]: boolean\r\n}\r\n\r\n// ============================================================================\r\n// Environment Variable Mapping\r\n// ============================================================================\r\n\r\n/**\r\n * Mapping of provider config keys to environment variable names.\r\n * Used by createConfigFromEnv().\r\n */\r\nexport interface EnvVarMapping {\r\n [envVarKey: string]: string\r\n}\r\n\r\n/**\r\n * Provider env var mapping: maps config keys to env var names\r\n */\r\nexport interface ProviderEnvMapping {\r\n providerName: string\r\n /** Map of config key -> env var name. Provider is considered configured if any key has a value. */\r\n keys: EnvVarMapping\r\n /** Keys that are all required for the provider to be considered configured */\r\n requiredKeys?: string[]\r\n}\r\n\r\n/**\r\n * Full env mapping configuration\r\n */\r\nexport interface EnvMappingConfig {\r\n providers: ProviderEnvMapping[]\r\n environmentVar?: string\r\n defaultCurrencyVar?: string\r\n}\r\n\r\n// ============================================================================\r\n// Configuration Factory Functions\r\n// ============================================================================\r\n\r\n/**\r\n * Create payment configuration from environment variables\r\n *\r\n * @param mapping - Mapping of config keys to env var names\r\n * @returns PaymentConfig populated from process.env\r\n */\r\nexport function createConfigFromEnv(mapping?: EnvMappingConfig): PaymentConfig {\r\n if (!mapping) {\r\n return createPartialConfig({})\r\n }\r\n\r\n const providers: ProvidersConfig = {}\r\n\r\n for (const providerMapping of mapping.providers) {\r\n const config: ProviderConfig = {}\r\n let hasValue = false\r\n\r\n for (const [configKey, envVarName] of Object.entries(providerMapping.keys)) {\r\n const value = process.env[envVarName]\r\n if (value?.trim()) {\r\n config[configKey] = value\r\n hasValue = true\r\n }\r\n }\r\n\r\n // Check if required keys are all present\r\n if (providerMapping.requiredKeys) {\r\n const allRequired = providerMapping.requiredKeys.every(\r\n (key) => config[key] && typeof config[key] === 'string' && (config[key] as string).trim()\r\n )\r\n if (allRequired) {\r\n providers[providerMapping.providerName] = config\r\n }\r\n } else if (hasValue) {\r\n providers[providerMapping.providerName] = config\r\n }\r\n }\r\n\r\n const environment = (process.env[mapping.environmentVar ?? 'PAYMENT_ENVIRONMENT'] as 'sandbox' | 'production') ?? 'sandbox'\r\n const defaultCurrency = process.env[mapping.defaultCurrencyVar ?? 'DEFAULT_CURRENCY'] ?? 'USD'\r\n\r\n return {\r\n providers,\r\n environment,\r\n defaultCurrency,\r\n }\r\n}\r\n\r\n/**\r\n * Create payment configuration from a custom source\r\n *\r\n * @param config - Custom configuration object\r\n * @returns Validated PaymentConfig\r\n */\r\nexport function createConfig(config: PaymentConfig): PaymentConfig {\r\n validateConfig(config)\r\n return {\r\n providers: { ...config.providers },\r\n environment: config.environment,\r\n defaultCurrency: config.defaultCurrency,\r\n }\r\n}\r\n\r\n/**\r\n * Create a partial configuration (useful for testing)\r\n *\r\n * @param partial - Partial configuration\r\n * @returns Full configuration with defaults\r\n */\r\nexport function createPartialConfig(partial: Partial<PaymentConfig>): PaymentConfig {\r\n return {\r\n providers: partial.providers ?? {},\r\n environment: partial.environment ?? 'sandbox',\r\n defaultCurrency: partial.defaultCurrency ?? 'USD',\r\n }\r\n}\r\n\r\n// ============================================================================\r\n// Configuration Utilities\r\n// ============================================================================\r\n\r\n/**\r\n * Check which providers are configured\r\n */\r\nexport function getConfiguredProviders(config: PaymentConfig): ConfiguredProviderAvailability {\r\n const availability: ConfiguredProviderAvailability = {}\r\n\r\n for (const [name, providerConfig] of Object.entries(config.providers)) {\r\n availability[name] = providerConfig !== undefined && Object.keys(providerConfig).length > 0\r\n }\r\n\r\n return availability\r\n}\r\n\r\n/**\r\n * Get list of configured provider names\r\n */\r\nexport function getConfiguredProviderList(config: PaymentConfig): string[] {\r\n const availability = getConfiguredProviders(config)\r\n return Object.entries(availability)\r\n .filter(([, isAvailable]) => isAvailable)\r\n .map(([name]) => name)\r\n}\r\n\r\n/**\r\n * Check if configuration is valid for production\r\n */\r\nexport function isProductionReady(config: PaymentConfig): boolean {\r\n const providers = getConfiguredProviderList(config)\r\n return config.environment === 'production' && providers.length > 0\r\n}\r\n\r\n/**\r\n * Validate configuration has at least one provider\r\n */\r\nexport function validateConfig(config: PaymentConfig): void {\r\n const providers = getConfiguredProviderList(config)\r\n\r\n if (providers.length === 0) {\r\n throw new Error(\r\n 'Payment configuration error: At least one payment provider must be configured'\r\n )\r\n }\r\n}\r\n","/**\r\n * @nehorai/payments - Circuit Breaker Storage Interface\r\n *\r\n * Abstracts storage for circuit breaker state, enabling:\r\n * - In-memory storage (default, for single-instance deployments)\r\n * - Database storage (for multi-instance/serverless deployments)\r\n * - Redis storage (for high-performance distributed systems)\r\n */\r\n\r\nimport type { PaymentProvider } from '../types/index.js'\r\n\r\n// ============================================================================\r\n// Circuit Breaker State (Storage-Agnostic)\r\n// ============================================================================\r\n\r\n/**\r\n * Circuit breaker states\r\n */\r\nexport type StoredCircuitState = 'closed' | 'open' | 'half_open'\r\n\r\n/**\r\n * Circuit breaker state record\r\n *\r\n * This is the state that gets persisted by storage implementations.\r\n */\r\nexport interface CircuitBreakerStateRecord {\r\n provider: PaymentProvider\r\n state: StoredCircuitState\r\n failureCount: number\r\n successCount: number\r\n lastFailure: Date | null\r\n openedAt: Date | null\r\n nextRetryAt: Date | null\r\n}\r\n\r\n// ============================================================================\r\n// Storage Interface\r\n// ============================================================================\r\n\r\n/**\r\n * Storage interface for circuit breaker state\r\n *\r\n * Implement this interface to provide custom storage backends:\r\n * - InMemoryCircuitBreakerStorage (default)\r\n * - Database-backed storage (uses provider_health table)\r\n * - Redis-backed storage (for high-performance needs)\r\n */\r\nexport interface ICircuitBreakerStorage {\r\n getState(provider: PaymentProvider): Promise<CircuitBreakerStateRecord | null>\r\n\r\n setState(provider: PaymentProvider, state: CircuitBreakerStateRecord): Promise<void>\r\n\r\n getAllStates(): Promise<Map<PaymentProvider, CircuitBreakerStateRecord>>\r\n\r\n deleteState(provider: PaymentProvider): Promise<void>\r\n\r\n getOpenCircuits(): Promise<PaymentProvider[]>\r\n\r\n isHealthy(): Promise<boolean>\r\n}\r\n\r\n// ============================================================================\r\n// Default State Factory\r\n// ============================================================================\r\n\r\n/**\r\n * Create default (closed) state for a provider\r\n */\r\nexport function createDefaultState(provider: PaymentProvider): CircuitBreakerStateRecord {\r\n return {\r\n provider,\r\n state: 'closed',\r\n failureCount: 0,\r\n successCount: 0,\r\n lastFailure: null,\r\n openedAt: null,\r\n nextRetryAt: null,\r\n }\r\n}\r\n\r\n/**\r\n * Check if state indicates circuit is open\r\n */\r\nexport function isCircuitOpen(state: CircuitBreakerStateRecord | null): boolean {\r\n return state?.state === 'open'\r\n}\r\n\r\n/**\r\n * Check if circuit should attempt half-open transition\r\n */\r\nexport function shouldAttemptHalfOpen(state: CircuitBreakerStateRecord | null): boolean {\r\n if (!state || state.state !== 'open') return false\r\n if (!state.nextRetryAt) return false\r\n\r\n return Date.now() >= state.nextRetryAt.getTime()\r\n}\r\n","/**\r\n * @nehorai/payments - In-Memory Circuit Breaker Storage\r\n *\r\n * Default storage implementation using a Map for circuit breaker state.\r\n * Suitable for single-instance deployments and development.\r\n *\r\n * Limitations:\r\n * - State is lost on process restart\r\n * - Not shared across multiple instances (not serverless-friendly)\r\n */\r\n\r\nimport type { PaymentProvider } from '../types/index.js'\r\nimport type {\r\n ICircuitBreakerStorage,\r\n CircuitBreakerStateRecord,\r\n} from './circuit-breaker-storage.interface.js'\r\nimport { createDefaultState } from './circuit-breaker-storage.interface.js'\r\n\r\n// ============================================================================\r\n// In-Memory Storage Implementation\r\n// ============================================================================\r\n\r\n/**\r\n * In-memory implementation of ICircuitBreakerStorage\r\n *\r\n * Uses a JavaScript Map for fast in-memory state storage.\r\n * This is the default storage and maintains backward compatibility.\r\n */\r\nexport class InMemoryCircuitBreakerStorage implements ICircuitBreakerStorage {\r\n protected internalStates: Map<PaymentProvider, CircuitBreakerStateRecord>\r\n\r\n constructor() {\r\n this.internalStates = new Map()\r\n }\r\n\r\n async getState(provider: PaymentProvider): Promise<CircuitBreakerStateRecord | null> {\r\n return this.internalStates.get(provider) ?? null\r\n }\r\n\r\n async setState(provider: PaymentProvider, state: CircuitBreakerStateRecord): Promise<void> {\r\n this.internalStates.set(provider, { ...state })\r\n }\r\n\r\n async getAllStates(): Promise<Map<PaymentProvider, CircuitBreakerStateRecord>> {\r\n return new Map(this.internalStates)\r\n }\r\n\r\n async deleteState(provider: PaymentProvider): Promise<void> {\r\n this.internalStates.delete(provider)\r\n }\r\n\r\n async getOpenCircuits(): Promise<PaymentProvider[]> {\r\n const open: PaymentProvider[] = []\r\n for (const [provider, state] of this.internalStates) {\r\n if (state.state === 'open') {\r\n open.push(provider)\r\n }\r\n }\r\n return open\r\n }\r\n\r\n async isHealthy(): Promise<boolean> {\r\n return true\r\n }\r\n\r\n /**\r\n * Clear all stored states (useful for testing)\r\n */\r\n clear(): void {\r\n this.internalStates.clear()\r\n }\r\n\r\n /**\r\n * Get current state count (useful for testing/debugging)\r\n */\r\n get size(): number {\r\n return this.internalStates.size\r\n }\r\n\r\n /**\r\n * Synchronous state access (for backward compatibility with CircuitBreaker.isOpen)\r\n *\r\n * Note: Only available on InMemoryCircuitBreakerStorage.\r\n * Database-backed storage cannot provide sync access.\r\n */\r\n getStateSync(provider: PaymentProvider): CircuitBreakerStateRecord | null {\r\n return this.internalStates.get(provider) ?? null\r\n }\r\n}\r\n\r\n// ============================================================================\r\n// Singleton Factory\r\n// ============================================================================\r\n\r\nlet defaultStorage: InMemoryCircuitBreakerStorage | null = null\r\n\r\n/**\r\n * Get or create the default in-memory storage instance\r\n */\r\nexport function getInMemoryStorage(): InMemoryCircuitBreakerStorage {\r\n if (!defaultStorage) {\r\n defaultStorage = new InMemoryCircuitBreakerStorage()\r\n }\r\n return defaultStorage\r\n}\r\n\r\n/**\r\n * Reset the default storage instance (useful for testing)\r\n */\r\nexport function resetInMemoryStorage(): void {\r\n if (defaultStorage) {\r\n defaultStorage.clear()\r\n }\r\n defaultStorage = null\r\n}\r\n\r\n// ============================================================================\r\n// Migration Helper\r\n// ============================================================================\r\n\r\n/**\r\n * Legacy state structure (for migration from old circuit breaker)\r\n */\r\nexport interface LegacyCircuitState {\r\n provider: PaymentProvider\r\n state: 'closed' | 'open' | 'half_open'\r\n failureCount: number\r\n successCount: number\r\n lastFailure: Date | null\r\n openedAt: Date | null\r\n nextRetryAt: Date | null\r\n}\r\n\r\n/**\r\n * Migrate from legacy Map storage to ICircuitBreakerStorage\r\n */\r\nexport async function migrateFromLegacyMap(\r\n legacyStates: Map<PaymentProvider, LegacyCircuitState>\r\n): Promise<InMemoryCircuitBreakerStorage> {\r\n const storage = new InMemoryCircuitBreakerStorage()\r\n\r\n for (const [provider, state] of legacyStates) {\r\n const record: CircuitBreakerStateRecord = {\r\n provider: state.provider,\r\n state: state.state,\r\n failureCount: state.failureCount,\r\n successCount: state.successCount,\r\n lastFailure: state.lastFailure,\r\n openedAt: state.openedAt,\r\n nextRetryAt: state.nextRetryAt,\r\n }\r\n await storage.setState(provider, record)\r\n }\r\n\r\n return storage\r\n}\r\n","/**\r\n * @nehorai/payments - Circuit Breaker Service\r\n *\r\n * Implements the circuit breaker pattern for payment provider resilience.\r\n * Prevents cascading failures by temporarily disabling unhealthy providers.\r\n *\r\n * States:\r\n * - CLOSED: Normal operation, all requests pass through\r\n * - OPEN: Provider disabled, all requests fail fast\r\n * - HALF_OPEN: Testing if provider recovered\r\n */\r\n\r\nimport type { PaymentProvider } from '../types/index.js'\r\nimport type {\r\n ICircuitBreakerStorage,\r\n CircuitBreakerStateRecord,\r\n} from './circuit-breaker-storage.interface.js'\r\nimport { createDefaultState } from './circuit-breaker-storage.interface.js'\r\nimport { InMemoryCircuitBreakerStorage } from './in-memory-storage.js'\r\n\r\n// ============================================================================\r\n// Configuration\r\n// ============================================================================\r\n\r\nexport interface CircuitBreakerConfig {\r\n /** Number of failures before opening circuit */\r\n failureThreshold: number\r\n /** Time in ms before attempting to close circuit */\r\n resetTimeoutMs: number\r\n /** Max requests allowed in half-open state */\r\n halfOpenMaxRequests: number\r\n}\r\n\r\nconst DEFAULT_CONFIG: CircuitBreakerConfig = {\r\n failureThreshold: 5,\r\n resetTimeoutMs: 60000, // 1 minute\r\n halfOpenMaxRequests: 3,\r\n}\r\n\r\n// ============================================================================\r\n// Types\r\n// ============================================================================\r\n\r\nexport type CircuitState = 'closed' | 'open' | 'half_open'\r\n\r\nexport interface CircuitBreakerState {\r\n provider: PaymentProvider\r\n state: CircuitState\r\n failureCount: number\r\n successCount: number\r\n lastFailure: Date | null\r\n openedAt: Date | null\r\n nextRetryAt: Date | null\r\n}\r\n\r\n/**\r\n * Circuit breaker dependencies (for dependency injection)\r\n */\r\nexport interface CircuitBreakerDeps {\r\n /** Storage implementation (optional, defaults to in-memory) */\r\n storage?: ICircuitBreakerStorage\r\n /** Configuration overrides */\r\n config?: Partial<CircuitBreakerConfig>\r\n}\r\n\r\n// ============================================================================\r\n// Circuit Breaker Service\r\n// ============================================================================\r\n\r\nexport class CircuitBreaker {\r\n private config: CircuitBreakerConfig\r\n private storage: ICircuitBreakerStorage\r\n\r\n constructor(deps: CircuitBreakerDeps = {}) {\r\n this.config = { ...DEFAULT_CONFIG, ...deps.config }\r\n this.storage = deps.storage ?? new InMemoryCircuitBreakerStorage()\r\n }\r\n\r\n /**\r\n * Check if a request can be executed for a provider\r\n */\r\n async canExecute(provider: PaymentProvider): Promise<boolean> {\r\n const state = await this.getState(provider)\r\n\r\n switch (state.state) {\r\n case 'closed':\r\n return true\r\n\r\n case 'open':\r\n if (state.nextRetryAt && Date.now() >= state.nextRetryAt.getTime()) {\r\n await this.transitionTo(provider, 'half_open')\r\n return true\r\n }\r\n return false\r\n\r\n case 'half_open':\r\n return state.failureCount < this.config.halfOpenMaxRequests\r\n }\r\n }\r\n\r\n /**\r\n * Record a successful request\r\n */\r\n async recordSuccess(provider: PaymentProvider): Promise<void> {\r\n const state = await this.getState(provider)\r\n\r\n if (state.state === 'half_open') {\r\n state.successCount++\r\n if (state.successCount >= this.config.halfOpenMaxRequests) {\r\n await this.transitionTo(provider, 'closed')\r\n return\r\n }\r\n } else if (state.state === 'closed') {\r\n state.failureCount = 0\r\n }\r\n\r\n await this.storage.setState(provider, state)\r\n }\r\n\r\n /**\r\n * Record a failed request\r\n */\r\n async recordFailure(provider: PaymentProvider): Promise<void> {\r\n const state = await this.getState(provider)\r\n\r\n state.failureCount++\r\n state.lastFailure = new Date()\r\n\r\n if (state.state === 'half_open') {\r\n await this.transitionTo(provider, 'open')\r\n } else if (state.state === 'closed') {\r\n if (state.failureCount >= this.config.failureThreshold) {\r\n await this.transitionTo(provider, 'open')\r\n } else {\r\n await this.storage.setState(provider, state)\r\n }\r\n } else {\r\n await this.storage.setState(provider, state)\r\n }\r\n }\r\n\r\n /**\r\n * Get current state for a provider\r\n */\r\n async getState(provider: PaymentProvider): Promise<CircuitBreakerState> {\r\n const stored = await this.storage.getState(provider)\r\n return stored ?? createDefaultState(provider)\r\n }\r\n\r\n /**\r\n * Check if circuit is open (provider unavailable)\r\n */\r\n isOpen(provider: PaymentProvider): boolean {\r\n return this.isOpenSync(provider)\r\n }\r\n\r\n /**\r\n * Async version of isOpen\r\n */\r\n async isOpenAsync(provider: PaymentProvider): Promise<boolean> {\r\n const state = await this.getState(provider)\r\n return state.state === 'open'\r\n }\r\n\r\n /**\r\n * Manually reset a provider's circuit\r\n */\r\n async reset(provider: PaymentProvider): Promise<void> {\r\n await this.storage.setState(provider, createDefaultState(provider))\r\n }\r\n\r\n /**\r\n * Get all providers with open circuits\r\n */\r\n async getOpenCircuits(): Promise<PaymentProvider[]> {\r\n return this.storage.getOpenCircuits()\r\n }\r\n\r\n /**\r\n * Get the storage instance (useful for testing)\r\n */\r\n getStorage(): ICircuitBreakerStorage {\r\n return this.storage\r\n }\r\n\r\n /**\r\n * Get configuration (useful for testing)\r\n */\r\n getConfig(): CircuitBreakerConfig {\r\n return { ...this.config }\r\n }\r\n\r\n // ==========================================================================\r\n // Private Methods\r\n // ==========================================================================\r\n\r\n private async transitionTo(provider: PaymentProvider, newState: CircuitState): Promise<void> {\r\n const state = await this.getState(provider)\r\n const now = new Date()\r\n\r\n state.state = newState\r\n\r\n if (newState === 'open') {\r\n state.openedAt = now\r\n state.nextRetryAt = new Date(now.getTime() + this.config.resetTimeoutMs)\r\n console.warn(\r\n `[CIRCUIT_BREAKER] Circuit OPENED for ${provider}. ` +\r\n `Retry at: ${state.nextRetryAt.toISOString()}`\r\n )\r\n } else if (newState === 'half_open') {\r\n state.failureCount = 0\r\n state.successCount = 0\r\n console.info(`[CIRCUIT_BREAKER] Circuit HALF_OPEN for ${provider}`)\r\n } else if (newState === 'closed') {\r\n state.failureCount = 0\r\n state.successCount = 0\r\n state.openedAt = null\r\n state.nextRetryAt = null\r\n console.info(`[CIRCUIT_BREAKER] Circuit CLOSED for ${provider}`)\r\n }\r\n\r\n await this.storage.setState(provider, state)\r\n }\r\n\r\n /**\r\n * Synchronous check for backward compatibility\r\n * Note: This always returns false for database-backed storage\r\n */\r\n private isOpenSync(provider: PaymentProvider): boolean {\r\n if (this.storage instanceof InMemoryCircuitBreakerStorage) {\r\n const state = this.storage.getStateSync(provider)\r\n return state?.state === 'open'\r\n }\r\n return false\r\n }\r\n}\r\n\r\n// ============================================================================\r\n// Singleton Pattern (Backward Compatible)\r\n// ============================================================================\r\n\r\nlet circuitBreakerInstance: CircuitBreaker | null = null\r\nlet defaultStorage: InMemoryCircuitBreakerStorage | null = null\r\n\r\n/**\r\n * Get or create singleton CircuitBreaker instance\r\n */\r\nexport function getCircuitBreaker(config?: Partial<CircuitBreakerConfig>): CircuitBreaker {\r\n if (!circuitBreakerInstance) {\r\n if (!defaultStorage) {\r\n defaultStorage = new InMemoryCircuitBreakerStorage()\r\n }\r\n circuitBreakerInstance = new CircuitBreaker({\r\n storage: defaultStorage,\r\n config,\r\n })\r\n }\r\n return circuitBreakerInstance\r\n}\r\n\r\n/**\r\n * Create a new CircuitBreaker with custom dependencies\r\n */\r\nexport function createCircuitBreaker(deps: CircuitBreakerDeps = {}): CircuitBreaker {\r\n return new CircuitBreaker(deps)\r\n}\r\n\r\n/**\r\n * Reset the singleton instance (useful for testing)\r\n */\r\nexport function resetCircuitBreaker(): void {\r\n circuitBreakerInstance = null\r\n if (defaultStorage) {\r\n defaultStorage.clear()\r\n }\r\n defaultStorage = null\r\n}\r\n","/**\r\n * @nehorai/payments - Routing Engine Service\r\n *\r\n * Intelligent payment routing based on configurable rules:\r\n * - Card BIN rules (match card ranges to preferred providers)\r\n * - Provider health (circuit breaker state)\r\n * - Transaction fees / provider priorities\r\n * - Currency support\r\n *\r\n * Unlike the Podcasto-specific version, this accepts generic RoutingRules\r\n * config instead of hardcoded Israeli card BIN ranges.\r\n */\r\n\r\nimport type { PaymentProvider } from '../types/index.js'\r\nimport type { IRoutingEngine, RoutingContext, RoutingDecision } from '../providers/interfaces/index.js'\r\nimport {\r\n type PaymentConfig,\r\n type ConfiguredProviderAvailability,\r\n getConfiguredProviders,\r\n createPartialConfig,\r\n} from '../config/payment-config.js'\r\nimport { getCircuitBreaker, type CircuitBreaker } from './circuit-breaker.js'\r\n\r\n// ============================================================================\r\n// Routing Rules Types\r\n// ============================================================================\r\n\r\n/**\r\n * Rule for matching card BIN ranges to preferred providers\r\n */\r\nexport interface CardBinRule {\r\n ranges: Array<{ start: string; end: string; issuer?: string; country?: string }>\r\n preferredProvider: string\r\n priority?: number\r\n}\r\n\r\n/**\r\n * Provider priority configuration\r\n */\r\nexport interface ProviderPriorityRule {\r\n provider: string\r\n priority: number\r\n maxFeePercent: number\r\n supportsCurrency: string[]\r\n supportsRecurring: boolean\r\n isLocalGateway?: boolean\r\n}\r\n\r\n/**\r\n * Currency-specific routing rule\r\n */\r\nexport interface CurrencyRule {\r\n currency: string\r\n preferredProvider: string\r\n}\r\n\r\n/**\r\n * Generic routing rules configuration.\r\n * Injected at construction time instead of hardcoded.\r\n */\r\nexport interface RoutingRules {\r\n cardBinRules?: CardBinRule[]\r\n providerPriorities?: ProviderPriorityRule[]\r\n currencyRules?: CurrencyRule[]\r\n}\r\n\r\n// ============================================================================\r\n// Types\r\n// ============================================================================\r\n\r\n/**\r\n * Routing engine dependencies (for dependency injection)\r\n */\r\nexport interface RoutingEngineDeps {\r\n /** Payment configuration (optional, defaults to empty config) */\r\n config?: PaymentConfig\r\n /** Circuit breaker instance (optional, defaults to singleton) */\r\n circuitBreaker?: CircuitBreaker\r\n /** Routing rules (optional, no rules means simple round-robin) */\r\n routingRules?: RoutingRules\r\n}\r\n\r\n// ============================================================================\r\n// Internal Routing Helpers\r\n// ============================================================================\r\n\r\nfunction matchCardBinToRule(\r\n bin: string,\r\n rules: CardBinRule[]\r\n): { rule: CardBinRule; issuer?: string; country?: string } | null {\r\n if (!bin || bin.length < 6) return null\r\n const binPrefix = bin.substring(0, 6)\r\n\r\n for (const rule of rules) {\r\n for (const range of rule.ranges) {\r\n if (binPrefix >= range.start && binPrefix <= range.end) {\r\n return { rule, issuer: range.issuer, country: range.country }\r\n }\r\n }\r\n }\r\n return null\r\n}\r\n\r\nfunction getOptimalProviderFromPriorities(\r\n matchedBin: boolean,\r\n currency: string,\r\n requiresRecurring: boolean,\r\n availableProviders: PaymentProvider[],\r\n priorities: ProviderPriorityRule[]\r\n): PaymentProvider | null {\r\n const candidates = priorities.filter((p) =>\r\n availableProviders.includes(p.provider)\r\n )\r\n if (candidates.length === 0) return availableProviders[0] ?? null\r\n\r\n const suitable = candidates.filter((p) => {\r\n if (!p.supportsCurrency.includes(currency)) return false\r\n if (requiresRecurring && !p.supportsRecurring) return false\r\n return true\r\n })\r\n\r\n if (suitable.length === 0) {\r\n return candidates.sort((a, b) => a.priority - b.priority)[0]?.provider ?? null\r\n }\r\n\r\n // If card matched a BIN rule, prefer local gateways\r\n if (matchedBin) {\r\n const localProviders = suitable.filter((p) => p.isLocalGateway)\r\n if (localProviders.length > 0) {\r\n return localProviders.sort((a, b) => a.priority - b.priority)[0].provider\r\n }\r\n }\r\n\r\n return suitable.sort((a, b) => a.priority - b.priority)[0].provider\r\n}\r\n\r\nfunction getFallbackProvidersFromPriorities(\r\n primaryProvider: PaymentProvider,\r\n availableProviders: PaymentProvider[],\r\n priorities: ProviderPriorityRule[]\r\n): PaymentProvider[] {\r\n return priorities\r\n .filter((p) =>\r\n p.provider !== primaryProvider &&\r\n availableProviders.includes(p.provider)\r\n )\r\n .sort((a, b) => a.priority - b.priority)\r\n .map((p) => p.provider)\r\n}\r\n\r\nfunction getProviderFeeFromPriorities(\r\n provider: PaymentProvider,\r\n priorities: ProviderPriorityRule[]\r\n): number {\r\n const config = priorities.find((p) => p.provider === provider)\r\n return config?.maxFeePercent ?? 3.0\r\n}\r\n\r\n// ============================================================================\r\n// Routing Engine Implementation\r\n// ============================================================================\r\n\r\n/**\r\n * Routing Engine Implementation\r\n *\r\n * Routes payments to optimal providers with automatic failover.\r\n * Uses injected RoutingRules instead of hardcoded locale-specific logic.\r\n */\r\nexport class RoutingEngine implements IRoutingEngine {\r\n private config: PaymentConfig\r\n private circuitBreaker: CircuitBreaker\r\n private routingRules: RoutingRules\r\n\r\n constructor(deps: RoutingEngineDeps = {}) {\r\n this.config = deps.config ?? createPartialConfig({})\r\n this.circuitBreaker = deps.circuitBreaker ?? getCircuitBreaker()\r\n this.routingRules = deps.routingRules ?? {}\r\n }\r\n\r\n /**\r\n * Determine optimal provider for a transaction\r\n */\r\n async route(context: RoutingContext): Promise<RoutingDecision> {\r\n const availability = getConfiguredProviders(this.config)\r\n const availableProviders = this.getProviderList(availability)\r\n\r\n if (availableProviders.length === 0) {\r\n throw new Error('No payment providers configured')\r\n }\r\n\r\n // If using saved payment method, must use same provider\r\n if (context.savedPaymentMethodId && context.savedPaymentMethodProvider) {\r\n return this.routeToSavedMethodProvider(context, availableProviders)\r\n }\r\n\r\n // Check card BIN against rules\r\n const binMatch = context.cardBin && this.routingRules.cardBinRules\r\n ? matchCardBinToRule(context.cardBin, this.routingRules.cardBinRules)\r\n : null\r\n\r\n // Check currency rules\r\n const currencyRule = this.routingRules.currencyRules?.find(\r\n (r) => r.currency === context.amount.currency\r\n )\r\n\r\n // Get healthy providers\r\n const healthyProviders = await this.getHealthyProviders(availableProviders)\r\n const availableHealthy = availableProviders.filter((p) => healthyProviders.includes(p))\r\n const effectiveProviders = availableHealthy.length > 0 ? availableHealthy : availableProviders\r\n\r\n // If BIN matched a rule and the preferred provider is available, use it\r\n if (binMatch && effectiveProviders.includes(binMatch.rule.preferredProvider)) {\r\n const provider = binMatch.rule.preferredProvider\r\n const fallbacks = this.getFallbackProviders(provider, availableProviders)\r\n const feePercent = this.getProviderFee(provider)\r\n\r\n return {\r\n provider,\r\n reason: binMatch.issuer\r\n ? `Card (${binMatch.issuer}) matched BIN rule, routed to preferred provider`\r\n : 'Card matched BIN rule, routed to preferred provider',\r\n fallbackProviders: fallbacks,\r\n estimatedFeePercent: feePercent,\r\n metadata: {\r\n matchedBinRule: true,\r\n cardIssuer: binMatch.issuer,\r\n cardCountry: binMatch.country,\r\n },\r\n }\r\n }\r\n\r\n // If currency rule matches and provider is available, use it\r\n if (currencyRule && effectiveProviders.includes(currencyRule.preferredProvider)) {\r\n const provider = currencyRule.preferredProvider\r\n const fallbacks = this.getFallbackProviders(provider, availableProviders)\r\n const feePercent = this.getProviderFee(provider)\r\n\r\n return {\r\n provider,\r\n reason: `Currency ${context.amount.currency} routed to preferred provider`,\r\n fallbackProviders: fallbacks,\r\n estimatedFeePercent: feePercent,\r\n }\r\n }\r\n\r\n // Use provider priorities if configured\r\n const priorities = this.routingRules.providerPriorities\r\n if (priorities && priorities.length > 0) {\r\n const provider = getOptimalProviderFromPriorities(\r\n !!binMatch,\r\n context.amount.currency,\r\n context.isRecurring,\r\n effectiveProviders,\r\n priorities\r\n )\r\n\r\n if (provider) {\r\n const fallbacks = getFallbackProvidersFromPriorities(provider, availableProviders, priorities)\r\n const feePercent = getProviderFeeFromPriorities(provider, priorities)\r\n\r\n return {\r\n provider,\r\n reason: `Selected ${provider} based on priority rules`,\r\n fallbackProviders: fallbacks,\r\n estimatedFeePercent: feePercent,\r\n metadata: {\r\n matchedBinRule: !!binMatch,\r\n cardIssuer: binMatch?.issuer,\r\n cardCountry: binMatch?.country,\r\n },\r\n }\r\n }\r\n }\r\n\r\n // Fallback: use first available provider\r\n const provider = effectiveProviders[0]\r\n const fallbacks = effectiveProviders.slice(1)\r\n\r\n return {\r\n provider,\r\n reason: `Default routing to ${provider}`,\r\n fallbackProviders: fallbacks,\r\n estimatedFeePercent: this.getProviderFee(provider),\r\n }\r\n }\r\n\r\n /**\r\n * Get next provider after a failure\r\n */\r\n async getFailoverProvider(\r\n failedProvider: PaymentProvider,\r\n _context: RoutingContext\r\n ): Promise<PaymentProvider | null> {\r\n const availability = getConfiguredProviders(this.config)\r\n const availableProviders = this.getProviderList(availability)\r\n const healthyProviders = await this.getHealthyProviders(availableProviders)\r\n\r\n const fallbacks = this.getFallbackProviders(failedProvider, availableProviders)\r\n\r\n for (const provider of fallbacks) {\r\n if (healthyProviders.includes(provider)) {\r\n return provider\r\n }\r\n }\r\n\r\n return fallbacks[0] ?? null\r\n }\r\n\r\n /**\r\n * Check if a card BIN matches any configured rule\r\n */\r\n matchCardBin(bin: string): boolean {\r\n if (!this.routingRules.cardBinRules) return false\r\n return matchCardBinToRule(bin, this.routingRules.cardBinRules) !== null\r\n }\r\n\r\n /**\r\n * Get all available (healthy) providers\r\n */\r\n async getAvailableProviders(): Promise<PaymentProvider[]> {\r\n const availability = getConfiguredProviders(this.config)\r\n const configured = this.getProviderList(availability)\r\n return this.getHealthyProviders(configured)\r\n }\r\n\r\n /**\r\n * Quick recommendation without full context\r\n */\r\n async getQuickRecommendation(\r\n currency: string,\r\n isRecurring: boolean\r\n ): Promise<PaymentProvider | null> {\r\n const availability = getConfiguredProviders(this.config)\r\n const available = this.getProviderList(availability)\r\n\r\n if (available.length === 0) return null\r\n\r\n // Check currency rules first\r\n const currencyRule = this.routingRules.currencyRules?.find(\r\n (r) => r.currency === currency\r\n )\r\n if (currencyRule && available.includes(currencyRule.preferredProvider)) {\r\n return currencyRule.preferredProvider\r\n }\r\n\r\n // Use provider priorities if configured\r\n const priorities = this.routingRules.providerPriorities\r\n if (priorities && priorities.length > 0) {\r\n return getOptimalProviderFromPriorities(false, currency, isRecurring, available, priorities)\r\n }\r\n\r\n return available[0] ?? null\r\n }\r\n\r\n /**\r\n * Get current configuration (for testing/debugging)\r\n */\r\n getConfig(): PaymentConfig {\r\n return this.config\r\n }\r\n\r\n /**\r\n * Get circuit breaker instance (for testing/debugging)\r\n */\r\n getCircuitBreaker(): CircuitBreaker {\r\n return this.circuitBreaker\r\n }\r\n\r\n /**\r\n * Get routing rules (for testing/debugging)\r\n */\r\n getRoutingRules(): RoutingRules {\r\n return this.routingRules\r\n }\r\n\r\n // ==========================================================================\r\n // Private Methods\r\n // ==========================================================================\r\n\r\n private getProviderList(availability: ConfiguredProviderAvailability): PaymentProvider[] {\r\n const providers: PaymentProvider[] = []\r\n for (const [name, isAvailable] of Object.entries(availability)) {\r\n if (isAvailable) providers.push(name)\r\n }\r\n return providers\r\n }\r\n\r\n private async getHealthyProviders(providers: PaymentProvider[]): Promise<PaymentProvider[]> {\r\n const healthy: PaymentProvider[] = []\r\n for (const provider of providers) {\r\n const isOpen = await this.circuitBreaker.isOpenAsync(provider)\r\n if (!isOpen) {\r\n healthy.push(provider)\r\n }\r\n }\r\n return healthy\r\n }\r\n\r\n private routeToSavedMethodProvider(\r\n context: RoutingContext,\r\n availableProviders: PaymentProvider[]\r\n ): RoutingDecision {\r\n const provider = context.savedPaymentMethodProvider!\r\n\r\n if (!availableProviders.includes(provider)) {\r\n throw new Error(`Saved payment method provider '${provider}' is not available`)\r\n }\r\n\r\n return {\r\n provider,\r\n reason: 'Using saved payment method provider',\r\n fallbackProviders: [],\r\n estimatedFeePercent: this.getProviderFee(provider),\r\n }\r\n }\r\n\r\n private getFallbackProviders(\r\n primaryProvider: PaymentProvider,\r\n availableProviders: PaymentProvider[]\r\n ): PaymentProvider[] {\r\n const priorities = this.routingRules.providerPriorities\r\n if (priorities && priorities.length > 0) {\r\n return getFallbackProvidersFromPriorities(primaryProvider, availableProviders, priorities)\r\n }\r\n return availableProviders.filter((p) => p !== primaryProvider)\r\n }\r\n\r\n private getProviderFee(provider: PaymentProvider): number {\r\n const priorities = this.routingRules.providerPriorities\r\n if (priorities && priorities.length > 0) {\r\n return getProviderFeeFromPriorities(provider, priorities)\r\n }\r\n return 3.0 // Default fee if no priorities configured\r\n }\r\n}\r\n\r\n// ============================================================================\r\n// Singleton Pattern (Backward Compatible)\r\n// ============================================================================\r\n\r\nlet routingEngineInstance: RoutingEngine | null = null\r\n\r\n/**\r\n * Get or create singleton RoutingEngine instance\r\n */\r\nexport function getRoutingEngine(): RoutingEngine {\r\n if (!routingEngineInstance) {\r\n routingEngineInstance = new RoutingEngine()\r\n }\r\n return routingEngineInstance\r\n}\r\n\r\n/**\r\n * Create a new RoutingEngine with custom dependencies\r\n */\r\nexport function createRoutingEngine(deps: RoutingEngineDeps = {}): RoutingEngine {\r\n return new RoutingEngine(deps)\r\n}\r\n\r\n/**\r\n * Reset the singleton instance (useful for testing)\r\n */\r\nexport function resetRoutingEngine(): void {\r\n routingEngineInstance = null\r\n}\r\n"],"mappings":"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","names":["provider","fallbacks"]}
|
|
@@ -0,0 +1,96 @@
|
|
|
1
|
+
import { k as PaymentProvider } from './payment-types-68W-PlGg.cjs';
|
|
2
|
+
import { I as IPaymentProvider } from './routing-engine.interface-DJzGXor9.cjs';
|
|
3
|
+
import { IWebhookHandler } from './providers/interfaces/index.cjs';
|
|
4
|
+
import { IPaymentRepositories } from './repository/interfaces/index.cjs';
|
|
5
|
+
import { m as PaymentOrchestrator, R as RoutingEngine, a as CircuitBreaker, b as CircuitBreakerConfig, I as ICircuitBreakerStorage, q as RoutingRules } from './payment-orchestrator-Co_X6T_V.cjs';
|
|
6
|
+
import { PaymentConfig } from './config/index.cjs';
|
|
7
|
+
import './state-machine-Cu6_qKnv.cjs';
|
|
8
|
+
import './types/index.cjs';
|
|
9
|
+
|
|
10
|
+
/**
|
|
11
|
+
* @nehorai/payments - Service Factory
|
|
12
|
+
*
|
|
13
|
+
* Factory functions for creating payment service instances.
|
|
14
|
+
* Framework-agnostic - can be used in any TypeScript application.
|
|
15
|
+
*
|
|
16
|
+
* Unlike the Podcasto-specific factory, this does NOT import any
|
|
17
|
+
* provider implementations. Providers are registered by the caller.
|
|
18
|
+
*
|
|
19
|
+
* Usage:
|
|
20
|
+
* ```typescript
|
|
21
|
+
* import { createPaymentServices } from '@nehorai/payments';
|
|
22
|
+
* import { StripeProvider } from '@nehorai/payments-stripe';
|
|
23
|
+
*
|
|
24
|
+
* const providers = new Map();
|
|
25
|
+
* providers.set('stripe', new StripeProvider(config));
|
|
26
|
+
*
|
|
27
|
+
* const services = createPaymentServices({
|
|
28
|
+
* providers,
|
|
29
|
+
* config: myConfig,
|
|
30
|
+
* });
|
|
31
|
+
* ```
|
|
32
|
+
*/
|
|
33
|
+
|
|
34
|
+
/**
|
|
35
|
+
* Full configuration for creating payment services
|
|
36
|
+
*/
|
|
37
|
+
interface PaymentServicesConfig {
|
|
38
|
+
/** Provider instances - callers must create and pass these in */
|
|
39
|
+
providers: Map<PaymentProvider, IPaymentProvider>;
|
|
40
|
+
/** Webhook handler instances (optional) */
|
|
41
|
+
webhookHandlers?: Map<PaymentProvider, IWebhookHandler>;
|
|
42
|
+
/** Payment configuration */
|
|
43
|
+
config?: PaymentConfig;
|
|
44
|
+
/** Circuit breaker configuration */
|
|
45
|
+
circuitBreaker?: Partial<CircuitBreakerConfig>;
|
|
46
|
+
/** Circuit breaker storage implementation */
|
|
47
|
+
circuitBreakerStorage?: ICircuitBreakerStorage;
|
|
48
|
+
/** Routing rules for intelligent provider selection */
|
|
49
|
+
routingRules?: RoutingRules;
|
|
50
|
+
/** Repository implementations (for database operations) */
|
|
51
|
+
repositories?: IPaymentRepositories;
|
|
52
|
+
}
|
|
53
|
+
/**
|
|
54
|
+
* Created payment services
|
|
55
|
+
*/
|
|
56
|
+
interface PaymentServices {
|
|
57
|
+
/** Main payment orchestrator */
|
|
58
|
+
orchestrator: PaymentOrchestrator;
|
|
59
|
+
/** Provider routing engine */
|
|
60
|
+
routingEngine: RoutingEngine;
|
|
61
|
+
/** Circuit breaker for resilience */
|
|
62
|
+
circuitBreaker: CircuitBreaker;
|
|
63
|
+
/** Map of available providers */
|
|
64
|
+
providers: Map<PaymentProvider, IPaymentProvider>;
|
|
65
|
+
/** Map of webhook handlers */
|
|
66
|
+
webhookHandlers: Map<PaymentProvider, IWebhookHandler>;
|
|
67
|
+
/** Current configuration */
|
|
68
|
+
config: PaymentConfig;
|
|
69
|
+
}
|
|
70
|
+
/**
|
|
71
|
+
* Create all payment services.
|
|
72
|
+
*
|
|
73
|
+
* Providers are passed in by the caller (no auto-discovery).
|
|
74
|
+
* This factory only wires up the core services.
|
|
75
|
+
*
|
|
76
|
+
* @param options - Configuration options including provider instances
|
|
77
|
+
* @returns PaymentServices instance with all components
|
|
78
|
+
*/
|
|
79
|
+
declare function createPaymentServices(options: PaymentServicesConfig): PaymentServices;
|
|
80
|
+
/**
|
|
81
|
+
* Register a provider and optional webhook handler to existing services.
|
|
82
|
+
*
|
|
83
|
+
* Returns a new PaymentServices with the provider added.
|
|
84
|
+
* The original services object is not mutated.
|
|
85
|
+
*/
|
|
86
|
+
declare function registerProvider(services: PaymentServices, name: PaymentProvider, provider: IPaymentProvider, webhookHandler?: IWebhookHandler): PaymentServices;
|
|
87
|
+
/**
|
|
88
|
+
* Get or create singleton PaymentOS services instance
|
|
89
|
+
*/
|
|
90
|
+
declare function getPaymentServices(config?: PaymentServicesConfig): PaymentServices;
|
|
91
|
+
/**
|
|
92
|
+
* Reset singleton instance (useful for testing)
|
|
93
|
+
*/
|
|
94
|
+
declare function resetPaymentServices(): void;
|
|
95
|
+
|
|
96
|
+
export { type PaymentServices, type PaymentServicesConfig, createPaymentServices, getPaymentServices, registerProvider, resetPaymentServices };
|
|
@@ -0,0 +1,96 @@
|
|
|
1
|
+
import { k as PaymentProvider } from './payment-types-68W-PlGg.js';
|
|
2
|
+
import { I as IPaymentProvider } from './routing-engine.interface-h9_GmQ4b.js';
|
|
3
|
+
import { IWebhookHandler } from './providers/interfaces/index.js';
|
|
4
|
+
import { IPaymentRepositories } from './repository/interfaces/index.js';
|
|
5
|
+
import { m as PaymentOrchestrator, R as RoutingEngine, a as CircuitBreaker, b as CircuitBreakerConfig, I as ICircuitBreakerStorage, q as RoutingRules } from './payment-orchestrator-CPaLmDM5.js';
|
|
6
|
+
import { PaymentConfig } from './config/index.js';
|
|
7
|
+
import './state-machine-Cu6_qKnv.js';
|
|
8
|
+
import './types/index.js';
|
|
9
|
+
|
|
10
|
+
/**
|
|
11
|
+
* @nehorai/payments - Service Factory
|
|
12
|
+
*
|
|
13
|
+
* Factory functions for creating payment service instances.
|
|
14
|
+
* Framework-agnostic - can be used in any TypeScript application.
|
|
15
|
+
*
|
|
16
|
+
* Unlike the Podcasto-specific factory, this does NOT import any
|
|
17
|
+
* provider implementations. Providers are registered by the caller.
|
|
18
|
+
*
|
|
19
|
+
* Usage:
|
|
20
|
+
* ```typescript
|
|
21
|
+
* import { createPaymentServices } from '@nehorai/payments';
|
|
22
|
+
* import { StripeProvider } from '@nehorai/payments-stripe';
|
|
23
|
+
*
|
|
24
|
+
* const providers = new Map();
|
|
25
|
+
* providers.set('stripe', new StripeProvider(config));
|
|
26
|
+
*
|
|
27
|
+
* const services = createPaymentServices({
|
|
28
|
+
* providers,
|
|
29
|
+
* config: myConfig,
|
|
30
|
+
* });
|
|
31
|
+
* ```
|
|
32
|
+
*/
|
|
33
|
+
|
|
34
|
+
/**
|
|
35
|
+
* Full configuration for creating payment services
|
|
36
|
+
*/
|
|
37
|
+
interface PaymentServicesConfig {
|
|
38
|
+
/** Provider instances - callers must create and pass these in */
|
|
39
|
+
providers: Map<PaymentProvider, IPaymentProvider>;
|
|
40
|
+
/** Webhook handler instances (optional) */
|
|
41
|
+
webhookHandlers?: Map<PaymentProvider, IWebhookHandler>;
|
|
42
|
+
/** Payment configuration */
|
|
43
|
+
config?: PaymentConfig;
|
|
44
|
+
/** Circuit breaker configuration */
|
|
45
|
+
circuitBreaker?: Partial<CircuitBreakerConfig>;
|
|
46
|
+
/** Circuit breaker storage implementation */
|
|
47
|
+
circuitBreakerStorage?: ICircuitBreakerStorage;
|
|
48
|
+
/** Routing rules for intelligent provider selection */
|
|
49
|
+
routingRules?: RoutingRules;
|
|
50
|
+
/** Repository implementations (for database operations) */
|
|
51
|
+
repositories?: IPaymentRepositories;
|
|
52
|
+
}
|
|
53
|
+
/**
|
|
54
|
+
* Created payment services
|
|
55
|
+
*/
|
|
56
|
+
interface PaymentServices {
|
|
57
|
+
/** Main payment orchestrator */
|
|
58
|
+
orchestrator: PaymentOrchestrator;
|
|
59
|
+
/** Provider routing engine */
|
|
60
|
+
routingEngine: RoutingEngine;
|
|
61
|
+
/** Circuit breaker for resilience */
|
|
62
|
+
circuitBreaker: CircuitBreaker;
|
|
63
|
+
/** Map of available providers */
|
|
64
|
+
providers: Map<PaymentProvider, IPaymentProvider>;
|
|
65
|
+
/** Map of webhook handlers */
|
|
66
|
+
webhookHandlers: Map<PaymentProvider, IWebhookHandler>;
|
|
67
|
+
/** Current configuration */
|
|
68
|
+
config: PaymentConfig;
|
|
69
|
+
}
|
|
70
|
+
/**
|
|
71
|
+
* Create all payment services.
|
|
72
|
+
*
|
|
73
|
+
* Providers are passed in by the caller (no auto-discovery).
|
|
74
|
+
* This factory only wires up the core services.
|
|
75
|
+
*
|
|
76
|
+
* @param options - Configuration options including provider instances
|
|
77
|
+
* @returns PaymentServices instance with all components
|
|
78
|
+
*/
|
|
79
|
+
declare function createPaymentServices(options: PaymentServicesConfig): PaymentServices;
|
|
80
|
+
/**
|
|
81
|
+
* Register a provider and optional webhook handler to existing services.
|
|
82
|
+
*
|
|
83
|
+
* Returns a new PaymentServices with the provider added.
|
|
84
|
+
* The original services object is not mutated.
|
|
85
|
+
*/
|
|
86
|
+
declare function registerProvider(services: PaymentServices, name: PaymentProvider, provider: IPaymentProvider, webhookHandler?: IWebhookHandler): PaymentServices;
|
|
87
|
+
/**
|
|
88
|
+
* Get or create singleton PaymentOS services instance
|
|
89
|
+
*/
|
|
90
|
+
declare function getPaymentServices(config?: PaymentServicesConfig): PaymentServices;
|
|
91
|
+
/**
|
|
92
|
+
* Reset singleton instance (useful for testing)
|
|
93
|
+
*/
|
|
94
|
+
declare function resetPaymentServices(): void;
|
|
95
|
+
|
|
96
|
+
export { type PaymentServices, type PaymentServicesConfig, createPaymentServices, getPaymentServices, registerProvider, resetPaymentServices };
|