@flopay/shared
v1.3.0
Published
Shared types, error classes, constants, and validation helpers used across all FloPay packages. This package contains no runtime logic beyond error factories and validation functions -- it is primarily a type/constant library.
Readme
@flopay/shared
Shared types, error classes, constants, and validation helpers used across all FloPay packages. This package contains no runtime logic beyond error factories and validation functions -- it is primarily a type/constant library.
Installation
pnpm add @flopay/sharedWithin the monorepo, packages depend on it via workspace:*.
Quick Start
Environment Configuration
import { configureFlopay } from '@flopay/shared';
// Call once at app startup — determines which billing API URL is used
configureFlopay({ environment: 'production' }); // or 'staging'
// Or set NEXT_PUBLIC_FLOPAY_ENV=production in your .env file (no code needed)Resolve Billing API URL
import { resolveBillingApiUrl } from '@flopay/shared';
// Reads from: explicit param → env var → configureFlopay() → staging fallback
const url = resolveBillingApiUrl();Other Imports
import {
FloPayError,
validationError,
SDK_VERSION,
DEFAULT_APPEARANCE,
NIGHT_APPEARANCE,
THEMES,
CURRENCY_MAP,
getCurrencyByCountry,
isValidPublishableKey,
} from '@flopay/shared';
// Pick a coherent theme bundle and pass both halves to your checkout
const { appearance, buttonsLayout } = THEMES['glass-dark'];
import type {
FloPayConfig,
FloPayEnvironment,
CheckoutSession,
PaymentResult,
PaymentProviderAdapter,
ElementType,
FloPayAppearance,
} from '@flopay/shared';
// Validate a key
isValidPublishableKey('pk_test_abc123'); // true
// Look up currency by country
const info = getCurrencyByCountry('DE');
// { currency: 'EUR', symbol: '\u20ac', country: 'Germany', countryCode: 'DE', tax: 1 }
// Create a structured error
throw validationError('Email is required', 'email');API Reference
Types
| Type | Description |
|------|-------------|
| FloPayConfig | Top-level config: publishableKey, locale?, appearance?, apiVersion? |
| FloPayAppearance | Theme config: theme ('default'/'flat'/'night'/'none'), variables?, rules? |
| FloPayThemeVariables | CSS custom property overrides: colorPrimary, colorBackground, colorText, colorDanger, borderRadius, fontFamily, fontSizeBase, spacingUnit |
| ButtonsLayoutStyles | Style overrides for the buttons layout: cardButton, cardButtonFontSize, cardFormContainer, cardInputBorder, cardInputColor, cardInputPlaceholderColor, cardInputFontSize, cardInputBackground, nameInput, backButton, backButtonFontSize, backButtonIcon, submitButton, submitButtonFontSize, title, titleFontSize, errorBanner |
| ButtonsLayoutTheme | Theme preset name: 'default' / 'minimal' / 'rounded' / 'dark' / 'modern-light' / 'modern-dark' / 'bold-light' / 'bold-dark' / 'glass-light' / 'glass-dark' |
| ThemeBundle | A coherent theme bundle: { appearance: FloPayAppearance, buttonsLayout: ButtonsLayoutStyles } |
| ThemeBundleId | Bundle id: 'modern-light' / 'modern-dark' / 'bold-light' / 'bold-dark' / 'glass-light' / 'glass-dark' |
| ThemeId | Accepted by the React components' theme prop: 'classic' ∪ ThemeBundleId |
| CheckoutMode | Checkout mode: 'full' / 'auto' / 'confirm' |
| CheckoutSession | Session object: id, clientSecret, mode, status, amount, currency, customer?, checkoutMode?, products? (unified CheckoutSessionProduct[]), successUrl?, cancelUrl?, coupons?, subtotalAmount? / discountAmount? / totalAmount? (cart-currency major units; populated by billing API ≥ v1.1.2), gateways? (map keyed by gateway code — stripe, paypal, …), accountData?, tagsData? |
| CheckoutSessionProduct | Unified product from session response: uuid, checkoutSessionId, type ('item'/'subscription'), code?, name?, description?, quantity, totalAmount?, overrideAmount?, currency?, metadata? |
| CheckoutProductType | 'item' / 'subscription' |
| CheckoutProduct | Unified product input for session creation: type, code?, name?, quantity?, totalAmount?, overrideAmount?, currency?, metadata? |
| CheckoutGateway | Per-gateway config: publishableKey?, environment? ('sandbox'/'live'), stripeClientSecret? (Stripe-only) |
| CheckoutGateways | Map keyed by gateway code (e.g. stripe, paypal). A session can advertise multiple concurrent gateways. |
| GatewayEnvironment | 'sandbox' / 'live' — drives the PayPal JS SDK script and any other environment-scoped behavior |
| PaymentResult | Payment outcome: status ('succeeded'/'processing'/'requires_action'/'failed'), paymentIntentId?, error? |
| ConfirmPaymentParams | clientSecret, returnUrl? |
| CreatePaymentMethodResult | paymentMethodId, error? |
| ConfirmCardPaymentParams | clientSecret, paymentMethodId |
| ConfirmCardPaymentResult | status, paymentIntentId?, paymentMethodId?, error? |
| ElementType | 'payment' / 'card' / 'cardNumber' / 'cardExpiry' / 'cardCvc' / 'address' |
| ElementOptions | Options for creating elements: appearance?, clientSecret?, amount?, currency?, paymentMethodCreation?, layout?, defaultValues?, readOnly?, mode?, style? |
| MountedElement | Runtime element: mount(), unmount(), update(), on(), off(), destroy() |
| PaymentProviderAdapter | Provider interface: initialize(), createElement(), getElement(), submitElements(), createPaymentMethod(), confirmCardPayment(), confirmPayment(), confirmPayPalPayment(), resumePayPalPayment(), getRawProvider(), createPayPalElements(), destroy() |
| ElementChangeEvent | Change event: elementType, complete, empty, error?, value? |
| Customer | id, email, firstName?, lastName?, gender?, city?, state?, country?, zip? |
| LineItem | price?, priceData?, quantity |
| PriceData | currency, unitAmount, productData, recurring? |
| RecurringInterval | interval ('month'/'year'), intervalCount? |
| BillingProvider | 'recurly' / 'chargebee' / 'stripe' |
| TokenizedBody | id?, type?, threeDSecureActionResultTokenId?, originalPaymentMethodId?, gateway? ('stripe' / 'paypal' / custom), paymentMethodType? (Stripe wire identifier — 'card', 'apple_pay', 'cashapp', 'klarna', … for gateway='stripe'; 'paypal' for gateway='paypal'), isPaypal? (deprecated — replaced by gateway + paymentMethodType; still set for PayPal during the deprecation window so backends gating on isPaypal === 'true' keep working) |
| CheckoutGateway | Per-gateway config from the billing API: publishableKey?, environment?, stripeClientSecret?, paypalPublishableKey?, enabledPaymentMethods? (Stripe-only — per-session list of Stripe method type identifiers that the gateway has enabled for this consumer; drives dynamic ExpressCheckoutElement / PaymentElement rendering in @flopay/react) |
| NormalizedCheckoutSession | Provider-agnostic session: provider, mode, data, raw? |
| CheckoutModeKind | 'tokenize' / 'redirect' |
| CreateSessionParams | Full session creation params: billingApiUrl, checkoutBaseUrl, clientId, currency (required — SDK throws FloPayError({ type: 'validation_error', code: 'CurrencyRequired' }) before issuing the request when none can be resolved), products? (unified shape; takes precedence), items?, subscriptions? (legacy — folded into products[] before send), account, successUrl, cancelUrl, checkoutMode?, couponCodes?, tagsData?, redirectParams?, setCookie?, timeoutMs?, utmMetadata? |
| CheckoutSessionResult | { status: 201; redirectUrl; nonce } / { status: 204 } / { status: number } (nonce is the session-bound checkout token returned by the billing API — forward it on every continuation call against the same session via x-checkout-session-token) |
| CheckoutItem | providerItemId, providerItemName?, quantity?, totalAmount, overrideAmount?, currency? |
| CheckoutSubscription | providerPlanId, providerPlanName?, quantity?, totalAmount, overrideAmount?, currency? |
| CheckoutAccount | userId, firstName?, lastName?, email, country?, gender?, city?, state?, zip? |
| ProcessPaymentParams | sessionId, nonce (required — session-bound checkout token, forwarded as x-checkout-session-token), tokenizedData?, accountData, chv? |
| CreateCustomerParams | email, name?, metadata? |
| UpdateCustomerParams | email?, name?, metadata? |
| WebhookEvent | id, type, data, created |
| CurrencyInfo | currency, symbol, country, countryCode, tax |
| CountryOption | code, name, flag |
| TagsData | googleContainerId?, sessionId?, testEventCode? |
Error Classes
| Export | Description |
|--------|-------------|
| FloPayError | Custom error class with type, code?, declineCode?, param?, statusCode? |
| FloPayErrorType | 'validation_error' / 'api_error' / 'authentication_error' / 'rate_limit_error' / 'network_error' |
| validationError(message, param?) | Factory for validation errors |
| apiError(message, code?, statusCode?) | Factory for API errors |
| authenticationError(message) | Factory for auth errors |
| rateLimitError(message) | Factory for rate limit errors |
| networkError(message) | Factory for network errors |
Constants
| Export | Description |
|--------|-------------|
| SDK_VERSION | Current SDK version ('0.1.0') |
| DEFAULT_API_BASE_URL | 'https://api.flopay.io' |
| DEFAULT_API_VERSION | '2024-01-01' |
| DEFAULT_APPEARANCE | Default theme (primary #4A49FF, white background, Poppins font) |
| FLAT_APPEARANCE | Flat theme (minimal borders, 4px radius) |
| NIGHT_APPEARANCE | Dark theme (dark background #1A1A2E, light text) |
| MODERN_LIGHT_APPEARANCE | Clean & airy light — Inter, FloPay-blue primary #1785E0, slate text, 14px radius, soft input shadows |
| MODERN_DARK_APPEARANCE | Clean & airy dark — Inter, sky-blue primary #60A5FA, deep-blue surface #0B1220, 14px radius |
| BOLD_LIGHT_APPEARANCE | Bold & vibrant light — Inter, saturated FloPay blue #1785E0, 2px borders, 600+ font weight, gradient-ready |
| BOLD_DARK_APPEARANCE | Bold & vibrant dark — Inter, sky #60A5FA on deep-blue #0C2B4D, accented borders |
| GLASS_LIGHT_APPEARANCE | Glass / elevated light — translucent inputs with backdrop blur, FloPay-blue primary #1785E0, 16px radius |
| GLASS_DARK_APPEARANCE | Glass / elevated dark — translucent inputs with backdrop blur, #60A5FA on slate #0F172A |
| BUTTONS_LAYOUT_DEFAULT / _MINIMAL / _ROUNDED / _DARK | Original buttons-layout style presets (back-compat) |
| BUTTONS_LAYOUT_MODERN_LIGHT / _MODERN_DARK | Wrapper styles paired with the modern appearance bundles |
| BUTTONS_LAYOUT_BOLD_LIGHT / _BOLD_DARK | Wrapper styles paired with the bold appearance bundles |
| BUTTONS_LAYOUT_GLASS_LIGHT / _GLASS_DARK | Wrapper styles paired with the glass appearance bundles |
| THEMES | Record<ThemeBundleId, ThemeBundle> — pick THEMES['glass-dark'] to get { appearance, buttonsLayout } |
| resolveTheme(id) | Resolve a ThemeId ('classic' ∪ ThemeBundleId) to its ThemeBundle; 'classic' and missing ids return undefined |
| resolveButtonsLayoutTheme(name) | Map a ButtonsLayoutTheme name to its ButtonsLayoutStyles preset |
| ELEMENT_TYPES | ['payment', 'card', 'cardNumber', 'cardExpiry', 'cardCvc', 'address'] |
| SUPPORTED_CARD_BRANDS | ['visa', 'mastercard', 'mastercard_debit', 'amex', 'discover'] |
| STRIPE_EXPRESS_METHODS | ['apple_pay', 'google_pay', 'paypal', 'link', 'amazon_pay', 'klarna'] — Stripe method type identifiers supported by ExpressCheckoutElement (everything else returned in gateways.stripe.enabledPaymentMethods falls into the PaymentElement accordion in the React SDK) |
| partitionStripeMethods(enabledMethods, { excludePaypal? }) | Split the backend's enabled list into { expressMethods, paymentElementMethods }. Drops card; also drops paypal when excludePaypal: true. |
| stripeExpressMethodToOptionKey(method) | Map Stripe wire identifiers (apple_pay, google_pay, amazon_pay) to the camelCase keys (applePay, googlePay, amazonPay) expected by ExpressCheckoutElement's paymentMethods options map. |
| CURRENCY_MAP | Country code to CurrencyInfo mapping (EU, GB, US, CA, NZ, AU) |
| DEFAULT_CURRENCY | USD fallback |
Validation Helpers
| Export | Description |
|--------|-------------|
| getCurrencyByCountry(countryCode) | Returns CurrencyInfo for a country code, falls back to USD |
| isValidPublishableKey(key) | Returns true if the key matches pk_(test|live)_... |
| isValidSecretKey(key) | Returns true if the key matches sk_(test|live)_... |