@emailcheck/email-validator-js 5.0.0 → 5.1.0-beta.1
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/README.md +40 -4
- package/dist/cli/index.js +34 -2
- package/dist/cli/index.js.map +1 -1
- package/dist/index.d.ts +1 -0
- package/dist/index.esm.js +36 -3
- package/dist/index.esm.js.map +1 -1
- package/dist/index.js +36 -2
- package/dist/index.js.map +1 -1
- package/dist/sender-strategy.d.ts +26 -0
- package/dist/serverless/adapters/aws-lambda.cjs.js +5 -5
- package/dist/serverless/adapters/aws-lambda.cjs.js.map +1 -1
- package/dist/serverless/adapters/aws-lambda.esm.js +5 -5
- package/dist/serverless/adapters/aws-lambda.esm.js.map +1 -1
- package/dist/serverless/adapters/azure.cjs.js +5 -5
- package/dist/serverless/adapters/azure.cjs.js.map +1 -1
- package/dist/serverless/adapters/azure.esm.js +5 -5
- package/dist/serverless/adapters/azure.esm.js.map +1 -1
- package/dist/serverless/adapters/cloudflare.cjs.js +5 -5
- package/dist/serverless/adapters/cloudflare.cjs.js.map +1 -1
- package/dist/serverless/adapters/cloudflare.esm.js +5 -5
- package/dist/serverless/adapters/cloudflare.esm.js.map +1 -1
- package/dist/serverless/adapters/gcp.cjs.js +5 -5
- package/dist/serverless/adapters/gcp.cjs.js.map +1 -1
- package/dist/serverless/adapters/gcp.esm.js +5 -5
- package/dist/serverless/adapters/gcp.esm.js.map +1 -1
- package/dist/serverless/adapters/netlify.cjs.js +5 -5
- package/dist/serverless/adapters/netlify.cjs.js.map +1 -1
- package/dist/serverless/adapters/netlify.esm.js +5 -5
- package/dist/serverless/adapters/netlify.esm.js.map +1 -1
- package/dist/serverless/adapters/vercel.cjs.js +5 -5
- package/dist/serverless/adapters/vercel.cjs.js.map +1 -1
- package/dist/serverless/adapters/vercel.esm.js +5 -5
- package/dist/serverless/adapters/vercel.esm.js.map +1 -1
- package/dist/serverless/index.cjs.js +5 -5
- package/dist/serverless/index.cjs.js.map +1 -1
- package/dist/serverless/index.esm.js +5 -5
- package/dist/serverless/index.esm.js.map +1 -1
- package/dist/serverless/verifier.cjs.js +5 -5
- package/dist/serverless/verifier.cjs.js.map +1 -1
- package/dist/serverless/verifier.esm.js +5 -5
- package/dist/serverless/verifier.esm.js.map +1 -1
- package/dist/serverless/verifier.min.js +1 -1
- package/dist/types.d.ts +72 -0
- package/package.json +3 -3
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"azure.cjs.js","sources":["../../../src/serverless/_shared/cors.ts","../../../node_modules/string-similarity-js/dist/string-similarity.js","../../../src/serverless/verifier.ts","../../../src/serverless/_shared/dispatch.ts","../../../src/serverless/_shared/validation.ts","../../../src/serverless/adapters/azure.ts"],"sourcesContent":["/**\n * Standard CORS header set used by every adapter. `methods` lets each platform\n * advertise the verbs it actually supports without re-declaring the rest.\n */\nexport function corsHeaders(methods: string = 'GET, POST, OPTIONS'): Record<string, string> {\n return {\n 'Access-Control-Allow-Origin': '*',\n 'Access-Control-Allow-Methods': methods,\n 'Access-Control-Allow-Headers': 'Content-Type',\n };\n}\n\nexport function jsonHeaders(extra?: Record<string, string>): Record<string, string> {\n return { 'Content-Type': 'application/json', ...extra };\n}\n","\"use strict\";\nObject.defineProperty(exports, \"__esModule\", { value: true });\nexports.stringSimilarity = void 0;\n/* global exports, Map */\n/**\n * Calculate similarity between two strings\n * @param {string} str1 First string to match\n * @param {string} str2 Second string to match\n * @param {number} [substringLength=2] Optional. Length of substring to be used in calculating similarity. Default 2.\n * @param {boolean} [caseSensitive=false] Optional. Whether you want to consider case in string matching. Default false;\n * @returns Number between 0 and 1, with 0 being a low match score.\n */\nvar stringSimilarity = function (str1, str2, substringLength, caseSensitive) {\n if (substringLength === void 0) { substringLength = 2; }\n if (caseSensitive === void 0) { caseSensitive = false; }\n if (!caseSensitive) {\n str1 = str1.toLowerCase();\n str2 = str2.toLowerCase();\n }\n if (str1.length < substringLength || str2.length < substringLength)\n return 0;\n var map = new Map();\n for (var i = 0; i < str1.length - (substringLength - 1); i++) {\n var substr1 = str1.substr(i, substringLength);\n map.set(substr1, map.has(substr1) ? map.get(substr1) + 1 : 1);\n }\n var match = 0;\n for (var j = 0; j < str2.length - (substringLength - 1); j++) {\n var substr2 = str2.substr(j, substringLength);\n var count = map.has(substr2) ? map.get(substr2) : 0;\n if (count > 0) {\n map.set(substr2, count - 1);\n match++;\n }\n }\n return (match * 2) / (str1.length + str2.length - ((substringLength - 1) * 2));\n};\nexports.stringSimilarity = stringSimilarity;\nexports.default = exports.stringSimilarity;\n//# sourceMappingURL=string-similarity.js.map","/**\n * Edge-runtime / serverless email validator.\n *\n * No Node.js APIs (no `node:net`, no `node:dns`) — DNS is delegated to a\n * caller-supplied `DNSResolver`, so the same code runs on Cloudflare Workers,\n * Vercel Edge, Lambda@Edge, and Deno Deploy.\n *\n * Shares data with the main validator: `commonEmailDomains` and the typo map\n * are imported from `src/data/`, so we never drift between the two surfaces.\n */\n\nimport { stringSimilarity } from 'string-similarity-js';\nimport commonEmailDomainsJson from '../data/common-email-domains.json';\nimport typoPatternsJson from '../data/typo-patterns.json';\nimport disposableProviders from '../disposable-email-providers.json';\nimport freeProviders from '../free-email-providers.json';\nimport type { DomainSuggesterOptions, EmailValidationResult, ValidateEmailOptions } from '../types';\n\n/** Compact LRU/TTL cache. One Map, expiry stamp per entry, batched eviction. */\nexport class EdgeCache<T> {\n private readonly cache = new Map<string, { value: T; expires: number }>();\n\n constructor(\n private readonly maxSize = 1000,\n private readonly ttl = 3_600_000\n ) {}\n\n get(key: string): T | undefined {\n const item = this.cache.get(key);\n if (!item) return undefined;\n if (Date.now() > item.expires) {\n this.cache.delete(key);\n return undefined;\n }\n return item.value;\n }\n\n set(key: string, value: T): void {\n if (this.cache.size >= this.maxSize) this.evict();\n this.cache.set(key, { value, expires: Date.now() + this.ttl });\n }\n\n clear(): void {\n this.cache.clear();\n }\n\n size(): number {\n return this.cache.size;\n }\n\n private evict(): void {\n // Drop the oldest 10% in one pass — Map preserves insertion order so\n // `keys()` walks oldest-first.\n const drop = Math.max(1, Math.floor(this.maxSize * 0.1));\n let n = 0;\n for (const key of this.cache.keys()) {\n if (n++ >= drop) break;\n this.cache.delete(key);\n }\n }\n}\n\n// Module-level per-isolate caches. Edge runtimes get cold-start fresh; warm\n// invocations benefit from the in-memory hits.\nexport const validationCache = new EdgeCache<EmailValidationResult>(1000);\nexport const mxCache = new EdgeCache<string[]>(500);\n\n/** Same regex the main validator uses — kept inline because edge runtimes don't auto-resolve psl. */\nconst VALID_EMAIL_REGEX =\n /^(([a-zA-Z0-9_+'-]+(\\.[a-zA-Z0-9_+'-]+)*)|(\".+\"))@((\\[[0-9]{1,3}\\.[0-9]{1,3}\\.[0-9]{1,3}\\.[0-9]{1,3}])|(([a-zA-Z0-9-]+\\.)+[a-zA-Z]{2,}))$/;\n\n/**\n * Common email domains — re-exported so callers (Vercel Edge, etc.) can pass a\n * custom subset via `DomainSuggesterOptions.customDomains`.\n */\nexport const COMMON_DOMAINS: readonly string[] = commonEmailDomainsJson as string[];\n\nconst TYPO_PATTERNS = typoPatternsJson as Record<string, string[]>;\n/** Reverse index for O(1) typo → canonical lookup. */\nconst TYPO_LOOKUP = new Map<string, string>();\nfor (const [canonical, typos] of Object.entries(TYPO_PATTERNS)) {\n for (const typo of typos) TYPO_LOOKUP.set(typo, canonical);\n}\n\n/** DNS resolver contract — caller-supplied so we don't import `node:dns`. */\nexport interface DNSResolver {\n resolveMx(domain: string): Promise<Array<{ exchange: string; priority: number }>>;\n resolveTxt(domain: string): Promise<string[]>;\n}\n\n/** No-op resolver for environments where DNS isn't available. */\nexport class StubDNSResolver implements DNSResolver {\n async resolveMx(): Promise<Array<{ exchange: string; priority: number }>> {\n return [];\n }\n async resolveTxt(): Promise<string[]> {\n return [];\n }\n}\n\n/**\n * DNS-over-HTTPS resolver — works in any runtime with `fetch` (Cloudflare\n * Workers, Vercel Edge, Deno, browsers, Node 18+). Defaults to Cloudflare's\n * 1.1.1.1 endpoint; pass `endpoint` to use Google (8.8.8.8), NextDNS, or\n * a self-hosted resolver.\n *\n * Compatible with [`cf-doh`](https://www.npmjs.com/package/cf-doh) — if you\n * already use that, drop it in directly. This built-in keeps the package\n * zero-dep so the same code works on every edge runtime without an extra\n * install step.\n */\nexport interface DoHResolverOptions {\n /** DoH endpoint URL. Default: https://cloudflare-dns.com/dns-query */\n endpoint?: string;\n /** Per-query request timeout, ms. Default: 5000 */\n timeoutMs?: number;\n /** Custom fetch (e.g. to add headers / proxy). Default: globalThis.fetch */\n fetch?: typeof fetch;\n}\n\ninterface DoHAnswer {\n name: string;\n type: number;\n TTL: number;\n data: string;\n}\n\ninterface DoHResponse {\n Status: number;\n Answer?: DoHAnswer[];\n}\n\nconst DOH_RECORD_TYPE = { MX: 15, TXT: 16 } as const;\n\nexport class DoHResolver implements DNSResolver {\n private readonly endpoint: string;\n private readonly timeoutMs: number;\n private readonly fetchFn: typeof fetch;\n\n constructor(options: DoHResolverOptions = {}) {\n this.endpoint = options.endpoint ?? 'https://cloudflare-dns.com/dns-query';\n this.timeoutMs = options.timeoutMs ?? 5000;\n this.fetchFn = options.fetch ?? globalThis.fetch;\n }\n\n async resolveMx(domain: string): Promise<Array<{ exchange: string; priority: number }>> {\n const records = await this.query(domain, DOH_RECORD_TYPE.MX);\n if (!records) return [];\n return records\n .map((answer) => {\n // MX answer data: \"<priority> <exchange>\" (with optional trailing dot).\n const match = answer.data.match(/^(\\d+)\\s+(.+?)\\.?$/);\n if (!match) return null;\n return { priority: Number(match[1]), exchange: match[2] as string };\n })\n .filter((r): r is { exchange: string; priority: number } => r !== null)\n .sort((a, b) => a.priority - b.priority);\n }\n\n async resolveTxt(domain: string): Promise<string[]> {\n const records = await this.query(domain, DOH_RECORD_TYPE.TXT);\n if (!records) return [];\n // TXT answers come back as quoted strings — strip the surrounding quotes.\n return records.map((answer) => answer.data.replace(/^\"(.*)\"$/, '$1'));\n }\n\n private async query(domain: string, type: number): Promise<DoHAnswer[] | null> {\n const url = `${this.endpoint}?name=${encodeURIComponent(domain)}&type=${type}`;\n const controller = new AbortController();\n const timer = setTimeout(() => controller.abort(), this.timeoutMs);\n try {\n const response = await this.fetchFn(url, {\n headers: { Accept: 'application/dns-json' },\n signal: controller.signal,\n });\n if (!response.ok) return null;\n const json = (await response.json()) as DoHResponse;\n // Status 0 = NOERROR. Anything else (NXDOMAIN, SERVFAIL, etc.) → no answers.\n if (json.Status !== 0) return [];\n return json.Answer ?? [];\n } catch {\n return null;\n } finally {\n clearTimeout(timer);\n }\n }\n}\n\n/**\n * Suggest a corrected domain. Returns the canonical for a known typo,\n * otherwise the closest match within the threshold, otherwise null.\n */\nexport function suggestDomain(domain: string, options?: DomainSuggesterOptions): string | null {\n const lower = domain.toLowerCase();\n\n // Hand-curated typo map first — beats similarity for common cases.\n const known = TYPO_LOOKUP.get(lower);\n if (known) return known;\n\n const domains = options?.customDomains ?? COMMON_DOMAINS;\n if (domains.includes(lower)) return null;\n\n const threshold = options?.threshold ?? 2;\n let minDistance = Infinity;\n let suggestion: string | null = null;\n\n for (const candidate of domains) {\n const candidateLower = candidate.toLowerCase();\n if (lower === candidateLower) return null;\n const similarity = stringSimilarity(lower, candidateLower);\n const distance = Math.round((1 - similarity) * Math.max(domain.length, candidate.length));\n if (distance > 0 && distance <= threshold && distance < minDistance) {\n minDistance = distance;\n suggestion = candidate;\n }\n }\n return suggestion;\n}\n\n/**\n * Validate one email — syntax / typo / disposable / free / MX (if a resolver\n * is supplied). Each step is independently flag-gated so callers pay only for\n * what they use.\n */\nexport async function validateEmailCore(\n email: string,\n options?: ValidateEmailOptions & { dnsResolver?: DNSResolver }\n): Promise<EmailValidationResult> {\n const normalized = email.toLowerCase().trim();\n\n if (!options?.skipCache) {\n const cached = validationCache.get(normalized);\n if (cached) return cached;\n }\n\n const result: EmailValidationResult = { valid: false, email: normalized, validators: {} };\n\n if (options?.validateSyntax !== false) {\n const syntaxValid = VALID_EMAIL_REGEX.test(normalized);\n result.validators.syntax = { valid: syntaxValid };\n if (!syntaxValid) {\n validationCache.set(normalized, result);\n return result;\n }\n }\n\n const [local, domain] = normalized.split('@');\n result.local = local;\n result.domain = domain;\n\n if (options?.validateTypo !== false) {\n const suggestion = suggestDomain(domain, options?.domainSuggesterOptions);\n result.validators.typo = { valid: !suggestion, suggestion: suggestion ?? undefined };\n }\n\n if (options?.validateDisposable !== false) {\n result.validators.disposable = { valid: !disposableProviders.includes(domain) };\n }\n\n if (options?.validateFree !== false) {\n result.validators.free = { valid: !freeProviders.includes(domain) };\n }\n\n if (options?.validateMx && options.dnsResolver) {\n try {\n const records = await options.dnsResolver.resolveMx(domain);\n const hasMx = records.length > 0;\n result.validators.mx = {\n valid: hasMx,\n records: hasMx ? records.map((r) => r.exchange) : undefined,\n };\n } catch (error) {\n result.validators.mx = {\n valid: false,\n error: error instanceof Error ? error.message : 'MX validation failed',\n };\n }\n }\n\n // Free-provider detection is informational; only the hard validators gate validity.\n result.valid = (['syntax', 'typo', 'disposable', 'mx'] as const).every((key) => {\n const validator = result.validators[key];\n return !validator || validator.valid !== false;\n });\n\n if (!options?.skipCache) validationCache.set(normalized, result);\n return result;\n}\n\nexport async function validateEmailBatch(\n emails: string[],\n options?: ValidateEmailOptions & { dnsResolver?: DNSResolver }\n): Promise<EmailValidationResult[]> {\n const chunkSize = options?.batchSize ?? 10;\n const results: EmailValidationResult[] = [];\n for (let i = 0; i < emails.length; i += chunkSize) {\n const chunk = emails.slice(i, i + chunkSize);\n const chunkResults = await Promise.all(chunk.map((email) => validateEmailCore(email, options)));\n results.push(...chunkResults);\n }\n return results;\n}\n\nexport function clearCache(): void {\n validationCache.clear();\n mxCache.clear();\n}\n\nexport type { DomainSuggesterOptions, EmailValidationResult, ValidateEmailOptions } from '../types';\n","import type { EmailValidationResult } from '../../types';\nimport { validateEmailBatch, validateEmailCore } from '../verifier';\nimport type { ValidationDispatch } from './validation';\n\n/**\n * Execute a classified request against the core validator. Single-email\n * requests yield one result; batch requests yield an array.\n */\nexport async function executeValidation(\n dispatch: ValidationDispatch\n): Promise<EmailValidationResult | EmailValidationResult[]> {\n if (dispatch.kind === 'single') {\n return validateEmailCore(dispatch.email, dispatch.options);\n }\n return validateEmailBatch(dispatch.emails, dispatch.options);\n}\n","import type { ValidateEmailOptions } from '../../types';\n\n/** Hard limit on batch size enforced by every adapter. */\nexport const MAX_BATCH_SIZE = 100;\n\n/** Shape of POST bodies and Lambda invocations across all serverless adapters. */\nexport interface ValidationRequestBody {\n email?: string;\n emails?: string[];\n options?: ValidateEmailOptions;\n}\n\nexport type ValidationDispatch =\n | { kind: 'single'; email: string; options?: ValidateEmailOptions }\n | { kind: 'batch'; emails: string[]; options?: ValidateEmailOptions };\n\nexport interface ValidationFailure {\n kind: 'invalid';\n status: 400;\n message: string;\n}\n\n/**\n * Validation for endpoints that accept ONLY a batch (`emails`). Returns\n * a 400 failure if emails is missing/empty/oversized, or null when valid.\n * Routed `/validate/batch` paths use this so error messages stay batch-specific.\n */\nexport type BatchValidation = { ok: true; emails: string[] } | { ok: false; status: 400; message: string };\n\nexport function validateBatchEmailsField(emails: unknown): BatchValidation {\n if (!Array.isArray(emails) || emails.length === 0) {\n return { ok: false, status: 400, message: 'Emails array is required' };\n }\n if (emails.length > MAX_BATCH_SIZE) {\n return { ok: false, status: 400, message: `Maximum ${MAX_BATCH_SIZE} emails allowed per batch` };\n }\n return { ok: true, emails: emails as string[] };\n}\n\n/**\n * Apply the rules every serverless adapter shares:\n * 1. body must request either `email` or `emails`\n * 2. `emails` must be a non-empty array of ≤ MAX_BATCH_SIZE entries\n *\n * Centralising this means a future rule change (say, raising the cap) lands\n * in one place instead of three.\n */\nexport function classifyRequest(\n body: ValidationRequestBody | null | undefined\n): ValidationDispatch | ValidationFailure {\n if (!body || (!body.email && !body.emails)) {\n return { kind: 'invalid', status: 400, message: 'Email or emails array is required' };\n }\n if (body.emails) {\n if (!Array.isArray(body.emails) || body.emails.length === 0) {\n return { kind: 'invalid', status: 400, message: 'Emails array is required' };\n }\n if (body.emails.length > MAX_BATCH_SIZE) {\n return { kind: 'invalid', status: 400, message: `Maximum ${MAX_BATCH_SIZE} emails allowed per batch` };\n }\n return { kind: 'batch', emails: body.emails, options: body.options };\n }\n // body.email must be set per the first guard (which checks both fields).\n if (!body.email) {\n return { kind: 'invalid', status: 400, message: 'Email or emails array is required' };\n }\n return { kind: 'single', email: body.email, options: body.options };\n}\n","/**\n * Azure Functions adapter for email validation.\n *\n * Targets the v4 programming model:\n * `(request: HttpRequest, context: InvocationContext): Promise<HttpResponseInit>`\n *\n * The HttpRequest is a Web-API-aligned shape (`request.json()`, `request.method`,\n * `request.query`, `request.headers`), so the adapter reads the body via the\n * Web API. Routes:\n * - GET /api/health\n * - POST /api/validate\n * - POST /api/validate/batch\n *\n * Two handler shapes are exported:\n * - `azureHandler`: routed (recommended).\n * - `azureFunction`: single-route convenience that infers single vs. batch\n * from the body — for one-function-per-URL setups.\n *\n * The interfaces below are minimal subsets of the official `@azure/functions`\n * types so callers can pass real Azure types without an extra cast.\n */\nimport type { ValidateEmailOptions } from '../../types';\nimport { corsHeaders, jsonHeaders } from '../_shared/cors';\nimport { executeValidation } from '../_shared/dispatch';\nimport { classifyRequest, type ValidationRequestBody, validateBatchEmailsField } from '../_shared/validation';\nimport { validateEmailCore } from '../verifier';\n\nexport interface AzureHttpRequest {\n method: string;\n url: string;\n headers: { get(name: string): string | null } | Record<string, string | undefined>;\n query: { get(name: string): string | null } | Record<string, string | undefined>;\n json(): Promise<unknown>;\n text?: () => Promise<string>;\n}\n\nexport interface AzureInvocationContext {\n invocationId?: string;\n functionName?: string;\n log?: (...args: unknown[]) => void;\n error?: (...args: unknown[]) => void;\n}\n\nexport interface AzureHttpResponseInit {\n status: number;\n headers: Record<string, string>;\n jsonBody?: unknown;\n body?: string;\n}\n\nconst ROUTED_HEADERS = jsonHeaders(corsHeaders());\n\nfunction jsonResponse(\n status: number,\n body: unknown,\n headers: Record<string, string> = ROUTED_HEADERS\n): AzureHttpResponseInit {\n return { status, headers, jsonBody: body };\n}\n\nfunction pathOf(req: AzureHttpRequest): string {\n try {\n return new URL(req.url).pathname || '/';\n } catch {\n // Some test harnesses pass a bare path. Treat it as the pathname.\n const idx = req.url.indexOf('?');\n return idx === -1 ? req.url : req.url.slice(0, idx);\n }\n}\n\nfunction readQuery(query: AzureHttpRequest['query'], key: string): string | undefined {\n if (typeof (query as { get?: unknown }).get === 'function') {\n const v = (query as { get: (k: string) => string | null }).get(key);\n return v ?? undefined;\n }\n const value = (query as Record<string, string | undefined>)[key];\n return value;\n}\n\nfunction parseValidateOptions(query: AzureHttpRequest['query']): Partial<ValidateEmailOptions> {\n const options: Partial<ValidateEmailOptions> = {};\n if (readQuery(query, 'skipCache') === 'true') options.skipCache = true;\n if (readQuery(query, 'validateTypo') === 'false') options.validateTypo = false;\n return options;\n}\n\nasync function readJsonBody(req: AzureHttpRequest): Promise<unknown> {\n try {\n return await req.json();\n } catch {\n throw new SyntaxError('Invalid JSON body');\n }\n}\n\n/** Routed Azure Functions v4 handler. */\nexport async function azureHandler(\n req: AzureHttpRequest,\n _context?: AzureInvocationContext\n): Promise<AzureHttpResponseInit> {\n if (req.method === 'OPTIONS') {\n return { status: 204, headers: corsHeaders() };\n }\n\n const path = pathOf(req);\n\n if (path === '/api/health' && req.method === 'GET') {\n return jsonResponse(200, { status: 'healthy', platform: 'azure', timestamp: new Date().toISOString() });\n }\n\n const isValidatePath = path === '/api/validate' || path === '/api/validate/batch';\n if (isValidatePath && req.method !== 'POST') {\n return jsonResponse(405, { error: 'Method not allowed' });\n }\n\n if (path === '/api/validate' && req.method === 'POST') {\n try {\n const body = (await readJsonBody(req)) as { email?: string };\n if (!body.email) return jsonResponse(400, { error: 'Email is required' });\n const options = parseValidateOptions(req.query);\n const result = await validateEmailCore(body.email, options);\n return jsonResponse(200, result);\n } catch (error) {\n if (error instanceof SyntaxError) return jsonResponse(400, { error: 'Invalid request body' });\n console.error('Azure validation error:', error);\n return jsonResponse(500, { error: 'Internal server error' });\n }\n }\n\n if (path === '/api/validate/batch' && req.method === 'POST') {\n try {\n const body = (await readJsonBody(req)) as ValidationRequestBody;\n const validated = validateBatchEmailsField(body.emails);\n if (!validated.ok) return jsonResponse(validated.status, { error: validated.message });\n const results = await executeValidation({ kind: 'batch', emails: validated.emails });\n return jsonResponse(200, { results });\n } catch (error) {\n if (error instanceof SyntaxError) return jsonResponse(400, { error: 'Invalid request body' });\n console.error('Azure batch validation error:', error);\n return jsonResponse(500, { error: 'Internal server error' });\n }\n }\n\n return jsonResponse(404, { error: 'Not found' });\n}\n\n/** Single-route convenience — infers single vs. batch from the body. */\nexport async function azureFunction(\n req: AzureHttpRequest,\n _context?: AzureInvocationContext\n): Promise<AzureHttpResponseInit> {\n if (req.method === 'OPTIONS') {\n return { status: 204, headers: corsHeaders('POST, OPTIONS') };\n }\n if (req.method !== 'POST') return jsonResponse(405, { success: false, error: 'Method not allowed' });\n\n try {\n const body = (await readJsonBody(req)) as ValidationRequestBody;\n const classified = classifyRequest(body);\n if (classified.kind === 'invalid') {\n return jsonResponse(classified.status, { success: false, error: classified.message });\n }\n const data = await executeValidation(classified);\n return jsonResponse(200, { success: true, data });\n } catch (error) {\n if (error instanceof SyntaxError) return jsonResponse(400, { success: false, error: 'Invalid request body' });\n console.error('Azure function error:', error);\n const message = error instanceof Error ? error.message : 'Internal server error';\n return jsonResponse(500, { success: false, error: message });\n }\n}\n\nexport default {\n azureHandler,\n azureFunction,\n};\n"],"names":["exports","stringSimilarity","__async"],"mappings":";;;;;;;;;;;;;;;;;;;;AAIO,SAAS,WAAA,CAAY,UAAkB,oBAAA,EAA8C;AAC1F,EAAA,OAAO;AAAA,IACL,6BAAA,EAA+B,GAAA;AAAA,IAC/B,8BAAA,EAAgC,OAAA;AAAA,IAChC,8BAAA,EAAgC;AAAA,GAClC;AACF;AAEO,SAAS,YAAY,KAAA,EAAwD;AAClF,EAAA,OAAO,cAAA,CAAA,EAAE,gBAAgB,kBAAA,EAAA,EAAuB,KAAA,CAAA;AAClD;;;;;;;;;;ECbA,MAAM,CAAC,cAAc,CAAAA,SAAA,EAAU,YAAY,EAAE,EAAE,KAAK,EAAE,IAAI,EAAE,CAAC;AAC7D,EAAAA,SAAA,CAAA,gBAAA,GAA2B,MAAM;AACjC;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;EACA,IAAI,gBAAgB,GAAG,UAAU,IAAI,EAAE,IAAI,EAAE,eAAe,EAAE,aAAa,EAAE;MACzE,IAAI,eAAe,KAAK,MAAM,EAAE,EAAE,eAAe,GAAG,CAAC,CAAC,CAAA;MACtD,IAAI,aAAa,KAAK,MAAM,EAAE,EAAE,aAAa,GAAG,KAAK,CAAC,CAAA;MACtD,IAAI,CAAC,aAAa,EAAE;AACxB,UAAQ,IAAI,GAAG,IAAI,CAAC,WAAW,EAAE;AACjC,UAAQ,IAAI,GAAG,IAAI,CAAC,WAAW,EAAE;AACjC,MAAA;MACI,IAAI,IAAI,CAAC,MAAM,GAAG,eAAe,IAAI,IAAI,CAAC,MAAM,GAAG,eAAe;AACtE,UAAQ,OAAO,CAAC;AAChB,MAAI,IAAI,GAAG,GAAG,IAAI,GAAG,EAAE;AACvB,MAAI,KAAK,IAAI,CAAC,GAAG,CAAC,EAAE,CAAC,GAAG,IAAI,CAAC,MAAM,IAAI,eAAe,GAAG,CAAC,CAAC,EAAE,CAAC,EAAE,EAAE;UAC1D,IAAI,OAAO,GAAG,IAAI,CAAC,MAAM,CAAC,CAAC,EAAE,eAAe,CAAC;UAC7C,GAAG,CAAC,GAAG,CAAC,OAAO,EAAE,GAAG,CAAC,GAAG,CAAC,OAAO,CAAC,GAAG,GAAG,CAAC,GAAG,CAAC,OAAO,CAAC,GAAG,CAAC,GAAG,CAAC,CAAC;AACrE,MAAA;MACI,IAAI,KAAK,GAAG,CAAC;AACjB,MAAI,KAAK,IAAI,CAAC,GAAG,CAAC,EAAE,CAAC,GAAG,IAAI,CAAC,MAAM,IAAI,eAAe,GAAG,CAAC,CAAC,EAAE,CAAC,EAAE,EAAE;UAC1D,IAAI,OAAO,GAAG,IAAI,CAAC,MAAM,CAAC,CAAC,EAAE,eAAe,CAAC;AACrD,UAAQ,IAAI,KAAK,GAAG,GAAG,CAAC,GAAG,CAAC,OAAO,CAAC,GAAG,GAAG,CAAC,GAAG,CAAC,OAAO,CAAC,GAAG,CAAC;AAC3D,UAAQ,IAAI,KAAK,GAAG,CAAC,EAAE;cACX,GAAG,CAAC,GAAG,CAAC,OAAO,EAAE,KAAK,GAAG,CAAC,CAAC;AACvC,cAAY,KAAK,EAAE;AACnB,UAAA;AACA,MAAA;MACI,OAAO,CAAC,KAAK,GAAG,CAAC,KAAK,IAAI,CAAC,MAAM,GAAG,IAAI,CAAC,MAAM,IAAI,CAAC,eAAe,GAAG,CAAC,IAAI,CAAC,CAAC,CAAC;EAClF,CAAC;AACD,EAAAA,SAAA,CAAA,gBAAA,GAA2B,gBAAgB;EAC3CA,SAAA,CAAA,OAAA,GAAkBA,SAAO,CAAC,gBAAgB;AAC1C;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;ACpBO,MAAM,SAAA,CAAa;AAAA,EAGxB,WAAA,CACmB,OAAA,GAAU,GAAA,EACV,GAAA,GAAM,IAAA,EACvB;AAFiB,IAAA,IAAA,CAAA,OAAA,GAAA,OAAA;AACA,IAAA,IAAA,CAAA,GAAA,GAAA,GAAA;AAJnB,IAAA,IAAA,CAAiB,KAAA,uBAAY,GAAA,EAA2C;AAAA,EAKrE;AAAA,EAEH,IAAI,GAAA,EAA4B;AAC9B,IAAA,MAAM,IAAA,GAAO,IAAA,CAAK,KAAA,CAAM,GAAA,CAAI,GAAG,CAAA;AAC/B,IAAA,IAAI,CAAC,MAAM,OAAO,MAAA;AAClB,IAAA,IAAI,IAAA,CAAK,GAAA,EAAI,GAAI,IAAA,CAAK,OAAA,EAAS;AAC7B,MAAA,IAAA,CAAK,KAAA,CAAM,OAAO,GAAG,CAAA;AACrB,MAAA,OAAO,MAAA;AAAA,IACT;AACA,IAAA,OAAO,IAAA,CAAK,KAAA;AAAA,EACd;AAAA,EAEA,GAAA,CAAI,KAAa,KAAA,EAAgB;AAC/B,IAAA,IAAI,KAAK,KAAA,CAAM,IAAA,IAAQ,IAAA,CAAK,OAAA,OAAc,KAAA,EAAM;AAChD,IAAA,IAAA,CAAK,KAAA,CAAM,GAAA,CAAI,GAAA,EAAK,EAAE,KAAA,EAAO,OAAA,EAAS,IAAA,CAAK,GAAA,EAAI,GAAI,IAAA,CAAK,GAAA,EAAK,CAAA;AAAA,EAC/D;AAAA,EAEA,KAAA,GAAc;AACZ,IAAA,IAAA,CAAK,MAAM,KAAA,EAAM;AAAA,EACnB;AAAA,EAEA,IAAA,GAAe;AACb,IAAA,OAAO,KAAK,KAAA,CAAM,IAAA;AAAA,EACpB;AAAA,EAEQ,KAAA,GAAc;AAGpB,IAAA,MAAM,IAAA,GAAO,KAAK,GAAA,CAAI,CAAA,EAAG,KAAK,KAAA,CAAM,IAAA,CAAK,OAAA,GAAU,GAAG,CAAC,CAAA;AACvD,IAAA,IAAI,CAAA,GAAI,CAAA;AACR,IAAA,KAAA,MAAW,GAAA,IAAO,IAAA,CAAK,KAAA,CAAM,IAAA,EAAK,EAAG;AACnC,MAAA,IAAI,OAAO,IAAA,EAAM;AACjB,MAAA,IAAA,CAAK,KAAA,CAAM,OAAO,GAAG,CAAA;AAAA,IACvB;AAAA,EACF;AACF;AAIO,MAAM,eAAA,GAAkB,IAAI,SAAA,CAAiC,GAAI,CAAA;AAIxE,MAAM,iBAAA,GACJ,2IAAA;AAMK,MAAM,cAAA,GAAoC,sBAAA;AAEjD,MAAM,aAAA,GAAgB,gBAAA;AAEtB,MAAM,WAAA,uBAAkB,GAAA,EAAoB;AAC5C,KAAA,MAAW,CAAC,SAAA,EAAW,KAAK,KAAK,MAAA,CAAO,OAAA,CAAQ,aAAa,CAAA,EAAG;AAC9D,EAAA,KAAA,MAAW,IAAA,IAAQ,KAAA,EAAO,WAAA,CAAY,GAAA,CAAI,MAAM,SAAS,CAAA;AAC3D;AA8GO,SAAS,aAAA,CAAc,QAAgB,OAAA,EAAiD;AAhM/F,EAAA,IAAA,EAAA,EAAA,EAAA;AAiME,EAAA,MAAM,KAAA,GAAQ,OAAO,WAAA,EAAY;AAGjC,EAAA,MAAM,KAAA,GAAQ,WAAA,CAAY,GAAA,CAAI,KAAK,CAAA;AACnC,EAAA,IAAI,OAAO,OAAO,KAAA;AAElB,EAAA,MAAM,OAAA,GAAA,CAAU,EAAA,GAAA,OAAA,IAAA,IAAA,GAAA,MAAA,GAAA,OAAA,CAAS,aAAA,KAAT,IAAA,GAAA,EAAA,GAA0B,cAAA;AAC1C,EAAA,IAAI,OAAA,CAAQ,QAAA,CAAS,KAAK,CAAA,EAAG,OAAO,IAAA;AAEpC,EAAA,MAAM,SAAA,GAAA,CAAY,EAAA,GAAA,OAAA,IAAA,IAAA,GAAA,MAAA,GAAA,OAAA,CAAS,SAAA,KAAT,IAAA,GAAA,EAAA,GAAsB,CAAA;AACxC,EAAA,IAAI,WAAA,GAAc,QAAA;AAClB,EAAA,IAAI,UAAA,GAA4B,IAAA;AAEhC,EAAA,KAAA,MAAW,aAAa,OAAA,EAAS;AAC/B,IAAA,MAAM,cAAA,GAAiB,UAAU,WAAA,EAAY;AAC7C,IAAA,IAAI,KAAA,KAAU,gBAAgB,OAAO,IAAA;AACrC,IAAA,MAAM,UAAA,GAAaC,wCAAA,CAAiB,KAAA,EAAO,cAAc,CAAA;AACzD,IAAA,MAAM,QAAA,GAAW,IAAA,CAAK,KAAA,CAAA,CAAO,CAAA,GAAI,UAAA,IAAc,IAAA,CAAK,GAAA,CAAI,MAAA,CAAO,MAAA,EAAQ,SAAA,CAAU,MAAM,CAAC,CAAA;AACxF,IAAA,IAAI,QAAA,GAAW,CAAA,IAAK,QAAA,IAAY,SAAA,IAAa,WAAW,WAAA,EAAa;AACnE,MAAA,WAAA,GAAc,QAAA;AACd,MAAA,UAAA,GAAa,SAAA;AAAA,IACf;AAAA,EACF;AACA,EAAA,OAAO,UAAA;AACT;AAOA,SAAsB,iBAAA,CACpB,OACA,OAAA,EACgC;AAAA,EAAA,OAAAC,SAAA,CAAA,IAAA,EAAA,IAAA,EAAA,aAAA;AAChC,IAAA,MAAM,UAAA,GAAa,KAAA,CAAM,WAAA,EAAY,CAAE,IAAA,EAAK;AAE5C,IAAA,IAAI,EAAC,mCAAS,SAAA,CAAA,EAAW;AACvB,MAAA,MAAM,MAAA,GAAS,eAAA,CAAgB,GAAA,CAAI,UAAU,CAAA;AAC7C,MAAA,IAAI,QAAQ,OAAO,MAAA;AAAA,IACrB;AAEA,IAAA,MAAM,MAAA,GAAgC,EAAE,KAAA,EAAO,KAAA,EAAO,OAAO,UAAA,EAAY,UAAA,EAAY,EAAC,EAAE;AAExF,IAAA,IAAA,CAAI,OAAA,IAAA,IAAA,GAAA,MAAA,GAAA,OAAA,CAAS,oBAAmB,KAAA,EAAO;AACrC,MAAA,MAAM,WAAA,GAAc,iBAAA,CAAkB,IAAA,CAAK,UAAU,CAAA;AACrD,MAAA,MAAA,CAAO,UAAA,CAAW,MAAA,GAAS,EAAE,KAAA,EAAO,WAAA,EAAY;AAChD,MAAA,IAAI,CAAC,WAAA,EAAa;AAChB,QAAA,eAAA,CAAgB,GAAA,CAAI,YAAY,MAAM,CAAA;AACtC,QAAA,OAAO,MAAA;AAAA,MACT;AAAA,IACF;AAEA,IAAA,MAAM,CAAC,KAAA,EAAO,MAAM,CAAA,GAAI,UAAA,CAAW,MAAM,GAAG,CAAA;AAC5C,IAAA,MAAA,CAAO,KAAA,GAAQ,KAAA;AACf,IAAA,MAAA,CAAO,MAAA,GAAS,MAAA;AAEhB,IAAA,IAAA,CAAI,OAAA,IAAA,IAAA,GAAA,MAAA,GAAA,OAAA,CAAS,kBAAiB,KAAA,EAAO;AACnC,MAAA,MAAM,UAAA,GAAa,aAAA,CAAc,MAAA,EAAQ,OAAA,IAAA,IAAA,GAAA,MAAA,GAAA,OAAA,CAAS,sBAAsB,CAAA;AACxE,MAAA,MAAA,CAAO,UAAA,CAAW,OAAO,EAAE,KAAA,EAAO,CAAC,UAAA,EAAY,UAAA,EAAY,kCAAc,MAAA,EAAU;AAAA,IACrF;AAEA,IAAA,IAAA,CAAI,OAAA,IAAA,IAAA,GAAA,MAAA,GAAA,OAAA,CAAS,wBAAuB,KAAA,EAAO;AACzC,MAAA,MAAA,CAAO,UAAA,CAAW,aAAa,EAAE,KAAA,EAAO,CAAC,mBAAA,CAAoB,QAAA,CAAS,MAAM,CAAA,EAAE;AAAA,IAChF;AAEA,IAAA,IAAA,CAAI,OAAA,IAAA,IAAA,GAAA,MAAA,GAAA,OAAA,CAAS,kBAAiB,KAAA,EAAO;AACnC,MAAA,MAAA,CAAO,UAAA,CAAW,OAAO,EAAE,KAAA,EAAO,CAAC,aAAA,CAAc,QAAA,CAAS,MAAM,CAAA,EAAE;AAAA,IACpE;AAEA,IAAA,IAAA,CAAI,OAAA,IAAA,IAAA,GAAA,MAAA,GAAA,OAAA,CAAS,UAAA,KAAc,OAAA,CAAQ,WAAA,EAAa;AAC9C,MAAA,IAAI;AACF,QAAA,MAAM,OAAA,GAAU,MAAM,OAAA,CAAQ,WAAA,CAAY,UAAU,MAAM,CAAA;AAC1D,QAAA,MAAM,KAAA,GAAQ,QAAQ,MAAA,GAAS,CAAA;AAC/B,QAAA,MAAA,CAAO,WAAW,EAAA,GAAK;AAAA,UACrB,KAAA,EAAO,KAAA;AAAA,UACP,OAAA,EAAS,QAAQ,OAAA,CAAQ,GAAA,CAAI,CAAC,CAAA,KAAM,CAAA,CAAE,QAAQ,CAAA,GAAI,KAAA;AAAA,SACpD;AAAA,MACF,SAAS,KAAA,EAAO;AACd,QAAA,MAAA,CAAO,WAAW,EAAA,GAAK;AAAA,UACrB,KAAA,EAAO,KAAA;AAAA,UACP,KAAA,EAAO,KAAA,YAAiB,KAAA,GAAQ,KAAA,CAAM,OAAA,GAAU;AAAA,SAClD;AAAA,MACF;AAAA,IACF;AAGA,IAAA,MAAA,CAAO,KAAA,GAAS,CAAC,QAAA,EAAU,MAAA,EAAQ,cAAc,IAAI,CAAA,CAAY,KAAA,CAAM,CAAC,GAAA,KAAQ;AAC9E,MAAA,MAAM,SAAA,GAAY,MAAA,CAAO,UAAA,CAAW,GAAG,CAAA;AACvC,MAAA,OAAO,CAAC,SAAA,IAAa,SAAA,CAAU,KAAA,KAAU,KAAA;AAAA,IAC3C,CAAC,CAAA;AAED,IAAA,IAAI,EAAC,OAAA,IAAA,IAAA,GAAA,MAAA,GAAA,OAAA,CAAS,SAAA,CAAA,EAAW,eAAA,CAAgB,GAAA,CAAI,YAAY,MAAM,CAAA;AAC/D,IAAA,OAAO,MAAA;AAAA,EACT,CAAA,CAAA;AAAA;AAEA,SAAsB,kBAAA,CACpB,QACA,OAAA,EACkC;AAAA,EAAA,OAAAA,SAAA,CAAA,IAAA,EAAA,IAAA,EAAA,aAAA;AApSpC,IAAA,IAAA,EAAA;AAqSE,IAAA,MAAM,SAAA,GAAA,CAAY,EAAA,GAAA,OAAA,IAAA,IAAA,GAAA,MAAA,GAAA,OAAA,CAAS,SAAA,KAAT,IAAA,GAAA,EAAA,GAAsB,EAAA;AACxC,IAAA,MAAM,UAAmC,EAAC;AAC1C,IAAA,KAAA,IAAS,IAAI,CAAA,EAAG,CAAA,GAAI,MAAA,CAAO,MAAA,EAAQ,KAAK,SAAA,EAAW;AACjD,MAAA,MAAM,KAAA,GAAQ,MAAA,CAAO,KAAA,CAAM,CAAA,EAAG,IAAI,SAAS,CAAA;AAC3C,MAAA,MAAM,YAAA,GAAe,MAAM,OAAA,CAAQ,GAAA,CAAI,KAAA,CAAM,GAAA,CAAI,CAAC,KAAA,KAAU,iBAAA,CAAkB,KAAA,EAAO,OAAO,CAAC,CAAC,CAAA;AAC9F,MAAA,OAAA,CAAQ,IAAA,CAAK,GAAG,YAAY,CAAA;AAAA,IAC9B;AACA,IAAA,OAAO,OAAA;AAAA,EACT,CAAA,CAAA;AAAA;;;;;;;;;;;;;;;;;;;;;;ACrSA,SAAsB,kBACpB,QAAA,EAC0D;AAAA,EAAA,OAAAA,SAAA,CAAA,IAAA,EAAA,IAAA,EAAA,aAAA;AAC1D,IAAA,IAAI,QAAA,CAAS,SAAS,QAAA,EAAU;AAC9B,MAAA,OAAO,iBAAA,CAAkB,QAAA,CAAS,KAAA,EAAO,QAAA,CAAS,OAAO,CAAA;AAAA,IAC3D;AACA,IAAA,OAAO,kBAAA,CAAmB,QAAA,CAAS,MAAA,EAAQ,QAAA,CAAS,OAAO,CAAA;AAAA,EAC7D,CAAA,CAAA;AAAA;;ACZO,MAAM,cAAA,GAAiB,GAAA;AA0BvB,SAAS,yBAAyB,MAAA,EAAkC;AACzE,EAAA,IAAI,CAAC,KAAA,CAAM,OAAA,CAAQ,MAAM,CAAA,IAAK,MAAA,CAAO,WAAW,CAAA,EAAG;AACjD,IAAA,OAAO,EAAE,EAAA,EAAI,KAAA,EAAO,MAAA,EAAQ,GAAA,EAAK,SAAS,0BAAA,EAA2B;AAAA,EACvE;AACA,EAAA,IAAI,MAAA,CAAO,SAAS,cAAA,EAAgB;AAClC,IAAA,OAAO,EAAE,IAAI,KAAA,EAAO,MAAA,EAAQ,KAAK,OAAA,EAAS,CAAA,QAAA,EAAW,cAAc,CAAA,yBAAA,CAAA,EAA4B;AAAA,EACjG;AACA,EAAA,OAAO,EAAE,EAAA,EAAI,IAAA,EAAM,MAAA,EAA2B;AAChD;AAUO,SAAS,gBACd,IAAA,EACwC;AACxC,EAAA,IAAI,CAAC,IAAA,IAAS,CAAC,KAAK,KAAA,IAAS,CAAC,KAAK,MAAA,EAAS;AAC1C,IAAA,OAAO,EAAE,IAAA,EAAM,SAAA,EAAW,MAAA,EAAQ,GAAA,EAAK,SAAS,mCAAA,EAAoC;AAAA,EACtF;AACA,EAAA,IAAI,KAAK,MAAA,EAAQ;AACf,IAAA,IAAI,CAAC,MAAM,OAAA,CAAQ,IAAA,CAAK,MAAM,CAAA,IAAK,IAAA,CAAK,MAAA,CAAO,MAAA,KAAW,CAAA,EAAG;AAC3D,MAAA,OAAO,EAAE,IAAA,EAAM,SAAA,EAAW,MAAA,EAAQ,GAAA,EAAK,SAAS,0BAAA,EAA2B;AAAA,IAC7E;AACA,IAAA,IAAI,IAAA,CAAK,MAAA,CAAO,MAAA,GAAS,cAAA,EAAgB;AACvC,MAAA,OAAO,EAAE,MAAM,SAAA,EAAW,MAAA,EAAQ,KAAK,OAAA,EAAS,CAAA,QAAA,EAAW,cAAc,CAAA,yBAAA,CAAA,EAA4B;AAAA,IACvG;AACA,IAAA,OAAO,EAAE,MAAM,OAAA,EAAS,MAAA,EAAQ,KAAK,MAAA,EAAQ,OAAA,EAAS,KAAK,OAAA,EAAQ;AAAA,EACrE;AAEA,EAAA,IAAI,CAAC,KAAK,KAAA,EAAO;AACf,IAAA,OAAO,EAAE,IAAA,EAAM,SAAA,EAAW,MAAA,EAAQ,GAAA,EAAK,SAAS,mCAAA,EAAoC;AAAA,EACtF;AACA,EAAA,OAAO,EAAE,MAAM,QAAA,EAAU,KAAA,EAAO,KAAK,KAAA,EAAO,OAAA,EAAS,KAAK,OAAA,EAAQ;AACpE;;;;;;;;;;;;;;;;;;;;;;ACjBA,MAAM,cAAA,GAAiB,WAAA,CAAY,WAAA,EAAa,CAAA;AAEhD,SAAS,YAAA,CACP,MAAA,EACA,IAAA,EACA,OAAA,GAAkC,cAAA,EACX;AACvB,EAAA,OAAO,EAAE,MAAA,EAAQ,OAAA,EAAS,QAAA,EAAU,IAAA,EAAK;AAC3C;AAEA,SAAS,OAAO,GAAA,EAA+B;AAC7C,EAAA,IAAI;AACF,IAAA,OAAO,IAAI,GAAA,CAAI,GAAA,CAAI,GAAG,EAAE,QAAA,IAAY,GAAA;AAAA,EACtC,CAAA,CAAA,OAAQ,CAAA,EAAA;AAEN,IAAA,MAAM,GAAA,GAAM,GAAA,CAAI,GAAA,CAAI,OAAA,CAAQ,GAAG,CAAA;AAC/B,IAAA,OAAO,GAAA,KAAQ,KAAK,GAAA,CAAI,GAAA,GAAM,IAAI,GAAA,CAAI,KAAA,CAAM,GAAG,GAAG,CAAA;AAAA,EACpD;AACF;AAEA,SAAS,SAAA,CAAU,OAAkC,GAAA,EAAiC;AACpF,EAAA,IAAI,OAAQ,KAAA,CAA4B,GAAA,KAAQ,UAAA,EAAY;AAC1D,IAAA,MAAM,CAAA,GAAK,KAAA,CAAgD,GAAA,CAAI,GAAG,CAAA;AAClE,IAAA,OAAO,CAAA,IAAA,IAAA,GAAA,CAAA,GAAK,MAAA;AAAA,EACd;AACA,EAAA,MAAM,KAAA,GAAS,MAA6C,GAAG,CAAA;AAC/D,EAAA,OAAO,KAAA;AACT;AAEA,SAAS,qBAAqB,KAAA,EAAiE;AAC7F,EAAA,MAAM,UAAyC,EAAC;AAChD,EAAA,IAAI,UAAU,KAAA,EAAO,WAAW,CAAA,KAAM,MAAA,UAAgB,SAAA,GAAY,IAAA;AAClE,EAAA,IAAI,UAAU,KAAA,EAAO,cAAc,CAAA,KAAM,OAAA,UAAiB,YAAA,GAAe,KAAA;AACzE,EAAA,OAAO,OAAA;AACT;AAEA,SAAe,aAAa,GAAA,EAAyC;AAAA,EAAA,OAAA,OAAA,CAAA,IAAA,EAAA,IAAA,EAAA,aAAA;AACnE,IAAA,IAAI;AACF,MAAA,OAAO,MAAM,IAAI,IAAA,EAAK;AAAA,IACxB,CAAA,CAAA,OAAQ,CAAA,EAAA;AACN,MAAA,MAAM,IAAI,YAAY,mBAAmB,CAAA;AAAA,IAC3C;AAAA,EACF,CAAA,CAAA;AAAA;AAGA,SAAsB,YAAA,CACpB,KACA,QAAA,EACgC;AAAA,EAAA,OAAA,OAAA,CAAA,IAAA,EAAA,IAAA,EAAA,aAAA;AAChC,IAAA,IAAI,GAAA,CAAI,WAAW,SAAA,EAAW;AAC5B,MAAA,OAAO,EAAE,MAAA,EAAQ,GAAA,EAAK,OAAA,EAAS,aAAY,EAAE;AAAA,IAC/C;AAEA,IAAA,MAAM,IAAA,GAAO,OAAO,GAAG,CAAA;AAEvB,IAAA,IAAI,IAAA,KAAS,aAAA,IAAiB,GAAA,CAAI,MAAA,KAAW,KAAA,EAAO;AAClD,MAAA,OAAO,YAAA,CAAa,GAAA,EAAK,EAAE,MAAA,EAAQ,SAAA,EAAW,QAAA,EAAU,OAAA,EAAS,SAAA,EAAA,iBAAW,IAAI,IAAA,EAAK,EAAE,WAAA,IAAe,CAAA;AAAA,IACxG;AAEA,IAAA,MAAM,cAAA,GAAiB,IAAA,KAAS,eAAA,IAAmB,IAAA,KAAS,qBAAA;AAC5D,IAAA,IAAI,cAAA,IAAkB,GAAA,CAAI,MAAA,KAAW,MAAA,EAAQ;AAC3C,MAAA,OAAO,YAAA,CAAa,GAAA,EAAK,EAAE,KAAA,EAAO,sBAAsB,CAAA;AAAA,IAC1D;AAEA,IAAA,IAAI,IAAA,KAAS,eAAA,IAAmB,GAAA,CAAI,MAAA,KAAW,MAAA,EAAQ;AACrD,MAAA,IAAI;AACF,QAAA,MAAM,IAAA,GAAQ,MAAM,YAAA,CAAa,GAAG,CAAA;AACpC,QAAA,IAAI,CAAC,KAAK,KAAA,EAAO,OAAO,aAAa,GAAA,EAAK,EAAE,KAAA,EAAO,mBAAA,EAAqB,CAAA;AACxE,QAAA,MAAM,OAAA,GAAU,oBAAA,CAAqB,GAAA,CAAI,KAAK,CAAA;AAC9C,QAAA,MAAM,MAAA,GAAS,MAAM,iBAAA,CAAkB,IAAA,CAAK,OAAO,OAAO,CAAA;AAC1D,QAAA,OAAO,YAAA,CAAa,KAAK,MAAM,CAAA;AAAA,MACjC,SAAS,KAAA,EAAO;AACd,QAAA,IAAI,KAAA,YAAiB,aAAa,OAAO,YAAA,CAAa,KAAK,EAAE,KAAA,EAAO,wBAAwB,CAAA;AAC5F,QAAA,OAAA,CAAQ,KAAA,CAAM,2BAA2B,KAAK,CAAA;AAC9C,QAAA,OAAO,YAAA,CAAa,GAAA,EAAK,EAAE,KAAA,EAAO,yBAAyB,CAAA;AAAA,MAC7D;AAAA,IACF;AAEA,IAAA,IAAI,IAAA,KAAS,qBAAA,IAAyB,GAAA,CAAI,MAAA,KAAW,MAAA,EAAQ;AAC3D,MAAA,IAAI;AACF,QAAA,MAAM,IAAA,GAAQ,MAAM,YAAA,CAAa,GAAG,CAAA;AACpC,QAAA,MAAM,SAAA,GAAY,wBAAA,CAAyB,IAAA,CAAK,MAAM,CAAA;AACtD,QAAA,IAAI,CAAC,SAAA,CAAU,EAAA,EAAI,OAAO,YAAA,CAAa,SAAA,CAAU,MAAA,EAAQ,EAAE,KAAA,EAAO,SAAA,CAAU,OAAA,EAAS,CAAA;AACrF,QAAA,MAAM,OAAA,GAAU,MAAM,iBAAA,CAAkB,EAAE,MAAM,OAAA,EAAS,MAAA,EAAQ,SAAA,CAAU,MAAA,EAAQ,CAAA;AACnF,QAAA,OAAO,YAAA,CAAa,GAAA,EAAK,EAAE,OAAA,EAAS,CAAA;AAAA,MACtC,SAAS,KAAA,EAAO;AACd,QAAA,IAAI,KAAA,YAAiB,aAAa,OAAO,YAAA,CAAa,KAAK,EAAE,KAAA,EAAO,wBAAwB,CAAA;AAC5F,QAAA,OAAA,CAAQ,KAAA,CAAM,iCAAiC,KAAK,CAAA;AACpD,QAAA,OAAO,YAAA,CAAa,GAAA,EAAK,EAAE,KAAA,EAAO,yBAAyB,CAAA;AAAA,MAC7D;AAAA,IACF;AAEA,IAAA,OAAO,YAAA,CAAa,GAAA,EAAK,EAAE,KAAA,EAAO,aAAa,CAAA;AAAA,EACjD,CAAA,CAAA;AAAA;AAGA,SAAsB,aAAA,CACpB,KACA,QAAA,EACgC;AAAA,EAAA,OAAA,OAAA,CAAA,IAAA,EAAA,IAAA,EAAA,aAAA;AAChC,IAAA,IAAI,GAAA,CAAI,WAAW,SAAA,EAAW;AAC5B,MAAA,OAAO,EAAE,MAAA,EAAQ,GAAA,EAAK,OAAA,EAAS,WAAA,CAAY,eAAe,CAAA,EAAE;AAAA,IAC9D;AACA,IAAA,IAAI,GAAA,CAAI,MAAA,KAAW,MAAA,EAAQ,OAAO,YAAA,CAAa,GAAA,EAAK,EAAE,OAAA,EAAS,KAAA,EAAO,KAAA,EAAO,oBAAA,EAAsB,CAAA;AAEnG,IAAA,IAAI;AACF,MAAA,MAAM,IAAA,GAAQ,MAAM,YAAA,CAAa,GAAG,CAAA;AACpC,MAAA,MAAM,UAAA,GAAa,gBAAgB,IAAI,CAAA;AACvC,MAAA,IAAI,UAAA,CAAW,SAAS,SAAA,EAAW;AACjC,QAAA,OAAO,YAAA,CAAa,WAAW,MAAA,EAAQ,EAAE,SAAS,KAAA,EAAO,KAAA,EAAO,UAAA,CAAW,OAAA,EAAS,CAAA;AAAA,MACtF;AACA,MAAA,MAAM,IAAA,GAAO,MAAM,iBAAA,CAAkB,UAAU,CAAA;AAC/C,MAAA,OAAO,aAAa,GAAA,EAAK,EAAE,OAAA,EAAS,IAAA,EAAM,MAAM,CAAA;AAAA,IAClD,SAAS,KAAA,EAAO;AACd,MAAA,IAAI,KAAA,YAAiB,WAAA,EAAa,OAAO,YAAA,CAAa,GAAA,EAAK,EAAE,OAAA,EAAS,KAAA,EAAO,KAAA,EAAO,sBAAA,EAAwB,CAAA;AAC5G,MAAA,OAAA,CAAQ,KAAA,CAAM,yBAAyB,KAAK,CAAA;AAC5C,MAAA,MAAM,OAAA,GAAU,KAAA,YAAiB,KAAA,GAAQ,KAAA,CAAM,OAAA,GAAU,uBAAA;AACzD,MAAA,OAAO,aAAa,GAAA,EAAK,EAAE,SAAS,KAAA,EAAO,KAAA,EAAO,SAAS,CAAA;AAAA,IAC7D;AAAA,EACF,CAAA,CAAA;AAAA;AAEA,YAAe;AAAA,EACb,YAAA;AAAA,EACA;AACF,CAAA;;;;;;","x_google_ignoreList":[1]}
|
|
1
|
+
{"version":3,"file":"azure.cjs.js","sources":["../../../src/serverless/_shared/cors.ts","../../../node_modules/string-similarity-js/dist/string-similarity.js","../../../src/serverless/verifier.ts","../../../src/serverless/_shared/dispatch.ts","../../../src/serverless/_shared/validation.ts","../../../src/serverless/adapters/azure.ts"],"sourcesContent":["/**\n * Standard CORS header set used by every adapter. `methods` lets each platform\n * advertise the verbs it actually supports without re-declaring the rest.\n */\nexport function corsHeaders(methods: string = 'GET, POST, OPTIONS'): Record<string, string> {\n return {\n 'Access-Control-Allow-Origin': '*',\n 'Access-Control-Allow-Methods': methods,\n 'Access-Control-Allow-Headers': 'Content-Type',\n };\n}\n\nexport function jsonHeaders(extra?: Record<string, string>): Record<string, string> {\n return { 'Content-Type': 'application/json', ...extra };\n}\n","\"use strict\";\nObject.defineProperty(exports, \"__esModule\", { value: true });\nexports.stringSimilarity = void 0;\n/* global exports, Map */\n/**\n * Calculate similarity between two strings\n * @param {string} str1 First string to match\n * @param {string} str2 Second string to match\n * @param {number} [substringLength=2] Optional. Length of substring to be used in calculating similarity. Default 2.\n * @param {boolean} [caseSensitive=false] Optional. Whether you want to consider case in string matching. Default false;\n * @returns Number between 0 and 1, with 0 being a low match score.\n */\nvar stringSimilarity = function (str1, str2, substringLength, caseSensitive) {\n if (substringLength === void 0) { substringLength = 2; }\n if (caseSensitive === void 0) { caseSensitive = false; }\n if (!caseSensitive) {\n str1 = str1.toLowerCase();\n str2 = str2.toLowerCase();\n }\n if (str1.length < substringLength || str2.length < substringLength)\n return 0;\n var map = new Map();\n for (var i = 0; i < str1.length - (substringLength - 1); i++) {\n var substr1 = str1.substr(i, substringLength);\n map.set(substr1, map.has(substr1) ? map.get(substr1) + 1 : 1);\n }\n var match = 0;\n for (var j = 0; j < str2.length - (substringLength - 1); j++) {\n var substr2 = str2.substr(j, substringLength);\n var count = map.has(substr2) ? map.get(substr2) : 0;\n if (count > 0) {\n map.set(substr2, count - 1);\n match++;\n }\n }\n return (match * 2) / (str1.length + str2.length - ((substringLength - 1) * 2));\n};\nexports.stringSimilarity = stringSimilarity;\nexports.default = exports.stringSimilarity;\n//# sourceMappingURL=string-similarity.js.map","/**\n * Edge-runtime / serverless email validator.\n *\n * No Node.js APIs (no `node:net`, no `node:dns`) — DNS is delegated to a\n * caller-supplied `DNSResolver`, so the same code runs on Cloudflare Workers,\n * Vercel Edge, Lambda@Edge, and Deno Deploy.\n *\n * Shares data with the main validator: `commonEmailDomains` and the typo map\n * are imported from `src/data/`, so we never drift between the two surfaces.\n */\n\nimport { stringSimilarity } from 'string-similarity-js';\nimport commonEmailDomainsJson from '../data/common-email-domains.json';\nimport typoPatternsJson from '../data/typo-patterns.json';\nimport disposableProviders from '../disposable-email-providers.json';\nimport freeProviders from '../free-email-providers.json';\nimport type { DomainSuggesterOptions, EmailValidationResult, ValidateEmailOptions } from '../types';\n\n/** Compact LRU/TTL cache. One Map, expiry stamp per entry, batched eviction. */\nexport class EdgeCache<T> {\n private readonly cache = new Map<string, { value: T; expires: number }>();\n\n constructor(\n private readonly maxSize = 1000,\n private readonly ttl = 3_600_000\n ) {}\n\n get(key: string): T | undefined {\n const item = this.cache.get(key);\n if (!item) return undefined;\n if (Date.now() > item.expires) {\n this.cache.delete(key);\n return undefined;\n }\n return item.value;\n }\n\n set(key: string, value: T): void {\n if (this.cache.size >= this.maxSize) this.evict();\n this.cache.set(key, { value, expires: Date.now() + this.ttl });\n }\n\n clear(): void {\n this.cache.clear();\n }\n\n size(): number {\n return this.cache.size;\n }\n\n private evict(): void {\n // Drop the oldest 10% in one pass — Map preserves insertion order so\n // `keys()` walks oldest-first.\n const drop = Math.max(1, Math.floor(this.maxSize * 0.1));\n let n = 0;\n for (const key of this.cache.keys()) {\n if (n++ >= drop) break;\n this.cache.delete(key);\n }\n }\n}\n\n// Module-level per-isolate caches. Edge runtimes get cold-start fresh; warm\n// invocations benefit from the in-memory hits.\nexport const validationCache = new EdgeCache<EmailValidationResult>(1000);\nexport const mxCache = new EdgeCache<string[]>(500);\n\n/** Same regex the main validator uses — kept inline because edge runtimes don't auto-resolve psl. */\nconst VALID_EMAIL_REGEX =\n /^(([a-zA-Z0-9_+'-]+(\\.[a-zA-Z0-9_+'-]+)*)|(\".+\"))@((\\[[0-9]{1,3}\\.[0-9]{1,3}\\.[0-9]{1,3}\\.[0-9]{1,3}])|(([a-zA-Z0-9-]+\\.)+[a-zA-Z]{2,}))$/;\n\n/**\n * Common email domains — re-exported so callers (Vercel Edge, etc.) can pass a\n * custom subset via `DomainSuggesterOptions.customDomains`.\n */\nexport const COMMON_DOMAINS: readonly string[] = commonEmailDomainsJson as string[];\n\nconst TYPO_PATTERNS = typoPatternsJson as Record<string, string[]>;\n/** Reverse index for O(1) typo → canonical lookup. */\nconst TYPO_LOOKUP = new Map<string, string>();\nfor (const [canonical, typos] of Object.entries(TYPO_PATTERNS)) {\n for (const typo of typos) TYPO_LOOKUP.set(typo, canonical);\n}\n\n/** DNS resolver contract — caller-supplied so we don't import `node:dns`. */\nexport interface DNSResolver {\n resolveMx(domain: string): Promise<Array<{ exchange: string; priority: number }>>;\n resolveTxt(domain: string): Promise<string[]>;\n}\n\n/** No-op resolver for environments where DNS isn't available. */\nexport class StubDNSResolver implements DNSResolver {\n async resolveMx(): Promise<Array<{ exchange: string; priority: number }>> {\n return [];\n }\n async resolveTxt(): Promise<string[]> {\n return [];\n }\n}\n\n/**\n * DNS-over-HTTPS resolver — works in any runtime with `fetch` (Cloudflare\n * Workers, Vercel Edge, Deno, browsers, Node 18+). Defaults to Cloudflare's\n * 1.1.1.1 endpoint; pass `endpoint` to use Google (8.8.8.8), NextDNS, or\n * a self-hosted resolver.\n *\n * Compatible with [`cf-doh`](https://www.npmjs.com/package/cf-doh) — if you\n * already use that, drop it in directly. This built-in keeps the package\n * zero-dep so the same code works on every edge runtime without an extra\n * install step.\n */\nexport interface DoHResolverOptions {\n /** DoH endpoint URL. Default: https://cloudflare-dns.com/dns-query */\n endpoint?: string;\n /** Per-query request timeout, ms. Default: 5000 */\n timeoutMs?: number;\n /** Custom fetch (e.g. to add headers / proxy). Default: globalThis.fetch */\n fetch?: typeof fetch;\n}\n\ninterface DoHAnswer {\n name: string;\n type: number;\n TTL: number;\n data: string;\n}\n\ninterface DoHResponse {\n Status: number;\n Answer?: DoHAnswer[];\n}\n\nconst DOH_RECORD_TYPE = { MX: 15, TXT: 16 } as const;\n\nexport class DoHResolver implements DNSResolver {\n private readonly endpoint: string;\n private readonly timeoutMs: number;\n private readonly fetchFn: typeof fetch;\n\n constructor(options: DoHResolverOptions = {}) {\n this.endpoint = options.endpoint ?? 'https://cloudflare-dns.com/dns-query';\n this.timeoutMs = options.timeoutMs ?? 5000;\n this.fetchFn = options.fetch ?? globalThis.fetch;\n }\n\n async resolveMx(domain: string): Promise<Array<{ exchange: string; priority: number }>> {\n const records = await this.query(domain, DOH_RECORD_TYPE.MX);\n if (!records) return [];\n return records\n .map((answer) => {\n // MX answer data: \"<priority> <exchange>\" (with optional trailing dot).\n const match = answer.data.match(/^(\\d+)\\s+(.+?)\\.?$/);\n if (!match) return null;\n return { priority: Number(match[1]), exchange: match[2] as string };\n })\n .filter((r): r is { exchange: string; priority: number } => r !== null)\n .sort((a, b) => a.priority - b.priority);\n }\n\n async resolveTxt(domain: string): Promise<string[]> {\n const records = await this.query(domain, DOH_RECORD_TYPE.TXT);\n if (!records) return [];\n // TXT answers come back as quoted strings — strip the surrounding quotes.\n return records.map((answer) => answer.data.replace(/^\"(.*)\"$/, '$1'));\n }\n\n private async query(domain: string, type: number): Promise<DoHAnswer[] | null> {\n const url = `${this.endpoint}?name=${encodeURIComponent(domain)}&type=${type}`;\n const controller = new AbortController();\n const timer = setTimeout(() => controller.abort(), this.timeoutMs);\n try {\n const response = await this.fetchFn(url, {\n headers: { Accept: 'application/dns-json' },\n signal: controller.signal,\n });\n if (!response.ok) return null;\n const json = (await response.json()) as DoHResponse;\n // Status 0 = NOERROR. Anything else (NXDOMAIN, SERVFAIL, etc.) → no answers.\n if (json.Status !== 0) return [];\n return json.Answer ?? [];\n } catch {\n return null;\n } finally {\n clearTimeout(timer);\n }\n }\n}\n\n/**\n * Suggest a corrected domain. Returns the canonical for a known typo,\n * otherwise the closest match within the threshold, otherwise null.\n */\nexport function suggestDomain(domain: string, options?: DomainSuggesterOptions): string | null {\n const lower = domain.toLowerCase();\n\n // Hand-curated typo map first — beats similarity for common cases.\n const known = TYPO_LOOKUP.get(lower);\n if (known) return known;\n\n const domains = options?.customDomains ?? COMMON_DOMAINS;\n if (domains.includes(lower)) return null;\n\n const threshold = options?.threshold ?? 2;\n let minDistance = Infinity;\n let suggestion: string | null = null;\n\n for (const candidate of domains) {\n const candidateLower = candidate.toLowerCase();\n if (lower === candidateLower) return null;\n const similarity = stringSimilarity(lower, candidateLower);\n const distance = Math.round((1 - similarity) * Math.max(domain.length, candidate.length));\n if (distance > 0 && distance <= threshold && distance < minDistance) {\n minDistance = distance;\n suggestion = candidate;\n }\n }\n return suggestion;\n}\n\n/**\n * Validate one email — syntax / typo / disposable / free / MX (if a resolver\n * is supplied). Each step is independently flag-gated so callers pay only for\n * what they use.\n */\nexport async function validateEmailCore(\n email: string,\n options?: ValidateEmailOptions & { dnsResolver?: DNSResolver }\n): Promise<EmailValidationResult> {\n const normalized = email.toLowerCase().trim();\n\n if (!options?.skipCache) {\n const cached = validationCache.get(normalized);\n if (cached) return cached;\n }\n\n const result: EmailValidationResult = { valid: false, email: normalized, validators: {} };\n\n if (options?.validateSyntax !== false) {\n const syntaxValid = VALID_EMAIL_REGEX.test(normalized);\n result.validators.syntax = { valid: syntaxValid };\n if (!syntaxValid) {\n validationCache.set(normalized, result);\n return result;\n }\n }\n\n const [local, domain] = normalized.split('@');\n result.local = local;\n result.domain = domain;\n\n if (options?.validateTypo !== false) {\n const suggestion = suggestDomain(domain, options?.domainSuggesterOptions);\n result.validators.typo = { valid: !suggestion, suggestion: suggestion ?? undefined };\n }\n\n if (options?.validateDisposable !== false) {\n result.validators.disposable = { valid: !disposableProviders.includes(domain) };\n }\n\n if (options?.validateFree !== false) {\n result.validators.free = { valid: !freeProviders.includes(domain) };\n }\n\n if (options?.validateMx && options.dnsResolver) {\n try {\n const records = await options.dnsResolver.resolveMx(domain);\n const hasMx = records.length > 0;\n result.validators.mx = {\n valid: hasMx,\n records: hasMx ? records.map((r) => r.exchange) : undefined,\n };\n } catch (error) {\n result.validators.mx = {\n valid: false,\n error: error instanceof Error ? error.message : 'MX validation failed',\n };\n }\n }\n\n // Free-provider detection is informational; only the hard validators gate validity.\n result.valid = (['syntax', 'typo', 'disposable', 'mx'] as const).every((key) => {\n const validator = result.validators[key];\n return !validator || validator.valid !== false;\n });\n\n if (!options?.skipCache) validationCache.set(normalized, result);\n return result;\n}\n\nexport async function validateEmailBatch(\n emails: string[],\n options?: ValidateEmailOptions & { dnsResolver?: DNSResolver }\n): Promise<EmailValidationResult[]> {\n const chunkSize = options?.batchSize ?? 10;\n const results: EmailValidationResult[] = [];\n for (let i = 0; i < emails.length; i += chunkSize) {\n const chunk = emails.slice(i, i + chunkSize);\n const chunkResults = await Promise.all(chunk.map((email) => validateEmailCore(email, options)));\n results.push(...chunkResults);\n }\n return results;\n}\n\nexport function clearCache(): void {\n validationCache.clear();\n mxCache.clear();\n}\n\nexport type { DomainSuggesterOptions, EmailValidationResult, ValidateEmailOptions } from '../types';\n","import type { EmailValidationResult } from '../../types';\nimport { validateEmailBatch, validateEmailCore } from '../verifier';\nimport type { ValidationDispatch } from './validation';\n\n/**\n * Execute a classified request against the core validator. Single-email\n * requests yield one result; batch requests yield an array.\n */\nexport async function executeValidation(\n dispatch: ValidationDispatch\n): Promise<EmailValidationResult | EmailValidationResult[]> {\n if (dispatch.kind === 'single') {\n return validateEmailCore(dispatch.email, dispatch.options);\n }\n return validateEmailBatch(dispatch.emails, dispatch.options);\n}\n","import type { ValidateEmailOptions } from '../../types';\n\n/** Hard limit on batch size enforced by every adapter. */\nexport const MAX_BATCH_SIZE = 100;\n\n/** Shape of POST bodies and Lambda invocations across all serverless adapters. */\nexport interface ValidationRequestBody {\n email?: string;\n emails?: string[];\n options?: ValidateEmailOptions;\n}\n\nexport type ValidationDispatch =\n | { kind: 'single'; email: string; options?: ValidateEmailOptions }\n | { kind: 'batch'; emails: string[]; options?: ValidateEmailOptions };\n\nexport interface ValidationFailure {\n kind: 'invalid';\n status: 400;\n message: string;\n}\n\n/**\n * Validation for endpoints that accept ONLY a batch (`emails`). Returns\n * a 400 failure if emails is missing/empty/oversized, or null when valid.\n * Routed `/validate/batch` paths use this so error messages stay batch-specific.\n */\nexport type BatchValidation = { ok: true; emails: string[] } | { ok: false; status: 400; message: string };\n\nexport function validateBatchEmailsField(emails: unknown): BatchValidation {\n if (!Array.isArray(emails) || emails.length === 0) {\n return { ok: false, status: 400, message: 'Emails array is required' };\n }\n if (emails.length > MAX_BATCH_SIZE) {\n return { ok: false, status: 400, message: `Maximum ${MAX_BATCH_SIZE} emails allowed per batch` };\n }\n return { ok: true, emails: emails as string[] };\n}\n\n/**\n * Apply the rules every serverless adapter shares:\n * 1. body must request either `email` or `emails`\n * 2. `emails` must be a non-empty array of ≤ MAX_BATCH_SIZE entries\n *\n * Centralising this means a future rule change (say, raising the cap) lands\n * in one place instead of three.\n */\nexport function classifyRequest(\n body: ValidationRequestBody | null | undefined\n): ValidationDispatch | ValidationFailure {\n if (!body || (!body.email && !body.emails)) {\n return { kind: 'invalid', status: 400, message: 'Email or emails array is required' };\n }\n if (body.emails) {\n if (!Array.isArray(body.emails) || body.emails.length === 0) {\n return { kind: 'invalid', status: 400, message: 'Emails array is required' };\n }\n if (body.emails.length > MAX_BATCH_SIZE) {\n return { kind: 'invalid', status: 400, message: `Maximum ${MAX_BATCH_SIZE} emails allowed per batch` };\n }\n return { kind: 'batch', emails: body.emails, options: body.options };\n }\n // body.email must be set per the first guard (which checks both fields).\n if (!body.email) {\n return { kind: 'invalid', status: 400, message: 'Email or emails array is required' };\n }\n return { kind: 'single', email: body.email, options: body.options };\n}\n","/**\n * Azure Functions adapter for email validation.\n *\n * Targets the v4 programming model:\n * `(request: HttpRequest, context: InvocationContext): Promise<HttpResponseInit>`\n *\n * The HttpRequest is a Web-API-aligned shape (`request.json()`, `request.method`,\n * `request.query`, `request.headers`), so the adapter reads the body via the\n * Web API. Routes:\n * - GET /api/health\n * - POST /api/validate\n * - POST /api/validate/batch\n *\n * Two handler shapes are exported:\n * - `azureHandler`: routed (recommended).\n * - `azureFunction`: single-route convenience that infers single vs. batch\n * from the body — for one-function-per-URL setups.\n *\n * The interfaces below are minimal subsets of the official `@azure/functions`\n * types so callers can pass real Azure types without an extra cast.\n */\nimport type { ValidateEmailOptions } from '../../types';\nimport { corsHeaders, jsonHeaders } from '../_shared/cors';\nimport { executeValidation } from '../_shared/dispatch';\nimport { classifyRequest, type ValidationRequestBody, validateBatchEmailsField } from '../_shared/validation';\nimport { validateEmailCore } from '../verifier';\n\nexport interface AzureHttpRequest {\n method: string;\n url: string;\n headers: { get(name: string): string | null } | Record<string, string | undefined>;\n query: { get(name: string): string | null } | Record<string, string | undefined>;\n json(): Promise<unknown>;\n text?: () => Promise<string>;\n}\n\nexport interface AzureInvocationContext {\n invocationId?: string;\n functionName?: string;\n log?: (...args: unknown[]) => void;\n error?: (...args: unknown[]) => void;\n}\n\nexport interface AzureHttpResponseInit {\n status: number;\n headers: Record<string, string>;\n jsonBody?: unknown;\n body?: string;\n}\n\nconst ROUTED_HEADERS = jsonHeaders(corsHeaders());\n\nfunction jsonResponse(\n status: number,\n body: unknown,\n headers: Record<string, string> = ROUTED_HEADERS\n): AzureHttpResponseInit {\n return { status, headers, jsonBody: body };\n}\n\nfunction pathOf(req: AzureHttpRequest): string {\n try {\n return new URL(req.url).pathname || '/';\n } catch {\n // Some test harnesses pass a bare path. Treat it as the pathname.\n const idx = req.url.indexOf('?');\n return idx === -1 ? req.url : req.url.slice(0, idx);\n }\n}\n\nfunction readQuery(query: AzureHttpRequest['query'], key: string): string | undefined {\n if (typeof (query as { get?: unknown }).get === 'function') {\n const v = (query as { get: (k: string) => string | null }).get(key);\n return v ?? undefined;\n }\n const value = (query as Record<string, string | undefined>)[key];\n return value;\n}\n\nfunction parseValidateOptions(query: AzureHttpRequest['query']): Partial<ValidateEmailOptions> {\n const options: Partial<ValidateEmailOptions> = {};\n if (readQuery(query, 'skipCache') === 'true') options.skipCache = true;\n if (readQuery(query, 'validateTypo') === 'false') options.validateTypo = false;\n return options;\n}\n\nasync function readJsonBody(req: AzureHttpRequest): Promise<unknown> {\n try {\n return await req.json();\n } catch {\n throw new SyntaxError('Invalid JSON body');\n }\n}\n\n/** Routed Azure Functions v4 handler. */\nexport async function azureHandler(\n req: AzureHttpRequest,\n _context?: AzureInvocationContext\n): Promise<AzureHttpResponseInit> {\n if (req.method === 'OPTIONS') {\n return { status: 204, headers: corsHeaders() };\n }\n\n const path = pathOf(req);\n\n if (path === '/api/health' && req.method === 'GET') {\n return jsonResponse(200, { status: 'healthy', platform: 'azure', timestamp: new Date().toISOString() });\n }\n\n const isValidatePath = path === '/api/validate' || path === '/api/validate/batch';\n if (isValidatePath && req.method !== 'POST') {\n return jsonResponse(405, { error: 'Method not allowed' });\n }\n\n if (path === '/api/validate' && req.method === 'POST') {\n try {\n const body = (await readJsonBody(req)) as { email?: string };\n if (!body.email) return jsonResponse(400, { error: 'Email is required' });\n const options = parseValidateOptions(req.query);\n const result = await validateEmailCore(body.email, options);\n return jsonResponse(200, result);\n } catch (error) {\n if (error instanceof SyntaxError) return jsonResponse(400, { error: 'Invalid request body' });\n console.error('Azure validation error:', error);\n return jsonResponse(500, { error: 'Internal server error' });\n }\n }\n\n if (path === '/api/validate/batch' && req.method === 'POST') {\n try {\n const body = (await readJsonBody(req)) as ValidationRequestBody;\n const validated = validateBatchEmailsField(body.emails);\n if (!validated.ok) return jsonResponse(validated.status, { error: validated.message });\n const results = await executeValidation({ kind: 'batch', emails: validated.emails });\n return jsonResponse(200, { results });\n } catch (error) {\n if (error instanceof SyntaxError) return jsonResponse(400, { error: 'Invalid request body' });\n console.error('Azure batch validation error:', error);\n return jsonResponse(500, { error: 'Internal server error' });\n }\n }\n\n return jsonResponse(404, { error: 'Not found' });\n}\n\n/** Single-route convenience — infers single vs. batch from the body. */\nexport async function azureFunction(\n req: AzureHttpRequest,\n _context?: AzureInvocationContext\n): Promise<AzureHttpResponseInit> {\n if (req.method === 'OPTIONS') {\n return { status: 204, headers: corsHeaders('POST, OPTIONS') };\n }\n if (req.method !== 'POST') return jsonResponse(405, { success: false, error: 'Method not allowed' });\n\n try {\n const body = (await readJsonBody(req)) as ValidationRequestBody;\n const classified = classifyRequest(body);\n if (classified.kind === 'invalid') {\n return jsonResponse(classified.status, { success: false, error: classified.message });\n }\n const data = await executeValidation(classified);\n return jsonResponse(200, { success: true, data });\n } catch (error) {\n if (error instanceof SyntaxError) return jsonResponse(400, { success: false, error: 'Invalid request body' });\n console.error('Azure function error:', error);\n const message = error instanceof Error ? error.message : 'Internal server error';\n return jsonResponse(500, { success: false, error: message });\n }\n}\n\nexport default {\n azureHandler,\n azureFunction,\n};\n"],"names":["stringSimilarity","__async"],"mappings":"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","x_google_ignoreList":[1]}
|
|
@@ -32,9 +32,9 @@ var hasRequiredStringSimilarity;
|
|
|
32
32
|
function requireStringSimilarity () {
|
|
33
33
|
if (hasRequiredStringSimilarity) return stringSimilarity;
|
|
34
34
|
hasRequiredStringSimilarity = 1;
|
|
35
|
-
(function (exports
|
|
36
|
-
Object.defineProperty(exports
|
|
37
|
-
exports
|
|
35
|
+
(function (exports) {
|
|
36
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
|
37
|
+
exports.stringSimilarity = void 0;
|
|
38
38
|
/* global exports, Map */
|
|
39
39
|
/**
|
|
40
40
|
* Calculate similarity between two strings
|
|
@@ -69,8 +69,8 @@ function requireStringSimilarity () {
|
|
|
69
69
|
}
|
|
70
70
|
return (match * 2) / (str1.length + str2.length - ((substringLength - 1) * 2));
|
|
71
71
|
};
|
|
72
|
-
exports
|
|
73
|
-
exports
|
|
72
|
+
exports.stringSimilarity = stringSimilarity;
|
|
73
|
+
exports.default = exports.stringSimilarity;
|
|
74
74
|
|
|
75
75
|
} (stringSimilarity));
|
|
76
76
|
return stringSimilarity;
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"azure.esm.js","sources":["../../../src/serverless/_shared/cors.ts","../../../node_modules/string-similarity-js/dist/string-similarity.js","../../../src/serverless/verifier.ts","../../../src/serverless/_shared/dispatch.ts","../../../src/serverless/_shared/validation.ts","../../../src/serverless/adapters/azure.ts"],"sourcesContent":["/**\n * Standard CORS header set used by every adapter. `methods` lets each platform\n * advertise the verbs it actually supports without re-declaring the rest.\n */\nexport function corsHeaders(methods: string = 'GET, POST, OPTIONS'): Record<string, string> {\n return {\n 'Access-Control-Allow-Origin': '*',\n 'Access-Control-Allow-Methods': methods,\n 'Access-Control-Allow-Headers': 'Content-Type',\n };\n}\n\nexport function jsonHeaders(extra?: Record<string, string>): Record<string, string> {\n return { 'Content-Type': 'application/json', ...extra };\n}\n","\"use strict\";\nObject.defineProperty(exports, \"__esModule\", { value: true });\nexports.stringSimilarity = void 0;\n/* global exports, Map */\n/**\n * Calculate similarity between two strings\n * @param {string} str1 First string to match\n * @param {string} str2 Second string to match\n * @param {number} [substringLength=2] Optional. Length of substring to be used in calculating similarity. Default 2.\n * @param {boolean} [caseSensitive=false] Optional. Whether you want to consider case in string matching. Default false;\n * @returns Number between 0 and 1, with 0 being a low match score.\n */\nvar stringSimilarity = function (str1, str2, substringLength, caseSensitive) {\n if (substringLength === void 0) { substringLength = 2; }\n if (caseSensitive === void 0) { caseSensitive = false; }\n if (!caseSensitive) {\n str1 = str1.toLowerCase();\n str2 = str2.toLowerCase();\n }\n if (str1.length < substringLength || str2.length < substringLength)\n return 0;\n var map = new Map();\n for (var i = 0; i < str1.length - (substringLength - 1); i++) {\n var substr1 = str1.substr(i, substringLength);\n map.set(substr1, map.has(substr1) ? map.get(substr1) + 1 : 1);\n }\n var match = 0;\n for (var j = 0; j < str2.length - (substringLength - 1); j++) {\n var substr2 = str2.substr(j, substringLength);\n var count = map.has(substr2) ? map.get(substr2) : 0;\n if (count > 0) {\n map.set(substr2, count - 1);\n match++;\n }\n }\n return (match * 2) / (str1.length + str2.length - ((substringLength - 1) * 2));\n};\nexports.stringSimilarity = stringSimilarity;\nexports.default = exports.stringSimilarity;\n//# sourceMappingURL=string-similarity.js.map","/**\n * Edge-runtime / serverless email validator.\n *\n * No Node.js APIs (no `node:net`, no `node:dns`) — DNS is delegated to a\n * caller-supplied `DNSResolver`, so the same code runs on Cloudflare Workers,\n * Vercel Edge, Lambda@Edge, and Deno Deploy.\n *\n * Shares data with the main validator: `commonEmailDomains` and the typo map\n * are imported from `src/data/`, so we never drift between the two surfaces.\n */\n\nimport { stringSimilarity } from 'string-similarity-js';\nimport commonEmailDomainsJson from '../data/common-email-domains.json';\nimport typoPatternsJson from '../data/typo-patterns.json';\nimport disposableProviders from '../disposable-email-providers.json';\nimport freeProviders from '../free-email-providers.json';\nimport type { DomainSuggesterOptions, EmailValidationResult, ValidateEmailOptions } from '../types';\n\n/** Compact LRU/TTL cache. One Map, expiry stamp per entry, batched eviction. */\nexport class EdgeCache<T> {\n private readonly cache = new Map<string, { value: T; expires: number }>();\n\n constructor(\n private readonly maxSize = 1000,\n private readonly ttl = 3_600_000\n ) {}\n\n get(key: string): T | undefined {\n const item = this.cache.get(key);\n if (!item) return undefined;\n if (Date.now() > item.expires) {\n this.cache.delete(key);\n return undefined;\n }\n return item.value;\n }\n\n set(key: string, value: T): void {\n if (this.cache.size >= this.maxSize) this.evict();\n this.cache.set(key, { value, expires: Date.now() + this.ttl });\n }\n\n clear(): void {\n this.cache.clear();\n }\n\n size(): number {\n return this.cache.size;\n }\n\n private evict(): void {\n // Drop the oldest 10% in one pass — Map preserves insertion order so\n // `keys()` walks oldest-first.\n const drop = Math.max(1, Math.floor(this.maxSize * 0.1));\n let n = 0;\n for (const key of this.cache.keys()) {\n if (n++ >= drop) break;\n this.cache.delete(key);\n }\n }\n}\n\n// Module-level per-isolate caches. Edge runtimes get cold-start fresh; warm\n// invocations benefit from the in-memory hits.\nexport const validationCache = new EdgeCache<EmailValidationResult>(1000);\nexport const mxCache = new EdgeCache<string[]>(500);\n\n/** Same regex the main validator uses — kept inline because edge runtimes don't auto-resolve psl. */\nconst VALID_EMAIL_REGEX =\n /^(([a-zA-Z0-9_+'-]+(\\.[a-zA-Z0-9_+'-]+)*)|(\".+\"))@((\\[[0-9]{1,3}\\.[0-9]{1,3}\\.[0-9]{1,3}\\.[0-9]{1,3}])|(([a-zA-Z0-9-]+\\.)+[a-zA-Z]{2,}))$/;\n\n/**\n * Common email domains — re-exported so callers (Vercel Edge, etc.) can pass a\n * custom subset via `DomainSuggesterOptions.customDomains`.\n */\nexport const COMMON_DOMAINS: readonly string[] = commonEmailDomainsJson as string[];\n\nconst TYPO_PATTERNS = typoPatternsJson as Record<string, string[]>;\n/** Reverse index for O(1) typo → canonical lookup. */\nconst TYPO_LOOKUP = new Map<string, string>();\nfor (const [canonical, typos] of Object.entries(TYPO_PATTERNS)) {\n for (const typo of typos) TYPO_LOOKUP.set(typo, canonical);\n}\n\n/** DNS resolver contract — caller-supplied so we don't import `node:dns`. */\nexport interface DNSResolver {\n resolveMx(domain: string): Promise<Array<{ exchange: string; priority: number }>>;\n resolveTxt(domain: string): Promise<string[]>;\n}\n\n/** No-op resolver for environments where DNS isn't available. */\nexport class StubDNSResolver implements DNSResolver {\n async resolveMx(): Promise<Array<{ exchange: string; priority: number }>> {\n return [];\n }\n async resolveTxt(): Promise<string[]> {\n return [];\n }\n}\n\n/**\n * DNS-over-HTTPS resolver — works in any runtime with `fetch` (Cloudflare\n * Workers, Vercel Edge, Deno, browsers, Node 18+). Defaults to Cloudflare's\n * 1.1.1.1 endpoint; pass `endpoint` to use Google (8.8.8.8), NextDNS, or\n * a self-hosted resolver.\n *\n * Compatible with [`cf-doh`](https://www.npmjs.com/package/cf-doh) — if you\n * already use that, drop it in directly. This built-in keeps the package\n * zero-dep so the same code works on every edge runtime without an extra\n * install step.\n */\nexport interface DoHResolverOptions {\n /** DoH endpoint URL. Default: https://cloudflare-dns.com/dns-query */\n endpoint?: string;\n /** Per-query request timeout, ms. Default: 5000 */\n timeoutMs?: number;\n /** Custom fetch (e.g. to add headers / proxy). Default: globalThis.fetch */\n fetch?: typeof fetch;\n}\n\ninterface DoHAnswer {\n name: string;\n type: number;\n TTL: number;\n data: string;\n}\n\ninterface DoHResponse {\n Status: number;\n Answer?: DoHAnswer[];\n}\n\nconst DOH_RECORD_TYPE = { MX: 15, TXT: 16 } as const;\n\nexport class DoHResolver implements DNSResolver {\n private readonly endpoint: string;\n private readonly timeoutMs: number;\n private readonly fetchFn: typeof fetch;\n\n constructor(options: DoHResolverOptions = {}) {\n this.endpoint = options.endpoint ?? 'https://cloudflare-dns.com/dns-query';\n this.timeoutMs = options.timeoutMs ?? 5000;\n this.fetchFn = options.fetch ?? globalThis.fetch;\n }\n\n async resolveMx(domain: string): Promise<Array<{ exchange: string; priority: number }>> {\n const records = await this.query(domain, DOH_RECORD_TYPE.MX);\n if (!records) return [];\n return records\n .map((answer) => {\n // MX answer data: \"<priority> <exchange>\" (with optional trailing dot).\n const match = answer.data.match(/^(\\d+)\\s+(.+?)\\.?$/);\n if (!match) return null;\n return { priority: Number(match[1]), exchange: match[2] as string };\n })\n .filter((r): r is { exchange: string; priority: number } => r !== null)\n .sort((a, b) => a.priority - b.priority);\n }\n\n async resolveTxt(domain: string): Promise<string[]> {\n const records = await this.query(domain, DOH_RECORD_TYPE.TXT);\n if (!records) return [];\n // TXT answers come back as quoted strings — strip the surrounding quotes.\n return records.map((answer) => answer.data.replace(/^\"(.*)\"$/, '$1'));\n }\n\n private async query(domain: string, type: number): Promise<DoHAnswer[] | null> {\n const url = `${this.endpoint}?name=${encodeURIComponent(domain)}&type=${type}`;\n const controller = new AbortController();\n const timer = setTimeout(() => controller.abort(), this.timeoutMs);\n try {\n const response = await this.fetchFn(url, {\n headers: { Accept: 'application/dns-json' },\n signal: controller.signal,\n });\n if (!response.ok) return null;\n const json = (await response.json()) as DoHResponse;\n // Status 0 = NOERROR. Anything else (NXDOMAIN, SERVFAIL, etc.) → no answers.\n if (json.Status !== 0) return [];\n return json.Answer ?? [];\n } catch {\n return null;\n } finally {\n clearTimeout(timer);\n }\n }\n}\n\n/**\n * Suggest a corrected domain. Returns the canonical for a known typo,\n * otherwise the closest match within the threshold, otherwise null.\n */\nexport function suggestDomain(domain: string, options?: DomainSuggesterOptions): string | null {\n const lower = domain.toLowerCase();\n\n // Hand-curated typo map first — beats similarity for common cases.\n const known = TYPO_LOOKUP.get(lower);\n if (known) return known;\n\n const domains = options?.customDomains ?? COMMON_DOMAINS;\n if (domains.includes(lower)) return null;\n\n const threshold = options?.threshold ?? 2;\n let minDistance = Infinity;\n let suggestion: string | null = null;\n\n for (const candidate of domains) {\n const candidateLower = candidate.toLowerCase();\n if (lower === candidateLower) return null;\n const similarity = stringSimilarity(lower, candidateLower);\n const distance = Math.round((1 - similarity) * Math.max(domain.length, candidate.length));\n if (distance > 0 && distance <= threshold && distance < minDistance) {\n minDistance = distance;\n suggestion = candidate;\n }\n }\n return suggestion;\n}\n\n/**\n * Validate one email — syntax / typo / disposable / free / MX (if a resolver\n * is supplied). Each step is independently flag-gated so callers pay only for\n * what they use.\n */\nexport async function validateEmailCore(\n email: string,\n options?: ValidateEmailOptions & { dnsResolver?: DNSResolver }\n): Promise<EmailValidationResult> {\n const normalized = email.toLowerCase().trim();\n\n if (!options?.skipCache) {\n const cached = validationCache.get(normalized);\n if (cached) return cached;\n }\n\n const result: EmailValidationResult = { valid: false, email: normalized, validators: {} };\n\n if (options?.validateSyntax !== false) {\n const syntaxValid = VALID_EMAIL_REGEX.test(normalized);\n result.validators.syntax = { valid: syntaxValid };\n if (!syntaxValid) {\n validationCache.set(normalized, result);\n return result;\n }\n }\n\n const [local, domain] = normalized.split('@');\n result.local = local;\n result.domain = domain;\n\n if (options?.validateTypo !== false) {\n const suggestion = suggestDomain(domain, options?.domainSuggesterOptions);\n result.validators.typo = { valid: !suggestion, suggestion: suggestion ?? undefined };\n }\n\n if (options?.validateDisposable !== false) {\n result.validators.disposable = { valid: !disposableProviders.includes(domain) };\n }\n\n if (options?.validateFree !== false) {\n result.validators.free = { valid: !freeProviders.includes(domain) };\n }\n\n if (options?.validateMx && options.dnsResolver) {\n try {\n const records = await options.dnsResolver.resolveMx(domain);\n const hasMx = records.length > 0;\n result.validators.mx = {\n valid: hasMx,\n records: hasMx ? records.map((r) => r.exchange) : undefined,\n };\n } catch (error) {\n result.validators.mx = {\n valid: false,\n error: error instanceof Error ? error.message : 'MX validation failed',\n };\n }\n }\n\n // Free-provider detection is informational; only the hard validators gate validity.\n result.valid = (['syntax', 'typo', 'disposable', 'mx'] as const).every((key) => {\n const validator = result.validators[key];\n return !validator || validator.valid !== false;\n });\n\n if (!options?.skipCache) validationCache.set(normalized, result);\n return result;\n}\n\nexport async function validateEmailBatch(\n emails: string[],\n options?: ValidateEmailOptions & { dnsResolver?: DNSResolver }\n): Promise<EmailValidationResult[]> {\n const chunkSize = options?.batchSize ?? 10;\n const results: EmailValidationResult[] = [];\n for (let i = 0; i < emails.length; i += chunkSize) {\n const chunk = emails.slice(i, i + chunkSize);\n const chunkResults = await Promise.all(chunk.map((email) => validateEmailCore(email, options)));\n results.push(...chunkResults);\n }\n return results;\n}\n\nexport function clearCache(): void {\n validationCache.clear();\n mxCache.clear();\n}\n\nexport type { DomainSuggesterOptions, EmailValidationResult, ValidateEmailOptions } from '../types';\n","import type { EmailValidationResult } from '../../types';\nimport { validateEmailBatch, validateEmailCore } from '../verifier';\nimport type { ValidationDispatch } from './validation';\n\n/**\n * Execute a classified request against the core validator. Single-email\n * requests yield one result; batch requests yield an array.\n */\nexport async function executeValidation(\n dispatch: ValidationDispatch\n): Promise<EmailValidationResult | EmailValidationResult[]> {\n if (dispatch.kind === 'single') {\n return validateEmailCore(dispatch.email, dispatch.options);\n }\n return validateEmailBatch(dispatch.emails, dispatch.options);\n}\n","import type { ValidateEmailOptions } from '../../types';\n\n/** Hard limit on batch size enforced by every adapter. */\nexport const MAX_BATCH_SIZE = 100;\n\n/** Shape of POST bodies and Lambda invocations across all serverless adapters. */\nexport interface ValidationRequestBody {\n email?: string;\n emails?: string[];\n options?: ValidateEmailOptions;\n}\n\nexport type ValidationDispatch =\n | { kind: 'single'; email: string; options?: ValidateEmailOptions }\n | { kind: 'batch'; emails: string[]; options?: ValidateEmailOptions };\n\nexport interface ValidationFailure {\n kind: 'invalid';\n status: 400;\n message: string;\n}\n\n/**\n * Validation for endpoints that accept ONLY a batch (`emails`). Returns\n * a 400 failure if emails is missing/empty/oversized, or null when valid.\n * Routed `/validate/batch` paths use this so error messages stay batch-specific.\n */\nexport type BatchValidation = { ok: true; emails: string[] } | { ok: false; status: 400; message: string };\n\nexport function validateBatchEmailsField(emails: unknown): BatchValidation {\n if (!Array.isArray(emails) || emails.length === 0) {\n return { ok: false, status: 400, message: 'Emails array is required' };\n }\n if (emails.length > MAX_BATCH_SIZE) {\n return { ok: false, status: 400, message: `Maximum ${MAX_BATCH_SIZE} emails allowed per batch` };\n }\n return { ok: true, emails: emails as string[] };\n}\n\n/**\n * Apply the rules every serverless adapter shares:\n * 1. body must request either `email` or `emails`\n * 2. `emails` must be a non-empty array of ≤ MAX_BATCH_SIZE entries\n *\n * Centralising this means a future rule change (say, raising the cap) lands\n * in one place instead of three.\n */\nexport function classifyRequest(\n body: ValidationRequestBody | null | undefined\n): ValidationDispatch | ValidationFailure {\n if (!body || (!body.email && !body.emails)) {\n return { kind: 'invalid', status: 400, message: 'Email or emails array is required' };\n }\n if (body.emails) {\n if (!Array.isArray(body.emails) || body.emails.length === 0) {\n return { kind: 'invalid', status: 400, message: 'Emails array is required' };\n }\n if (body.emails.length > MAX_BATCH_SIZE) {\n return { kind: 'invalid', status: 400, message: `Maximum ${MAX_BATCH_SIZE} emails allowed per batch` };\n }\n return { kind: 'batch', emails: body.emails, options: body.options };\n }\n // body.email must be set per the first guard (which checks both fields).\n if (!body.email) {\n return { kind: 'invalid', status: 400, message: 'Email or emails array is required' };\n }\n return { kind: 'single', email: body.email, options: body.options };\n}\n","/**\n * Azure Functions adapter for email validation.\n *\n * Targets the v4 programming model:\n * `(request: HttpRequest, context: InvocationContext): Promise<HttpResponseInit>`\n *\n * The HttpRequest is a Web-API-aligned shape (`request.json()`, `request.method`,\n * `request.query`, `request.headers`), so the adapter reads the body via the\n * Web API. Routes:\n * - GET /api/health\n * - POST /api/validate\n * - POST /api/validate/batch\n *\n * Two handler shapes are exported:\n * - `azureHandler`: routed (recommended).\n * - `azureFunction`: single-route convenience that infers single vs. batch\n * from the body — for one-function-per-URL setups.\n *\n * The interfaces below are minimal subsets of the official `@azure/functions`\n * types so callers can pass real Azure types without an extra cast.\n */\nimport type { ValidateEmailOptions } from '../../types';\nimport { corsHeaders, jsonHeaders } from '../_shared/cors';\nimport { executeValidation } from '../_shared/dispatch';\nimport { classifyRequest, type ValidationRequestBody, validateBatchEmailsField } from '../_shared/validation';\nimport { validateEmailCore } from '../verifier';\n\nexport interface AzureHttpRequest {\n method: string;\n url: string;\n headers: { get(name: string): string | null } | Record<string, string | undefined>;\n query: { get(name: string): string | null } | Record<string, string | undefined>;\n json(): Promise<unknown>;\n text?: () => Promise<string>;\n}\n\nexport interface AzureInvocationContext {\n invocationId?: string;\n functionName?: string;\n log?: (...args: unknown[]) => void;\n error?: (...args: unknown[]) => void;\n}\n\nexport interface AzureHttpResponseInit {\n status: number;\n headers: Record<string, string>;\n jsonBody?: unknown;\n body?: string;\n}\n\nconst ROUTED_HEADERS = jsonHeaders(corsHeaders());\n\nfunction jsonResponse(\n status: number,\n body: unknown,\n headers: Record<string, string> = ROUTED_HEADERS\n): AzureHttpResponseInit {\n return { status, headers, jsonBody: body };\n}\n\nfunction pathOf(req: AzureHttpRequest): string {\n try {\n return new URL(req.url).pathname || '/';\n } catch {\n // Some test harnesses pass a bare path. Treat it as the pathname.\n const idx = req.url.indexOf('?');\n return idx === -1 ? req.url : req.url.slice(0, idx);\n }\n}\n\nfunction readQuery(query: AzureHttpRequest['query'], key: string): string | undefined {\n if (typeof (query as { get?: unknown }).get === 'function') {\n const v = (query as { get: (k: string) => string | null }).get(key);\n return v ?? undefined;\n }\n const value = (query as Record<string, string | undefined>)[key];\n return value;\n}\n\nfunction parseValidateOptions(query: AzureHttpRequest['query']): Partial<ValidateEmailOptions> {\n const options: Partial<ValidateEmailOptions> = {};\n if (readQuery(query, 'skipCache') === 'true') options.skipCache = true;\n if (readQuery(query, 'validateTypo') === 'false') options.validateTypo = false;\n return options;\n}\n\nasync function readJsonBody(req: AzureHttpRequest): Promise<unknown> {\n try {\n return await req.json();\n } catch {\n throw new SyntaxError('Invalid JSON body');\n }\n}\n\n/** Routed Azure Functions v4 handler. */\nexport async function azureHandler(\n req: AzureHttpRequest,\n _context?: AzureInvocationContext\n): Promise<AzureHttpResponseInit> {\n if (req.method === 'OPTIONS') {\n return { status: 204, headers: corsHeaders() };\n }\n\n const path = pathOf(req);\n\n if (path === '/api/health' && req.method === 'GET') {\n return jsonResponse(200, { status: 'healthy', platform: 'azure', timestamp: new Date().toISOString() });\n }\n\n const isValidatePath = path === '/api/validate' || path === '/api/validate/batch';\n if (isValidatePath && req.method !== 'POST') {\n return jsonResponse(405, { error: 'Method not allowed' });\n }\n\n if (path === '/api/validate' && req.method === 'POST') {\n try {\n const body = (await readJsonBody(req)) as { email?: string };\n if (!body.email) return jsonResponse(400, { error: 'Email is required' });\n const options = parseValidateOptions(req.query);\n const result = await validateEmailCore(body.email, options);\n return jsonResponse(200, result);\n } catch (error) {\n if (error instanceof SyntaxError) return jsonResponse(400, { error: 'Invalid request body' });\n console.error('Azure validation error:', error);\n return jsonResponse(500, { error: 'Internal server error' });\n }\n }\n\n if (path === '/api/validate/batch' && req.method === 'POST') {\n try {\n const body = (await readJsonBody(req)) as ValidationRequestBody;\n const validated = validateBatchEmailsField(body.emails);\n if (!validated.ok) return jsonResponse(validated.status, { error: validated.message });\n const results = await executeValidation({ kind: 'batch', emails: validated.emails });\n return jsonResponse(200, { results });\n } catch (error) {\n if (error instanceof SyntaxError) return jsonResponse(400, { error: 'Invalid request body' });\n console.error('Azure batch validation error:', error);\n return jsonResponse(500, { error: 'Internal server error' });\n }\n }\n\n return jsonResponse(404, { error: 'Not found' });\n}\n\n/** Single-route convenience — infers single vs. batch from the body. */\nexport async function azureFunction(\n req: AzureHttpRequest,\n _context?: AzureInvocationContext\n): Promise<AzureHttpResponseInit> {\n if (req.method === 'OPTIONS') {\n return { status: 204, headers: corsHeaders('POST, OPTIONS') };\n }\n if (req.method !== 'POST') return jsonResponse(405, { success: false, error: 'Method not allowed' });\n\n try {\n const body = (await readJsonBody(req)) as ValidationRequestBody;\n const classified = classifyRequest(body);\n if (classified.kind === 'invalid') {\n return jsonResponse(classified.status, { success: false, error: classified.message });\n }\n const data = await executeValidation(classified);\n return jsonResponse(200, { success: true, data });\n } catch (error) {\n if (error instanceof SyntaxError) return jsonResponse(400, { success: false, error: 'Invalid request body' });\n console.error('Azure function error:', error);\n const message = error instanceof Error ? error.message : 'Internal server error';\n return jsonResponse(500, { success: false, error: message });\n }\n}\n\nexport default {\n azureHandler,\n azureFunction,\n};\n"],"names":["exports","stringSimilarity","__async"],"mappings":"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","x_google_ignoreList":[1]}
|
|
1
|
+
{"version":3,"file":"azure.esm.js","sources":["../../../src/serverless/_shared/cors.ts","../../../node_modules/string-similarity-js/dist/string-similarity.js","../../../src/serverless/verifier.ts","../../../src/serverless/_shared/dispatch.ts","../../../src/serverless/_shared/validation.ts","../../../src/serverless/adapters/azure.ts"],"sourcesContent":["/**\n * Standard CORS header set used by every adapter. `methods` lets each platform\n * advertise the verbs it actually supports without re-declaring the rest.\n */\nexport function corsHeaders(methods: string = 'GET, POST, OPTIONS'): Record<string, string> {\n return {\n 'Access-Control-Allow-Origin': '*',\n 'Access-Control-Allow-Methods': methods,\n 'Access-Control-Allow-Headers': 'Content-Type',\n };\n}\n\nexport function jsonHeaders(extra?: Record<string, string>): Record<string, string> {\n return { 'Content-Type': 'application/json', ...extra };\n}\n","\"use strict\";\nObject.defineProperty(exports, \"__esModule\", { value: true });\nexports.stringSimilarity = void 0;\n/* global exports, Map */\n/**\n * Calculate similarity between two strings\n * @param {string} str1 First string to match\n * @param {string} str2 Second string to match\n * @param {number} [substringLength=2] Optional. Length of substring to be used in calculating similarity. Default 2.\n * @param {boolean} [caseSensitive=false] Optional. Whether you want to consider case in string matching. Default false;\n * @returns Number between 0 and 1, with 0 being a low match score.\n */\nvar stringSimilarity = function (str1, str2, substringLength, caseSensitive) {\n if (substringLength === void 0) { substringLength = 2; }\n if (caseSensitive === void 0) { caseSensitive = false; }\n if (!caseSensitive) {\n str1 = str1.toLowerCase();\n str2 = str2.toLowerCase();\n }\n if (str1.length < substringLength || str2.length < substringLength)\n return 0;\n var map = new Map();\n for (var i = 0; i < str1.length - (substringLength - 1); i++) {\n var substr1 = str1.substr(i, substringLength);\n map.set(substr1, map.has(substr1) ? map.get(substr1) + 1 : 1);\n }\n var match = 0;\n for (var j = 0; j < str2.length - (substringLength - 1); j++) {\n var substr2 = str2.substr(j, substringLength);\n var count = map.has(substr2) ? map.get(substr2) : 0;\n if (count > 0) {\n map.set(substr2, count - 1);\n match++;\n }\n }\n return (match * 2) / (str1.length + str2.length - ((substringLength - 1) * 2));\n};\nexports.stringSimilarity = stringSimilarity;\nexports.default = exports.stringSimilarity;\n//# sourceMappingURL=string-similarity.js.map","/**\n * Edge-runtime / serverless email validator.\n *\n * No Node.js APIs (no `node:net`, no `node:dns`) — DNS is delegated to a\n * caller-supplied `DNSResolver`, so the same code runs on Cloudflare Workers,\n * Vercel Edge, Lambda@Edge, and Deno Deploy.\n *\n * Shares data with the main validator: `commonEmailDomains` and the typo map\n * are imported from `src/data/`, so we never drift between the two surfaces.\n */\n\nimport { stringSimilarity } from 'string-similarity-js';\nimport commonEmailDomainsJson from '../data/common-email-domains.json';\nimport typoPatternsJson from '../data/typo-patterns.json';\nimport disposableProviders from '../disposable-email-providers.json';\nimport freeProviders from '../free-email-providers.json';\nimport type { DomainSuggesterOptions, EmailValidationResult, ValidateEmailOptions } from '../types';\n\n/** Compact LRU/TTL cache. One Map, expiry stamp per entry, batched eviction. */\nexport class EdgeCache<T> {\n private readonly cache = new Map<string, { value: T; expires: number }>();\n\n constructor(\n private readonly maxSize = 1000,\n private readonly ttl = 3_600_000\n ) {}\n\n get(key: string): T | undefined {\n const item = this.cache.get(key);\n if (!item) return undefined;\n if (Date.now() > item.expires) {\n this.cache.delete(key);\n return undefined;\n }\n return item.value;\n }\n\n set(key: string, value: T): void {\n if (this.cache.size >= this.maxSize) this.evict();\n this.cache.set(key, { value, expires: Date.now() + this.ttl });\n }\n\n clear(): void {\n this.cache.clear();\n }\n\n size(): number {\n return this.cache.size;\n }\n\n private evict(): void {\n // Drop the oldest 10% in one pass — Map preserves insertion order so\n // `keys()` walks oldest-first.\n const drop = Math.max(1, Math.floor(this.maxSize * 0.1));\n let n = 0;\n for (const key of this.cache.keys()) {\n if (n++ >= drop) break;\n this.cache.delete(key);\n }\n }\n}\n\n// Module-level per-isolate caches. Edge runtimes get cold-start fresh; warm\n// invocations benefit from the in-memory hits.\nexport const validationCache = new EdgeCache<EmailValidationResult>(1000);\nexport const mxCache = new EdgeCache<string[]>(500);\n\n/** Same regex the main validator uses — kept inline because edge runtimes don't auto-resolve psl. */\nconst VALID_EMAIL_REGEX =\n /^(([a-zA-Z0-9_+'-]+(\\.[a-zA-Z0-9_+'-]+)*)|(\".+\"))@((\\[[0-9]{1,3}\\.[0-9]{1,3}\\.[0-9]{1,3}\\.[0-9]{1,3}])|(([a-zA-Z0-9-]+\\.)+[a-zA-Z]{2,}))$/;\n\n/**\n * Common email domains — re-exported so callers (Vercel Edge, etc.) can pass a\n * custom subset via `DomainSuggesterOptions.customDomains`.\n */\nexport const COMMON_DOMAINS: readonly string[] = commonEmailDomainsJson as string[];\n\nconst TYPO_PATTERNS = typoPatternsJson as Record<string, string[]>;\n/** Reverse index for O(1) typo → canonical lookup. */\nconst TYPO_LOOKUP = new Map<string, string>();\nfor (const [canonical, typos] of Object.entries(TYPO_PATTERNS)) {\n for (const typo of typos) TYPO_LOOKUP.set(typo, canonical);\n}\n\n/** DNS resolver contract — caller-supplied so we don't import `node:dns`. */\nexport interface DNSResolver {\n resolveMx(domain: string): Promise<Array<{ exchange: string; priority: number }>>;\n resolveTxt(domain: string): Promise<string[]>;\n}\n\n/** No-op resolver for environments where DNS isn't available. */\nexport class StubDNSResolver implements DNSResolver {\n async resolveMx(): Promise<Array<{ exchange: string; priority: number }>> {\n return [];\n }\n async resolveTxt(): Promise<string[]> {\n return [];\n }\n}\n\n/**\n * DNS-over-HTTPS resolver — works in any runtime with `fetch` (Cloudflare\n * Workers, Vercel Edge, Deno, browsers, Node 18+). Defaults to Cloudflare's\n * 1.1.1.1 endpoint; pass `endpoint` to use Google (8.8.8.8), NextDNS, or\n * a self-hosted resolver.\n *\n * Compatible with [`cf-doh`](https://www.npmjs.com/package/cf-doh) — if you\n * already use that, drop it in directly. This built-in keeps the package\n * zero-dep so the same code works on every edge runtime without an extra\n * install step.\n */\nexport interface DoHResolverOptions {\n /** DoH endpoint URL. Default: https://cloudflare-dns.com/dns-query */\n endpoint?: string;\n /** Per-query request timeout, ms. Default: 5000 */\n timeoutMs?: number;\n /** Custom fetch (e.g. to add headers / proxy). Default: globalThis.fetch */\n fetch?: typeof fetch;\n}\n\ninterface DoHAnswer {\n name: string;\n type: number;\n TTL: number;\n data: string;\n}\n\ninterface DoHResponse {\n Status: number;\n Answer?: DoHAnswer[];\n}\n\nconst DOH_RECORD_TYPE = { MX: 15, TXT: 16 } as const;\n\nexport class DoHResolver implements DNSResolver {\n private readonly endpoint: string;\n private readonly timeoutMs: number;\n private readonly fetchFn: typeof fetch;\n\n constructor(options: DoHResolverOptions = {}) {\n this.endpoint = options.endpoint ?? 'https://cloudflare-dns.com/dns-query';\n this.timeoutMs = options.timeoutMs ?? 5000;\n this.fetchFn = options.fetch ?? globalThis.fetch;\n }\n\n async resolveMx(domain: string): Promise<Array<{ exchange: string; priority: number }>> {\n const records = await this.query(domain, DOH_RECORD_TYPE.MX);\n if (!records) return [];\n return records\n .map((answer) => {\n // MX answer data: \"<priority> <exchange>\" (with optional trailing dot).\n const match = answer.data.match(/^(\\d+)\\s+(.+?)\\.?$/);\n if (!match) return null;\n return { priority: Number(match[1]), exchange: match[2] as string };\n })\n .filter((r): r is { exchange: string; priority: number } => r !== null)\n .sort((a, b) => a.priority - b.priority);\n }\n\n async resolveTxt(domain: string): Promise<string[]> {\n const records = await this.query(domain, DOH_RECORD_TYPE.TXT);\n if (!records) return [];\n // TXT answers come back as quoted strings — strip the surrounding quotes.\n return records.map((answer) => answer.data.replace(/^\"(.*)\"$/, '$1'));\n }\n\n private async query(domain: string, type: number): Promise<DoHAnswer[] | null> {\n const url = `${this.endpoint}?name=${encodeURIComponent(domain)}&type=${type}`;\n const controller = new AbortController();\n const timer = setTimeout(() => controller.abort(), this.timeoutMs);\n try {\n const response = await this.fetchFn(url, {\n headers: { Accept: 'application/dns-json' },\n signal: controller.signal,\n });\n if (!response.ok) return null;\n const json = (await response.json()) as DoHResponse;\n // Status 0 = NOERROR. Anything else (NXDOMAIN, SERVFAIL, etc.) → no answers.\n if (json.Status !== 0) return [];\n return json.Answer ?? [];\n } catch {\n return null;\n } finally {\n clearTimeout(timer);\n }\n }\n}\n\n/**\n * Suggest a corrected domain. Returns the canonical for a known typo,\n * otherwise the closest match within the threshold, otherwise null.\n */\nexport function suggestDomain(domain: string, options?: DomainSuggesterOptions): string | null {\n const lower = domain.toLowerCase();\n\n // Hand-curated typo map first — beats similarity for common cases.\n const known = TYPO_LOOKUP.get(lower);\n if (known) return known;\n\n const domains = options?.customDomains ?? COMMON_DOMAINS;\n if (domains.includes(lower)) return null;\n\n const threshold = options?.threshold ?? 2;\n let minDistance = Infinity;\n let suggestion: string | null = null;\n\n for (const candidate of domains) {\n const candidateLower = candidate.toLowerCase();\n if (lower === candidateLower) return null;\n const similarity = stringSimilarity(lower, candidateLower);\n const distance = Math.round((1 - similarity) * Math.max(domain.length, candidate.length));\n if (distance > 0 && distance <= threshold && distance < minDistance) {\n minDistance = distance;\n suggestion = candidate;\n }\n }\n return suggestion;\n}\n\n/**\n * Validate one email — syntax / typo / disposable / free / MX (if a resolver\n * is supplied). Each step is independently flag-gated so callers pay only for\n * what they use.\n */\nexport async function validateEmailCore(\n email: string,\n options?: ValidateEmailOptions & { dnsResolver?: DNSResolver }\n): Promise<EmailValidationResult> {\n const normalized = email.toLowerCase().trim();\n\n if (!options?.skipCache) {\n const cached = validationCache.get(normalized);\n if (cached) return cached;\n }\n\n const result: EmailValidationResult = { valid: false, email: normalized, validators: {} };\n\n if (options?.validateSyntax !== false) {\n const syntaxValid = VALID_EMAIL_REGEX.test(normalized);\n result.validators.syntax = { valid: syntaxValid };\n if (!syntaxValid) {\n validationCache.set(normalized, result);\n return result;\n }\n }\n\n const [local, domain] = normalized.split('@');\n result.local = local;\n result.domain = domain;\n\n if (options?.validateTypo !== false) {\n const suggestion = suggestDomain(domain, options?.domainSuggesterOptions);\n result.validators.typo = { valid: !suggestion, suggestion: suggestion ?? undefined };\n }\n\n if (options?.validateDisposable !== false) {\n result.validators.disposable = { valid: !disposableProviders.includes(domain) };\n }\n\n if (options?.validateFree !== false) {\n result.validators.free = { valid: !freeProviders.includes(domain) };\n }\n\n if (options?.validateMx && options.dnsResolver) {\n try {\n const records = await options.dnsResolver.resolveMx(domain);\n const hasMx = records.length > 0;\n result.validators.mx = {\n valid: hasMx,\n records: hasMx ? records.map((r) => r.exchange) : undefined,\n };\n } catch (error) {\n result.validators.mx = {\n valid: false,\n error: error instanceof Error ? error.message : 'MX validation failed',\n };\n }\n }\n\n // Free-provider detection is informational; only the hard validators gate validity.\n result.valid = (['syntax', 'typo', 'disposable', 'mx'] as const).every((key) => {\n const validator = result.validators[key];\n return !validator || validator.valid !== false;\n });\n\n if (!options?.skipCache) validationCache.set(normalized, result);\n return result;\n}\n\nexport async function validateEmailBatch(\n emails: string[],\n options?: ValidateEmailOptions & { dnsResolver?: DNSResolver }\n): Promise<EmailValidationResult[]> {\n const chunkSize = options?.batchSize ?? 10;\n const results: EmailValidationResult[] = [];\n for (let i = 0; i < emails.length; i += chunkSize) {\n const chunk = emails.slice(i, i + chunkSize);\n const chunkResults = await Promise.all(chunk.map((email) => validateEmailCore(email, options)));\n results.push(...chunkResults);\n }\n return results;\n}\n\nexport function clearCache(): void {\n validationCache.clear();\n mxCache.clear();\n}\n\nexport type { DomainSuggesterOptions, EmailValidationResult, ValidateEmailOptions } from '../types';\n","import type { EmailValidationResult } from '../../types';\nimport { validateEmailBatch, validateEmailCore } from '../verifier';\nimport type { ValidationDispatch } from './validation';\n\n/**\n * Execute a classified request against the core validator. Single-email\n * requests yield one result; batch requests yield an array.\n */\nexport async function executeValidation(\n dispatch: ValidationDispatch\n): Promise<EmailValidationResult | EmailValidationResult[]> {\n if (dispatch.kind === 'single') {\n return validateEmailCore(dispatch.email, dispatch.options);\n }\n return validateEmailBatch(dispatch.emails, dispatch.options);\n}\n","import type { ValidateEmailOptions } from '../../types';\n\n/** Hard limit on batch size enforced by every adapter. */\nexport const MAX_BATCH_SIZE = 100;\n\n/** Shape of POST bodies and Lambda invocations across all serverless adapters. */\nexport interface ValidationRequestBody {\n email?: string;\n emails?: string[];\n options?: ValidateEmailOptions;\n}\n\nexport type ValidationDispatch =\n | { kind: 'single'; email: string; options?: ValidateEmailOptions }\n | { kind: 'batch'; emails: string[]; options?: ValidateEmailOptions };\n\nexport interface ValidationFailure {\n kind: 'invalid';\n status: 400;\n message: string;\n}\n\n/**\n * Validation for endpoints that accept ONLY a batch (`emails`). Returns\n * a 400 failure if emails is missing/empty/oversized, or null when valid.\n * Routed `/validate/batch` paths use this so error messages stay batch-specific.\n */\nexport type BatchValidation = { ok: true; emails: string[] } | { ok: false; status: 400; message: string };\n\nexport function validateBatchEmailsField(emails: unknown): BatchValidation {\n if (!Array.isArray(emails) || emails.length === 0) {\n return { ok: false, status: 400, message: 'Emails array is required' };\n }\n if (emails.length > MAX_BATCH_SIZE) {\n return { ok: false, status: 400, message: `Maximum ${MAX_BATCH_SIZE} emails allowed per batch` };\n }\n return { ok: true, emails: emails as string[] };\n}\n\n/**\n * Apply the rules every serverless adapter shares:\n * 1. body must request either `email` or `emails`\n * 2. `emails` must be a non-empty array of ≤ MAX_BATCH_SIZE entries\n *\n * Centralising this means a future rule change (say, raising the cap) lands\n * in one place instead of three.\n */\nexport function classifyRequest(\n body: ValidationRequestBody | null | undefined\n): ValidationDispatch | ValidationFailure {\n if (!body || (!body.email && !body.emails)) {\n return { kind: 'invalid', status: 400, message: 'Email or emails array is required' };\n }\n if (body.emails) {\n if (!Array.isArray(body.emails) || body.emails.length === 0) {\n return { kind: 'invalid', status: 400, message: 'Emails array is required' };\n }\n if (body.emails.length > MAX_BATCH_SIZE) {\n return { kind: 'invalid', status: 400, message: `Maximum ${MAX_BATCH_SIZE} emails allowed per batch` };\n }\n return { kind: 'batch', emails: body.emails, options: body.options };\n }\n // body.email must be set per the first guard (which checks both fields).\n if (!body.email) {\n return { kind: 'invalid', status: 400, message: 'Email or emails array is required' };\n }\n return { kind: 'single', email: body.email, options: body.options };\n}\n","/**\n * Azure Functions adapter for email validation.\n *\n * Targets the v4 programming model:\n * `(request: HttpRequest, context: InvocationContext): Promise<HttpResponseInit>`\n *\n * The HttpRequest is a Web-API-aligned shape (`request.json()`, `request.method`,\n * `request.query`, `request.headers`), so the adapter reads the body via the\n * Web API. Routes:\n * - GET /api/health\n * - POST /api/validate\n * - POST /api/validate/batch\n *\n * Two handler shapes are exported:\n * - `azureHandler`: routed (recommended).\n * - `azureFunction`: single-route convenience that infers single vs. batch\n * from the body — for one-function-per-URL setups.\n *\n * The interfaces below are minimal subsets of the official `@azure/functions`\n * types so callers can pass real Azure types without an extra cast.\n */\nimport type { ValidateEmailOptions } from '../../types';\nimport { corsHeaders, jsonHeaders } from '../_shared/cors';\nimport { executeValidation } from '../_shared/dispatch';\nimport { classifyRequest, type ValidationRequestBody, validateBatchEmailsField } from '../_shared/validation';\nimport { validateEmailCore } from '../verifier';\n\nexport interface AzureHttpRequest {\n method: string;\n url: string;\n headers: { get(name: string): string | null } | Record<string, string | undefined>;\n query: { get(name: string): string | null } | Record<string, string | undefined>;\n json(): Promise<unknown>;\n text?: () => Promise<string>;\n}\n\nexport interface AzureInvocationContext {\n invocationId?: string;\n functionName?: string;\n log?: (...args: unknown[]) => void;\n error?: (...args: unknown[]) => void;\n}\n\nexport interface AzureHttpResponseInit {\n status: number;\n headers: Record<string, string>;\n jsonBody?: unknown;\n body?: string;\n}\n\nconst ROUTED_HEADERS = jsonHeaders(corsHeaders());\n\nfunction jsonResponse(\n status: number,\n body: unknown,\n headers: Record<string, string> = ROUTED_HEADERS\n): AzureHttpResponseInit {\n return { status, headers, jsonBody: body };\n}\n\nfunction pathOf(req: AzureHttpRequest): string {\n try {\n return new URL(req.url).pathname || '/';\n } catch {\n // Some test harnesses pass a bare path. Treat it as the pathname.\n const idx = req.url.indexOf('?');\n return idx === -1 ? req.url : req.url.slice(0, idx);\n }\n}\n\nfunction readQuery(query: AzureHttpRequest['query'], key: string): string | undefined {\n if (typeof (query as { get?: unknown }).get === 'function') {\n const v = (query as { get: (k: string) => string | null }).get(key);\n return v ?? undefined;\n }\n const value = (query as Record<string, string | undefined>)[key];\n return value;\n}\n\nfunction parseValidateOptions(query: AzureHttpRequest['query']): Partial<ValidateEmailOptions> {\n const options: Partial<ValidateEmailOptions> = {};\n if (readQuery(query, 'skipCache') === 'true') options.skipCache = true;\n if (readQuery(query, 'validateTypo') === 'false') options.validateTypo = false;\n return options;\n}\n\nasync function readJsonBody(req: AzureHttpRequest): Promise<unknown> {\n try {\n return await req.json();\n } catch {\n throw new SyntaxError('Invalid JSON body');\n }\n}\n\n/** Routed Azure Functions v4 handler. */\nexport async function azureHandler(\n req: AzureHttpRequest,\n _context?: AzureInvocationContext\n): Promise<AzureHttpResponseInit> {\n if (req.method === 'OPTIONS') {\n return { status: 204, headers: corsHeaders() };\n }\n\n const path = pathOf(req);\n\n if (path === '/api/health' && req.method === 'GET') {\n return jsonResponse(200, { status: 'healthy', platform: 'azure', timestamp: new Date().toISOString() });\n }\n\n const isValidatePath = path === '/api/validate' || path === '/api/validate/batch';\n if (isValidatePath && req.method !== 'POST') {\n return jsonResponse(405, { error: 'Method not allowed' });\n }\n\n if (path === '/api/validate' && req.method === 'POST') {\n try {\n const body = (await readJsonBody(req)) as { email?: string };\n if (!body.email) return jsonResponse(400, { error: 'Email is required' });\n const options = parseValidateOptions(req.query);\n const result = await validateEmailCore(body.email, options);\n return jsonResponse(200, result);\n } catch (error) {\n if (error instanceof SyntaxError) return jsonResponse(400, { error: 'Invalid request body' });\n console.error('Azure validation error:', error);\n return jsonResponse(500, { error: 'Internal server error' });\n }\n }\n\n if (path === '/api/validate/batch' && req.method === 'POST') {\n try {\n const body = (await readJsonBody(req)) as ValidationRequestBody;\n const validated = validateBatchEmailsField(body.emails);\n if (!validated.ok) return jsonResponse(validated.status, { error: validated.message });\n const results = await executeValidation({ kind: 'batch', emails: validated.emails });\n return jsonResponse(200, { results });\n } catch (error) {\n if (error instanceof SyntaxError) return jsonResponse(400, { error: 'Invalid request body' });\n console.error('Azure batch validation error:', error);\n return jsonResponse(500, { error: 'Internal server error' });\n }\n }\n\n return jsonResponse(404, { error: 'Not found' });\n}\n\n/** Single-route convenience — infers single vs. batch from the body. */\nexport async function azureFunction(\n req: AzureHttpRequest,\n _context?: AzureInvocationContext\n): Promise<AzureHttpResponseInit> {\n if (req.method === 'OPTIONS') {\n return { status: 204, headers: corsHeaders('POST, OPTIONS') };\n }\n if (req.method !== 'POST') return jsonResponse(405, { success: false, error: 'Method not allowed' });\n\n try {\n const body = (await readJsonBody(req)) as ValidationRequestBody;\n const classified = classifyRequest(body);\n if (classified.kind === 'invalid') {\n return jsonResponse(classified.status, { success: false, error: classified.message });\n }\n const data = await executeValidation(classified);\n return jsonResponse(200, { success: true, data });\n } catch (error) {\n if (error instanceof SyntaxError) return jsonResponse(400, { success: false, error: 'Invalid request body' });\n console.error('Azure function error:', error);\n const message = error instanceof Error ? error.message : 'Internal server error';\n return jsonResponse(500, { success: false, error: message });\n }\n}\n\nexport default {\n azureHandler,\n azureFunction,\n};\n"],"names":["stringSimilarity","__async"],"mappings":"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","x_google_ignoreList":[1]}
|
|
@@ -36,9 +36,9 @@ var hasRequiredStringSimilarity;
|
|
|
36
36
|
function requireStringSimilarity () {
|
|
37
37
|
if (hasRequiredStringSimilarity) return stringSimilarity;
|
|
38
38
|
hasRequiredStringSimilarity = 1;
|
|
39
|
-
(function (exports
|
|
40
|
-
Object.defineProperty(exports
|
|
41
|
-
exports
|
|
39
|
+
(function (exports) {
|
|
40
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
|
41
|
+
exports.stringSimilarity = void 0;
|
|
42
42
|
/* global exports, Map */
|
|
43
43
|
/**
|
|
44
44
|
* Calculate similarity between two strings
|
|
@@ -73,8 +73,8 @@ function requireStringSimilarity () {
|
|
|
73
73
|
}
|
|
74
74
|
return (match * 2) / (str1.length + str2.length - ((substringLength - 1) * 2));
|
|
75
75
|
};
|
|
76
|
-
exports
|
|
77
|
-
exports
|
|
76
|
+
exports.stringSimilarity = stringSimilarity;
|
|
77
|
+
exports.default = exports.stringSimilarity;
|
|
78
78
|
|
|
79
79
|
} (stringSimilarity));
|
|
80
80
|
return stringSimilarity;
|