a0-purchases
Version:
Lightweight subscription management for AI apps with auto-detecting providers
144 lines • 5.73 kB
JavaScript
import { Platform, Linking } from 'react-native';
import { BasePlatformAdapter } from '../../core/adapters';
import { PURCHASES_ERROR_CODE } from '../../types';
import { backendClient } from '../../api/backendClient';
// Try to import Stripe if available
let stripeModule;
try {
stripeModule = require('../../stripe');
}
catch (e) {
// Stripe module not available, that's okay
}
export class WebAdapter extends BasePlatformAdapter {
constructor() {
super(...arguments);
this.name = 'web';
this.isStripeInitialized = false;
}
logEvent(event, data) {
if (this.config.debug) {
console.log(`[WebAdapter] ${event}`, data ? JSON.stringify(data, null, 2) : '');
}
}
createError(message, code = PURCHASES_ERROR_CODE.UNKNOWN_ERROR, originalError) {
const error = new Error(message);
error.code = code;
error.message = message;
error.userCancelled = false;
if (originalError) {
error.underlyingError = originalError;
}
return error;
}
isSupported() {
// Web adapter is always supported as fallback
return true;
}
async init(config) {
// Store configuration
if (config) {
this.config = Object.assign(Object.assign({}, this.config), config);
}
try {
this.logEvent('Initializing web adapter...');
// Try to initialize Stripe if we're on a platform that supports it
if (Platform.OS !== 'ios' && Platform.OS !== 'android') {
// We're on web, try to initialize Stripe for payment sheets
try {
await this.initializeStripe();
}
catch (error) {
this.logEvent('Stripe initialization failed, will use checkout URLs', error);
// Don't fail - we can still use checkout URLs
}
}
else {
// On mobile but using web adapter (fallback), just use checkout URLs
this.logEvent('Mobile platform using web adapter, will use checkout URLs');
}
this.logEvent('Web adapter initialized');
}
catch (error) {
this.logEvent('Web adapter initialization failed', error);
throw this.createError('Web adapter initialization failed', PURCHASES_ERROR_CODE.INITIALIZATION_ERROR, error);
}
}
async initializeStripe() {
try {
const stripeInfo = await backendClient.getStripeInformation();
if (!(stripeInfo === null || stripeInfo === void 0 ? void 0 : stripeInfo.publishableKey)) {
throw new Error('Missing Stripe publishable key');
}
// Try to use Stripe module if available
if (stripeModule && stripeModule.initStripe) {
await stripeModule.initStripe({
publishableKey: stripeInfo.publishableKey,
stripeAccountId: stripeInfo.stripeAccountId,
});
this.isStripeInitialized = true;
this.logEvent('Stripe initialized successfully');
}
else {
// Stripe module not available
this.logEvent('Stripe module not available');
}
}
catch (error) {
this.logEvent('Failed to initialize Stripe', error);
throw error;
}
}
async purchase(pkg, userId) {
this.logEvent('Starting web purchase', {
packageId: pkg.identifier,
productId: pkg.product.identifier,
userId
});
if (!userId) {
throw this.createError('User ID is required for web purchases', PURCHASES_ERROR_CODE.INVALID_APP_USER_ID_ERROR);
}
try {
// Create checkout session
const session = await backendClient.createCheckoutSession(userId, pkg);
if (!(session === null || session === void 0 ? void 0 : session.url)) {
throw this.createError('Invalid checkout session URL', PURCHASES_ERROR_CODE.BACKEND_VALIDATION_ERROR);
}
this.logEvent('Opening checkout URL', { url: session.url });
// Open the checkout URL
if (Platform.OS === 'web' || typeof window !== 'undefined') {
// On web, open in new tab
window.open(session.url, '_blank');
}
else {
// On mobile, use Linking
await Linking.openURL(session.url);
}
// For web purchases, we return a minimal purchase object
// The actual validation happens via webhooks on the backend
const result = {
id: pkg.product.identifier,
transactionId: `web_${Date.now()}`, // Generate a pseudo transaction ID
};
this.logEvent('Web purchase initiated', result);
return result;
}
catch (error) {
this.logEvent('Web purchase failed', error);
if (error.code) {
throw error; // Re-throw library errors
}
throw this.createError(error.message || 'Web purchase failed', PURCHASES_ERROR_CODE.PURCHASE_INVALID_ERROR, error);
}
}
async restore(_userId) {
// For web, restore is essentially a no-op
// Customer info refresh is handled by the service
this.logEvent('Web restore completed (no-op)');
}
dispose() {
this.logEvent('Disposing web adapter');
this.isStripeInitialized = false;
}
}
//# sourceMappingURL=WebAdapter.js.map