import { html } from '@design.estate/dees-element'; import * as appstate from '../../appstate.js'; import * as interfaces from '../../../dist_ts_interfaces/index.js'; export const letsEncryptHttp01ManagedRouteKind = 'letsencrypt-http01-forward' as const; export function getSpecialForwardDomains( route: interfaces.data.IMergedRoute, ): string[] { const domains = route.route.match.domains; if (!domains) return []; return Array.isArray(domains) ? domains : [domains]; } export function getSpecialForwardTarget( route: interfaces.data.IMergedRoute, ): { host: string; port: number } | undefined { const target = route.route.action.targets?.[0]; if (!target || typeof target.port !== 'number') return undefined; const host = typeof target.host === 'string' ? target.host : Array.isArray(target.host) ? target.host[0] : undefined; return host ? { host, port: target.port } : undefined; } function getDropdownKey(value: unknown): string { return typeof value === 'string' ? value : value && typeof value === 'object' && 'key' in value ? String((value as { key: unknown }).key) : ''; } export async function showLetsEncryptHttp01ForwardDialog(options: { existing?: interfaces.data.IMergedRoute; targets: interfaces.data.INetworkTarget[]; }): Promise { const { DeesModal } = await import('@design.estate/dees-catalog'); const { existing, targets } = options; const target = existing ? getSpecialForwardTarget(existing) : undefined; const targetOptions = [ { key: '', option: '(none — inline target)' }, ...targets.map((networkTarget) => ({ key: networkTarget.id, option: `${networkTarget.name} (${ Array.isArray(networkTarget.host) ? networkTarget.host.join(', ') : networkTarget.host }:${networkTarget.port})`, })), ]; const selectedTarget = targetOptions.find((option) => { return option.key === (existing?.metadata?.networkTargetRef || ''); }) || targetOptions[0]; await DeesModal.createAndShow({ heading: existing ? `Edit User HTTP-01 Forward: ${existing.route.name || existing.id}` : 'Add User Let\'s Encrypt HTTP-01 Forward', content: html` `, menuOptions: [ { name: 'Cancel', iconName: 'lucide:x', action: async (modalArg: any) => modalArg.destroy(), }, { name: existing ? 'Save' : 'Create', iconName: existing ? 'lucide:check' : 'lucide:plus', action: async (modalArg: any) => { const form = modalArg.shadowRoot?.querySelector('.content')?.querySelector('dees-form'); if (!form) return; const data = await form.collectFormData(); const name = String(data.name || '').trim(); const domains = Array.isArray(data.domains) ? data.domains.map((domain: unknown) => String(domain).trim()).filter(Boolean) : []; const networkTargetRef = getDropdownKey(data.networkTargetRef).trim(); const targetHost = String(data.targetHost || '').trim(); const targetPort = Number.parseInt(String(data.targetPort || ''), 10); if (!name || domains.length === 0) { alert('Name and at least one domain are required.'); return; } if ( !networkTargetRef && (!targetHost || !Number.isInteger(targetPort) || targetPort < 1 || targetPort > 65535) ) { alert('A valid inline target host and port are required.'); return; } const edgeFilter = Array.isArray(data.remoteIngressEdgeFilter) ? data.remoteIngressEdgeFilter.map((entry: unknown) => String(entry).trim()).filter(Boolean) : []; const config: interfaces.data.ILetsEncryptHttp01ForwardConfig = { name, domains, ...(networkTargetRef ? { networkTargetRef } : { target: { host: targetHost, port: targetPort } }), ...(data.remoteIngressEnabled ? { remoteIngress: { enabled: true, ...(edgeFilter.length ? { edgeFilter } : {}), }, } : {}), }; if (existing) { await appstate.routeManagementStatePart.dispatchAction( appstate.updateLetsEncryptHttp01ForwardAction, { id: existing.id, config, enabled: existing.enabled }, ); } else { await appstate.routeManagementStatePart.dispatchAction( appstate.createLetsEncryptHttp01ForwardAction, { config }, ); } await modalArg.destroy(); }, }, ], }); }