import { KlaviyoPluginProps } from '../types'; import * as fs from 'fs'; import * as path from 'path'; export class KlaviyoConfigError extends Error { constructor(message: string) { super(message); this.name = 'KlaviyoConfigError'; } } export const validateAndroidConfig = (config: KlaviyoPluginProps['android'], projectRoot?: string) => { if (!config) return; // Validate logLevel if (config.logLevel !== undefined) { if (!Number.isInteger(config.logLevel) || config.logLevel < 0 || config.logLevel > 7) { throw new KlaviyoConfigError('Android logLevel must be an integer between 0 and 6'); } } // Validate openTracking if (config.openTracking !== undefined && typeof config.openTracking !== 'boolean') { throw new KlaviyoConfigError('Android openTracking must be a boolean value'); } // Validate notificationColor if provided if (config.notificationColor) { const hexColorRegex = /^#([A-Fa-f0-9]{6}|[A-Fa-f0-9]{3})$/; if (!hexColorRegex.test(config.notificationColor)) { throw new KlaviyoConfigError('Android notificationColor must be a valid hex color code (e.g., "#FF0000" or "#F00")'); } } // Validate geofencingEnabled if (config.geofencingEnabled !== undefined && typeof config.geofencingEnabled !== 'boolean') { throw new KlaviyoConfigError('Android geofencingEnabled must be a boolean'); } // Validate formsEnabled if (config.formsEnabled !== undefined && typeof config.formsEnabled !== 'boolean') { throw new KlaviyoConfigError('Android formsEnabled must be a boolean'); } // Validate notificationIconFilePath if provided if (config.notificationIconFilePath) { if (typeof config.notificationIconFilePath !== 'string') { throw new KlaviyoConfigError('Android notificationIconFilePath must be a string'); } // Always validate file existence if (!projectRoot) { throw new KlaviyoConfigError('projectRoot is required to validate notificationIconFilePath'); } const fullPath = path.join(projectRoot, config.notificationIconFilePath); if (!fs.existsSync(fullPath)) { throw new KlaviyoConfigError(`Android notificationIconFilePath does not exist: ${config.notificationIconFilePath}`); } } }; export const validateIosConfig = (config: KlaviyoPluginProps['ios']) => { if (!config) return; // Warn if deprecated version props are used (deprecated in 0.3.0; use Expo-level build numbers instead) const configWithExtras = config as unknown as Record; if (configWithExtras.projectVersion != null || configWithExtras.marketingVersion != null) { console.warn( '\tWARNING: klaviyo-expo-plugin: projectVersion and marketingVersion are deprecated in 0.3.0 and are ignored. Use Expo-level version and ios.buildNumber the app config instead.' ); } // Validate badgeAutoclearing if (config.badgeAutoclearing !== undefined && typeof config.badgeAutoclearing !== 'boolean') { throw new KlaviyoConfigError('iOS badgeAutoclearing must be a boolean'); } // Validate codeSigningStyle if (config.codeSigningStyle && !['Automatic', 'Manual'].includes(config.codeSigningStyle)) { throw new KlaviyoConfigError('iOS codeSigningStyle must be either "Automatic" or "Manual"'); } // Validate devTeam if (config.devTeam !== undefined) { if (typeof config.devTeam !== 'string' || !/^[A-Z0-9]{10}$/.test(config.devTeam)) { throw new KlaviyoConfigError('iOS devTeam must be a 10-digit alphanumeric string'); } } // Validate geofencingEnabled if (config.geofencingEnabled !== undefined && typeof config.geofencingEnabled !== 'boolean') { throw new KlaviyoConfigError('iOS geofencingEnabled must be a boolean'); } // Validate formsEnabled if (config.formsEnabled !== undefined && typeof config.formsEnabled !== 'boolean') { throw new KlaviyoConfigError('iOS formsEnabled must be a boolean'); } // Validate includeNotificationServiceExtension if (config.includeNotificationServiceExtension !== undefined && typeof config.includeNotificationServiceExtension !== 'boolean') { throw new KlaviyoConfigError('iOS includeNotificationServiceExtension must be a boolean'); } };