UNPKG

@mikkelscheike/email-provider-links

Version:

TypeScript library for email provider detection with 93 providers (207 domains), concurrent DNS resolution, optimized performance, 94.65% test coverage, and enterprise security for login and password reset flows

163 lines 5.62 kB
"use strict"; /** * Provider Data Loader * * Handles loading email provider data with performance optimizations. */ Object.defineProperty(exports, "__esModule", { value: true }); exports.buildDomainMap = buildDomainMap; exports.clearCache = clearCache; exports.getLoadingStats = getLoadingStats; exports.loadProviders = loadProviders; exports.loadProvidersDebug = loadProvidersDebug; const fs_1 = require("fs"); const path_1 = require("path"); const schema_1 = require("./schema"); /** * Internal cached data */ let cachedProviders = null; let cachedDomainMap = null; let loadingStats = null; /** * Default loader configuration */ const DEFAULT_CONFIG = { debug: false }; /** * Convert compressed provider to EmailProvider format */ function convertProviderToEmailProvider(compressedProvider) { if (!compressedProvider.type) { console.warn(`Missing type for provider ${compressedProvider.id}`); } const provider = { companyProvider: compressedProvider.companyProvider, loginUrl: compressedProvider.loginUrl || null, domains: compressedProvider.domains || [], type: compressedProvider.type, alias: compressedProvider.alias }; // Include DNS detection patterns for business email services and proxy services const needsCustomDomainDetection = compressedProvider.type === 'custom_provider' || compressedProvider.type === 'proxy_service'; if (needsCustomDomainDetection && (compressedProvider.mx?.length || compressedProvider.txt?.length)) { provider.customDomainDetection = {}; if (compressedProvider.mx?.length) { provider.customDomainDetection.mxPatterns = compressedProvider.mx; } if (compressedProvider.txt?.length) { // Decompress TXT patterns provider.customDomainDetection.txtPatterns = compressedProvider.txt.map(schema_1.decompressTxtPattern); } } return provider; } /** * Internal provider data loader with configuration */ function loadProvidersInternal(config = {}) { const mergedConfig = { ...DEFAULT_CONFIG, ...config }; const startTime = Date.now(); // Return cached data if available if (cachedProviders && !mergedConfig.debug) { return { providers: cachedProviders, stats: loadingStats }; } try { // Determine file path const basePath = (0, path_1.join)(__dirname, '..', 'providers'); const dataPath = mergedConfig.path || (0, path_1.join)(basePath, 'emailproviders.json'); if (mergedConfig.debug) console.log('🔄 Loading provider data...'); const content = (0, fs_1.readFileSync)(dataPath, 'utf8'); const data = JSON.parse(content); // Validate format if (!data.version || !data.providers || !Array.isArray(data.providers)) { throw new Error('Invalid provider data format'); } const providers = data.providers.map(convertProviderToEmailProvider); const fileSize = content.length; if (mergedConfig.debug) { console.log(`✅ Loaded ${providers.length} providers`); console.log(`📊 File size: ${(fileSize / 1024).toFixed(1)} KB`); } const loadTime = Date.now() - startTime; const domainCount = providers.reduce((sum, p) => sum + p.domains.length, 0); // Cache the results cachedProviders = providers; loadingStats = { fileSize, loadTime, providerCount: providers.length, domainCount }; if (mergedConfig.debug) { console.log(`⚡ Loading completed in ${loadTime}ms`); console.log(`📊 Stats: ${providers.length} providers, ${domainCount} domains`); } if (process.env.NODE_ENV === 'development') { const memoryUsageInMB = process.memoryUsage().heapUsed / 1024 / 1024; console.log(`🚀 Current memory usage: ${memoryUsageInMB.toFixed(2)} MB`); } return { providers, stats: loadingStats }; } catch (error) { const errorMessage = error instanceof Error ? error.message : 'Unknown error'; throw new Error(`Failed to load provider data: ${errorMessage}`); } } /** * Build optimized domain-to-provider lookup map */ function buildDomainMap(providers) { if (cachedDomainMap) { return cachedDomainMap; } const domainMap = new Map(); for (const provider of providers) { for (const domain of provider.domains) { domainMap.set(domain.toLowerCase(), provider); } } cachedDomainMap = domainMap; return domainMap; } /** * Clear all caches (useful for testing or hot reloading) */ function clearCache() { cachedProviders = null; cachedDomainMap = null; loadingStats = null; } /** * Get loading statistics from the last load operation */ function getLoadingStats() { return loadingStats; } /** * Load all providers with optimized domain map for production */ function loadProviders() { const { providers, stats } = loadProvidersInternal({ debug: false }); const domainMap = buildDomainMap(providers); return { providers, domainMap, stats }; } /** * Load providers with debug information */ function loadProvidersDebug() { clearCache(); // Always reload in debug mode const { providers, stats } = loadProvidersInternal({ debug: true }); const domainMap = buildDomainMap(providers); return { providers, domainMap, stats }; } //# sourceMappingURL=loader.js.map