shared-features 0.1.6 → 0.1.7
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/{admin-commonFeatures-BKjytwx5.js → admin-commonFeatures-CFhvjgp9.js} +3 -3
- package/dist/{admin-commonFeatures-BKjytwx5.js.map → admin-commonFeatures-CFhvjgp9.js.map} +1 -1
- package/dist/{admin-commonFeatures-bjszYcI3.cjs → admin-commonFeatures-pnaXeix_.cjs} +3 -3
- package/dist/{admin-commonFeatures-bjszYcI3.cjs.map → admin-commonFeatures-pnaXeix_.cjs.map} +1 -1
- package/dist/{broadcasts-BeTm29_q.cjs → broadcasts-DZsQNd4R.cjs} +2 -2
- package/dist/{broadcasts-BeTm29_q.cjs.map → broadcasts-DZsQNd4R.cjs.map} +1 -1
- package/dist/{broadcasts-CbrWZpcI.js → broadcasts-Dlu51_38.js} +2 -2
- package/dist/{broadcasts-CbrWZpcI.js.map → broadcasts-Dlu51_38.js.map} +1 -1
- package/dist/{commonFeatures-DMYLR629.cjs → commonFeatures-BuY97_K4.cjs} +10 -2
- package/dist/{commonFeatures-DMYLR629.cjs.map → commonFeatures-BuY97_K4.cjs.map} +1 -1
- package/dist/{commonFeatures-78YVrQq1.js → commonFeatures-LzPnbR6z.js} +10 -2
- package/dist/{commonFeatures-78YVrQq1.js.map → commonFeatures-LzPnbR6z.js.map} +1 -1
- package/dist/components/index.cjs +1 -1
- package/dist/components/index.js +1 -1
- package/dist/{featureFlags-DLdibcv_.js → featureFlags-CSudFX4x.js} +3 -2
- package/dist/featureFlags-CSudFX4x.js.map +1 -0
- package/dist/{featureFlags-DOwy_uOj.cjs → featureFlags-CfDmshkF.cjs} +3 -2
- package/dist/featureFlags-CfDmshkF.cjs.map +1 -0
- package/dist/hooks/index.cjs +2 -2
- package/dist/hooks/index.js +2 -2
- package/dist/{index-CQNjI6V7.js → index-D2YWycum.js} +3 -3
- package/dist/{index-CQNjI6V7.js.map → index-D2YWycum.js.map} +1 -1
- package/dist/{index-B5uAGS9G.cjs → index-DxjbpnFC.cjs} +3 -3
- package/dist/{index-B5uAGS9G.cjs.map → index-DxjbpnFC.cjs.map} +1 -1
- package/dist/index.cjs +7 -7
- package/dist/index.js +7 -7
- package/dist/services/commonFeatures.d.ts.map +1 -1
- package/dist/services/index.cjs +4 -4
- package/dist/services/index.js +4 -4
- package/dist/types/commonFeatures.d.ts +11 -0
- package/dist/types/commonFeatures.d.ts.map +1 -1
- package/dist/types/index.cjs +1 -1
- package/dist/types/index.js +1 -1
- package/dist/{useCommonFeatures-NobppaW9.cjs → useCommonFeatures-CWqe4EhH.cjs} +2 -2
- package/dist/{useCommonFeatures-NobppaW9.cjs.map → useCommonFeatures-CWqe4EhH.cjs.map} +1 -1
- package/dist/{useCommonFeatures-BVaPDaPy.js → useCommonFeatures-CnmI83Er.js} +2 -2
- package/dist/{useCommonFeatures-BVaPDaPy.js.map → useCommonFeatures-CnmI83Er.js.map} +1 -1
- package/dist/{useFeatureFlags-8nC71ue-.cjs → useFeatureFlags-9_E7gair.cjs} +3 -3
- package/dist/{useFeatureFlags-8nC71ue-.cjs.map → useFeatureFlags-9_E7gair.cjs.map} +1 -1
- package/dist/{useFeatureFlags-DlMeLBH2.js → useFeatureFlags-DhIb0HYi.js} +3 -3
- package/dist/{useFeatureFlags-DlMeLBH2.js.map → useFeatureFlags-DhIb0HYi.js.map} +1 -1
- package/package.json +1 -1
- package/dist/featureFlags-DLdibcv_.js.map +0 -1
- package/dist/featureFlags-DOwy_uOj.cjs.map +0 -1
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"commonFeatures-DMYLR629.cjs","sources":["../src/firebase/config.ts","../src/firebase/init.ts","../src/services/campaigns.ts","../src/services/analytics.ts","../src/services/featureFlags.ts","../src/services/commonFeatures.ts"],"sourcesContent":["/**\n * Firebase Configuration Types\n *\n * Types and interfaces for configuring the shared-features Firebase connection.\n *\n * @author Ahsan Mahmood <aoneahsan@gmail.com>\n */\n\nimport type { CommonFeatureCollectionKey } from '../types/commonFeatures';\n\n/**\n * Firebase configuration object\n */\nexport interface FirebaseConfig {\n apiKey: string;\n authDomain: string;\n projectId: string;\n storageBucket?: string;\n messagingSenderId?: string;\n appId?: string;\n measurementId?: string;\n}\n\n/**\n * Target platform for the consumer project\n */\nexport type ConsumerPlatform = 'web' | 'android' | 'ios' | 'extension';\n\n/**\n * Feature version preferences for a consumer project\n * Specifies which API versions the consumer supports\n */\nexport interface ConsumerFeatureVersions {\n /** Campaigns API version */\n campaigns?: number;\n /** Broadcasts API version */\n broadcasts?: number;\n /** Contact info API version */\n contactInfo?: number;\n /** Developer info API version */\n developerInfo?: number;\n /** Social links API version */\n socialLinks?: number;\n /** Payment options API version */\n paymentOptions?: number;\n /** Address info API version */\n addressInfo?: number;\n /** Services API version */\n services?: number;\n /** Skills API version */\n skills?: number;\n /** Testimonials API version */\n testimonials?: number;\n /** Projects API version */\n projects?: number;\n}\n\n/**\n * Configuration for initializing shared-features\n */\nexport interface SharedFeaturesConfig {\n /**\n * Firebase configuration for aoneahsan.com's Firebase project.\n * All values from environment variables.\n */\n firebaseConfig: FirebaseConfig;\n\n /**\n * Unique identifier for this project (e.g., 'ztools', '2fa-studio')\n */\n projectId: string;\n\n /**\n * Display name for this project (e.g., 'ZTools', '2FA Studio')\n */\n projectName: string;\n\n /**\n * Platform type for targeting\n */\n platform: ConsumerPlatform;\n\n /**\n * Whether to enable debug logging (default: false)\n */\n debug?: boolean;\n\n /**\n * Feature version preferences for this consumer.\n * Specifies which API versions this consumer supports.\n * If not specified, latest versions are used.\n */\n featureVersions?: ConsumerFeatureVersions;\n\n /**\n * Override collection names for common features.\n * Use this to point shared-features at existing collections\n * instead of creating new zaions_ prefixed ones.\n *\n * @example\n * ```typescript\n * collectionNames: {\n * PROJECTS: 'portfolio_projects',\n * CONTACT_INFO: 'portfolio_contact_info',\n * TESTIMONIALS: 'testimonials',\n * }\n * ```\n */\n collectionNames?: Partial<Record<CommonFeatureCollectionKey, string>>;\n}\n\n/**\n * Internal state after initialization\n */\nexport interface SharedFeaturesState {\n /** Whether the package has been initialized */\n initialized: boolean;\n /** The active configuration */\n config: SharedFeaturesConfig | null;\n /** Unique device ID for anonymous tracking */\n deviceId: string | null;\n}\n\n/**\n * Singleton state\n */\nlet state: SharedFeaturesState = {\n initialized: false,\n config: null,\n deviceId: null,\n};\n\n/**\n * Get current state\n */\nexport function getState(): SharedFeaturesState {\n return state;\n}\n\n/**\n * Set state (internal use only)\n */\nexport function setState(newState: Partial<SharedFeaturesState>): void {\n state = { ...state, ...newState };\n}\n\n/**\n * Get configuration (throws if not initialized)\n */\nexport function getConfig(): SharedFeaturesConfig {\n if (!state.initialized || !state.config) {\n throw new Error(\n 'shared-features has not been initialized. Call initSharedFeatures() first.'\n );\n }\n return state.config;\n}\n\n/**\n * Check if initialized\n */\nexport function isInitialized(): boolean {\n return state.initialized;\n}\n","/**\n * Firebase Initialization\n *\n * Initialize a secondary Firebase app for connecting to aoneahsan.com's\n * Firebase project from consumer projects.\n *\n * @author Ahsan Mahmood <aoneahsan@gmail.com>\n */\n\nimport { initializeApp, getApps, FirebaseApp } from 'firebase/app';\nimport { getFirestore, Firestore } from 'firebase/firestore';\nimport { getAuth, Auth } from 'firebase/auth';\nimport {\n SharedFeaturesConfig,\n setState,\n getState,\n isInitialized,\n} from './config';\nimport { setCommonFeatureCollectionNames } from '../types/commonFeatures';\n\nconst SHARED_FEATURES_APP_NAME = 'shared-features';\n\nlet firebaseApp: FirebaseApp | null = null;\nlet firestoreDb: Firestore | null = null;\nlet firebaseAuth: Auth | null = null;\n\n/**\n * Generate a unique device ID for anonymous tracking\n */\nfunction generateDeviceId(): string {\n const timestamp = Date.now();\n const randomPart = Math.random().toString(36).substring(2, 15);\n return `device_${timestamp}_${randomPart}`;\n}\n\n/**\n * Get or create device ID from storage\n */\nasync function getOrCreateDeviceId(): Promise<string> {\n const STORAGE_KEY = 'shared_features_device_id';\n\n try {\n // Try Capacitor Preferences first\n const { Preferences } = await import('@capacitor/preferences');\n const result = await Preferences.get({ key: STORAGE_KEY });\n if (result.value) {\n return result.value;\n }\n const newId = generateDeviceId();\n await Preferences.set({ key: STORAGE_KEY, value: newId });\n return newId;\n } catch {\n // Fallback to localStorage for web\n try {\n const stored = localStorage.getItem(STORAGE_KEY);\n if (stored) {\n return stored;\n }\n const newId = generateDeviceId();\n localStorage.setItem(STORAGE_KEY, newId);\n return newId;\n } catch {\n // If all storage fails, generate ephemeral ID\n return generateDeviceId();\n }\n }\n}\n\n/**\n * Initialize shared-features with the given configuration.\n *\n * This creates a secondary Firebase app connection to aoneahsan.com's\n * Firebase project, separate from the consumer project's own Firebase.\n *\n * @param config - Configuration object with Firebase config and project info\n * @returns Initialized state object\n *\n * @example\n * ```typescript\n * import { initSharedFeatures } from 'shared-features';\n *\n * initSharedFeatures({\n * firebaseConfig: {\n * apiKey: import.meta.env.VITE_SHARED_FEATURES_API_KEY,\n * authDomain: import.meta.env.VITE_SHARED_FEATURES_AUTH_DOMAIN,\n * projectId: import.meta.env.VITE_SHARED_FEATURES_PROJECT_ID,\n * },\n * projectId: 'ztools',\n * projectName: 'ZTools',\n * platform: 'web',\n * });\n * ```\n */\nexport async function initSharedFeatures(\n config: SharedFeaturesConfig\n): Promise<{ app: FirebaseApp; db: Firestore; auth: Auth }> {\n // Return existing instance if already initialized with same config\n if (isInitialized() && firebaseApp && firestoreDb && firebaseAuth) {\n const currentConfig = getState().config;\n if (\n currentConfig &&\n currentConfig.firebaseConfig.projectId === config.firebaseConfig.projectId\n ) {\n return { app: firebaseApp, db: firestoreDb, auth: firebaseAuth };\n }\n }\n\n // Check if app already exists\n const existingApps = getApps();\n const existingApp = existingApps.find(\n (app) => app.name === SHARED_FEATURES_APP_NAME\n );\n\n if (existingApp) {\n firebaseApp = existingApp;\n } else {\n // Initialize new Firebase app with config from environment variables\n firebaseApp = initializeApp(config.firebaseConfig, SHARED_FEATURES_APP_NAME);\n }\n\n // Get Firestore and Auth instances\n firestoreDb = getFirestore(firebaseApp);\n firebaseAuth = getAuth(firebaseApp);\n\n // Apply collection name overrides if provided\n if (config.collectionNames) {\n setCommonFeatureCollectionNames(config.collectionNames);\n }\n\n // Get or create device ID\n const deviceId = await getOrCreateDeviceId();\n\n // Update state\n setState({\n initialized: true,\n config,\n deviceId,\n });\n\n if (config.debug) {\n console.log('[shared-features] Initialized:', {\n projectId: config.projectId,\n projectName: config.projectName,\n platform: config.platform,\n deviceId,\n });\n }\n\n return { app: firebaseApp, db: firestoreDb, auth: firebaseAuth };\n}\n\n/**\n * Get the shared-features Firebase app instance.\n * Throws if not initialized.\n */\nexport function getSharedFeaturesApp(): FirebaseApp {\n if (!firebaseApp) {\n throw new Error(\n 'shared-features has not been initialized. Call initSharedFeatures() first.'\n );\n }\n return firebaseApp;\n}\n\n/**\n * Get the shared-features Firestore instance.\n * Throws if not initialized.\n */\nexport function getSharedFeaturesDb(): Firestore {\n if (!firestoreDb) {\n throw new Error(\n 'shared-features has not been initialized. Call initSharedFeatures() first.'\n );\n }\n return firestoreDb;\n}\n\n/**\n * Get the shared-features Auth instance.\n * Throws if not initialized.\n */\nexport function getSharedFeaturesAuth(): Auth {\n if (!firebaseAuth) {\n throw new Error(\n 'shared-features has not been initialized. Call initSharedFeatures() first.'\n );\n }\n return firebaseAuth;\n}\n\n/**\n * Get the device ID for anonymous tracking.\n * Returns null if not initialized.\n */\nexport function getDeviceId(): string | null {\n return getState().deviceId;\n}\n","/**\n * Campaigns Service\n *\n * Handles fetching and displaying advertising campaigns from the\n * centralized aoneahsan.com Firebase backend.\n *\n * Consumer projects only need read access - all campaign management\n * is done through the aoneahsan.com admin panel.\n *\n * @author Ahsan Mahmood <aoneahsan@gmail.com>\n */\n\nimport {\n collection,\n doc,\n getDocs,\n getDoc,\n query,\n where,\n orderBy,\n limit as firestoreLimit,\n Timestamp,\n} from 'firebase/firestore';\nimport { getSharedFeaturesDb } from '../firebase/init';\nimport { getConfig } from '../firebase/config';\nimport type {\n Campaign,\n CampaignWithProduct,\n Product,\n AdPlacement,\n CampaignStatus,\n FetchCampaignsOptions,\n} from '../types/campaigns';\n\n// ============================================================================\n// CONSTANTS\n// ============================================================================\n\nconst COLLECTION_CAMPAIGNS = 'zaions_campaigns';\nconst COLLECTION_PRODUCTS = 'zaions_products';\n\n// Cache for campaigns\ninterface CampaignsCache {\n data: Campaign[];\n timestamp: number;\n}\nlet campaignsCache: CampaignsCache | null = null;\nconst CACHE_TTL_MS = 5 * 60 * 1000; // 5 minutes\n\n// Products cache\nlet productsCache: Map<string, Product> | null = null;\n\n// ============================================================================\n// HELPER FUNCTIONS\n// ============================================================================\n\n/**\n * Check if cache is valid\n */\nfunction isCacheValid(): boolean {\n if (!campaignsCache) return false;\n return Date.now() - campaignsCache.timestamp < CACHE_TTL_MS;\n}\n\n/**\n * Convert Firestore document to Campaign\n */\nfunction docToCampaign(\n docId: string,\n data: Record<string, unknown>\n): Campaign {\n return {\n id: docId,\n productId: data.productId as string,\n name: data.name as string,\n status: data.status as CampaignStatus,\n targetPlatforms: data.targetPlatforms as Campaign['targetPlatforms'],\n targetAudience: data.targetAudience as Campaign['targetAudience'],\n targetProjects: (data.targetProjects as string[]) || [],\n excludeProductUsers: data.excludeProductUsers as boolean,\n placements: data.placements as AdPlacement[],\n priority: data.priority as number,\n frequencyDays: data.frequencyDays as number,\n maxImpressions: data.maxImpressions as number | null,\n startDate: data.startDate as Timestamp,\n endDate: data.endDate as Timestamp | null,\n variant: data.variant as Campaign['variant'],\n customTitle: data.customTitle as string | undefined,\n customTagline: data.customTagline as string | undefined,\n customCta: data.customCta as string | undefined,\n customCtaUrl: data.customCtaUrl as string | undefined,\n customDescription: data.customDescription as string | undefined,\n customProductColor: data.customProductColor as string | undefined,\n customIcon: data.customIcon as string | undefined,\n customFeatures: data.customFeatures as string[] | undefined,\n totalImpressions: data.totalImpressions as number,\n totalClicks: data.totalClicks as number,\n totalCloses: data.totalCloses as number,\n createdAt: data.createdAt as Timestamp,\n updatedAt: data.updatedAt as Timestamp,\n createdBy: data.createdBy as string,\n updatedBy: data.updatedBy as string | undefined,\n };\n}\n\n/**\n * Convert Firestore document to Product\n */\nfunction docToProduct(docId: string, data: Record<string, unknown>): Product {\n return {\n id: docId,\n name: data.name as string,\n tagline: data.tagline as string,\n description: data.description as string,\n type: data.type as Product['type'],\n url: data.url as string,\n color: data.color as string,\n features: (data.features as string[]) || [],\n icon64: data.icon64 as string | undefined,\n icon128: data.icon128 as string | undefined,\n chromeStoreUrl: data.chromeStoreUrl as string | undefined,\n playStoreUrl: data.playStoreUrl as string | undefined,\n appStoreUrl: data.appStoreUrl as string | undefined,\n webUrl: data.webUrl as string | undefined,\n enabled: data.enabled as boolean,\n createdAt: data.createdAt as Timestamp,\n updatedAt: data.updatedAt as Timestamp,\n };\n}\n\n// ============================================================================\n// PRODUCTS\n// ============================================================================\n\n/**\n * Fetch all products from Firestore\n */\nexport async function fetchProducts(): Promise<Product[]> {\n const db = getSharedFeaturesDb();\n const snapshot = await getDocs(collection(db, COLLECTION_PRODUCTS));\n const products = snapshot.docs.map((d) => docToProduct(d.id, d.data()));\n\n // Update cache\n productsCache = new Map(products.map((p) => [p.id, p]));\n\n return products;\n}\n\n/**\n * Get a product by ID (uses cache if available)\n */\nexport async function getProductById(\n productId: string\n): Promise<Product | null> {\n // Check cache first\n if (productsCache?.has(productId)) {\n return productsCache.get(productId) || null;\n }\n\n // Fetch from Firestore\n const db = getSharedFeaturesDb();\n const docSnap = await getDoc(doc(db, COLLECTION_PRODUCTS, productId));\n\n if (!docSnap.exists()) return null;\n\n const product = docToProduct(docSnap.id, docSnap.data());\n\n // Add to cache\n if (!productsCache) productsCache = new Map();\n productsCache.set(productId, product);\n\n return product;\n}\n\n// ============================================================================\n// CAMPAIGNS\n// ============================================================================\n\n/**\n * Fetch campaigns with optional filters\n */\nexport async function fetchCampaigns(\n options: FetchCampaignsOptions = {}\n): Promise<Campaign[]> {\n const config = getConfig();\n const db = getSharedFeaturesDb();\n\n // Check cache first (only for unfiltered queries)\n if (\n !options.placement &&\n !options.status &&\n !options.productId &&\n isCacheValid()\n ) {\n return campaignsCache!.data;\n }\n\n let q = query(collection(db, COLLECTION_CAMPAIGNS));\n\n // Apply filters\n if (options.status) {\n q = query(q, where('status', '==', options.status));\n }\n\n if (options.productId) {\n q = query(q, where('productId', '==', options.productId));\n }\n\n q = query(q, orderBy('priority', 'desc'));\n\n if (options.limit) {\n q = query(q, firestoreLimit(options.limit));\n }\n\n const snapshot = await getDocs(q);\n let campaigns = snapshot.docs.map((d) => docToCampaign(d.id, d.data()));\n\n // Client-side filtering for array fields\n if (options.placement) {\n campaigns = campaigns.filter((c) =>\n c.placements.includes(options.placement!)\n );\n }\n\n // Filter by target platform (from config)\n campaigns = campaigns.filter(\n (c) =>\n c.targetPlatforms.includes(config.platform) ||\n c.targetPlatforms.length === 0\n );\n\n // Filter by target projects (empty = all projects)\n campaigns = campaigns.filter(\n (c) =>\n c.targetProjects.length === 0 ||\n c.targetProjects.includes(config.projectId)\n );\n\n // Cache unfiltered results\n if (!options.placement && !options.status && !options.productId) {\n campaignsCache = {\n data: campaigns,\n timestamp: Date.now(),\n };\n }\n\n return campaigns;\n}\n\n/**\n * Fetch active campaigns for a specific placement\n * Returns campaigns with resolved product data\n */\nexport async function fetchActiveCampaigns(\n placement: AdPlacement\n): Promise<CampaignWithProduct[]> {\n const now = Timestamp.now();\n\n const campaigns = await fetchCampaigns({ status: 'active' });\n\n // Ensure products are loaded\n if (!productsCache || productsCache.size === 0) {\n await fetchProducts();\n }\n\n // Filter by placement and date range\n const eligible = campaigns.filter((c) => {\n // Placement check\n if (!c.placements.includes(placement)) return false;\n\n // Date range check\n if (c.startDate.toMillis() > now.toMillis()) return false;\n if (c.endDate && c.endDate.toMillis() < now.toMillis()) return false;\n\n // Max impressions check\n if (c.maxImpressions !== null && c.totalImpressions >= c.maxImpressions)\n return false;\n\n return true;\n });\n\n // Resolve products\n const result: CampaignWithProduct[] = [];\n\n for (const campaign of eligible) {\n const product = await getProductById(campaign.productId);\n if (product && product.enabled) {\n result.push({ ...campaign, product });\n }\n }\n\n return result;\n}\n\n/**\n * Get a single campaign by ID\n */\nexport async function getCampaignById(\n campaignId: string\n): Promise<Campaign | null> {\n const db = getSharedFeaturesDb();\n const docSnap = await getDoc(doc(db, COLLECTION_CAMPAIGNS, campaignId));\n\n if (!docSnap.exists()) return null;\n return docToCampaign(docSnap.id, docSnap.data());\n}\n\n/**\n * Clear the campaigns cache (useful for manual refresh)\n */\nexport function clearCampaignsCache(): void {\n campaignsCache = null;\n}\n\n/**\n * Clear the products cache\n */\nexport function clearProductsCache(): void {\n productsCache = null;\n}\n","/**\n * Analytics Service\n *\n * Handles recording impressions, clicks, and other ad interactions\n * from consumer projects to the centralized aoneahsan.com Firebase.\n *\n * @author Ahsan Mahmood <aoneahsan@gmail.com>\n */\n\nimport {\n collection,\n addDoc,\n serverTimestamp,\n} from 'firebase/firestore';\nimport { getSharedFeaturesDb } from '../firebase/init';\nimport { getConfig, getState } from '../firebase/config';\nimport type {\n AdAction,\n AdPlacement,\n AdVariant,\n RecordImpressionInput,\n AdHistoryEntry,\n} from '../types/campaigns';\n\n// ============================================================================\n// CONSTANTS\n// ============================================================================\n\nconst COLLECTION_IMPRESSIONS = 'zaions_impressions';\nconst LOCAL_STORAGE_KEY = 'shared_features_ad_history';\n\n// ============================================================================\n// LOCAL HISTORY MANAGEMENT\n// ============================================================================\n\n/**\n * Get ad history from local storage\n */\nasync function getLocalAdHistory(): Promise<Record<string, AdHistoryEntry>> {\n try {\n // Try Capacitor Preferences first\n const { Preferences } = await import('@capacitor/preferences');\n const result = await Preferences.get({ key: LOCAL_STORAGE_KEY });\n if (result.value) {\n return JSON.parse(result.value);\n }\n } catch {\n // Fallback to localStorage\n try {\n const stored = localStorage.getItem(LOCAL_STORAGE_KEY);\n if (stored) {\n return JSON.parse(stored);\n }\n } catch {\n // Ignore\n }\n }\n return {};\n}\n\n/**\n * Save ad history to local storage\n */\nasync function saveLocalAdHistory(\n history: Record<string, AdHistoryEntry>\n): Promise<void> {\n const serialized = JSON.stringify(history);\n\n try {\n // Try Capacitor Preferences first\n const { Preferences } = await import('@capacitor/preferences');\n await Preferences.set({ key: LOCAL_STORAGE_KEY, value: serialized });\n } catch {\n // Fallback to localStorage\n try {\n localStorage.setItem(LOCAL_STORAGE_KEY, serialized);\n } catch {\n // Ignore storage errors\n }\n }\n}\n\n/**\n * Update local ad history for a campaign\n */\nasync function updateLocalHistory(\n campaignId: string,\n productId: string,\n action: AdAction,\n frequencyDays: number\n): Promise<void> {\n const history = await getLocalAdHistory();\n const now = Date.now();\n const nextEligibleAt = now + frequencyDays * 24 * 60 * 60 * 1000;\n\n const existing = history[campaignId];\n\n if (existing) {\n history[campaignId] = {\n ...existing,\n lastSeenAt: now,\n impressionCount:\n action === 'impression'\n ? existing.impressionCount + 1\n : existing.impressionCount,\n clicked: existing.clicked || action === 'click',\n closed: existing.closed || action === 'close',\n nextEligibleAt:\n action === 'impression' ? nextEligibleAt : existing.nextEligibleAt,\n };\n } else {\n history[campaignId] = {\n campaignId,\n productId,\n lastSeenAt: now,\n impressionCount: action === 'impression' ? 1 : 0,\n clicked: action === 'click',\n closed: action === 'close',\n nextEligibleAt,\n };\n }\n\n await saveLocalAdHistory(history);\n}\n\n// ============================================================================\n// ELIGIBILITY CHECKING\n// ============================================================================\n\n/**\n * Check if user is eligible to see a campaign (based on frequency capping)\n */\nexport async function isEligibleForCampaign(\n campaignId: string,\n _frequencyDays: number = 20\n): Promise<boolean> {\n // Note: _frequencyDays kept for API consistency; eligibility uses stored nextEligibleAt\n const history = await getLocalAdHistory();\n const entry = history[campaignId];\n\n if (!entry) return true;\n\n return Date.now() >= entry.nextEligibleAt;\n}\n\n/**\n * Get all campaigns the user is currently eligible to see\n */\nexport async function getEligibleCampaignIds(): Promise<string[]> {\n const history = await getLocalAdHistory();\n const now = Date.now();\n\n return Object.entries(history)\n .filter(([, entry]) => now >= entry.nextEligibleAt)\n .map(([campaignId]) => campaignId);\n}\n\n/**\n * Get local ad history for a campaign\n */\nexport async function getCampaignHistory(\n campaignId: string\n): Promise<AdHistoryEntry | null> {\n const history = await getLocalAdHistory();\n return history[campaignId] || null;\n}\n\n// ============================================================================\n// IMPRESSION RECORDING\n// ============================================================================\n\n/**\n * Record an ad impression, click, or close\n *\n * This sends the event to the centralized Firebase and updates local history.\n */\nexport async function recordImpression(\n input: RecordImpressionInput,\n frequencyDays: number = 20\n): Promise<void> {\n const config = getConfig();\n const state = getState();\n const db = getSharedFeaturesDb();\n\n const impressionData = {\n campaignId: input.campaignId,\n productId: input.productId,\n projectId: config.projectId,\n userId: null, // Consumer projects don't authenticate with aoneahsan.com\n deviceId: state.deviceId || 'unknown',\n platform: config.platform,\n placement: input.placement,\n action: input.action,\n variant: input.variant,\n timestamp: serverTimestamp(),\n ...(input.sessionId && { sessionId: input.sessionId }),\n };\n\n try {\n // Record to centralized Firebase\n await addDoc(collection(db, COLLECTION_IMPRESSIONS), impressionData);\n\n if (config.debug) {\n console.log('[shared-features] Recorded impression:', impressionData);\n }\n } catch (error) {\n if (config.debug) {\n console.error('[shared-features] Failed to record impression:', error);\n }\n // Don't throw - we don't want analytics failures to break the UI\n }\n\n // Update local history for frequency capping\n await updateLocalHistory(\n input.campaignId,\n input.productId,\n input.action,\n frequencyDays\n );\n}\n\n/**\n * Convenience function to record an impression\n */\nexport async function trackImpression(\n campaignId: string,\n productId: string,\n placement: AdPlacement,\n variant: AdVariant,\n frequencyDays?: number\n): Promise<void> {\n await recordImpression(\n {\n campaignId,\n productId,\n placement,\n action: 'impression',\n variant,\n },\n frequencyDays\n );\n}\n\n/**\n * Convenience function to record a click\n */\nexport async function trackClick(\n campaignId: string,\n productId: string,\n placement: AdPlacement,\n variant: AdVariant\n): Promise<void> {\n await recordImpression({\n campaignId,\n productId,\n placement,\n action: 'click',\n variant,\n });\n}\n\n/**\n * Convenience function to record a close/dismiss\n */\nexport async function trackClose(\n campaignId: string,\n productId: string,\n placement: AdPlacement,\n variant: AdVariant\n): Promise<void> {\n await recordImpression({\n campaignId,\n productId,\n placement,\n action: 'close',\n variant,\n });\n}\n","/**\n * Feature Flags Service\n *\n * Handles fetching and checking feature flags from the centralized\n * aoneahsan.com Firebase backend. Consumer projects use this to\n * determine which features are available and at what version.\n *\n * @author Ahsan Mahmood <aoneahsan@gmail.com>\n */\n\nimport {\n doc,\n getDoc,\n setDoc,\n onSnapshot,\n Timestamp,\n Unsubscribe,\n} from 'firebase/firestore';\nimport { getSharedFeaturesDb } from '../firebase/init';\nimport { getConfig } from '../firebase/config';\nimport type {\n FeatureId,\n FeatureConfig,\n FeatureFlagsDocument,\n FeatureAvailability,\n SharedFeaturesStatus,\n UpdateFeatureConfigInput,\n UpdateGlobalFlagsInput,\n ConsumerFeatureVersions,\n} from '../types/featureFlags';\nimport {\n COLLECTION_FEATURE_FLAGS,\n FEATURE_FLAGS_DOC_ID,\n DEFAULT_FEATURE_FLAGS,\n} from '../types/featureFlags';\n\n// Re-export constants\nexport { COLLECTION_FEATURE_FLAGS, FEATURE_FLAGS_DOC_ID } from '../types/featureFlags';\n\n// ============================================================================\n// CACHE\n// ============================================================================\n\ninterface FeatureFlagsCache {\n data: FeatureFlagsDocument | null;\n timestamp: number;\n}\n\nlet flagsCache: FeatureFlagsCache | null = null;\nconst CACHE_TTL_MS = 2 * 60 * 1000; // 2 minutes (shorter than campaigns for fresher data)\n\n/**\n * Check if cache is valid\n */\nfunction isCacheValid(): boolean {\n if (!flagsCache || !flagsCache.data) return false;\n return Date.now() - flagsCache.timestamp < CACHE_TTL_MS;\n}\n\n/**\n * Clear the feature flags cache\n */\nexport function clearFeatureFlagsCache(): void {\n flagsCache = null;\n}\n\n// ============================================================================\n// HELPER FUNCTIONS\n// ============================================================================\n\n/**\n * Convert Firestore document to FeatureFlagsDocument\n */\nfunction docToFeatureFlags(\n docId: string,\n data: Record<string, unknown>\n): FeatureFlagsDocument {\n return {\n id: docId,\n globalEnabled: (data.globalEnabled as boolean) ?? true,\n currentApiVersion: (data.currentApiVersion as string) ?? 'v1',\n supportedApiVersions: (data.supportedApiVersions as string[]) ?? ['v1'],\n features: data.features as FeatureFlagsDocument['features'],\n maintenanceMode: (data.maintenanceMode as boolean) ?? false,\n maintenanceMessage: data.maintenanceMessage as string | undefined,\n maintenanceEndTime: data.maintenanceEndTime as Timestamp | undefined,\n updatedAt: data.updatedAt as Timestamp,\n updatedBy: data.updatedBy as string,\n };\n}\n\n/**\n * Get the consumer's requested version for a feature\n */\nfunction getConsumerVersion(\n featureId: FeatureId,\n consumerVersions?: ConsumerFeatureVersions\n): number | undefined {\n if (!consumerVersions) return undefined;\n return consumerVersions[featureId];\n}\n\n// ============================================================================\n// FETCH FUNCTIONS\n// ============================================================================\n\n/**\n * Fetch feature flags from Firestore\n *\n * @param forceRefresh - Skip cache and fetch fresh data\n * @returns Feature flags document or null if not found\n */\nexport async function fetchFeatureFlags(\n forceRefresh = false\n): Promise<FeatureFlagsDocument | null> {\n // Check cache first\n if (!forceRefresh && isCacheValid()) {\n return flagsCache!.data;\n }\n\n try {\n const db = getSharedFeaturesDb();\n const docRef = doc(db, COLLECTION_FEATURE_FLAGS, FEATURE_FLAGS_DOC_ID);\n const docSnap = await getDoc(docRef);\n\n if (!docSnap.exists()) {\n // Return default flags if document doesn't exist\n const config = getConfig();\n if (config.debug) {\n console.log(\n '[shared-features] Feature flags document not found, using defaults'\n );\n }\n\n // Create default document for first-time setup\n const defaultDoc: FeatureFlagsDocument = {\n ...DEFAULT_FEATURE_FLAGS,\n updatedAt: Timestamp.now(),\n updatedBy: 'system',\n } as FeatureFlagsDocument;\n\n flagsCache = {\n data: defaultDoc,\n timestamp: Date.now(),\n };\n\n return defaultDoc;\n }\n\n const flags = docToFeatureFlags(docSnap.id, docSnap.data());\n\n // Update cache\n flagsCache = {\n data: flags,\n timestamp: Date.now(),\n };\n\n const config = getConfig();\n if (config.debug) {\n console.log('[shared-features] Feature flags fetched:', {\n globalEnabled: flags.globalEnabled,\n maintenanceMode: flags.maintenanceMode,\n apiVersion: flags.currentApiVersion,\n });\n }\n\n return flags;\n } catch (error) {\n const config = getConfig();\n if (config.debug) {\n console.error('[shared-features] Error fetching feature flags:', error);\n }\n\n // Return cached data if available, even if stale\n if (flagsCache?.data) {\n return flagsCache.data;\n }\n\n return null;\n }\n}\n\n/**\n * Subscribe to real-time feature flag updates\n *\n * @param callback - Function to call when flags change\n * @returns Unsubscribe function\n */\nexport function subscribeToFeatureFlags(\n callback: (flags: FeatureFlagsDocument | null) => void\n): Unsubscribe {\n const db = getSharedFeaturesDb();\n const docRef = doc(db, COLLECTION_FEATURE_FLAGS, FEATURE_FLAGS_DOC_ID);\n\n return onSnapshot(\n docRef,\n (docSnap) => {\n if (!docSnap.exists()) {\n callback(null);\n return;\n }\n\n const flags = docToFeatureFlags(docSnap.id, docSnap.data());\n\n // Update cache\n flagsCache = {\n data: flags,\n timestamp: Date.now(),\n };\n\n callback(flags);\n },\n (error) => {\n const config = getConfig();\n if (config.debug) {\n console.error(\n '[shared-features] Error subscribing to feature flags:',\n error\n );\n }\n callback(null);\n }\n );\n}\n\n// ============================================================================\n// FEATURE AVAILABILITY CHECKS\n// ============================================================================\n\n/**\n * Check if a specific feature is available\n *\n * @param featureId - The feature to check\n * @param consumerVersions - Optional consumer version preferences\n * @returns Availability details\n */\nexport async function checkFeatureAvailability(\n featureId: FeatureId,\n consumerVersions?: ConsumerFeatureVersions\n): Promise<FeatureAvailability> {\n const flags = await fetchFeatureFlags();\n const config = getConfig();\n\n // Default unavailable response\n const unavailable: FeatureAvailability = {\n available: false,\n enabled: false,\n version: 1,\n deprecated: false,\n upgradeRequired: false,\n unavailableReason: 'Feature flags not loaded',\n };\n\n if (!flags) {\n return unavailable;\n }\n\n // Check global enabled\n if (!flags.globalEnabled) {\n return {\n ...unavailable,\n unavailableReason: 'shared-features is globally disabled',\n };\n }\n\n // Check maintenance mode\n if (flags.maintenanceMode) {\n return {\n ...unavailable,\n unavailableReason: flags.maintenanceMessage || 'Maintenance in progress',\n };\n }\n\n // Get feature config\n const featureConfig = flags.features[featureId];\n if (!featureConfig) {\n return {\n ...unavailable,\n unavailableReason: `Feature '${featureId}' not found in configuration`,\n };\n }\n\n // Check if feature is enabled\n if (!featureConfig.enabled) {\n return {\n ...unavailable,\n version: featureConfig.version,\n unavailableReason: `Feature '${featureId}' is not enabled`,\n };\n }\n\n // Check platform availability\n if (\n featureConfig.availablePlatforms &&\n featureConfig.availablePlatforms.length > 0\n ) {\n if (!featureConfig.availablePlatforms.includes(config.platform)) {\n return {\n ...unavailable,\n version: featureConfig.version,\n unavailableReason: `Feature '${featureId}' is not available on platform '${config.platform}'`,\n };\n }\n }\n\n // Check project availability\n if (\n featureConfig.availableProjects &&\n featureConfig.availableProjects.length > 0\n ) {\n if (!featureConfig.availableProjects.includes(config.projectId)) {\n return {\n ...unavailable,\n version: featureConfig.version,\n unavailableReason: `Feature '${featureId}' is not available for project '${config.projectId}'`,\n };\n }\n }\n\n // Check consumer version compatibility\n const consumerVersion = getConsumerVersion(featureId, consumerVersions);\n const currentVersion = featureConfig.version;\n const minVersion = featureConfig.minVersion;\n const maxVersion = featureConfig.maxVersion;\n\n let deprecated = false;\n let deprecationWarning: string | undefined;\n let upgradeRequired = false;\n let upgradeMessage: string | undefined;\n\n if (consumerVersion !== undefined) {\n // Consumer specified a version\n if (consumerVersion < minVersion) {\n // Version too old, upgrade required\n upgradeRequired = true;\n upgradeMessage = `Feature '${featureId}' requires minimum version ${minVersion}, but consumer is using version ${consumerVersion}. Please upgrade.`;\n } else if (consumerVersion < currentVersion) {\n // Version is older but still supported\n deprecated = true;\n deprecationWarning =\n featureConfig.deprecationMessage ||\n `Feature '${featureId}' version ${consumerVersion} is deprecated. Current version is ${currentVersion}.`;\n } else if (consumerVersion > maxVersion) {\n // Version too new (edge case)\n return {\n ...unavailable,\n version: currentVersion,\n unavailableReason: `Feature '${featureId}' version ${consumerVersion} is not yet supported. Maximum supported version is ${maxVersion}.`,\n };\n }\n }\n\n // Feature is available\n return {\n available: !upgradeRequired,\n enabled: true,\n version: currentVersion,\n deprecated,\n deprecationWarning,\n upgradeRequired,\n upgradeMessage,\n };\n}\n\n/**\n * Quick check if a feature is available (cached)\n *\n * @param featureId - The feature to check\n * @returns true if feature is available\n */\nexport function isFeatureEnabled(featureId: FeatureId): boolean {\n // Use cached data for quick checks\n if (!flagsCache?.data) return false;\n\n const flags = flagsCache.data;\n\n if (!flags.globalEnabled || flags.maintenanceMode) return false;\n\n const featureConfig = flags.features[featureId];\n if (!featureConfig || !featureConfig.enabled) return false;\n\n // Quick platform/project check\n const config = getConfig();\n\n if (\n featureConfig.availablePlatforms &&\n featureConfig.availablePlatforms.length > 0\n ) {\n if (!featureConfig.availablePlatforms.includes(config.platform)) {\n return false;\n }\n }\n\n if (\n featureConfig.availableProjects &&\n featureConfig.availableProjects.length > 0\n ) {\n if (!featureConfig.availableProjects.includes(config.projectId)) {\n return false;\n }\n }\n\n return true;\n}\n\n/**\n * Get the current version of a feature\n *\n * @param featureId - The feature to check\n * @returns Current version number or 0 if not available\n */\nexport function getFeatureVersion(featureId: FeatureId): number {\n if (!flagsCache?.data) return 0;\n return flagsCache.data.features[featureId]?.version ?? 0;\n}\n\n// ============================================================================\n// STATUS FUNCTIONS\n// ============================================================================\n\n/**\n * Get overall status of shared-features for the current consumer\n *\n * @param consumerVersions - Optional consumer version preferences\n * @returns Complete status object\n */\nexport async function getSharedFeaturesStatus(\n consumerVersions?: ConsumerFeatureVersions\n): Promise<SharedFeaturesStatus> {\n const flags = await fetchFeatureFlags();\n\n const defaultStatus: SharedFeaturesStatus = {\n operational: false,\n maintenanceMode: false,\n apiVersion: 'v1',\n features: {} as Record<FeatureId, FeatureAvailability>,\n deprecatedFeatures: [],\n upgradeRequiredFeatures: [],\n fetchedAt: new Date(),\n };\n\n if (!flags) {\n return defaultStatus;\n }\n\n // Check all features\n const featureIds: FeatureId[] = [\n 'campaigns',\n 'broadcasts',\n 'contactInfo',\n 'developerInfo',\n 'socialLinks',\n 'paymentOptions',\n 'addressInfo',\n 'services',\n 'skills',\n 'testimonials',\n 'projects',\n ];\n\n const features: Record<FeatureId, FeatureAvailability> = {} as Record<\n FeatureId,\n FeatureAvailability\n >;\n const deprecatedFeatures: FeatureId[] = [];\n const upgradeRequiredFeatures: FeatureId[] = [];\n\n for (const featureId of featureIds) {\n const availability = await checkFeatureAvailability(\n featureId,\n consumerVersions\n );\n features[featureId] = availability;\n\n if (availability.deprecated) {\n deprecatedFeatures.push(featureId);\n }\n\n if (availability.upgradeRequired) {\n upgradeRequiredFeatures.push(featureId);\n }\n }\n\n return {\n operational: flags.globalEnabled && !flags.maintenanceMode,\n maintenanceMode: flags.maintenanceMode,\n maintenanceMessage: flags.maintenanceMessage,\n apiVersion: flags.currentApiVersion,\n features,\n deprecatedFeatures,\n upgradeRequiredFeatures,\n fetchedAt: new Date(),\n };\n}\n\n// ============================================================================\n// ADMIN FUNCTIONS\n// ============================================================================\n\n/**\n * Update a feature's configuration (admin only)\n *\n * @param input - Feature configuration updates\n * @param adminEmail - Email of admin making the change\n */\nexport async function updateFeatureConfig(\n input: UpdateFeatureConfigInput,\n adminEmail: string\n): Promise<void> {\n const db = getSharedFeaturesDb();\n const docRef = doc(db, COLLECTION_FEATURE_FLAGS, FEATURE_FLAGS_DOC_ID);\n\n // Fetch current document\n const docSnap = await getDoc(docRef);\n let currentFlags: FeatureFlagsDocument;\n\n if (!docSnap.exists()) {\n // Create with defaults\n currentFlags = {\n ...DEFAULT_FEATURE_FLAGS,\n updatedAt: Timestamp.now(),\n updatedBy: adminEmail,\n } as FeatureFlagsDocument;\n } else {\n currentFlags = docToFeatureFlags(docSnap.id, docSnap.data());\n }\n\n // Update the specific feature\n const featureConfig = currentFlags.features[input.featureId];\n const updatedFeature: FeatureConfig = {\n enabled: input.enabled ?? featureConfig.enabled,\n version: input.version ?? featureConfig.version,\n minVersion: input.minVersion ?? featureConfig.minVersion,\n maxVersion: input.maxVersion ?? featureConfig.maxVersion,\n deprecationMessage: input.deprecationMessage ?? featureConfig.deprecationMessage,\n requiresAuth: input.requiresAuth ?? featureConfig.requiresAuth,\n availablePlatforms: input.availablePlatforms ?? featureConfig.availablePlatforms,\n availableProjects: input.availableProjects ?? featureConfig.availableProjects,\n };\n\n // Update document\n await setDoc(\n docRef,\n {\n ...currentFlags,\n features: {\n ...currentFlags.features,\n [input.featureId]: updatedFeature,\n },\n updatedAt: Timestamp.now(),\n updatedBy: adminEmail,\n },\n { merge: true }\n );\n\n // Clear cache\n clearFeatureFlagsCache();\n}\n\n/**\n * Update global flags (admin only)\n *\n * @param input - Global flag updates\n * @param adminEmail - Email of admin making the change\n */\nexport async function updateGlobalFlags(\n input: UpdateGlobalFlagsInput,\n adminEmail: string\n): Promise<void> {\n const db = getSharedFeaturesDb();\n const docRef = doc(db, COLLECTION_FEATURE_FLAGS, FEATURE_FLAGS_DOC_ID);\n\n const updateData: Record<string, unknown> = {\n updatedAt: Timestamp.now(),\n updatedBy: adminEmail,\n };\n\n if (input.globalEnabled !== undefined) {\n updateData.globalEnabled = input.globalEnabled;\n }\n\n if (input.currentApiVersion !== undefined) {\n updateData.currentApiVersion = input.currentApiVersion;\n }\n\n if (input.supportedApiVersions !== undefined) {\n updateData.supportedApiVersions = input.supportedApiVersions;\n }\n\n if (input.maintenanceMode !== undefined) {\n updateData.maintenanceMode = input.maintenanceMode;\n }\n\n if (input.maintenanceMessage !== undefined) {\n updateData.maintenanceMessage = input.maintenanceMessage;\n }\n\n if (input.maintenanceEndTime !== undefined) {\n updateData.maintenanceEndTime = input.maintenanceEndTime\n ? Timestamp.fromDate(input.maintenanceEndTime)\n : null;\n }\n\n await setDoc(docRef, updateData, { merge: true });\n\n // Clear cache\n clearFeatureFlagsCache();\n}\n\n/**\n * Initialize feature flags document with defaults (admin only)\n *\n * @param adminEmail - Email of admin creating the document\n */\nexport async function initializeFeatureFlags(\n adminEmail: string\n): Promise<void> {\n const db = getSharedFeaturesDb();\n const docRef = doc(db, COLLECTION_FEATURE_FLAGS, FEATURE_FLAGS_DOC_ID);\n\n const docSnap = await getDoc(docRef);\n\n if (docSnap.exists()) {\n throw new Error('Feature flags document already exists');\n }\n\n await setDoc(docRef, {\n ...DEFAULT_FEATURE_FLAGS,\n updatedAt: Timestamp.now(),\n updatedBy: adminEmail,\n });\n\n // Clear cache\n clearFeatureFlagsCache();\n}\n","/**\n * Common Features Service\n *\n * Handles fetching common features from the centralized\n * aoneahsan.com Firebase backend.\n *\n * @author Ahsan Mahmood <aoneahsan@gmail.com>\n */\n\nimport {\n collection,\n doc,\n getDoc,\n getDocs,\n query,\n orderBy,\n limit as firestoreLimit,\n onSnapshot,\n Timestamp,\n Unsubscribe,\n} from 'firebase/firestore';\nimport { getSharedFeaturesDb } from '../firebase/init';\nimport { getConfig } from '../firebase/config';\nimport { isFeatureEnabled } from './featureFlags';\nimport {\n COMMON_FEATURE_COLLECTIONS,\n type ContactInfo,\n type DeveloperInfo,\n type SocialLink,\n type AddressInfo,\n type PaymentOption,\n type Service,\n type Skill,\n type Testimonial,\n type Project,\n type FetchSocialLinksOptions,\n type FetchServicesOptions,\n type FetchSkillsOptions,\n type FetchTestimonialsOptions,\n type FetchPaymentOptionsOptions,\n type FetchProjectsOptions,\n} from '../types/commonFeatures';\n\n// ============================================================================\n// CACHE\n// ============================================================================\n\ninterface Cache<T> {\n data: T | null;\n timestamp: number;\n}\n\nconst CACHE_TTL_MS = 5 * 60 * 1000; // 5 minutes\n\nlet contactInfoCache: Cache<ContactInfo> | null = null;\nlet developerInfoCache: Cache<DeveloperInfo> | null = null;\nlet addressInfoCache: Cache<AddressInfo> | null = null;\nlet socialLinksCache: Cache<SocialLink[]> | null = null;\nlet paymentOptionsCache: Cache<PaymentOption[]> | null = null;\nlet servicesCache: Cache<Service[]> | null = null;\nlet skillsCache: Cache<Skill[]> | null = null;\nlet testimonialsCache: Cache<Testimonial[]> | null = null;\nlet projectsCache: Cache<Project[]> | null = null;\n\nfunction isCacheValid<T>(cache: Cache<T> | null): boolean {\n if (!cache || !cache.data) return false;\n return Date.now() - cache.timestamp < CACHE_TTL_MS;\n}\n\nexport function clearAllCommonFeaturesCache(): void {\n contactInfoCache = null;\n developerInfoCache = null;\n addressInfoCache = null;\n socialLinksCache = null;\n paymentOptionsCache = null;\n servicesCache = null;\n skillsCache = null;\n testimonialsCache = null;\n projectsCache = null;\n}\n\n// ============================================================================\n// CONTACT INFO\n// ============================================================================\n\nfunction docToContactInfo(docId: string, data: Record<string, unknown>): ContactInfo {\n // Portfolio may nest timezone in location object\n const locationObj = data.location as Record<string, unknown> | undefined;\n return {\n id: docId,\n email: (data.email as string) || '',\n supportEmail: data.supportEmail as string | undefined,\n phone: data.phone as string | undefined,\n whatsapp: data.whatsapp as string | undefined,\n telegram: data.telegram as string | undefined,\n skype: data.skype as string | undefined,\n freelanceAvailable: ((data.freelanceAvailable ?? data.availableForFreelance) as boolean) ?? false,\n workingHours: data.workingHours as string | undefined,\n timezone: (data.timezone ?? (typeof locationObj === 'object' && locationObj ? locationObj.timezone : undefined)) as string | undefined,\n preferredContact: (data.preferredContact ?? data.preferredContactMethod) as ContactInfo['preferredContact'],\n responseTime: data.responseTime as string | undefined,\n updatedAt: data.updatedAt as Timestamp,\n };\n}\n\nexport async function fetchContactInfo(): Promise<ContactInfo | null> {\n if (!isFeatureEnabled('contactInfo')) {\n const config = getConfig();\n if (config.debug) console.log('[shared-features] contactInfo feature is disabled');\n return null;\n }\n\n if (isCacheValid(contactInfoCache)) return contactInfoCache!.data;\n\n try {\n const db = getSharedFeaturesDb();\n const docRef = doc(db, COMMON_FEATURE_COLLECTIONS.CONTACT_INFO, 'main');\n const docSnap = await getDoc(docRef);\n\n if (!docSnap.exists()) return null;\n\n const data = docToContactInfo(docSnap.id, docSnap.data());\n contactInfoCache = { data, timestamp: Date.now() };\n return data;\n } catch (error) {\n const config = getConfig();\n if (config.debug) console.error('[shared-features] Error fetching contact info:', error);\n return contactInfoCache?.data ?? null;\n }\n}\n\nexport function subscribeToContactInfo(callback: (data: ContactInfo | null) => void): Unsubscribe {\n const db = getSharedFeaturesDb();\n const docRef = doc(db, COMMON_FEATURE_COLLECTIONS.CONTACT_INFO, 'main');\n\n return onSnapshot(docRef, (docSnap) => {\n if (!docSnap.exists()) {\n callback(null);\n return;\n }\n const data = docToContactInfo(docSnap.id, docSnap.data());\n contactInfoCache = { data, timestamp: Date.now() };\n callback(data);\n });\n}\n\nexport function clearContactInfoCache(): void {\n contactInfoCache = null;\n}\n\n// ============================================================================\n// DEVELOPER INFO\n// ============================================================================\n\nfunction docToDeveloperInfo(docId: string, data: Record<string, unknown>): DeveloperInfo {\n return {\n id: docId,\n name: (data.name as string) || '',\n title: (data.title as string) || '',\n tagline: data.tagline as string | undefined,\n bio: (data.bio as string) || '',\n shortBio: data.shortBio as string | undefined,\n avatar: data.avatar as string | undefined,\n website: data.website as string | undefined,\n github: data.github as string | undefined,\n linkedin: data.linkedin as string | undefined,\n twitter: data.twitter as string | undefined,\n yearsOfExperience: data.yearsOfExperience as number | undefined,\n location: data.location as string | undefined,\n availableForHire: (data.availableForHire as boolean) ?? false,\n resumeUrl: data.resumeUrl as string | undefined,\n updatedAt: data.updatedAt as Timestamp,\n };\n}\n\nexport async function fetchDeveloperInfo(): Promise<DeveloperInfo | null> {\n if (!isFeatureEnabled('developerInfo')) {\n const config = getConfig();\n if (config.debug) console.log('[shared-features] developerInfo feature is disabled');\n return null;\n }\n\n if (isCacheValid(developerInfoCache)) return developerInfoCache!.data;\n\n try {\n const db = getSharedFeaturesDb();\n const docRef = doc(db, COMMON_FEATURE_COLLECTIONS.DEVELOPER_INFO, 'main');\n const docSnap = await getDoc(docRef);\n\n if (!docSnap.exists()) return null;\n\n const data = docToDeveloperInfo(docSnap.id, docSnap.data());\n developerInfoCache = { data, timestamp: Date.now() };\n return data;\n } catch (error) {\n const config = getConfig();\n if (config.debug) console.error('[shared-features] Error fetching developer info:', error);\n return developerInfoCache?.data ?? null;\n }\n}\n\nexport function subscribeToDeveloperInfo(callback: (data: DeveloperInfo | null) => void): Unsubscribe {\n const db = getSharedFeaturesDb();\n const docRef = doc(db, COMMON_FEATURE_COLLECTIONS.DEVELOPER_INFO, 'main');\n\n return onSnapshot(docRef, (docSnap) => {\n if (!docSnap.exists()) {\n callback(null);\n return;\n }\n const data = docToDeveloperInfo(docSnap.id, docSnap.data());\n developerInfoCache = { data, timestamp: Date.now() };\n callback(data);\n });\n}\n\nexport function clearDeveloperInfoCache(): void {\n developerInfoCache = null;\n}\n\n// ============================================================================\n// ADDRESS INFO\n// ============================================================================\n\nfunction docToAddressInfo(docId: string, data: Record<string, unknown>): AddressInfo {\n // Portfolio may nest address fields in addressDetails object\n const details = (data.addressDetails as Record<string, unknown>) || {};\n return {\n id: docId,\n label: data.label as string | undefined,\n streetAddress: (data.streetAddress ?? details.streetAddress) as string | undefined,\n city: (data.city ?? details.city) as string | undefined,\n state: (data.state ?? details.state) as string | undefined,\n postalCode: (data.postalCode ?? details.postalCode) as string | undefined,\n country: (data.country ?? details.country) as string | undefined,\n fullAddress: (data.fullAddress ?? data.displayAddress) as string | undefined,\n googleMapsUrl: (data.googleMapsUrl ?? data.googleMapsLink) as string | undefined,\n isPublic: (data.isPublic as boolean) ?? false,\n updatedAt: data.updatedAt as Timestamp,\n };\n}\n\nexport async function fetchAddressInfo(): Promise<AddressInfo | null> {\n if (!isFeatureEnabled('addressInfo')) {\n const config = getConfig();\n if (config.debug) console.log('[shared-features] addressInfo feature is disabled');\n return null;\n }\n\n if (isCacheValid(addressInfoCache)) return addressInfoCache!.data;\n\n try {\n const db = getSharedFeaturesDb();\n const docRef = doc(db, COMMON_FEATURE_COLLECTIONS.ADDRESS_INFO, 'main');\n const docSnap = await getDoc(docRef);\n\n if (!docSnap.exists()) return null;\n\n const data = docToAddressInfo(docSnap.id, docSnap.data());\n\n // Only return if public or user is authorized\n if (!data.isPublic) return null;\n\n addressInfoCache = { data, timestamp: Date.now() };\n return data;\n } catch (error) {\n const config = getConfig();\n if (config.debug) console.error('[shared-features] Error fetching address info:', error);\n return addressInfoCache?.data ?? null;\n }\n}\n\nexport function clearAddressInfoCache(): void {\n addressInfoCache = null;\n}\n\n// ============================================================================\n// SOCIAL LINKS\n// ============================================================================\n\n/**\n * Build showIn array from individual boolean fields written by portfolio admin.\n * Portfolio writes showInFooter, showInContact, showInAbout, showInHeader as booleans.\n */\nfunction buildShowInArray(data: Record<string, unknown>): SocialLink['showIn'] | undefined {\n const hasAnyBool = 'showInFooter' in data || 'showInContact' in data || 'showInAbout' in data || 'showInHeader' in data;\n if (!hasAnyBool) return undefined;\n const result: SocialLink['showIn'] = [];\n if (data.showInFooter) result.push('footer');\n if (data.showInContact) result.push('contact');\n if (data.showInAbout) result.push('about');\n if (data.showInHeader) result.push('header');\n return result.length > 0 ? result : ['footer'];\n}\n\nfunction docToSocialLink(docId: string, data: Record<string, unknown>): SocialLink {\n return {\n id: docId,\n platform: data.platform as SocialLink['platform'],\n url: (data.url as string) || '',\n displayName: data.displayName as string | undefined,\n username: data.username as string | undefined,\n icon: data.icon as string | undefined,\n order: (data.order as number) ?? 0,\n isActive: ((data.isActive ?? data.enabled) as boolean) ?? true,\n showIn: (data.showIn as SocialLink['showIn']) ?? buildShowInArray(data) ?? ['footer'],\n updatedAt: data.updatedAt as Timestamp,\n };\n}\n\nexport async function fetchSocialLinks(options: FetchSocialLinksOptions = {}): Promise<SocialLink[]> {\n if (!isFeatureEnabled('socialLinks')) {\n const config = getConfig();\n if (config.debug) console.log('[shared-features] socialLinks feature is disabled');\n return [];\n }\n\n // Use cache for unfiltered queries\n if (!options.showIn && options.activeOnly !== false && isCacheValid(socialLinksCache)) {\n return socialLinksCache!.data ?? [];\n }\n\n try {\n const db = getSharedFeaturesDb();\n let q = query(collection(db, COMMON_FEATURE_COLLECTIONS.SOCIAL_LINKS), orderBy('order', 'asc'));\n\n const snapshot = await getDocs(q);\n let links = snapshot.docs.map((d) => docToSocialLink(d.id, d.data()));\n\n // Filter by active\n if (options.activeOnly !== false) {\n links = links.filter((l) => l.isActive);\n }\n\n // Filter by showIn\n if (options.showIn && options.showIn.length > 0) {\n links = links.filter((l) => options.showIn!.some((loc) => l.showIn.includes(loc)));\n }\n\n // Cache unfiltered results\n if (!options.showIn && options.activeOnly !== false) {\n socialLinksCache = { data: links, timestamp: Date.now() };\n }\n\n return links;\n } catch (error) {\n const config = getConfig();\n if (config.debug) console.error('[shared-features] Error fetching social links:', error);\n return socialLinksCache?.data ?? [];\n }\n}\n\nexport function clearSocialLinksCache(): void {\n socialLinksCache = null;\n}\n\n// ============================================================================\n// PAYMENT OPTIONS\n// ============================================================================\n\nfunction docToPaymentOption(docId: string, data: Record<string, unknown>): PaymentOption {\n return {\n id: docId,\n type: data.type as PaymentOption['type'],\n name: (data.name as string) || '',\n displayName: data.displayName as string | undefined,\n description: data.description as string | undefined,\n instructions: data.instructions as string | undefined,\n icon: data.icon as string | undefined,\n details: (data.details as PaymentOption['details']) || {},\n isActive: ((data.isActive ?? data.enabled) as boolean) ?? true,\n isPrimary: (data.isPrimary as boolean) ?? false,\n order: (data.order as number) ?? 0,\n updatedAt: data.updatedAt as Timestamp,\n };\n}\n\nexport async function fetchPaymentOptions(options: FetchPaymentOptionsOptions = {}): Promise<PaymentOption[]> {\n if (!isFeatureEnabled('paymentOptions')) {\n const config = getConfig();\n if (config.debug) console.log('[shared-features] paymentOptions feature is disabled');\n return [];\n }\n\n if (!options.type && options.activeOnly !== false && isCacheValid(paymentOptionsCache)) {\n return paymentOptionsCache!.data ?? [];\n }\n\n try {\n const db = getSharedFeaturesDb();\n let q = query(collection(db, COMMON_FEATURE_COLLECTIONS.PAYMENT_OPTIONS), orderBy('order', 'asc'));\n\n const snapshot = await getDocs(q);\n let items = snapshot.docs.map((d) => docToPaymentOption(d.id, d.data()));\n\n if (options.activeOnly !== false) {\n items = items.filter((i) => i.isActive);\n }\n\n if (options.type) {\n items = items.filter((i) => i.type === options.type);\n }\n\n if (!options.type && options.activeOnly !== false) {\n paymentOptionsCache = { data: items, timestamp: Date.now() };\n }\n\n return items;\n } catch (error) {\n const config = getConfig();\n if (config.debug) console.error('[shared-features] Error fetching payment options:', error);\n return paymentOptionsCache?.data ?? [];\n }\n}\n\nexport function clearPaymentOptionsCache(): void {\n paymentOptionsCache = null;\n}\n\n// ============================================================================\n// SERVICES\n// ============================================================================\n\nfunction docToService(docId: string, data: Record<string, unknown>): Service {\n return {\n id: docId,\n title: (data.title as string) || '',\n description: (data.description as string) || '',\n shortDescription: data.shortDescription as string | undefined,\n category: data.category as Service['category'],\n icon: data.icon as string | undefined,\n features: data.features as string[] | undefined,\n technologies: data.technologies as string[] | undefined,\n priceRange: data.priceRange as string | undefined,\n isActive: (data.isActive as boolean) ?? true,\n isFeatured: (data.isFeatured as boolean) ?? false,\n order: (data.order as number) ?? 0,\n updatedAt: data.updatedAt as Timestamp,\n };\n}\n\nexport async function fetchServices(options: FetchServicesOptions = {}): Promise<Service[]> {\n if (!isFeatureEnabled('services')) {\n const config = getConfig();\n if (config.debug) console.log('[shared-features] services feature is disabled');\n return [];\n }\n\n if (!options.category && !options.featuredOnly && options.activeOnly !== false && isCacheValid(servicesCache)) {\n return servicesCache!.data ?? [];\n }\n\n try {\n const db = getSharedFeaturesDb();\n let q = query(collection(db, COMMON_FEATURE_COLLECTIONS.SERVICES), orderBy('order', 'asc'));\n\n const snapshot = await getDocs(q);\n let items = snapshot.docs.map((d) => docToService(d.id, d.data()));\n\n if (options.activeOnly !== false) {\n items = items.filter((i) => i.isActive);\n }\n\n if (options.featuredOnly) {\n items = items.filter((i) => i.isFeatured);\n }\n\n if (options.category) {\n items = items.filter((i) => i.category === options.category);\n }\n\n if (!options.category && !options.featuredOnly && options.activeOnly !== false) {\n servicesCache = { data: items, timestamp: Date.now() };\n }\n\n return items;\n } catch (error) {\n const config = getConfig();\n if (config.debug) console.error('[shared-features] Error fetching services:', error);\n return servicesCache?.data ?? [];\n }\n}\n\nexport function clearServicesCache(): void {\n servicesCache = null;\n}\n\n// ============================================================================\n// SKILLS\n// ============================================================================\n\nfunction docToSkill(docId: string, data: Record<string, unknown>): Skill {\n return {\n id: docId,\n name: (data.name as string) || '',\n category: data.category as Skill['category'],\n level: data.level as Skill['level'],\n yearsOfExperience: data.yearsOfExperience as number | undefined,\n icon: data.icon as string | undefined,\n color: data.color as string | undefined,\n isActive: (data.isActive as boolean) ?? true,\n isFeatured: (data.isFeatured as boolean) ?? false,\n order: (data.order as number) ?? 0,\n updatedAt: data.updatedAt as Timestamp,\n };\n}\n\nexport async function fetchSkills(options: FetchSkillsOptions = {}): Promise<Skill[]> {\n if (!isFeatureEnabled('skills')) {\n const config = getConfig();\n if (config.debug) console.log('[shared-features] skills feature is disabled');\n return [];\n }\n\n if (!options.category && !options.featuredOnly && options.activeOnly !== false && isCacheValid(skillsCache)) {\n return skillsCache!.data ?? [];\n }\n\n try {\n const db = getSharedFeaturesDb();\n let q = query(collection(db, COMMON_FEATURE_COLLECTIONS.SKILLS), orderBy('order', 'asc'));\n\n const snapshot = await getDocs(q);\n let items = snapshot.docs.map((d) => docToSkill(d.id, d.data()));\n\n if (options.activeOnly !== false) {\n items = items.filter((i) => i.isActive);\n }\n\n if (options.featuredOnly) {\n items = items.filter((i) => i.isFeatured);\n }\n\n if (options.category) {\n items = items.filter((i) => i.category === options.category);\n }\n\n if (!options.category && !options.featuredOnly && options.activeOnly !== false) {\n skillsCache = { data: items, timestamp: Date.now() };\n }\n\n return items;\n } catch (error) {\n const config = getConfig();\n if (config.debug) console.error('[shared-features] Error fetching skills:', error);\n return skillsCache?.data ?? [];\n }\n}\n\nexport function clearSkillsCache(): void {\n skillsCache = null;\n}\n\n// ============================================================================\n// TESTIMONIALS\n// ============================================================================\n\nfunction docToTestimonial(docId: string, data: Record<string, unknown>): Testimonial {\n return {\n id: docId,\n authorName: ((data.authorName ?? data.name) as string) || '',\n authorTitle: (data.authorTitle ?? data.title) as string | undefined,\n authorCompany: (data.authorCompany ?? data.company) as string | undefined,\n authorAvatar: (data.authorAvatar ?? data.avatar) as string | undefined,\n authorLinkedin: (data.authorLinkedin ?? data.profileUrl) as string | undefined,\n content: ((data.content ?? data.text) as string) || '',\n shortContent: data.shortContent as string | undefined,\n rating: data.rating as number | undefined,\n projectName: data.projectName as string | undefined,\n projectUrl: data.projectUrl as string | undefined,\n date: data.date as Timestamp | undefined,\n isActive: ((data.isActive ?? data.enabled) as boolean) ?? true,\n isFeatured: (data.isFeatured as boolean) ?? false,\n order: (data.order as number) ?? 0,\n updatedAt: data.updatedAt as Timestamp,\n };\n}\n\nexport async function fetchTestimonials(options: FetchTestimonialsOptions = {}): Promise<Testimonial[]> {\n if (!isFeatureEnabled('testimonials')) {\n const config = getConfig();\n if (config.debug) console.log('[shared-features] testimonials feature is disabled');\n return [];\n }\n\n if (!options.featuredOnly && !options.limit && options.activeOnly !== false && isCacheValid(testimonialsCache)) {\n return testimonialsCache!.data ?? [];\n }\n\n try {\n const db = getSharedFeaturesDb();\n let q = query(collection(db, COMMON_FEATURE_COLLECTIONS.TESTIMONIALS), orderBy('order', 'asc'));\n\n if (options.limit) {\n q = query(q, firestoreLimit(options.limit));\n }\n\n const snapshot = await getDocs(q);\n let items = snapshot.docs.map((d) => docToTestimonial(d.id, d.data()));\n\n if (options.activeOnly !== false) {\n items = items.filter((i) => i.isActive);\n }\n\n if (options.featuredOnly) {\n items = items.filter((i) => i.isFeatured);\n }\n\n if (!options.featuredOnly && !options.limit && options.activeOnly !== false) {\n testimonialsCache = { data: items, timestamp: Date.now() };\n }\n\n return items;\n } catch (error) {\n const config = getConfig();\n if (config.debug) console.error('[shared-features] Error fetching testimonials:', error);\n return testimonialsCache?.data ?? [];\n }\n}\n\nexport function clearTestimonialsCache(): void {\n testimonialsCache = null;\n}\n\n// ============================================================================\n// PROJECTS\n// ============================================================================\n\n/**\n * Build ProjectLink[] from flat URL fields written by portfolio admin.\n * Portfolio writes liveUrl, githubUrl, playStoreUrl, etc. as individual string fields.\n */\nfunction buildLinksFromFlatUrls(data: Record<string, unknown>): Project['links'] | undefined {\n const links: NonNullable<Project['links']> = [];\n if (data.liveUrl) links.push({ type: 'live', url: data.liveUrl as string });\n if (data.githubUrl) links.push({ type: 'github', url: data.githubUrl as string });\n if (data.playStoreUrl) links.push({ type: 'playstore', url: data.playStoreUrl as string });\n if (data.appStoreUrl) links.push({ type: 'appstore', url: data.appStoreUrl as string });\n if (data.npmUrl) links.push({ type: 'npm', url: data.npmUrl as string });\n if (data.docsUrl) links.push({ type: 'docs', url: data.docsUrl as string });\n if (data.demoUrl) links.push({ type: 'demo', url: data.demoUrl as string });\n if (data.chromeExtensionUrl) links.push({ type: 'other', url: data.chromeExtensionUrl as string, label: 'Chrome Extension' });\n if (data.firefoxExtensionUrl) links.push({ type: 'other', url: data.firefoxExtensionUrl as string, label: 'Firefox Extension' });\n if (data.edgeExtensionUrl) links.push({ type: 'other', url: data.edgeExtensionUrl as string, label: 'Edge Extension' });\n return links.length > 0 ? links : undefined;\n}\n\nfunction docToProject(docId: string, data: Record<string, unknown>): Project {\n return {\n id: docId,\n title: (data.title as string) || '',\n slug: ((data.slug ?? data.appIdentifier) as string) || '',\n description: ((data.description ?? data.longDescription) as string) || '',\n shortDescription: data.shortDescription as string | undefined,\n category: data.category as Project['category'],\n status: data.status as Project['status'],\n thumbnailUrl: data.thumbnailUrl as string | undefined,\n images: data.images as string[] | undefined,\n technologies: ((data.technologies ?? data.techStack) as string[]) || [],\n features: data.features as string[] | undefined,\n links: (data.links as Project['links']) ?? buildLinksFromFlatUrls(data),\n clientName: data.clientName as string | undefined,\n startDate: data.startDate as string | undefined,\n endDate: data.endDate as string | undefined,\n isActive: ((data.isActive ?? data.enabled) as boolean) ?? true,\n isFeatured: (data.isFeatured as boolean) ?? false,\n order: (data.order as number) ?? 0,\n updatedAt: data.updatedAt as Timestamp,\n };\n}\n\nexport async function fetchProjects(options: FetchProjectsOptions = {}): Promise<Project[]> {\n if (!isFeatureEnabled('projects')) {\n const config = getConfig();\n if (config.debug) console.log('[shared-features] projects feature is disabled');\n return [];\n }\n\n if (!options.category && !options.status && !options.featuredOnly && !options.limit && options.activeOnly !== false && isCacheValid(projectsCache)) {\n return projectsCache!.data ?? [];\n }\n\n try {\n const db = getSharedFeaturesDb();\n let q = query(collection(db, COMMON_FEATURE_COLLECTIONS.PROJECTS), orderBy('order', 'asc'));\n\n if (options.limit) {\n q = query(q, firestoreLimit(options.limit));\n }\n\n const snapshot = await getDocs(q);\n let items = snapshot.docs.map((d) => docToProject(d.id, d.data()));\n\n if (options.activeOnly !== false) {\n items = items.filter((i) => i.isActive);\n }\n\n if (options.featuredOnly) {\n items = items.filter((i) => i.isFeatured);\n }\n\n if (options.category) {\n items = items.filter((i) => i.category === options.category);\n }\n\n if (options.status) {\n items = items.filter((i) => i.status === options.status);\n }\n\n if (!options.category && !options.status && !options.featuredOnly && !options.limit && options.activeOnly !== false) {\n projectsCache = { data: items, timestamp: Date.now() };\n }\n\n return items;\n } catch (error) {\n const config = getConfig();\n if (config.debug) console.error('[shared-features] Error fetching projects:', error);\n return projectsCache?.data ?? [];\n }\n}\n\nexport async function fetchProjectBySlug(slug: string): Promise<Project | null> {\n if (!isFeatureEnabled('projects')) return null;\n\n try {\n // First check cache\n if (isCacheValid(projectsCache)) {\n const cached = projectsCache!.data?.find((p) => p.slug === slug);\n if (cached) return cached;\n }\n\n // Fetch all and find\n const projects = await fetchProjects();\n return projects.find((p) => p.slug === slug) ?? null;\n } catch (error) {\n const config = getConfig();\n if (config.debug) console.error('[shared-features] Error fetching project by slug:', error);\n return null;\n }\n}\n\nexport function clearProjectsCache(): void {\n projectsCache = null;\n}\n"],"names":["getApps","app","initializeApp","getFirestore","getAuth","setCommonFeatureCollectionNames","CACHE_TTL_MS","isCacheValid","getDocs","collection","getDoc","doc","query","where","orderBy","firestoreLimit","Timestamp","state","serverTimestamp","addDoc","COLLECTION_FEATURE_FLAGS","FEATURE_FLAGS_DOC_ID","config","DEFAULT_FEATURE_FLAGS","onSnapshot","setDoc","COMMON_FEATURE_COLLECTIONS"],"mappings":"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"}
|
|
1
|
+
{"version":3,"file":"commonFeatures-BuY97_K4.cjs","sources":["../src/firebase/config.ts","../src/firebase/init.ts","../src/services/campaigns.ts","../src/services/analytics.ts","../src/services/featureFlags.ts","../src/services/commonFeatures.ts"],"sourcesContent":["/**\n * Firebase Configuration Types\n *\n * Types and interfaces for configuring the shared-features Firebase connection.\n *\n * @author Ahsan Mahmood <aoneahsan@gmail.com>\n */\n\nimport type { CommonFeatureCollectionKey } from '../types/commonFeatures';\n\n/**\n * Firebase configuration object\n */\nexport interface FirebaseConfig {\n apiKey: string;\n authDomain: string;\n projectId: string;\n storageBucket?: string;\n messagingSenderId?: string;\n appId?: string;\n measurementId?: string;\n}\n\n/**\n * Target platform for the consumer project\n */\nexport type ConsumerPlatform = 'web' | 'android' | 'ios' | 'extension';\n\n/**\n * Feature version preferences for a consumer project\n * Specifies which API versions the consumer supports\n */\nexport interface ConsumerFeatureVersions {\n /** Campaigns API version */\n campaigns?: number;\n /** Broadcasts API version */\n broadcasts?: number;\n /** Contact info API version */\n contactInfo?: number;\n /** Developer info API version */\n developerInfo?: number;\n /** Social links API version */\n socialLinks?: number;\n /** Payment options API version */\n paymentOptions?: number;\n /** Address info API version */\n addressInfo?: number;\n /** Services API version */\n services?: number;\n /** Skills API version */\n skills?: number;\n /** Testimonials API version */\n testimonials?: number;\n /** Projects API version */\n projects?: number;\n}\n\n/**\n * Configuration for initializing shared-features\n */\nexport interface SharedFeaturesConfig {\n /**\n * Firebase configuration for aoneahsan.com's Firebase project.\n * All values from environment variables.\n */\n firebaseConfig: FirebaseConfig;\n\n /**\n * Unique identifier for this project (e.g., 'ztools', '2fa-studio')\n */\n projectId: string;\n\n /**\n * Display name for this project (e.g., 'ZTools', '2FA Studio')\n */\n projectName: string;\n\n /**\n * Platform type for targeting\n */\n platform: ConsumerPlatform;\n\n /**\n * Whether to enable debug logging (default: false)\n */\n debug?: boolean;\n\n /**\n * Feature version preferences for this consumer.\n * Specifies which API versions this consumer supports.\n * If not specified, latest versions are used.\n */\n featureVersions?: ConsumerFeatureVersions;\n\n /**\n * Override collection names for common features.\n * Use this to point shared-features at existing collections\n * instead of creating new zaions_ prefixed ones.\n *\n * @example\n * ```typescript\n * collectionNames: {\n * PROJECTS: 'portfolio_projects',\n * CONTACT_INFO: 'portfolio_contact_info',\n * TESTIMONIALS: 'testimonials',\n * }\n * ```\n */\n collectionNames?: Partial<Record<CommonFeatureCollectionKey, string>>;\n}\n\n/**\n * Internal state after initialization\n */\nexport interface SharedFeaturesState {\n /** Whether the package has been initialized */\n initialized: boolean;\n /** The active configuration */\n config: SharedFeaturesConfig | null;\n /** Unique device ID for anonymous tracking */\n deviceId: string | null;\n}\n\n/**\n * Singleton state\n */\nlet state: SharedFeaturesState = {\n initialized: false,\n config: null,\n deviceId: null,\n};\n\n/**\n * Get current state\n */\nexport function getState(): SharedFeaturesState {\n return state;\n}\n\n/**\n * Set state (internal use only)\n */\nexport function setState(newState: Partial<SharedFeaturesState>): void {\n state = { ...state, ...newState };\n}\n\n/**\n * Get configuration (throws if not initialized)\n */\nexport function getConfig(): SharedFeaturesConfig {\n if (!state.initialized || !state.config) {\n throw new Error(\n 'shared-features has not been initialized. Call initSharedFeatures() first.'\n );\n }\n return state.config;\n}\n\n/**\n * Check if initialized\n */\nexport function isInitialized(): boolean {\n return state.initialized;\n}\n","/**\n * Firebase Initialization\n *\n * Initialize a secondary Firebase app for connecting to aoneahsan.com's\n * Firebase project from consumer projects.\n *\n * @author Ahsan Mahmood <aoneahsan@gmail.com>\n */\n\nimport { initializeApp, getApps, FirebaseApp } from 'firebase/app';\nimport { getFirestore, Firestore } from 'firebase/firestore';\nimport { getAuth, Auth } from 'firebase/auth';\nimport {\n SharedFeaturesConfig,\n setState,\n getState,\n isInitialized,\n} from './config';\nimport { setCommonFeatureCollectionNames } from '../types/commonFeatures';\n\nconst SHARED_FEATURES_APP_NAME = 'shared-features';\n\nlet firebaseApp: FirebaseApp | null = null;\nlet firestoreDb: Firestore | null = null;\nlet firebaseAuth: Auth | null = null;\n\n/**\n * Generate a unique device ID for anonymous tracking\n */\nfunction generateDeviceId(): string {\n const timestamp = Date.now();\n const randomPart = Math.random().toString(36).substring(2, 15);\n return `device_${timestamp}_${randomPart}`;\n}\n\n/**\n * Get or create device ID from storage\n */\nasync function getOrCreateDeviceId(): Promise<string> {\n const STORAGE_KEY = 'shared_features_device_id';\n\n try {\n // Try Capacitor Preferences first\n const { Preferences } = await import('@capacitor/preferences');\n const result = await Preferences.get({ key: STORAGE_KEY });\n if (result.value) {\n return result.value;\n }\n const newId = generateDeviceId();\n await Preferences.set({ key: STORAGE_KEY, value: newId });\n return newId;\n } catch {\n // Fallback to localStorage for web\n try {\n const stored = localStorage.getItem(STORAGE_KEY);\n if (stored) {\n return stored;\n }\n const newId = generateDeviceId();\n localStorage.setItem(STORAGE_KEY, newId);\n return newId;\n } catch {\n // If all storage fails, generate ephemeral ID\n return generateDeviceId();\n }\n }\n}\n\n/**\n * Initialize shared-features with the given configuration.\n *\n * This creates a secondary Firebase app connection to aoneahsan.com's\n * Firebase project, separate from the consumer project's own Firebase.\n *\n * @param config - Configuration object with Firebase config and project info\n * @returns Initialized state object\n *\n * @example\n * ```typescript\n * import { initSharedFeatures } from 'shared-features';\n *\n * initSharedFeatures({\n * firebaseConfig: {\n * apiKey: import.meta.env.VITE_SHARED_FEATURES_API_KEY,\n * authDomain: import.meta.env.VITE_SHARED_FEATURES_AUTH_DOMAIN,\n * projectId: import.meta.env.VITE_SHARED_FEATURES_PROJECT_ID,\n * },\n * projectId: 'ztools',\n * projectName: 'ZTools',\n * platform: 'web',\n * });\n * ```\n */\nexport async function initSharedFeatures(\n config: SharedFeaturesConfig\n): Promise<{ app: FirebaseApp; db: Firestore; auth: Auth }> {\n // Return existing instance if already initialized with same config\n if (isInitialized() && firebaseApp && firestoreDb && firebaseAuth) {\n const currentConfig = getState().config;\n if (\n currentConfig &&\n currentConfig.firebaseConfig.projectId === config.firebaseConfig.projectId\n ) {\n return { app: firebaseApp, db: firestoreDb, auth: firebaseAuth };\n }\n }\n\n // Check if app already exists\n const existingApps = getApps();\n const existingApp = existingApps.find(\n (app) => app.name === SHARED_FEATURES_APP_NAME\n );\n\n if (existingApp) {\n firebaseApp = existingApp;\n } else {\n // Initialize new Firebase app with config from environment variables\n firebaseApp = initializeApp(config.firebaseConfig, SHARED_FEATURES_APP_NAME);\n }\n\n // Get Firestore and Auth instances\n firestoreDb = getFirestore(firebaseApp);\n firebaseAuth = getAuth(firebaseApp);\n\n // Apply collection name overrides if provided\n if (config.collectionNames) {\n setCommonFeatureCollectionNames(config.collectionNames);\n }\n\n // Get or create device ID\n const deviceId = await getOrCreateDeviceId();\n\n // Update state\n setState({\n initialized: true,\n config,\n deviceId,\n });\n\n if (config.debug) {\n console.log('[shared-features] Initialized:', {\n projectId: config.projectId,\n projectName: config.projectName,\n platform: config.platform,\n deviceId,\n });\n }\n\n return { app: firebaseApp, db: firestoreDb, auth: firebaseAuth };\n}\n\n/**\n * Get the shared-features Firebase app instance.\n * Throws if not initialized.\n */\nexport function getSharedFeaturesApp(): FirebaseApp {\n if (!firebaseApp) {\n throw new Error(\n 'shared-features has not been initialized. Call initSharedFeatures() first.'\n );\n }\n return firebaseApp;\n}\n\n/**\n * Get the shared-features Firestore instance.\n * Throws if not initialized.\n */\nexport function getSharedFeaturesDb(): Firestore {\n if (!firestoreDb) {\n throw new Error(\n 'shared-features has not been initialized. Call initSharedFeatures() first.'\n );\n }\n return firestoreDb;\n}\n\n/**\n * Get the shared-features Auth instance.\n * Throws if not initialized.\n */\nexport function getSharedFeaturesAuth(): Auth {\n if (!firebaseAuth) {\n throw new Error(\n 'shared-features has not been initialized. Call initSharedFeatures() first.'\n );\n }\n return firebaseAuth;\n}\n\n/**\n * Get the device ID for anonymous tracking.\n * Returns null if not initialized.\n */\nexport function getDeviceId(): string | null {\n return getState().deviceId;\n}\n","/**\n * Campaigns Service\n *\n * Handles fetching and displaying advertising campaigns from the\n * centralized aoneahsan.com Firebase backend.\n *\n * Consumer projects only need read access - all campaign management\n * is done through the aoneahsan.com admin panel.\n *\n * @author Ahsan Mahmood <aoneahsan@gmail.com>\n */\n\nimport {\n collection,\n doc,\n getDocs,\n getDoc,\n query,\n where,\n orderBy,\n limit as firestoreLimit,\n Timestamp,\n} from 'firebase/firestore';\nimport { getSharedFeaturesDb } from '../firebase/init';\nimport { getConfig } from '../firebase/config';\nimport type {\n Campaign,\n CampaignWithProduct,\n Product,\n AdPlacement,\n CampaignStatus,\n FetchCampaignsOptions,\n} from '../types/campaigns';\n\n// ============================================================================\n// CONSTANTS\n// ============================================================================\n\nconst COLLECTION_CAMPAIGNS = 'zaions_campaigns';\nconst COLLECTION_PRODUCTS = 'zaions_products';\n\n// Cache for campaigns\ninterface CampaignsCache {\n data: Campaign[];\n timestamp: number;\n}\nlet campaignsCache: CampaignsCache | null = null;\nconst CACHE_TTL_MS = 5 * 60 * 1000; // 5 minutes\n\n// Products cache\nlet productsCache: Map<string, Product> | null = null;\n\n// ============================================================================\n// HELPER FUNCTIONS\n// ============================================================================\n\n/**\n * Check if cache is valid\n */\nfunction isCacheValid(): boolean {\n if (!campaignsCache) return false;\n return Date.now() - campaignsCache.timestamp < CACHE_TTL_MS;\n}\n\n/**\n * Convert Firestore document to Campaign\n */\nfunction docToCampaign(\n docId: string,\n data: Record<string, unknown>\n): Campaign {\n return {\n id: docId,\n productId: data.productId as string,\n name: data.name as string,\n status: data.status as CampaignStatus,\n targetPlatforms: data.targetPlatforms as Campaign['targetPlatforms'],\n targetAudience: data.targetAudience as Campaign['targetAudience'],\n targetProjects: (data.targetProjects as string[]) || [],\n excludeProductUsers: data.excludeProductUsers as boolean,\n placements: data.placements as AdPlacement[],\n priority: data.priority as number,\n frequencyDays: data.frequencyDays as number,\n maxImpressions: data.maxImpressions as number | null,\n startDate: data.startDate as Timestamp,\n endDate: data.endDate as Timestamp | null,\n variant: data.variant as Campaign['variant'],\n customTitle: data.customTitle as string | undefined,\n customTagline: data.customTagline as string | undefined,\n customCta: data.customCta as string | undefined,\n customCtaUrl: data.customCtaUrl as string | undefined,\n customDescription: data.customDescription as string | undefined,\n customProductColor: data.customProductColor as string | undefined,\n customIcon: data.customIcon as string | undefined,\n customFeatures: data.customFeatures as string[] | undefined,\n totalImpressions: data.totalImpressions as number,\n totalClicks: data.totalClicks as number,\n totalCloses: data.totalCloses as number,\n createdAt: data.createdAt as Timestamp,\n updatedAt: data.updatedAt as Timestamp,\n createdBy: data.createdBy as string,\n updatedBy: data.updatedBy as string | undefined,\n };\n}\n\n/**\n * Convert Firestore document to Product\n */\nfunction docToProduct(docId: string, data: Record<string, unknown>): Product {\n return {\n id: docId,\n name: data.name as string,\n tagline: data.tagline as string,\n description: data.description as string,\n type: data.type as Product['type'],\n url: data.url as string,\n color: data.color as string,\n features: (data.features as string[]) || [],\n icon64: data.icon64 as string | undefined,\n icon128: data.icon128 as string | undefined,\n chromeStoreUrl: data.chromeStoreUrl as string | undefined,\n playStoreUrl: data.playStoreUrl as string | undefined,\n appStoreUrl: data.appStoreUrl as string | undefined,\n webUrl: data.webUrl as string | undefined,\n enabled: data.enabled as boolean,\n createdAt: data.createdAt as Timestamp,\n updatedAt: data.updatedAt as Timestamp,\n };\n}\n\n// ============================================================================\n// PRODUCTS\n// ============================================================================\n\n/**\n * Fetch all products from Firestore\n */\nexport async function fetchProducts(): Promise<Product[]> {\n const db = getSharedFeaturesDb();\n const snapshot = await getDocs(collection(db, COLLECTION_PRODUCTS));\n const products = snapshot.docs.map((d) => docToProduct(d.id, d.data()));\n\n // Update cache\n productsCache = new Map(products.map((p) => [p.id, p]));\n\n return products;\n}\n\n/**\n * Get a product by ID (uses cache if available)\n */\nexport async function getProductById(\n productId: string\n): Promise<Product | null> {\n // Check cache first\n if (productsCache?.has(productId)) {\n return productsCache.get(productId) || null;\n }\n\n // Fetch from Firestore\n const db = getSharedFeaturesDb();\n const docSnap = await getDoc(doc(db, COLLECTION_PRODUCTS, productId));\n\n if (!docSnap.exists()) return null;\n\n const product = docToProduct(docSnap.id, docSnap.data());\n\n // Add to cache\n if (!productsCache) productsCache = new Map();\n productsCache.set(productId, product);\n\n return product;\n}\n\n// ============================================================================\n// CAMPAIGNS\n// ============================================================================\n\n/**\n * Fetch campaigns with optional filters\n */\nexport async function fetchCampaigns(\n options: FetchCampaignsOptions = {}\n): Promise<Campaign[]> {\n const config = getConfig();\n const db = getSharedFeaturesDb();\n\n // Check cache first (only for unfiltered queries)\n if (\n !options.placement &&\n !options.status &&\n !options.productId &&\n isCacheValid()\n ) {\n return campaignsCache!.data;\n }\n\n let q = query(collection(db, COLLECTION_CAMPAIGNS));\n\n // Apply filters\n if (options.status) {\n q = query(q, where('status', '==', options.status));\n }\n\n if (options.productId) {\n q = query(q, where('productId', '==', options.productId));\n }\n\n q = query(q, orderBy('priority', 'desc'));\n\n if (options.limit) {\n q = query(q, firestoreLimit(options.limit));\n }\n\n const snapshot = await getDocs(q);\n let campaigns = snapshot.docs.map((d) => docToCampaign(d.id, d.data()));\n\n // Client-side filtering for array fields\n if (options.placement) {\n campaigns = campaigns.filter((c) =>\n c.placements.includes(options.placement!)\n );\n }\n\n // Filter by target platform (from config)\n campaigns = campaigns.filter(\n (c) =>\n c.targetPlatforms.includes(config.platform) ||\n c.targetPlatforms.length === 0\n );\n\n // Filter by target projects (empty = all projects)\n campaigns = campaigns.filter(\n (c) =>\n c.targetProjects.length === 0 ||\n c.targetProjects.includes(config.projectId)\n );\n\n // Cache unfiltered results\n if (!options.placement && !options.status && !options.productId) {\n campaignsCache = {\n data: campaigns,\n timestamp: Date.now(),\n };\n }\n\n return campaigns;\n}\n\n/**\n * Fetch active campaigns for a specific placement\n * Returns campaigns with resolved product data\n */\nexport async function fetchActiveCampaigns(\n placement: AdPlacement\n): Promise<CampaignWithProduct[]> {\n const now = Timestamp.now();\n\n const campaigns = await fetchCampaigns({ status: 'active' });\n\n // Ensure products are loaded\n if (!productsCache || productsCache.size === 0) {\n await fetchProducts();\n }\n\n // Filter by placement and date range\n const eligible = campaigns.filter((c) => {\n // Placement check\n if (!c.placements.includes(placement)) return false;\n\n // Date range check\n if (c.startDate.toMillis() > now.toMillis()) return false;\n if (c.endDate && c.endDate.toMillis() < now.toMillis()) return false;\n\n // Max impressions check\n if (c.maxImpressions !== null && c.totalImpressions >= c.maxImpressions)\n return false;\n\n return true;\n });\n\n // Resolve products\n const result: CampaignWithProduct[] = [];\n\n for (const campaign of eligible) {\n const product = await getProductById(campaign.productId);\n if (product && product.enabled) {\n result.push({ ...campaign, product });\n }\n }\n\n return result;\n}\n\n/**\n * Get a single campaign by ID\n */\nexport async function getCampaignById(\n campaignId: string\n): Promise<Campaign | null> {\n const db = getSharedFeaturesDb();\n const docSnap = await getDoc(doc(db, COLLECTION_CAMPAIGNS, campaignId));\n\n if (!docSnap.exists()) return null;\n return docToCampaign(docSnap.id, docSnap.data());\n}\n\n/**\n * Clear the campaigns cache (useful for manual refresh)\n */\nexport function clearCampaignsCache(): void {\n campaignsCache = null;\n}\n\n/**\n * Clear the products cache\n */\nexport function clearProductsCache(): void {\n productsCache = null;\n}\n","/**\n * Analytics Service\n *\n * Handles recording impressions, clicks, and other ad interactions\n * from consumer projects to the centralized aoneahsan.com Firebase.\n *\n * @author Ahsan Mahmood <aoneahsan@gmail.com>\n */\n\nimport {\n collection,\n addDoc,\n serverTimestamp,\n} from 'firebase/firestore';\nimport { getSharedFeaturesDb } from '../firebase/init';\nimport { getConfig, getState } from '../firebase/config';\nimport type {\n AdAction,\n AdPlacement,\n AdVariant,\n RecordImpressionInput,\n AdHistoryEntry,\n} from '../types/campaigns';\n\n// ============================================================================\n// CONSTANTS\n// ============================================================================\n\nconst COLLECTION_IMPRESSIONS = 'zaions_impressions';\nconst LOCAL_STORAGE_KEY = 'shared_features_ad_history';\n\n// ============================================================================\n// LOCAL HISTORY MANAGEMENT\n// ============================================================================\n\n/**\n * Get ad history from local storage\n */\nasync function getLocalAdHistory(): Promise<Record<string, AdHistoryEntry>> {\n try {\n // Try Capacitor Preferences first\n const { Preferences } = await import('@capacitor/preferences');\n const result = await Preferences.get({ key: LOCAL_STORAGE_KEY });\n if (result.value) {\n return JSON.parse(result.value);\n }\n } catch {\n // Fallback to localStorage\n try {\n const stored = localStorage.getItem(LOCAL_STORAGE_KEY);\n if (stored) {\n return JSON.parse(stored);\n }\n } catch {\n // Ignore\n }\n }\n return {};\n}\n\n/**\n * Save ad history to local storage\n */\nasync function saveLocalAdHistory(\n history: Record<string, AdHistoryEntry>\n): Promise<void> {\n const serialized = JSON.stringify(history);\n\n try {\n // Try Capacitor Preferences first\n const { Preferences } = await import('@capacitor/preferences');\n await Preferences.set({ key: LOCAL_STORAGE_KEY, value: serialized });\n } catch {\n // Fallback to localStorage\n try {\n localStorage.setItem(LOCAL_STORAGE_KEY, serialized);\n } catch {\n // Ignore storage errors\n }\n }\n}\n\n/**\n * Update local ad history for a campaign\n */\nasync function updateLocalHistory(\n campaignId: string,\n productId: string,\n action: AdAction,\n frequencyDays: number\n): Promise<void> {\n const history = await getLocalAdHistory();\n const now = Date.now();\n const nextEligibleAt = now + frequencyDays * 24 * 60 * 60 * 1000;\n\n const existing = history[campaignId];\n\n if (existing) {\n history[campaignId] = {\n ...existing,\n lastSeenAt: now,\n impressionCount:\n action === 'impression'\n ? existing.impressionCount + 1\n : existing.impressionCount,\n clicked: existing.clicked || action === 'click',\n closed: existing.closed || action === 'close',\n nextEligibleAt:\n action === 'impression' ? nextEligibleAt : existing.nextEligibleAt,\n };\n } else {\n history[campaignId] = {\n campaignId,\n productId,\n lastSeenAt: now,\n impressionCount: action === 'impression' ? 1 : 0,\n clicked: action === 'click',\n closed: action === 'close',\n nextEligibleAt,\n };\n }\n\n await saveLocalAdHistory(history);\n}\n\n// ============================================================================\n// ELIGIBILITY CHECKING\n// ============================================================================\n\n/**\n * Check if user is eligible to see a campaign (based on frequency capping)\n */\nexport async function isEligibleForCampaign(\n campaignId: string,\n _frequencyDays: number = 20\n): Promise<boolean> {\n // Note: _frequencyDays kept for API consistency; eligibility uses stored nextEligibleAt\n const history = await getLocalAdHistory();\n const entry = history[campaignId];\n\n if (!entry) return true;\n\n return Date.now() >= entry.nextEligibleAt;\n}\n\n/**\n * Get all campaigns the user is currently eligible to see\n */\nexport async function getEligibleCampaignIds(): Promise<string[]> {\n const history = await getLocalAdHistory();\n const now = Date.now();\n\n return Object.entries(history)\n .filter(([, entry]) => now >= entry.nextEligibleAt)\n .map(([campaignId]) => campaignId);\n}\n\n/**\n * Get local ad history for a campaign\n */\nexport async function getCampaignHistory(\n campaignId: string\n): Promise<AdHistoryEntry | null> {\n const history = await getLocalAdHistory();\n return history[campaignId] || null;\n}\n\n// ============================================================================\n// IMPRESSION RECORDING\n// ============================================================================\n\n/**\n * Record an ad impression, click, or close\n *\n * This sends the event to the centralized Firebase and updates local history.\n */\nexport async function recordImpression(\n input: RecordImpressionInput,\n frequencyDays: number = 20\n): Promise<void> {\n const config = getConfig();\n const state = getState();\n const db = getSharedFeaturesDb();\n\n const impressionData = {\n campaignId: input.campaignId,\n productId: input.productId,\n projectId: config.projectId,\n userId: null, // Consumer projects don't authenticate with aoneahsan.com\n deviceId: state.deviceId || 'unknown',\n platform: config.platform,\n placement: input.placement,\n action: input.action,\n variant: input.variant,\n timestamp: serverTimestamp(),\n ...(input.sessionId && { sessionId: input.sessionId }),\n };\n\n try {\n // Record to centralized Firebase\n await addDoc(collection(db, COLLECTION_IMPRESSIONS), impressionData);\n\n if (config.debug) {\n console.log('[shared-features] Recorded impression:', impressionData);\n }\n } catch (error) {\n if (config.debug) {\n console.error('[shared-features] Failed to record impression:', error);\n }\n // Don't throw - we don't want analytics failures to break the UI\n }\n\n // Update local history for frequency capping\n await updateLocalHistory(\n input.campaignId,\n input.productId,\n input.action,\n frequencyDays\n );\n}\n\n/**\n * Convenience function to record an impression\n */\nexport async function trackImpression(\n campaignId: string,\n productId: string,\n placement: AdPlacement,\n variant: AdVariant,\n frequencyDays?: number\n): Promise<void> {\n await recordImpression(\n {\n campaignId,\n productId,\n placement,\n action: 'impression',\n variant,\n },\n frequencyDays\n );\n}\n\n/**\n * Convenience function to record a click\n */\nexport async function trackClick(\n campaignId: string,\n productId: string,\n placement: AdPlacement,\n variant: AdVariant\n): Promise<void> {\n await recordImpression({\n campaignId,\n productId,\n placement,\n action: 'click',\n variant,\n });\n}\n\n/**\n * Convenience function to record a close/dismiss\n */\nexport async function trackClose(\n campaignId: string,\n productId: string,\n placement: AdPlacement,\n variant: AdVariant\n): Promise<void> {\n await recordImpression({\n campaignId,\n productId,\n placement,\n action: 'close',\n variant,\n });\n}\n","/**\n * Feature Flags Service\n *\n * Handles fetching and checking feature flags from the centralized\n * aoneahsan.com Firebase backend. Consumer projects use this to\n * determine which features are available and at what version.\n *\n * @author Ahsan Mahmood <aoneahsan@gmail.com>\n */\n\nimport {\n doc,\n getDoc,\n setDoc,\n onSnapshot,\n Timestamp,\n Unsubscribe,\n} from 'firebase/firestore';\nimport { getSharedFeaturesDb } from '../firebase/init';\nimport { getConfig } from '../firebase/config';\nimport type {\n FeatureId,\n FeatureConfig,\n FeatureFlagsDocument,\n FeatureAvailability,\n SharedFeaturesStatus,\n UpdateFeatureConfigInput,\n UpdateGlobalFlagsInput,\n ConsumerFeatureVersions,\n} from '../types/featureFlags';\nimport {\n COLLECTION_FEATURE_FLAGS,\n FEATURE_FLAGS_DOC_ID,\n DEFAULT_FEATURE_FLAGS,\n} from '../types/featureFlags';\n\n// Re-export constants\nexport { COLLECTION_FEATURE_FLAGS, FEATURE_FLAGS_DOC_ID } from '../types/featureFlags';\n\n// ============================================================================\n// CACHE\n// ============================================================================\n\ninterface FeatureFlagsCache {\n data: FeatureFlagsDocument | null;\n timestamp: number;\n}\n\nlet flagsCache: FeatureFlagsCache | null = null;\nconst CACHE_TTL_MS = 2 * 60 * 1000; // 2 minutes (shorter than campaigns for fresher data)\n\n/**\n * Check if cache is valid\n */\nfunction isCacheValid(): boolean {\n if (!flagsCache || !flagsCache.data) return false;\n return Date.now() - flagsCache.timestamp < CACHE_TTL_MS;\n}\n\n/**\n * Clear the feature flags cache\n */\nexport function clearFeatureFlagsCache(): void {\n flagsCache = null;\n}\n\n// ============================================================================\n// HELPER FUNCTIONS\n// ============================================================================\n\n/**\n * Convert Firestore document to FeatureFlagsDocument\n */\nfunction docToFeatureFlags(\n docId: string,\n data: Record<string, unknown>\n): FeatureFlagsDocument {\n return {\n id: docId,\n globalEnabled: (data.globalEnabled as boolean) ?? true,\n currentApiVersion: (data.currentApiVersion as string) ?? 'v1',\n supportedApiVersions: (data.supportedApiVersions as string[]) ?? ['v1'],\n features: data.features as FeatureFlagsDocument['features'],\n maintenanceMode: (data.maintenanceMode as boolean) ?? false,\n maintenanceMessage: data.maintenanceMessage as string | undefined,\n maintenanceEndTime: data.maintenanceEndTime as Timestamp | undefined,\n updatedAt: data.updatedAt as Timestamp,\n updatedBy: data.updatedBy as string,\n };\n}\n\n/**\n * Get the consumer's requested version for a feature\n */\nfunction getConsumerVersion(\n featureId: FeatureId,\n consumerVersions?: ConsumerFeatureVersions\n): number | undefined {\n if (!consumerVersions) return undefined;\n return consumerVersions[featureId];\n}\n\n// ============================================================================\n// FETCH FUNCTIONS\n// ============================================================================\n\n/**\n * Fetch feature flags from Firestore\n *\n * @param forceRefresh - Skip cache and fetch fresh data\n * @returns Feature flags document or null if not found\n */\nexport async function fetchFeatureFlags(\n forceRefresh = false\n): Promise<FeatureFlagsDocument | null> {\n // Check cache first\n if (!forceRefresh && isCacheValid()) {\n return flagsCache!.data;\n }\n\n try {\n const db = getSharedFeaturesDb();\n const docRef = doc(db, COLLECTION_FEATURE_FLAGS, FEATURE_FLAGS_DOC_ID);\n const docSnap = await getDoc(docRef);\n\n if (!docSnap.exists()) {\n // Return default flags if document doesn't exist\n const config = getConfig();\n if (config.debug) {\n console.log(\n '[shared-features] Feature flags document not found, using defaults'\n );\n }\n\n // Create default document for first-time setup\n const defaultDoc: FeatureFlagsDocument = {\n ...DEFAULT_FEATURE_FLAGS,\n updatedAt: Timestamp.now(),\n updatedBy: 'system',\n } as FeatureFlagsDocument;\n\n flagsCache = {\n data: defaultDoc,\n timestamp: Date.now(),\n };\n\n return defaultDoc;\n }\n\n const flags = docToFeatureFlags(docSnap.id, docSnap.data());\n\n // Update cache\n flagsCache = {\n data: flags,\n timestamp: Date.now(),\n };\n\n const config = getConfig();\n if (config.debug) {\n console.log('[shared-features] Feature flags fetched:', {\n globalEnabled: flags.globalEnabled,\n maintenanceMode: flags.maintenanceMode,\n apiVersion: flags.currentApiVersion,\n });\n }\n\n return flags;\n } catch (error) {\n const config = getConfig();\n if (config.debug) {\n console.error('[shared-features] Error fetching feature flags:', error);\n }\n\n // Return cached data if available, even if stale\n if (flagsCache?.data) {\n return flagsCache.data;\n }\n\n return null;\n }\n}\n\n/**\n * Subscribe to real-time feature flag updates\n *\n * @param callback - Function to call when flags change\n * @returns Unsubscribe function\n */\nexport function subscribeToFeatureFlags(\n callback: (flags: FeatureFlagsDocument | null) => void\n): Unsubscribe {\n const db = getSharedFeaturesDb();\n const docRef = doc(db, COLLECTION_FEATURE_FLAGS, FEATURE_FLAGS_DOC_ID);\n\n return onSnapshot(\n docRef,\n (docSnap) => {\n if (!docSnap.exists()) {\n callback(null);\n return;\n }\n\n const flags = docToFeatureFlags(docSnap.id, docSnap.data());\n\n // Update cache\n flagsCache = {\n data: flags,\n timestamp: Date.now(),\n };\n\n callback(flags);\n },\n (error) => {\n const config = getConfig();\n if (config.debug) {\n console.error(\n '[shared-features] Error subscribing to feature flags:',\n error\n );\n }\n callback(null);\n }\n );\n}\n\n// ============================================================================\n// FEATURE AVAILABILITY CHECKS\n// ============================================================================\n\n/**\n * Check if a specific feature is available\n *\n * @param featureId - The feature to check\n * @param consumerVersions - Optional consumer version preferences\n * @returns Availability details\n */\nexport async function checkFeatureAvailability(\n featureId: FeatureId,\n consumerVersions?: ConsumerFeatureVersions\n): Promise<FeatureAvailability> {\n const flags = await fetchFeatureFlags();\n const config = getConfig();\n\n // Default unavailable response\n const unavailable: FeatureAvailability = {\n available: false,\n enabled: false,\n version: 1,\n deprecated: false,\n upgradeRequired: false,\n unavailableReason: 'Feature flags not loaded',\n };\n\n if (!flags) {\n return unavailable;\n }\n\n // Check global enabled\n if (!flags.globalEnabled) {\n return {\n ...unavailable,\n unavailableReason: 'shared-features is globally disabled',\n };\n }\n\n // Check maintenance mode\n if (flags.maintenanceMode) {\n return {\n ...unavailable,\n unavailableReason: flags.maintenanceMessage || 'Maintenance in progress',\n };\n }\n\n // Get feature config\n const featureConfig = flags.features[featureId];\n if (!featureConfig) {\n return {\n ...unavailable,\n unavailableReason: `Feature '${featureId}' not found in configuration`,\n };\n }\n\n // Check if feature is enabled\n if (!featureConfig.enabled) {\n return {\n ...unavailable,\n version: featureConfig.version,\n unavailableReason: `Feature '${featureId}' is not enabled`,\n };\n }\n\n // Check platform availability\n if (\n featureConfig.availablePlatforms &&\n featureConfig.availablePlatforms.length > 0\n ) {\n if (!featureConfig.availablePlatforms.includes(config.platform)) {\n return {\n ...unavailable,\n version: featureConfig.version,\n unavailableReason: `Feature '${featureId}' is not available on platform '${config.platform}'`,\n };\n }\n }\n\n // Check project availability\n if (\n featureConfig.availableProjects &&\n featureConfig.availableProjects.length > 0\n ) {\n if (!featureConfig.availableProjects.includes(config.projectId)) {\n return {\n ...unavailable,\n version: featureConfig.version,\n unavailableReason: `Feature '${featureId}' is not available for project '${config.projectId}'`,\n };\n }\n }\n\n // Check consumer version compatibility\n const consumerVersion = getConsumerVersion(featureId, consumerVersions);\n const currentVersion = featureConfig.version;\n const minVersion = featureConfig.minVersion;\n const maxVersion = featureConfig.maxVersion;\n\n let deprecated = false;\n let deprecationWarning: string | undefined;\n let upgradeRequired = false;\n let upgradeMessage: string | undefined;\n\n if (consumerVersion !== undefined) {\n // Consumer specified a version\n if (consumerVersion < minVersion) {\n // Version too old, upgrade required\n upgradeRequired = true;\n upgradeMessage = `Feature '${featureId}' requires minimum version ${minVersion}, but consumer is using version ${consumerVersion}. Please upgrade.`;\n } else if (consumerVersion < currentVersion) {\n // Version is older but still supported\n deprecated = true;\n deprecationWarning =\n featureConfig.deprecationMessage ||\n `Feature '${featureId}' version ${consumerVersion} is deprecated. Current version is ${currentVersion}.`;\n } else if (consumerVersion > maxVersion) {\n // Version too new (edge case)\n return {\n ...unavailable,\n version: currentVersion,\n unavailableReason: `Feature '${featureId}' version ${consumerVersion} is not yet supported. Maximum supported version is ${maxVersion}.`,\n };\n }\n }\n\n // Feature is available\n return {\n available: !upgradeRequired,\n enabled: true,\n version: currentVersion,\n deprecated,\n deprecationWarning,\n upgradeRequired,\n upgradeMessage,\n };\n}\n\n/**\n * Quick check if a feature is available (cached)\n *\n * @param featureId - The feature to check\n * @returns true if feature is available\n */\nexport function isFeatureEnabled(featureId: FeatureId): boolean {\n // Use cached data for quick checks\n if (!flagsCache?.data) return false;\n\n const flags = flagsCache.data;\n\n if (!flags.globalEnabled || flags.maintenanceMode) return false;\n\n const featureConfig = flags.features[featureId];\n if (!featureConfig || !featureConfig.enabled) return false;\n\n // Quick platform/project check\n const config = getConfig();\n\n if (\n featureConfig.availablePlatforms &&\n featureConfig.availablePlatforms.length > 0\n ) {\n if (!featureConfig.availablePlatforms.includes(config.platform)) {\n return false;\n }\n }\n\n if (\n featureConfig.availableProjects &&\n featureConfig.availableProjects.length > 0\n ) {\n if (!featureConfig.availableProjects.includes(config.projectId)) {\n return false;\n }\n }\n\n return true;\n}\n\n/**\n * Get the current version of a feature\n *\n * @param featureId - The feature to check\n * @returns Current version number or 0 if not available\n */\nexport function getFeatureVersion(featureId: FeatureId): number {\n if (!flagsCache?.data) return 0;\n return flagsCache.data.features[featureId]?.version ?? 0;\n}\n\n// ============================================================================\n// STATUS FUNCTIONS\n// ============================================================================\n\n/**\n * Get overall status of shared-features for the current consumer\n *\n * @param consumerVersions - Optional consumer version preferences\n * @returns Complete status object\n */\nexport async function getSharedFeaturesStatus(\n consumerVersions?: ConsumerFeatureVersions\n): Promise<SharedFeaturesStatus> {\n const flags = await fetchFeatureFlags();\n\n const defaultStatus: SharedFeaturesStatus = {\n operational: false,\n maintenanceMode: false,\n apiVersion: 'v1',\n features: {} as Record<FeatureId, FeatureAvailability>,\n deprecatedFeatures: [],\n upgradeRequiredFeatures: [],\n fetchedAt: new Date(),\n };\n\n if (!flags) {\n return defaultStatus;\n }\n\n // Check all features\n const featureIds: FeatureId[] = [\n 'campaigns',\n 'broadcasts',\n 'contactInfo',\n 'developerInfo',\n 'socialLinks',\n 'paymentOptions',\n 'addressInfo',\n 'services',\n 'skills',\n 'testimonials',\n 'projects',\n ];\n\n const features: Record<FeatureId, FeatureAvailability> = {} as Record<\n FeatureId,\n FeatureAvailability\n >;\n const deprecatedFeatures: FeatureId[] = [];\n const upgradeRequiredFeatures: FeatureId[] = [];\n\n for (const featureId of featureIds) {\n const availability = await checkFeatureAvailability(\n featureId,\n consumerVersions\n );\n features[featureId] = availability;\n\n if (availability.deprecated) {\n deprecatedFeatures.push(featureId);\n }\n\n if (availability.upgradeRequired) {\n upgradeRequiredFeatures.push(featureId);\n }\n }\n\n return {\n operational: flags.globalEnabled && !flags.maintenanceMode,\n maintenanceMode: flags.maintenanceMode,\n maintenanceMessage: flags.maintenanceMessage,\n apiVersion: flags.currentApiVersion,\n features,\n deprecatedFeatures,\n upgradeRequiredFeatures,\n fetchedAt: new Date(),\n };\n}\n\n// ============================================================================\n// ADMIN FUNCTIONS\n// ============================================================================\n\n/**\n * Update a feature's configuration (admin only)\n *\n * @param input - Feature configuration updates\n * @param adminEmail - Email of admin making the change\n */\nexport async function updateFeatureConfig(\n input: UpdateFeatureConfigInput,\n adminEmail: string\n): Promise<void> {\n const db = getSharedFeaturesDb();\n const docRef = doc(db, COLLECTION_FEATURE_FLAGS, FEATURE_FLAGS_DOC_ID);\n\n // Fetch current document\n const docSnap = await getDoc(docRef);\n let currentFlags: FeatureFlagsDocument;\n\n if (!docSnap.exists()) {\n // Create with defaults\n currentFlags = {\n ...DEFAULT_FEATURE_FLAGS,\n updatedAt: Timestamp.now(),\n updatedBy: adminEmail,\n } as FeatureFlagsDocument;\n } else {\n currentFlags = docToFeatureFlags(docSnap.id, docSnap.data());\n }\n\n // Update the specific feature\n const featureConfig = currentFlags.features[input.featureId];\n const updatedFeature: FeatureConfig = {\n enabled: input.enabled ?? featureConfig.enabled,\n version: input.version ?? featureConfig.version,\n minVersion: input.minVersion ?? featureConfig.minVersion,\n maxVersion: input.maxVersion ?? featureConfig.maxVersion,\n deprecationMessage: input.deprecationMessage ?? featureConfig.deprecationMessage,\n requiresAuth: input.requiresAuth ?? featureConfig.requiresAuth,\n availablePlatforms: input.availablePlatforms ?? featureConfig.availablePlatforms,\n availableProjects: input.availableProjects ?? featureConfig.availableProjects,\n };\n\n // Update document\n await setDoc(\n docRef,\n {\n ...currentFlags,\n features: {\n ...currentFlags.features,\n [input.featureId]: updatedFeature,\n },\n updatedAt: Timestamp.now(),\n updatedBy: adminEmail,\n },\n { merge: true }\n );\n\n // Clear cache\n clearFeatureFlagsCache();\n}\n\n/**\n * Update global flags (admin only)\n *\n * @param input - Global flag updates\n * @param adminEmail - Email of admin making the change\n */\nexport async function updateGlobalFlags(\n input: UpdateGlobalFlagsInput,\n adminEmail: string\n): Promise<void> {\n const db = getSharedFeaturesDb();\n const docRef = doc(db, COLLECTION_FEATURE_FLAGS, FEATURE_FLAGS_DOC_ID);\n\n const updateData: Record<string, unknown> = {\n updatedAt: Timestamp.now(),\n updatedBy: adminEmail,\n };\n\n if (input.globalEnabled !== undefined) {\n updateData.globalEnabled = input.globalEnabled;\n }\n\n if (input.currentApiVersion !== undefined) {\n updateData.currentApiVersion = input.currentApiVersion;\n }\n\n if (input.supportedApiVersions !== undefined) {\n updateData.supportedApiVersions = input.supportedApiVersions;\n }\n\n if (input.maintenanceMode !== undefined) {\n updateData.maintenanceMode = input.maintenanceMode;\n }\n\n if (input.maintenanceMessage !== undefined) {\n updateData.maintenanceMessage = input.maintenanceMessage;\n }\n\n if (input.maintenanceEndTime !== undefined) {\n updateData.maintenanceEndTime = input.maintenanceEndTime\n ? Timestamp.fromDate(input.maintenanceEndTime)\n : null;\n }\n\n await setDoc(docRef, updateData, { merge: true });\n\n // Clear cache\n clearFeatureFlagsCache();\n}\n\n/**\n * Initialize feature flags document with defaults (admin only)\n *\n * @param adminEmail - Email of admin creating the document\n */\nexport async function initializeFeatureFlags(\n adminEmail: string\n): Promise<void> {\n const db = getSharedFeaturesDb();\n const docRef = doc(db, COLLECTION_FEATURE_FLAGS, FEATURE_FLAGS_DOC_ID);\n\n const docSnap = await getDoc(docRef);\n\n if (docSnap.exists()) {\n throw new Error('Feature flags document already exists');\n }\n\n await setDoc(docRef, {\n ...DEFAULT_FEATURE_FLAGS,\n updatedAt: Timestamp.now(),\n updatedBy: adminEmail,\n });\n\n // Clear cache\n clearFeatureFlagsCache();\n}\n","/**\n * Common Features Service\n *\n * Handles fetching common features from the centralized\n * aoneahsan.com Firebase backend.\n *\n * @author Ahsan Mahmood <aoneahsan@gmail.com>\n */\n\nimport {\n collection,\n doc,\n getDoc,\n getDocs,\n query,\n orderBy,\n limit as firestoreLimit,\n onSnapshot,\n Timestamp,\n Unsubscribe,\n} from 'firebase/firestore';\nimport { getSharedFeaturesDb } from '../firebase/init';\nimport { getConfig } from '../firebase/config';\nimport { isFeatureEnabled } from './featureFlags';\nimport {\n COMMON_FEATURE_COLLECTIONS,\n type ContactInfo,\n type DeveloperInfo,\n type SocialLink,\n type AddressInfo,\n type PaymentOption,\n type Service,\n type Skill,\n type Testimonial,\n type Project,\n type FetchSocialLinksOptions,\n type FetchServicesOptions,\n type FetchSkillsOptions,\n type FetchTestimonialsOptions,\n type FetchPaymentOptionsOptions,\n type FetchProjectsOptions,\n} from '../types/commonFeatures';\n\n// ============================================================================\n// CACHE\n// ============================================================================\n\ninterface Cache<T> {\n data: T | null;\n timestamp: number;\n}\n\nconst CACHE_TTL_MS = 5 * 60 * 1000; // 5 minutes\n\nlet contactInfoCache: Cache<ContactInfo> | null = null;\nlet developerInfoCache: Cache<DeveloperInfo> | null = null;\nlet addressInfoCache: Cache<AddressInfo> | null = null;\nlet socialLinksCache: Cache<SocialLink[]> | null = null;\nlet paymentOptionsCache: Cache<PaymentOption[]> | null = null;\nlet servicesCache: Cache<Service[]> | null = null;\nlet skillsCache: Cache<Skill[]> | null = null;\nlet testimonialsCache: Cache<Testimonial[]> | null = null;\nlet projectsCache: Cache<Project[]> | null = null;\n\nfunction isCacheValid<T>(cache: Cache<T> | null): boolean {\n if (!cache || !cache.data) return false;\n return Date.now() - cache.timestamp < CACHE_TTL_MS;\n}\n\nexport function clearAllCommonFeaturesCache(): void {\n contactInfoCache = null;\n developerInfoCache = null;\n addressInfoCache = null;\n socialLinksCache = null;\n paymentOptionsCache = null;\n servicesCache = null;\n skillsCache = null;\n testimonialsCache = null;\n projectsCache = null;\n}\n\n// ============================================================================\n// CONTACT INFO\n// ============================================================================\n\nfunction docToContactInfo(docId: string, data: Record<string, unknown>): ContactInfo {\n // Portfolio may nest timezone in location object\n const locationObj = data.location as Record<string, unknown> | undefined;\n return {\n id: docId,\n email: (data.email as string) || '',\n supportEmail: data.supportEmail as string | undefined,\n phone: data.phone as string | undefined,\n whatsapp: data.whatsapp as string | undefined,\n telegram: data.telegram as string | undefined,\n skype: data.skype as string | undefined,\n freelanceAvailable: ((data.freelanceAvailable ?? data.availableForFreelance) as boolean) ?? false,\n workingHours: data.workingHours as string | undefined,\n timezone: (data.timezone ?? (typeof locationObj === 'object' && locationObj ? locationObj.timezone : undefined)) as string | undefined,\n preferredContact: (data.preferredContact ?? data.preferredContactMethod) as ContactInfo['preferredContact'],\n responseTime: data.responseTime as string | undefined,\n updatedAt: data.updatedAt as Timestamp,\n };\n}\n\nexport async function fetchContactInfo(): Promise<ContactInfo | null> {\n if (!isFeatureEnabled('contactInfo')) {\n const config = getConfig();\n if (config.debug) console.log('[shared-features] contactInfo feature is disabled');\n return null;\n }\n\n if (isCacheValid(contactInfoCache)) return contactInfoCache!.data;\n\n try {\n const db = getSharedFeaturesDb();\n const docRef = doc(db, COMMON_FEATURE_COLLECTIONS.CONTACT_INFO, 'main');\n const docSnap = await getDoc(docRef);\n\n if (!docSnap.exists()) return null;\n\n const data = docToContactInfo(docSnap.id, docSnap.data());\n contactInfoCache = { data, timestamp: Date.now() };\n return data;\n } catch (error) {\n const config = getConfig();\n if (config.debug) console.error('[shared-features] Error fetching contact info:', error);\n return contactInfoCache?.data ?? null;\n }\n}\n\nexport function subscribeToContactInfo(callback: (data: ContactInfo | null) => void): Unsubscribe {\n const db = getSharedFeaturesDb();\n const docRef = doc(db, COMMON_FEATURE_COLLECTIONS.CONTACT_INFO, 'main');\n\n return onSnapshot(docRef, (docSnap) => {\n if (!docSnap.exists()) {\n callback(null);\n return;\n }\n const data = docToContactInfo(docSnap.id, docSnap.data());\n contactInfoCache = { data, timestamp: Date.now() };\n callback(data);\n });\n}\n\nexport function clearContactInfoCache(): void {\n contactInfoCache = null;\n}\n\n// ============================================================================\n// DEVELOPER INFO\n// ============================================================================\n\nfunction docToDeveloperInfo(docId: string, data: Record<string, unknown>): DeveloperInfo {\n return {\n id: docId,\n name: (data.name as string) || '',\n title: (data.title as string) || '',\n tagline: data.tagline as string | undefined,\n bio: (data.bio as string) || '',\n shortBio: data.shortBio as string | undefined,\n avatar: data.avatar as string | undefined,\n website: data.website as string | undefined,\n github: data.github as string | undefined,\n linkedin: data.linkedin as string | undefined,\n twitter: data.twitter as string | undefined,\n yearsOfExperience: data.yearsOfExperience as number | undefined,\n location: data.location as string | undefined,\n availableForHire: (data.availableForHire as boolean) ?? false,\n resumeUrl: data.resumeUrl as string | undefined,\n updatedAt: data.updatedAt as Timestamp,\n };\n}\n\nexport async function fetchDeveloperInfo(): Promise<DeveloperInfo | null> {\n if (!isFeatureEnabled('developerInfo')) {\n const config = getConfig();\n if (config.debug) console.log('[shared-features] developerInfo feature is disabled');\n return null;\n }\n\n if (isCacheValid(developerInfoCache)) return developerInfoCache!.data;\n\n try {\n const db = getSharedFeaturesDb();\n const docRef = doc(db, COMMON_FEATURE_COLLECTIONS.DEVELOPER_INFO, 'main');\n const docSnap = await getDoc(docRef);\n\n if (!docSnap.exists()) return null;\n\n const data = docToDeveloperInfo(docSnap.id, docSnap.data());\n developerInfoCache = { data, timestamp: Date.now() };\n return data;\n } catch (error) {\n const config = getConfig();\n if (config.debug) console.error('[shared-features] Error fetching developer info:', error);\n return developerInfoCache?.data ?? null;\n }\n}\n\nexport function subscribeToDeveloperInfo(callback: (data: DeveloperInfo | null) => void): Unsubscribe {\n const db = getSharedFeaturesDb();\n const docRef = doc(db, COMMON_FEATURE_COLLECTIONS.DEVELOPER_INFO, 'main');\n\n return onSnapshot(docRef, (docSnap) => {\n if (!docSnap.exists()) {\n callback(null);\n return;\n }\n const data = docToDeveloperInfo(docSnap.id, docSnap.data());\n developerInfoCache = { data, timestamp: Date.now() };\n callback(data);\n });\n}\n\nexport function clearDeveloperInfoCache(): void {\n developerInfoCache = null;\n}\n\n// ============================================================================\n// ADDRESS INFO\n// ============================================================================\n\nfunction docToAddressInfo(docId: string, data: Record<string, unknown>): AddressInfo {\n // Portfolio may nest address fields in addressDetails object\n const details = (data.addressDetails as Record<string, unknown>) || {};\n const coords = data.coordinates as { lat?: number; lng?: number } | undefined;\n return {\n id: docId,\n label: data.label as string | undefined,\n streetAddress: (data.streetAddress ?? details.streetAddress) as string | undefined,\n apartment: (data.apartment ?? details.apartment) as string | undefined,\n city: (data.city ?? details.city) as string | undefined,\n state: (data.state ?? details.state) as string | undefined,\n postalCode: (data.postalCode ?? details.postalCode) as string | undefined,\n country: (data.country ?? details.country) as string | undefined,\n landmark: (data.landmark ?? details.landmark) as string | undefined,\n fullAddress: (data.fullAddress ?? data.displayAddress) as string | undefined,\n googleMapsUrl: (data.googleMapsUrl ?? data.googleMapsLink) as string | undefined,\n googleMapsEmbedUrl: data.googleMapsEmbedUrl as string | undefined,\n coordinates: coords && typeof coords.lat === 'number' && typeof coords.lng === 'number'\n ? { lat: coords.lat, lng: coords.lng }\n : undefined,\n showMap: (data.showMap as boolean) ?? false,\n isPublic: (data.isPublic as boolean) ?? false,\n workingHours: data.workingHours as string | undefined,\n additionalInfo: data.additionalInfo as string | undefined,\n updatedAt: data.updatedAt as Timestamp,\n };\n}\n\nexport async function fetchAddressInfo(): Promise<AddressInfo | null> {\n if (!isFeatureEnabled('addressInfo')) {\n const config = getConfig();\n if (config.debug) console.log('[shared-features] addressInfo feature is disabled');\n return null;\n }\n\n if (isCacheValid(addressInfoCache)) return addressInfoCache!.data;\n\n try {\n const db = getSharedFeaturesDb();\n const docRef = doc(db, COMMON_FEATURE_COLLECTIONS.ADDRESS_INFO, 'main');\n const docSnap = await getDoc(docRef);\n\n if (!docSnap.exists()) return null;\n\n const data = docToAddressInfo(docSnap.id, docSnap.data());\n\n // Only return if public or user is authorized\n if (!data.isPublic) return null;\n\n addressInfoCache = { data, timestamp: Date.now() };\n return data;\n } catch (error) {\n const config = getConfig();\n if (config.debug) console.error('[shared-features] Error fetching address info:', error);\n return addressInfoCache?.data ?? null;\n }\n}\n\nexport function clearAddressInfoCache(): void {\n addressInfoCache = null;\n}\n\n// ============================================================================\n// SOCIAL LINKS\n// ============================================================================\n\n/**\n * Build showIn array from individual boolean fields written by portfolio admin.\n * Portfolio writes showInFooter, showInContact, showInAbout, showInHeader as booleans.\n */\nfunction buildShowInArray(data: Record<string, unknown>): SocialLink['showIn'] | undefined {\n const hasAnyBool = 'showInFooter' in data || 'showInContact' in data || 'showInAbout' in data || 'showInHeader' in data;\n if (!hasAnyBool) return undefined;\n const result: SocialLink['showIn'] = [];\n if (data.showInFooter) result.push('footer');\n if (data.showInContact) result.push('contact');\n if (data.showInAbout) result.push('about');\n if (data.showInHeader) result.push('header');\n return result.length > 0 ? result : ['footer'];\n}\n\nfunction docToSocialLink(docId: string, data: Record<string, unknown>): SocialLink {\n return {\n id: docId,\n platform: data.platform as SocialLink['platform'],\n url: (data.url as string) || '',\n displayName: data.displayName as string | undefined,\n username: data.username as string | undefined,\n icon: data.icon as string | undefined,\n order: (data.order as number) ?? 0,\n isActive: ((data.isActive ?? data.enabled) as boolean) ?? true,\n showIn: (data.showIn as SocialLink['showIn']) ?? buildShowInArray(data) ?? ['footer'],\n updatedAt: data.updatedAt as Timestamp,\n };\n}\n\nexport async function fetchSocialLinks(options: FetchSocialLinksOptions = {}): Promise<SocialLink[]> {\n if (!isFeatureEnabled('socialLinks')) {\n const config = getConfig();\n if (config.debug) console.log('[shared-features] socialLinks feature is disabled');\n return [];\n }\n\n // Use cache for unfiltered queries\n if (!options.showIn && options.activeOnly !== false && isCacheValid(socialLinksCache)) {\n return socialLinksCache!.data ?? [];\n }\n\n try {\n const db = getSharedFeaturesDb();\n let q = query(collection(db, COMMON_FEATURE_COLLECTIONS.SOCIAL_LINKS), orderBy('order', 'asc'));\n\n const snapshot = await getDocs(q);\n let links = snapshot.docs.map((d) => docToSocialLink(d.id, d.data()));\n\n // Filter by active\n if (options.activeOnly !== false) {\n links = links.filter((l) => l.isActive);\n }\n\n // Filter by showIn\n if (options.showIn && options.showIn.length > 0) {\n links = links.filter((l) => options.showIn!.some((loc) => l.showIn.includes(loc)));\n }\n\n // Cache unfiltered results\n if (!options.showIn && options.activeOnly !== false) {\n socialLinksCache = { data: links, timestamp: Date.now() };\n }\n\n return links;\n } catch (error) {\n const config = getConfig();\n if (config.debug) console.error('[shared-features] Error fetching social links:', error);\n return socialLinksCache?.data ?? [];\n }\n}\n\nexport function clearSocialLinksCache(): void {\n socialLinksCache = null;\n}\n\n// ============================================================================\n// PAYMENT OPTIONS\n// ============================================================================\n\nfunction docToPaymentOption(docId: string, data: Record<string, unknown>): PaymentOption {\n return {\n id: docId,\n type: data.type as PaymentOption['type'],\n name: (data.name as string) || '',\n displayName: data.displayName as string | undefined,\n description: data.description as string | undefined,\n instructions: data.instructions as string | undefined,\n icon: data.icon as string | undefined,\n details: (data.details as PaymentOption['details']) || {},\n isActive: ((data.isActive ?? data.enabled) as boolean) ?? true,\n isPrimary: (data.isPrimary as boolean) ?? false,\n order: (data.order as number) ?? 0,\n updatedAt: data.updatedAt as Timestamp,\n };\n}\n\nexport async function fetchPaymentOptions(options: FetchPaymentOptionsOptions = {}): Promise<PaymentOption[]> {\n if (!isFeatureEnabled('paymentOptions')) {\n const config = getConfig();\n if (config.debug) console.log('[shared-features] paymentOptions feature is disabled');\n return [];\n }\n\n if (!options.type && options.activeOnly !== false && isCacheValid(paymentOptionsCache)) {\n return paymentOptionsCache!.data ?? [];\n }\n\n try {\n const db = getSharedFeaturesDb();\n let q = query(collection(db, COMMON_FEATURE_COLLECTIONS.PAYMENT_OPTIONS), orderBy('order', 'asc'));\n\n const snapshot = await getDocs(q);\n let items = snapshot.docs.map((d) => docToPaymentOption(d.id, d.data()));\n\n if (options.activeOnly !== false) {\n items = items.filter((i) => i.isActive);\n }\n\n if (options.type) {\n items = items.filter((i) => i.type === options.type);\n }\n\n if (!options.type && options.activeOnly !== false) {\n paymentOptionsCache = { data: items, timestamp: Date.now() };\n }\n\n return items;\n } catch (error) {\n const config = getConfig();\n if (config.debug) console.error('[shared-features] Error fetching payment options:', error);\n return paymentOptionsCache?.data ?? [];\n }\n}\n\nexport function clearPaymentOptionsCache(): void {\n paymentOptionsCache = null;\n}\n\n// ============================================================================\n// SERVICES\n// ============================================================================\n\nfunction docToService(docId: string, data: Record<string, unknown>): Service {\n return {\n id: docId,\n title: (data.title as string) || '',\n description: (data.description as string) || '',\n shortDescription: data.shortDescription as string | undefined,\n category: data.category as Service['category'],\n icon: data.icon as string | undefined,\n features: data.features as string[] | undefined,\n technologies: data.technologies as string[] | undefined,\n priceRange: data.priceRange as string | undefined,\n isActive: (data.isActive as boolean) ?? true,\n isFeatured: (data.isFeatured as boolean) ?? false,\n order: (data.order as number) ?? 0,\n updatedAt: data.updatedAt as Timestamp,\n };\n}\n\nexport async function fetchServices(options: FetchServicesOptions = {}): Promise<Service[]> {\n if (!isFeatureEnabled('services')) {\n const config = getConfig();\n if (config.debug) console.log('[shared-features] services feature is disabled');\n return [];\n }\n\n if (!options.category && !options.featuredOnly && options.activeOnly !== false && isCacheValid(servicesCache)) {\n return servicesCache!.data ?? [];\n }\n\n try {\n const db = getSharedFeaturesDb();\n let q = query(collection(db, COMMON_FEATURE_COLLECTIONS.SERVICES), orderBy('order', 'asc'));\n\n const snapshot = await getDocs(q);\n let items = snapshot.docs.map((d) => docToService(d.id, d.data()));\n\n if (options.activeOnly !== false) {\n items = items.filter((i) => i.isActive);\n }\n\n if (options.featuredOnly) {\n items = items.filter((i) => i.isFeatured);\n }\n\n if (options.category) {\n items = items.filter((i) => i.category === options.category);\n }\n\n if (!options.category && !options.featuredOnly && options.activeOnly !== false) {\n servicesCache = { data: items, timestamp: Date.now() };\n }\n\n return items;\n } catch (error) {\n const config = getConfig();\n if (config.debug) console.error('[shared-features] Error fetching services:', error);\n return servicesCache?.data ?? [];\n }\n}\n\nexport function clearServicesCache(): void {\n servicesCache = null;\n}\n\n// ============================================================================\n// SKILLS\n// ============================================================================\n\nfunction docToSkill(docId: string, data: Record<string, unknown>): Skill {\n return {\n id: docId,\n name: (data.name as string) || '',\n category: data.category as Skill['category'],\n level: data.level as Skill['level'],\n yearsOfExperience: data.yearsOfExperience as number | undefined,\n icon: data.icon as string | undefined,\n color: data.color as string | undefined,\n isActive: (data.isActive as boolean) ?? true,\n isFeatured: (data.isFeatured as boolean) ?? false,\n order: (data.order as number) ?? 0,\n updatedAt: data.updatedAt as Timestamp,\n };\n}\n\nexport async function fetchSkills(options: FetchSkillsOptions = {}): Promise<Skill[]> {\n if (!isFeatureEnabled('skills')) {\n const config = getConfig();\n if (config.debug) console.log('[shared-features] skills feature is disabled');\n return [];\n }\n\n if (!options.category && !options.featuredOnly && options.activeOnly !== false && isCacheValid(skillsCache)) {\n return skillsCache!.data ?? [];\n }\n\n try {\n const db = getSharedFeaturesDb();\n let q = query(collection(db, COMMON_FEATURE_COLLECTIONS.SKILLS), orderBy('order', 'asc'));\n\n const snapshot = await getDocs(q);\n let items = snapshot.docs.map((d) => docToSkill(d.id, d.data()));\n\n if (options.activeOnly !== false) {\n items = items.filter((i) => i.isActive);\n }\n\n if (options.featuredOnly) {\n items = items.filter((i) => i.isFeatured);\n }\n\n if (options.category) {\n items = items.filter((i) => i.category === options.category);\n }\n\n if (!options.category && !options.featuredOnly && options.activeOnly !== false) {\n skillsCache = { data: items, timestamp: Date.now() };\n }\n\n return items;\n } catch (error) {\n const config = getConfig();\n if (config.debug) console.error('[shared-features] Error fetching skills:', error);\n return skillsCache?.data ?? [];\n }\n}\n\nexport function clearSkillsCache(): void {\n skillsCache = null;\n}\n\n// ============================================================================\n// TESTIMONIALS\n// ============================================================================\n\nfunction docToTestimonial(docId: string, data: Record<string, unknown>): Testimonial {\n return {\n id: docId,\n authorName: ((data.authorName ?? data.name) as string) || '',\n authorTitle: (data.authorTitle ?? data.title) as string | undefined,\n authorCompany: (data.authorCompany ?? data.company) as string | undefined,\n authorAvatar: (data.authorAvatar ?? data.avatar) as string | undefined,\n authorLinkedin: (data.authorLinkedin ?? data.profileUrl) as string | undefined,\n content: ((data.content ?? data.text) as string) || '',\n shortContent: data.shortContent as string | undefined,\n rating: data.rating as number | undefined,\n projectName: data.projectName as string | undefined,\n projectUrl: data.projectUrl as string | undefined,\n date: data.date as Timestamp | undefined,\n isActive: ((data.isActive ?? data.enabled) as boolean) ?? true,\n isFeatured: (data.isFeatured as boolean) ?? false,\n order: (data.order as number) ?? 0,\n updatedAt: data.updatedAt as Timestamp,\n };\n}\n\nexport async function fetchTestimonials(options: FetchTestimonialsOptions = {}): Promise<Testimonial[]> {\n if (!isFeatureEnabled('testimonials')) {\n const config = getConfig();\n if (config.debug) console.log('[shared-features] testimonials feature is disabled');\n return [];\n }\n\n if (!options.featuredOnly && !options.limit && options.activeOnly !== false && isCacheValid(testimonialsCache)) {\n return testimonialsCache!.data ?? [];\n }\n\n try {\n const db = getSharedFeaturesDb();\n let q = query(collection(db, COMMON_FEATURE_COLLECTIONS.TESTIMONIALS), orderBy('order', 'asc'));\n\n if (options.limit) {\n q = query(q, firestoreLimit(options.limit));\n }\n\n const snapshot = await getDocs(q);\n let items = snapshot.docs.map((d) => docToTestimonial(d.id, d.data()));\n\n if (options.activeOnly !== false) {\n items = items.filter((i) => i.isActive);\n }\n\n if (options.featuredOnly) {\n items = items.filter((i) => i.isFeatured);\n }\n\n if (!options.featuredOnly && !options.limit && options.activeOnly !== false) {\n testimonialsCache = { data: items, timestamp: Date.now() };\n }\n\n return items;\n } catch (error) {\n const config = getConfig();\n if (config.debug) console.error('[shared-features] Error fetching testimonials:', error);\n return testimonialsCache?.data ?? [];\n }\n}\n\nexport function clearTestimonialsCache(): void {\n testimonialsCache = null;\n}\n\n// ============================================================================\n// PROJECTS\n// ============================================================================\n\n/**\n * Build ProjectLink[] from flat URL fields written by portfolio admin.\n * Portfolio writes liveUrl, githubUrl, playStoreUrl, etc. as individual string fields.\n */\nfunction buildLinksFromFlatUrls(data: Record<string, unknown>): Project['links'] | undefined {\n const links: NonNullable<Project['links']> = [];\n if (data.liveUrl) links.push({ type: 'live', url: data.liveUrl as string });\n if (data.githubUrl) links.push({ type: 'github', url: data.githubUrl as string });\n if (data.playStoreUrl) links.push({ type: 'playstore', url: data.playStoreUrl as string });\n if (data.appStoreUrl) links.push({ type: 'appstore', url: data.appStoreUrl as string });\n if (data.npmUrl) links.push({ type: 'npm', url: data.npmUrl as string });\n if (data.docsUrl) links.push({ type: 'docs', url: data.docsUrl as string });\n if (data.demoUrl) links.push({ type: 'demo', url: data.demoUrl as string });\n if (data.chromeExtensionUrl) links.push({ type: 'other', url: data.chromeExtensionUrl as string, label: 'Chrome Extension' });\n if (data.firefoxExtensionUrl) links.push({ type: 'other', url: data.firefoxExtensionUrl as string, label: 'Firefox Extension' });\n if (data.edgeExtensionUrl) links.push({ type: 'other', url: data.edgeExtensionUrl as string, label: 'Edge Extension' });\n return links.length > 0 ? links : undefined;\n}\n\nfunction docToProject(docId: string, data: Record<string, unknown>): Project {\n return {\n id: docId,\n title: (data.title as string) || '',\n slug: ((data.slug ?? data.appIdentifier) as string) || '',\n description: ((data.description ?? data.longDescription) as string) || '',\n shortDescription: data.shortDescription as string | undefined,\n category: data.category as Project['category'],\n status: data.status as Project['status'],\n thumbnailUrl: data.thumbnailUrl as string | undefined,\n images: data.images as string[] | undefined,\n technologies: ((data.technologies ?? data.techStack) as string[]) || [],\n features: data.features as string[] | undefined,\n links: (data.links as Project['links']) ?? buildLinksFromFlatUrls(data),\n clientName: data.clientName as string | undefined,\n startDate: data.startDate as string | undefined,\n endDate: data.endDate as string | undefined,\n isActive: ((data.isActive ?? data.enabled) as boolean) ?? true,\n isFeatured: (data.isFeatured as boolean) ?? false,\n order: (data.order as number) ?? 0,\n updatedAt: data.updatedAt as Timestamp,\n };\n}\n\nexport async function fetchProjects(options: FetchProjectsOptions = {}): Promise<Project[]> {\n if (!isFeatureEnabled('projects')) {\n const config = getConfig();\n if (config.debug) console.log('[shared-features] projects feature is disabled');\n return [];\n }\n\n if (!options.category && !options.status && !options.featuredOnly && !options.limit && options.activeOnly !== false && isCacheValid(projectsCache)) {\n return projectsCache!.data ?? [];\n }\n\n try {\n const db = getSharedFeaturesDb();\n let q = query(collection(db, COMMON_FEATURE_COLLECTIONS.PROJECTS), orderBy('order', 'asc'));\n\n if (options.limit) {\n q = query(q, firestoreLimit(options.limit));\n }\n\n const snapshot = await getDocs(q);\n let items = snapshot.docs.map((d) => docToProject(d.id, d.data()));\n\n if (options.activeOnly !== false) {\n items = items.filter((i) => i.isActive);\n }\n\n if (options.featuredOnly) {\n items = items.filter((i) => i.isFeatured);\n }\n\n if (options.category) {\n items = items.filter((i) => i.category === options.category);\n }\n\n if (options.status) {\n items = items.filter((i) => i.status === options.status);\n }\n\n if (!options.category && !options.status && !options.featuredOnly && !options.limit && options.activeOnly !== false) {\n projectsCache = { data: items, timestamp: Date.now() };\n }\n\n return items;\n } catch (error) {\n const config = getConfig();\n if (config.debug) console.error('[shared-features] Error fetching projects:', error);\n return projectsCache?.data ?? [];\n }\n}\n\nexport async function fetchProjectBySlug(slug: string): Promise<Project | null> {\n if (!isFeatureEnabled('projects')) return null;\n\n try {\n // First check cache\n if (isCacheValid(projectsCache)) {\n const cached = projectsCache!.data?.find((p) => p.slug === slug);\n if (cached) return cached;\n }\n\n // Fetch all and find\n const projects = await fetchProjects();\n return projects.find((p) => p.slug === slug) ?? null;\n } catch (error) {\n const config = getConfig();\n if (config.debug) console.error('[shared-features] Error fetching project by slug:', error);\n return null;\n }\n}\n\nexport function clearProjectsCache(): void {\n projectsCache = null;\n}\n"],"names":["getApps","app","initializeApp","getFirestore","getAuth","setCommonFeatureCollectionNames","CACHE_TTL_MS","isCacheValid","getDocs","collection","getDoc","doc","query","where","orderBy","firestoreLimit","Timestamp","state","serverTimestamp","addDoc","COLLECTION_FEATURE_FLAGS","FEATURE_FLAGS_DOC_ID","config","DEFAULT_FEATURE_FLAGS","onSnapshot","setDoc","COMMON_FEATURE_COLLECTIONS"],"mappings":"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"}
|
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
import { getFirestore, Timestamp, query, collection, where, orderBy, limit, getDocs, getDoc, doc, serverTimestamp, addDoc, setDoc, onSnapshot } from "firebase/firestore";
|
|
2
2
|
import { getApps, initializeApp } from "firebase/app";
|
|
3
3
|
import { getAuth } from "firebase/auth";
|
|
4
|
-
import { s as setCommonFeatureCollectionNames, C as COLLECTION_FEATURE_FLAGS, F as FEATURE_FLAGS_DOC_ID, e as DEFAULT_FEATURE_FLAGS, a as COMMON_FEATURE_COLLECTIONS } from "./featureFlags-
|
|
4
|
+
import { s as setCommonFeatureCollectionNames, C as COLLECTION_FEATURE_FLAGS, F as FEATURE_FLAGS_DOC_ID, e as DEFAULT_FEATURE_FLAGS, a as COMMON_FEATURE_COLLECTIONS } from "./featureFlags-CSudFX4x.js";
|
|
5
5
|
let state = {
|
|
6
6
|
initialized: false,
|
|
7
7
|
config: null,
|
|
@@ -913,17 +913,25 @@ function clearDeveloperInfoCache() {
|
|
|
913
913
|
}
|
|
914
914
|
function docToAddressInfo(docId, data) {
|
|
915
915
|
const details = data.addressDetails || {};
|
|
916
|
+
const coords = data.coordinates;
|
|
916
917
|
return {
|
|
917
918
|
id: docId,
|
|
918
919
|
label: data.label,
|
|
919
920
|
streetAddress: data.streetAddress ?? details.streetAddress,
|
|
921
|
+
apartment: data.apartment ?? details.apartment,
|
|
920
922
|
city: data.city ?? details.city,
|
|
921
923
|
state: data.state ?? details.state,
|
|
922
924
|
postalCode: data.postalCode ?? details.postalCode,
|
|
923
925
|
country: data.country ?? details.country,
|
|
926
|
+
landmark: data.landmark ?? details.landmark,
|
|
924
927
|
fullAddress: data.fullAddress ?? data.displayAddress,
|
|
925
928
|
googleMapsUrl: data.googleMapsUrl ?? data.googleMapsLink,
|
|
929
|
+
googleMapsEmbedUrl: data.googleMapsEmbedUrl,
|
|
930
|
+
coordinates: coords && typeof coords.lat === "number" && typeof coords.lng === "number" ? { lat: coords.lat, lng: coords.lng } : void 0,
|
|
931
|
+
showMap: data.showMap ?? false,
|
|
926
932
|
isPublic: data.isPublic ?? false,
|
|
933
|
+
workingHours: data.workingHours,
|
|
934
|
+
additionalInfo: data.additionalInfo,
|
|
927
935
|
updatedAt: data.updatedAt
|
|
928
936
|
};
|
|
929
937
|
}
|
|
@@ -1368,4 +1376,4 @@ export {
|
|
|
1368
1376
|
fetchServices as y,
|
|
1369
1377
|
fetchSkills as z
|
|
1370
1378
|
};
|
|
1371
|
-
//# sourceMappingURL=commonFeatures-
|
|
1379
|
+
//# sourceMappingURL=commonFeatures-LzPnbR6z.js.map
|