@saastro/forms 0.1.3

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.
@@ -0,0 +1 @@
1
+ {"version":3,"sources":["../src/utils/submitActionExecutors.ts","../src/utils/fieldMapping.ts","../src/utils/submitOrchestrator.ts"],"sourcesContent":["/**\n * Submit Action Executors\n *\n * Ejecutores individuales para cada tipo de acción de submit.\n * Cada ejecutor maneja la lógica específica de su tipo.\n */\n\nimport type {\n SubmitAction,\n HttpSubmitAction,\n WebhookSubmitAction,\n EmailSubmitAction,\n CustomSubmitAction,\n HttpBodyConfig,\n HttpAuthConfig,\n} from '../types/submitActions';\n\n// ───────────────────────────────────────────────────────────────\n// Utilidades\n// ───────────────────────────────────────────────────────────────\n\n/**\n * Reemplaza placeholders {{fieldName}} con valores reales\n */\nfunction replacePlaceholders(template: string, values: Record<string, unknown>): string {\n return template.replace(/\\{\\{(\\w+)\\}\\}/g, (_, fieldName) => {\n const value = values[fieldName];\n if (value === undefined || value === null) return '';\n if (typeof value === 'object') return JSON.stringify(value);\n return String(value);\n });\n}\n\n/**\n * Filtra los campos según includeFields/excludeFields\n */\nfunction filterFields(\n values: Record<string, unknown>,\n includeFields?: string[],\n excludeFields?: string[],\n): Record<string, unknown> {\n let result = { ...values };\n\n if (includeFields && includeFields.length > 0) {\n result = {};\n for (const field of includeFields) {\n if (field in values) {\n result[field] = values[field];\n }\n }\n }\n\n if (excludeFields && excludeFields.length > 0) {\n for (const field of excludeFields) {\n delete result[field];\n }\n }\n\n return result;\n}\n\n/**\n * Construye headers de autenticación\n */\nfunction buildAuthHeaders(auth?: HttpAuthConfig): Record<string, string> {\n if (!auth || auth.type === 'none') return {};\n\n switch (auth.type) {\n case 'bearer':\n return auth.token ? { Authorization: `Bearer ${auth.token}` } : {};\n\n case 'basic':\n if (auth.username && auth.password) {\n const credentials = btoa(`${auth.username}:${auth.password}`);\n return { Authorization: `Basic ${credentials}` };\n }\n return {};\n\n case 'api-key':\n if (auth.token) {\n const headerName = auth.headerName || 'X-API-Key';\n return { [headerName]: auth.token };\n }\n return {};\n\n default:\n return {};\n }\n}\n\n/**\n * Construye el body según el formato especificado\n */\nfunction buildRequestBody(\n values: Record<string, unknown>,\n bodyConfig?: HttpBodyConfig,\n): { body: BodyInit; contentType: string } {\n const filteredValues = filterFields(values, bodyConfig?.includeFields, bodyConfig?.excludeFields);\n\n const format = bodyConfig?.format || 'json';\n\n switch (format) {\n case 'json': {\n const data = bodyConfig?.template\n ? JSON.parse(replacePlaceholders(bodyConfig.template, values))\n : filteredValues;\n return {\n body: JSON.stringify(data),\n contentType: 'application/json',\n };\n }\n\n case 'form-data': {\n const formData = new FormData();\n for (const [key, value] of Object.entries(filteredValues)) {\n if (value instanceof File) {\n formData.append(key, value);\n } else if (value !== undefined && value !== null) {\n formData.append(key, String(value));\n }\n }\n return {\n body: formData,\n contentType: '', // Browser sets this automatically with boundary\n };\n }\n\n case 'url-encoded': {\n const params = new URLSearchParams();\n for (const [key, value] of Object.entries(filteredValues)) {\n if (value !== undefined && value !== null) {\n params.append(key, String(value));\n }\n }\n return {\n body: params.toString(),\n contentType: 'application/x-www-form-urlencoded',\n };\n }\n\n default:\n return {\n body: JSON.stringify(filteredValues),\n contentType: 'application/json',\n };\n }\n}\n\n/**\n * Ejecuta con reintentos\n */\nasync function executeWithRetry<T>(\n fn: () => Promise<T>,\n retryConfig?: { enabled: boolean; maxAttempts: number; delayMs: number },\n): Promise<T> {\n const maxAttempts = retryConfig?.enabled ? retryConfig.maxAttempts : 1;\n const delayMs = retryConfig?.delayMs || 1000;\n\n let lastError: Error | undefined;\n\n for (let attempt = 1; attempt <= maxAttempts; attempt++) {\n try {\n return await fn();\n } catch (error) {\n lastError = error instanceof Error ? error : new Error(String(error));\n\n if (attempt < maxAttempts) {\n await new Promise((resolve) => setTimeout(resolve, delayMs * attempt));\n }\n }\n }\n\n throw lastError;\n}\n\n// ───────────────────────────────────────────────────────────────\n// Ejecutor HTTP/API\n// ───────────────────────────────────────────────────────────────\n\nexport async function executeHttpAction(\n action: HttpSubmitAction,\n values: Record<string, unknown>,\n): Promise<unknown> {\n const { endpoint, body: bodyConfig, auth, retry, timeout = 30000 } = action;\n\n const execute = async () => {\n const controller = new AbortController();\n const timeoutId = setTimeout(() => controller.abort(), timeout);\n\n try {\n const authHeaders = buildAuthHeaders(auth);\n const { body, contentType } = buildRequestBody(values, bodyConfig);\n\n const headers: Record<string, string> = {\n ...endpoint.headers,\n ...authHeaders,\n };\n\n // Solo agregar Content-Type si no es form-data (el browser lo maneja)\n if (contentType) {\n headers['Content-Type'] = contentType;\n }\n\n const response = await fetch(endpoint.url, {\n method: endpoint.method,\n headers,\n body: endpoint.method !== 'GET' ? body : undefined,\n signal: controller.signal,\n });\n\n if (!response.ok) {\n const errorText = await response.text().catch(() => 'Unknown error');\n throw new Error(`HTTP ${response.status}: ${response.statusText} - ${errorText}`);\n }\n\n // Intentar parsear como JSON, si falla retornar texto\n const responseText = await response.text();\n try {\n return JSON.parse(responseText);\n } catch {\n return responseText;\n }\n } finally {\n clearTimeout(timeoutId);\n }\n };\n\n return executeWithRetry(execute, retry);\n}\n\n// ───────────────────────────────────────────────────────────────\n// Ejecutor Webhook\n// ───────────────────────────────────────────────────────────────\n\n/**\n * Genera firma HMAC-SHA256 para webhooks\n */\nasync function generateHmacSignature(payload: string, secret: string): Promise<string> {\n const encoder = new TextEncoder();\n const keyData = encoder.encode(secret);\n const messageData = encoder.encode(payload);\n\n const key = await crypto.subtle.importKey(\n 'raw',\n keyData,\n { name: 'HMAC', hash: 'SHA-256' },\n false,\n ['sign'],\n );\n\n const signature = await crypto.subtle.sign('HMAC', key, messageData);\n const hashArray = Array.from(new Uint8Array(signature));\n return hashArray.map((b) => b.toString(16).padStart(2, '0')).join('');\n}\n\nexport async function executeWebhookAction(\n action: WebhookSubmitAction,\n values: Record<string, unknown>,\n): Promise<unknown> {\n const { url, secret, headers = {}, payloadTemplate, includeFields, excludeFields } = action;\n\n const filteredValues = filterFields(values, includeFields, excludeFields);\n\n const payload = payloadTemplate\n ? replacePlaceholders(payloadTemplate, values)\n : JSON.stringify(filteredValues);\n\n const requestHeaders: Record<string, string> = {\n 'Content-Type': 'application/json',\n ...headers,\n };\n\n // Agregar firma HMAC si hay secret\n if (secret) {\n const signature = await generateHmacSignature(payload, secret);\n requestHeaders['X-Webhook-Signature'] = `sha256=${signature}`;\n }\n\n const response = await fetch(url, {\n method: 'POST',\n headers: requestHeaders,\n body: payload,\n });\n\n if (!response.ok) {\n throw new Error(`Webhook failed: ${response.status} ${response.statusText}`);\n }\n\n const responseText = await response.text();\n try {\n return JSON.parse(responseText);\n } catch {\n return responseText;\n }\n}\n\n// ───────────────────────────────────────────────────────────────\n// Ejecutor Email\n// ───────────────────────────────────────────────────────────────\n\n/**\n * Genera template HTML por defecto para email\n */\nfunction generateDefaultEmailTemplate(values: Record<string, unknown>): string {\n const rows = Object.entries(values)\n .map(\n ([key, value]) => `\n <tr>\n <td style=\"padding: 8px; border: 1px solid #ddd; font-weight: bold;\">${key}</td>\n <td style=\"padding: 8px; border: 1px solid #ddd;\">${\n typeof value === 'object' ? JSON.stringify(value) : String(value ?? '')\n }</td>\n </tr>\n `,\n )\n .join('');\n\n return `\n <!DOCTYPE html>\n <html>\n <head>\n <meta charset=\"utf-8\">\n <title>Form Submission</title>\n </head>\n <body style=\"font-family: Arial, sans-serif; padding: 20px;\">\n <h2 style=\"color: #333;\">New Form Submission</h2>\n <table style=\"border-collapse: collapse; width: 100%; max-width: 600px;\">\n <thead>\n <tr style=\"background-color: #f5f5f5;\">\n <th style=\"padding: 8px; border: 1px solid #ddd; text-align: left;\">Field</th>\n <th style=\"padding: 8px; border: 1px solid #ddd; text-align: left;\">Value</th>\n </tr>\n </thead>\n <tbody>\n ${rows}\n </tbody>\n </table>\n <p style=\"color: #666; font-size: 12px; margin-top: 20px;\">\n Sent via @saastro/forms\n </p>\n </body>\n </html>\n `;\n}\n\nexport async function executeEmailAction(\n action: EmailSubmitAction,\n values: Record<string, unknown>,\n): Promise<unknown> {\n const {\n provider,\n endpoint,\n apiKey,\n to,\n cc,\n bcc,\n from,\n subject,\n template,\n customTemplate,\n replyTo,\n } = action;\n\n const recipients = Array.isArray(to) ? to : [to];\n const emailSubject = replacePlaceholders(subject, values);\n const emailBody =\n template === 'custom' && customTemplate\n ? replacePlaceholders(customTemplate, values)\n : generateDefaultEmailTemplate(values);\n\n // Construir payload según el proveedor\n const payload: Record<string, unknown> = {\n to: recipients,\n subject: emailSubject,\n html: emailBody,\n };\n\n if (cc) payload.cc = cc;\n if (bcc) payload.bcc = bcc;\n if (from) payload.from = from;\n if (replyTo) payload.replyTo = replyTo;\n\n // Determinar endpoint y headers según proveedor\n let url: string;\n const headers: Record<string, string> = {\n 'Content-Type': 'application/json',\n };\n\n switch (provider) {\n case 'sendgrid':\n url = endpoint || 'https://api.sendgrid.com/v3/mail/send';\n if (apiKey) headers['Authorization'] = `Bearer ${apiKey}`;\n // SendGrid tiene formato específico\n payload.personalizations = [{ to: recipients.map((email) => ({ email })) }];\n payload.content = [{ type: 'text/html', value: emailBody }];\n delete payload.to;\n delete payload.html;\n break;\n\n case 'resend':\n url = endpoint || 'https://api.resend.com/emails';\n if (apiKey) headers['Authorization'] = `Bearer ${apiKey}`;\n break;\n\n case 'mailgun':\n url = endpoint || 'https://api.mailgun.net/v3/YOUR_DOMAIN/messages';\n if (apiKey) {\n headers['Authorization'] = `Basic ${btoa(`api:${apiKey}`)}`;\n }\n break;\n\n case 'smtp':\n default:\n // Para SMTP, usar endpoint custom\n url = endpoint || '/api/send-email';\n break;\n }\n\n const response = await fetch(url, {\n method: 'POST',\n headers,\n body: JSON.stringify(payload),\n });\n\n if (!response.ok) {\n const errorText = await response.text().catch(() => 'Unknown error');\n throw new Error(`Email failed: ${response.status} - ${errorText}`);\n }\n\n return response.json().catch(() => ({ success: true }));\n}\n\n// ───────────────────────────────────────────────────────────────\n// Ejecutor Custom\n// ───────────────────────────────────────────────────────────────\n\nexport async function executeCustomAction(\n action: CustomSubmitAction,\n values: Record<string, unknown>,\n): Promise<unknown> {\n return action.handler(values);\n}\n\n// ───────────────────────────────────────────────────────────────\n// Ejecutor Principal (dispatcher)\n// ───────────────────────────────────────────────────────────────\n\nexport async function executeSubmitAction(\n action: SubmitAction,\n values: Record<string, unknown>,\n): Promise<unknown> {\n switch (action.type) {\n case 'http':\n return executeHttpAction(action, values);\n\n case 'webhook':\n return executeWebhookAction(action, values);\n\n case 'email':\n return executeEmailAction(action, values);\n\n case 'custom':\n return executeCustomAction(action, values);\n\n default:\n throw new Error(`Unknown action type: ${(action as SubmitAction).type}`);\n }\n}\n","/**\n * Field Mapping Utility\n *\n * Transforms form values before sending to an API endpoint.\n * Supports field renaming, value transforms, computed field injection,\n * field exclusion, and passthrough control.\n *\n * Two formats:\n * 1. Simple: Record<string, string> — rename fields only (backward compatible)\n * 2. Advanced: FieldMapping — rename, transform, inject, exclude\n */\n\nimport type {\n BuiltinTransform,\n FieldMapEntry,\n FieldMapping,\n FieldMappingConfig,\n FieldResolver,\n FieldTransformFn,\n} from '../types/submitActions';\n\n// ───────────────────────────────────────────────────────────────\n// Type Guards\n// ───────────────────────────────────────────────────────────────\n\n/**\n * Checks whether a mapping config is the advanced FieldMapping format\n * (vs the simple Record<string, string> format).\n */\nexport function isAdvancedMapping(mapping: FieldMappingConfig): mapping is FieldMapping {\n if (typeof mapping !== 'object' || mapping === null) return false;\n return (\n 'fields' in mapping || 'inject' in mapping || 'exclude' in mapping || 'passthrough' in mapping\n );\n}\n\nfunction isFieldMapEntry(entry: string | FieldMapEntry): entry is FieldMapEntry {\n return typeof entry === 'object' && 'to' in entry;\n}\n\nfunction isResolver(value: unknown): value is FieldResolver {\n return typeof value === 'object' && value !== null && '$resolver' in value;\n}\n\n// ───────────────────────────────────────────────────────────────\n// Built-in Transforms\n// ───────────────────────────────────────────────────────────────\n\nfunction formatDateYMD(d: Date): string {\n return `${d.getFullYear()}-${String(d.getMonth() + 1).padStart(2, '0')}-${String(d.getDate()).padStart(2, '0')}`;\n}\n\nfunction formatDateDMY(d: Date): string {\n return `${String(d.getDate()).padStart(2, '0')}/${String(d.getMonth() + 1).padStart(2, '0')}/${d.getFullYear()}`;\n}\n\nfunction toDate(value: unknown): Date {\n if (value instanceof Date) return value;\n return new Date(String(value));\n}\n\n/** Applies a built-in transform to a value. */\nexport function applyBuiltinTransform(value: unknown, transform: BuiltinTransform): unknown {\n switch (transform) {\n case 'toString':\n return value == null ? '' : String(value);\n case 'toNumber':\n return Number(value);\n case 'toBoolean':\n return Boolean(value);\n case 'booleanString':\n return value ? 'true' : 'false';\n case 'dateISO':\n return toDate(value).toISOString();\n case 'dateYMD':\n return formatDateYMD(toDate(value));\n case 'dateDMY':\n return formatDateDMY(toDate(value));\n case 'dateTimestamp':\n return toDate(value).getTime();\n case 'trim':\n return typeof value === 'string' ? value.trim() : value;\n case 'lowercase':\n return typeof value === 'string' ? value.toLowerCase() : value;\n case 'uppercase':\n return typeof value === 'string' ? value.toUpperCase() : value;\n case 'emptyToNull':\n return value === '' || value === undefined ? null : value;\n default:\n return value;\n }\n}\n\n/** Applies a transform (built-in or custom function) to a value. */\nexport function applyTransform(\n value: unknown,\n transform: BuiltinTransform | FieldTransformFn,\n): unknown {\n if (typeof transform === 'function') {\n return transform(value);\n }\n return applyBuiltinTransform(value, transform);\n}\n\n// ───────────────────────────────────────────────────────────────\n// Resolver Execution\n// ───────────────────────────────────────────────────────────────\n\n/** Resolves a dynamic field value from a FieldResolver (async — supports IP fetch). */\nexport async function resolveValue(resolver: FieldResolver): Promise<unknown> {\n switch (resolver.$resolver) {\n case 'timestamp':\n return new Date().toISOString();\n case 'hostname':\n return typeof window !== 'undefined' ? window.location.hostname : '';\n case 'pageUrl':\n return typeof window !== 'undefined' ? window.location.href : '';\n case 'referrer':\n return typeof document !== 'undefined' ? document.referrer : '';\n case 'userAgent':\n return typeof navigator !== 'undefined' ? navigator.userAgent : '';\n case 'urlParam': {\n if (typeof window === 'undefined') return resolver.fallback ?? '';\n const params = new URLSearchParams(window.location.search);\n return params.get(resolver.param) ?? resolver.fallback ?? '';\n }\n case 'ip': {\n const endpoint = resolver.endpoint || 'https://api.ipify.org?format=json';\n try {\n const res = await fetch(endpoint);\n const data = await res.json();\n return data.ip ?? resolver.fallback ?? '';\n } catch {\n return resolver.fallback ?? '';\n }\n }\n case 'custom':\n return resolver.fn();\n default:\n return undefined;\n }\n}\n\n/**\n * Synchronous resolver — returns instant values for sync resolvers,\n * placeholders for async ones (ip, custom). Used by debug panel dry-runs.\n */\nexport function resolveValueSync(resolver: FieldResolver): unknown {\n switch (resolver.$resolver) {\n case 'timestamp':\n return new Date().toISOString();\n case 'hostname':\n return typeof window !== 'undefined' ? window.location.hostname : '';\n case 'pageUrl':\n return typeof window !== 'undefined' ? window.location.href : '';\n case 'referrer':\n return typeof document !== 'undefined' ? document.referrer : '';\n case 'userAgent':\n return typeof navigator !== 'undefined' ? navigator.userAgent : '';\n case 'urlParam': {\n if (typeof window === 'undefined') return resolver.fallback ?? '';\n const params = new URLSearchParams(window.location.search);\n return params.get(resolver.param) ?? resolver.fallback ?? '';\n }\n case 'ip':\n return resolver.fallback ?? '[fetching IP...]';\n case 'custom':\n return '[custom resolver]';\n default:\n return undefined;\n }\n}\n\n// ───────────────────────────────────────────────────────────────\n// Main: applyFieldMapping\n// ───────────────────────────────────────────────────────────────\n\n/**\n * Applies field mapping configuration to form values.\n *\n * Supports two formats:\n * 1. Simple: `Record<string, string>` — rename fields, unmapped pass through\n * 2. Advanced: `FieldMapping` — rename, transform, inject, exclude, passthrough control\n *\n * @param values - Raw form values\n * @param mapping - Field mapping configuration\n * @returns Transformed values ready for the API\n *\n * @example\n * ```ts\n * // Simple rename\n * applyFieldMapping({ nombre: \"Ana\" }, { nombre: \"first_name\" });\n * // → { first_name: \"Ana\" }\n *\n * // Advanced: transform + inject\n * applyFieldMapping({ fecha: new Date(\"2000-01-15\"), acepta: true }, {\n * fields: {\n * fecha: { to: \"birth_date\", transform: \"dateYMD\" },\n * acepta: { to: \"accepts\", transform: \"booleanString\" },\n * },\n * inject: {\n * campaign: \"10653\",\n * timestamp: { $resolver: \"timestamp\" },\n * },\n * });\n * // → { birth_date: \"2000-01-15\", accepts: \"true\", campaign: \"10653\", timestamp: \"2026-...\" }\n * ```\n */\nexport async function applyFieldMapping(\n values: Record<string, unknown>,\n mapping: FieldMappingConfig,\n): Promise<Record<string, unknown>> {\n // ── Simple format: Record<string, string> (backward compatible) ──\n if (!isAdvancedMapping(mapping)) {\n const result: Record<string, unknown> = {};\n for (const [key, value] of Object.entries(values)) {\n const mappedKey = mapping[key] || key;\n result[mappedKey] = value;\n }\n return result;\n }\n\n // ── Advanced format: FieldMapping ──\n const { fields, inject, exclude, passthrough = true } = mapping;\n const excludeSet = new Set(exclude || []);\n const mappedKeys = new Set<string>();\n const result: Record<string, unknown> = {};\n\n // 1. Apply field mappings (rename + transform)\n if (fields) {\n for (const [formKey, target] of Object.entries(fields)) {\n mappedKeys.add(formKey);\n if (excludeSet.has(formKey)) continue;\n\n const rawValue = values[formKey];\n\n if (isFieldMapEntry(target)) {\n result[target.to] = target.transform\n ? applyTransform(rawValue, target.transform)\n : rawValue;\n } else {\n // Simple rename (string)\n result[target] = rawValue;\n }\n }\n }\n\n // 2. Passthrough unmapped fields (default: true)\n if (passthrough) {\n for (const [key, value] of Object.entries(values)) {\n if (!mappedKeys.has(key) && !excludeSet.has(key)) {\n result[key] = value;\n }\n }\n }\n\n // 3. Inject computed/static fields (resolve in parallel)\n if (inject) {\n const entries = Object.entries(inject);\n const resolverEntries = entries.filter(([, v]) => isResolver(v));\n const staticEntries = entries.filter(([, v]) => !isResolver(v));\n\n // Static values first\n for (const [key, value] of staticEntries) {\n result[key] = value;\n }\n\n // Resolve dynamic values in parallel\n if (resolverEntries.length > 0) {\n const resolved = await Promise.all(\n resolverEntries.map(async ([key, value]) => ({\n key,\n value: await resolveValue(value as FieldResolver),\n })),\n );\n for (const { key, value } of resolved) {\n result[key] = value;\n }\n }\n }\n\n return result;\n}\n\n/**\n * Synchronous version of applyFieldMapping — uses resolveValueSync for inject resolvers.\n * Suitable for debug panel dry-runs where async is not practical.\n */\nexport function applyFieldMappingSync(\n values: Record<string, unknown>,\n mapping: FieldMappingConfig,\n): Record<string, unknown> {\n // Simple format\n if (!isAdvancedMapping(mapping)) {\n const result: Record<string, unknown> = {};\n for (const [key, value] of Object.entries(values)) {\n const mappedKey = mapping[key] || key;\n result[mappedKey] = value;\n }\n return result;\n }\n\n const { fields, inject, exclude, passthrough = true } = mapping;\n const excludeSet = new Set(exclude || []);\n const mappedKeys = new Set<string>();\n const result: Record<string, unknown> = {};\n\n if (fields) {\n for (const [formKey, target] of Object.entries(fields)) {\n mappedKeys.add(formKey);\n if (excludeSet.has(formKey)) continue;\n const rawValue = values[formKey];\n if (isFieldMapEntry(target)) {\n result[target.to] = target.transform\n ? applyTransform(rawValue, target.transform)\n : rawValue;\n } else {\n result[target] = rawValue;\n }\n }\n }\n\n if (passthrough) {\n for (const [key, value] of Object.entries(values)) {\n if (!mappedKeys.has(key) && !excludeSet.has(key)) {\n result[key] = value;\n }\n }\n }\n\n if (inject) {\n for (const [key, value] of Object.entries(inject)) {\n if (isResolver(value)) {\n result[key] = resolveValueSync(value);\n } else {\n result[key] = value;\n }\n }\n }\n\n return result;\n}\n\n// ───────────────────────────────────────────────────────────────\n// Field-Level Transforms\n// ───────────────────────────────────────────────────────────────\n\n/**\n * Applies field-level transforms to form values.\n * Iterates over all fields in the config and applies their `transform` property.\n * Returns a new object with transformed values (does not mutate input).\n *\n * @param fields - Form field configurations (from config.fields)\n * @param values - Raw form values from react-hook-form\n * @returns New object with field-level transforms applied\n */\nexport function applyFieldTransforms(\n // eslint-disable-next-line @typescript-eslint/no-explicit-any\n fields: Record<string, any>,\n values: Record<string, unknown>,\n): Record<string, unknown> {\n const result = { ...values };\n\n for (const [fieldName, fieldConfig] of Object.entries(fields)) {\n const transform = fieldConfig?.transform as\n | BuiltinTransform\n | BuiltinTransform[]\n | FieldTransformFn\n | undefined;\n\n if (!transform || !(fieldName in result)) continue;\n\n if (typeof transform === 'function') {\n result[fieldName] = transform(result[fieldName]);\n } else if (Array.isArray(transform)) {\n // Chain built-in transforms left to right\n result[fieldName] = transform.reduce(\n (v, t) => applyBuiltinTransform(v, t),\n result[fieldName],\n );\n } else {\n // Single built-in transform\n result[fieldName] = applyBuiltinTransform(result[fieldName], transform);\n }\n }\n\n return result;\n}\n","/**\n * Submit Orchestrator\n *\n * Orquesta la ejecución de múltiples submit actions,\n * manejando ejecución secuencial o paralela, condiciones, y errores.\n */\n\nimport type { FormConfig } from '../types/common';\nimport type { ConditionOperator } from '../types/logic';\nimport type {\n SubmitActionNode,\n SubmitActionCondition,\n SubmitActionResult,\n SubmitActionsResult,\n SubmitTriggerType,\n} from '../types/submitActions';\nimport { executeSubmitAction } from './submitActionExecutors';\nimport { applyFieldMapping } from './fieldMapping';\n\n// ───────────────────────────────────────────────────────────────\n// Evaluador de condiciones\n// ───────────────────────────────────────────────────────────────\n\nfunction evaluateCondition(\n condition: SubmitActionCondition,\n values: Record<string, unknown>,\n): boolean {\n const fieldValue = values[condition.field];\n const compareValue = condition.value;\n\n const operators: Record<ConditionOperator, (a: unknown, b: unknown) => boolean> = {\n equals: (a, b) => a === b,\n notEquals: (a, b) => a !== b,\n contains: (a, b) => typeof a === 'string' && typeof b === 'string' && a.includes(b),\n notContains: (a, b) => typeof a === 'string' && typeof b === 'string' && !a.includes(b),\n greaterThan: (a, b) => Number(a) > Number(b),\n lessThan: (a, b) => Number(a) < Number(b),\n greaterThanOrEqual: (a, b) => Number(a) >= Number(b),\n lessThanOrEqual: (a, b) => Number(a) <= Number(b),\n isTrue: (a) => a === true || a === 'true' || a === 1,\n isFalse: (a) => a === false || a === 'false' || a === 0,\n isEmpty: (a) =>\n a === undefined || a === null || a === '' || (Array.isArray(a) && a.length === 0),\n isNotEmpty: (a) =>\n a !== undefined && a !== null && a !== '' && !(Array.isArray(a) && a.length === 0),\n };\n\n const evaluator = operators[condition.operator];\n return evaluator ? evaluator(fieldValue, compareValue) : true;\n}\n\n// ───────────────────────────────────────────────────────────────\n// Filtrado de acciones por trigger\n// ───────────────────────────────────────────────────────────────\n\nexport function getActionsByTrigger(\n config: FormConfig,\n triggerType: SubmitTriggerType,\n triggerValue?: string, // stepId o fieldName según el tipo\n): SubmitActionNode[] {\n const actions = config.submitActions;\n if (!actions) return [];\n\n return Object.values(actions).filter((node) => {\n if (node.disabled) return false;\n if (node.trigger.type !== triggerType) return false;\n\n // Verificar valor específico del trigger\n switch (triggerType) {\n case 'onStepEnter':\n case 'onStepExit':\n return !node.trigger.stepId || node.trigger.stepId === triggerValue;\n\n case 'onFieldChange':\n case 'onFieldBlur':\n return !node.trigger.fieldName || node.trigger.fieldName === triggerValue;\n\n default:\n return true;\n }\n });\n}\n\n/**\n * Obtiene el delay mínimo para acciones con trigger onDelay\n */\nexport function getMinDelayMs(config: FormConfig): number {\n const actions = config.submitActions;\n if (!actions) return 0;\n\n const delayActions = Object.values(actions).filter(\n (node) => !node.disabled && node.trigger.type === 'onDelay',\n );\n\n if (delayActions.length === 0) return 0;\n\n return Math.min(...delayActions.map((node) => node.trigger.delayMs || 30000));\n}\n\n// ───────────────────────────────────────────────────────────────\n// Ejecución de una acción individual\n// ───────────────────────────────────────────────────────────────\n\nasync function executeActionNode(\n node: SubmitActionNode,\n values: Record<string, unknown>,\n): Promise<SubmitActionResult> {\n const startedAt = new Date();\n\n // Verificar condición (conditions evaluate against original field names)\n if (node.condition && !evaluateCondition(node.condition, values)) {\n return {\n actionId: node.id,\n actionName: node.action.name,\n success: true,\n data: { skipped: true, reason: 'Condition not met' },\n durationMs: 0,\n startedAt,\n completedAt: new Date(),\n };\n }\n\n // Apply field mapping before executing\n const mappedValues = node.fieldMapping\n ? await applyFieldMapping(values, node.fieldMapping)\n : values;\n\n try {\n const data = await executeSubmitAction(node.action, mappedValues);\n const completedAt = new Date();\n\n return {\n actionId: node.id,\n actionName: node.action.name,\n success: true,\n data,\n durationMs: completedAt.getTime() - startedAt.getTime(),\n startedAt,\n completedAt,\n };\n } catch (err) {\n const completedAt = new Date();\n const error = err instanceof Error ? err : new Error(String(err));\n\n return {\n actionId: node.id,\n actionName: node.action.name,\n success: false,\n error,\n durationMs: completedAt.getTime() - startedAt.getTime(),\n startedAt,\n completedAt,\n };\n }\n}\n\n// ───────────────────────────────────────────────────────────────\n// Orquestador principal\n// ───────────────────────────────────────────────────────────────\n\n/**\n * Ejecuta múltiples acciones de submit según la configuración\n */\nexport async function executeSubmitActions(\n actions: SubmitActionNode[],\n values: Record<string, unknown>,\n config: FormConfig,\n): Promise<SubmitActionsResult> {\n const startTime = Date.now();\n const mode = config.submitExecution?.mode || 'sequential';\n const stopOnFirstError = config.submitExecution?.stopOnFirstError ?? false;\n\n // Ordenar por prioridad (order)\n const sortedActions = [...actions].sort((a, b) => (a.order || 0) - (b.order || 0));\n\n const results: SubmitActionResult[] = [];\n\n if (mode === 'parallel') {\n // Ejecución paralela\n const promises = sortedActions.map((node) => executeActionNode(node, values));\n const parallelResults = await Promise.all(promises);\n results.push(...parallelResults);\n } else {\n // Ejecución secuencial\n for (const node of sortedActions) {\n const result = await executeActionNode(node, values);\n results.push(result);\n\n // Si falló y stopOnFirstError está activo, detener\n if (!result.success && stopOnFirstError && !node.continueOnError) {\n break;\n }\n }\n }\n\n const successCount = results.filter((r) => r.success).length;\n const failureCount = results.filter((r) => !r.success).length;\n\n return {\n results,\n allSuccessful: failureCount === 0,\n successCount,\n failureCount,\n totalDurationMs: Date.now() - startTime,\n };\n}\n\n/**\n * Ejecuta todas las acciones de submit del formulario filtradas por trigger\n */\nexport async function executeSubmitActionsByTrigger(\n config: FormConfig,\n triggerType: SubmitTriggerType,\n values: Record<string, unknown>,\n triggerValue?: string,\n): Promise<SubmitActionsResult> {\n const actions = getActionsByTrigger(config, triggerType, triggerValue);\n\n if (actions.length === 0) {\n return {\n results: [],\n allSuccessful: true,\n successCount: 0,\n failureCount: 0,\n totalDurationMs: 0,\n };\n }\n\n return executeSubmitActions(actions, values, config);\n}\n"],"mappings":"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","names":["result"]}