ci: add GitHub Pages deployment workflow for docs site Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
336 lines
12 KiB
TypeScript
336 lines
12 KiB
TypeScript
/**
|
|
* Simple Configuration Interface - Declarative Category Schema
|
|
*
|
|
* Maps 7 simplified configuration categories to RouterOS paths,
|
|
* field definitions, and friendly labels. Consumed by all Simple
|
|
* mode category panels and the category sidebar.
|
|
*/
|
|
|
|
import type { LucideIcon } from 'lucide-react'
|
|
import {
|
|
Globe,
|
|
Network,
|
|
Wifi,
|
|
ArrowLeftRight,
|
|
Shield,
|
|
Server,
|
|
Settings,
|
|
} from 'lucide-react'
|
|
|
|
// ---------------------------------------------------------------------------
|
|
// Types
|
|
// ---------------------------------------------------------------------------
|
|
|
|
export interface SimpleCategory {
|
|
id: string
|
|
label: string
|
|
icon: LucideIcon
|
|
description: string
|
|
sections: SimpleCategorySection[]
|
|
}
|
|
|
|
export interface SimpleCategorySection {
|
|
label: string
|
|
routerosPath: string
|
|
isSingleton: boolean
|
|
fields: SimpleFieldDef[]
|
|
}
|
|
|
|
export interface SimpleFieldDef {
|
|
key: string
|
|
label: string
|
|
type: 'text' | 'ip' | 'cidr' | 'number' | 'boolean' | 'select' | 'password'
|
|
help?: string
|
|
placeholder?: string
|
|
required?: boolean
|
|
options?: { value: string; label: string }[]
|
|
validation?: (value: string) => string | null
|
|
minVersion?: number
|
|
}
|
|
|
|
// ---------------------------------------------------------------------------
|
|
// Validators
|
|
// ---------------------------------------------------------------------------
|
|
|
|
const IPV4_REGEX = /^(\d{1,3}\.){3}\d{1,3}$/
|
|
const IPV6_REGEX = /^([0-9a-fA-F]{0,4}:){2,7}[0-9a-fA-F]{0,4}$/
|
|
|
|
export function isValidIp(value: string): boolean {
|
|
if (!value) return false
|
|
if (IPV4_REGEX.test(value)) {
|
|
return value.split('.').every((octet) => {
|
|
const n = parseInt(octet, 10)
|
|
return n >= 0 && n <= 255
|
|
})
|
|
}
|
|
return IPV6_REGEX.test(value)
|
|
}
|
|
|
|
export function isValidCidr(value: string): boolean {
|
|
if (!value) return false
|
|
const parts = value.split('/')
|
|
if (parts.length !== 2) return false
|
|
const [ip, prefix] = parts
|
|
if (!isValidIp(ip)) return false
|
|
const prefixNum = parseInt(prefix, 10)
|
|
if (isNaN(prefixNum)) return false
|
|
// IPv4: 0-32, IPv6: 0-128
|
|
const maxPrefix = ip.includes(':') ? 128 : 32
|
|
return prefixNum >= 0 && prefixNum <= maxPrefix
|
|
}
|
|
|
|
export function isValidPort(value: string): boolean {
|
|
const n = parseInt(value, 10)
|
|
return !isNaN(n) && n >= 1 && n <= 65535
|
|
}
|
|
|
|
// ---------------------------------------------------------------------------
|
|
// Category Definitions
|
|
// ---------------------------------------------------------------------------
|
|
|
|
export const SIMPLE_CATEGORIES: SimpleCategory[] = [
|
|
{
|
|
id: 'internet',
|
|
label: 'Internet Setup',
|
|
icon: Globe,
|
|
description: 'Configure how this router connects to the internet',
|
|
sections: [
|
|
{
|
|
label: 'DHCP Client',
|
|
routerosPath: '/ip/dhcp-client',
|
|
isSingleton: false,
|
|
fields: [
|
|
{ key: 'interface', label: 'WAN Interface', type: 'select', required: true },
|
|
{ key: 'use-peer-dns', label: 'Use ISP DNS', type: 'boolean', help: 'Accept DNS servers from your ISP' },
|
|
{ key: 'use-peer-ntp', label: 'Use ISP NTP', type: 'boolean', help: 'Accept time servers from your ISP' },
|
|
{ key: 'add-default-route', label: 'Add Default Route', type: 'boolean', help: 'Automatically create a default route via this connection' },
|
|
],
|
|
},
|
|
{
|
|
label: 'PPPoE Client',
|
|
routerosPath: '/interface/pppoe-client',
|
|
isSingleton: false,
|
|
fields: [
|
|
{ key: 'interface', label: 'Interface', type: 'select', required: true },
|
|
{ key: 'user', label: 'PPPoE Username', type: 'text', required: true, placeholder: 'ISP username' },
|
|
{ key: 'password', label: 'PPPoE Password', type: 'password', required: true },
|
|
{ key: 'service-name', label: 'Service Name', type: 'text', placeholder: 'Optional' },
|
|
{ key: 'use-peer-dns', label: 'Use ISP DNS', type: 'boolean' },
|
|
],
|
|
},
|
|
{
|
|
label: 'Static IP',
|
|
routerosPath: '/ip/address',
|
|
isSingleton: false,
|
|
fields: [
|
|
{ key: 'address', label: 'IP Address / Mask', type: 'cidr', required: true, placeholder: '192.168.1.100/24' },
|
|
{ key: 'interface', label: 'WAN Interface', type: 'select', required: true },
|
|
],
|
|
},
|
|
],
|
|
},
|
|
{
|
|
id: 'lan',
|
|
label: 'LAN & DHCP',
|
|
icon: Network,
|
|
description: 'Local network addresses, DHCP server, and IP pools',
|
|
sections: [
|
|
{
|
|
label: 'LAN Address',
|
|
routerosPath: '/ip/address',
|
|
isSingleton: false,
|
|
fields: [
|
|
{ key: 'address', label: 'IP Address / Mask', type: 'cidr', required: true, placeholder: '192.168.88.1/24', help: 'The IP address of this router on the local network' },
|
|
{ key: 'interface', label: 'Interface', type: 'text' },
|
|
],
|
|
},
|
|
{
|
|
label: 'DHCP Server',
|
|
routerosPath: '/ip/dhcp-server',
|
|
isSingleton: false,
|
|
fields: [
|
|
{ key: 'disabled', label: 'Enabled', type: 'boolean', help: 'Enable or disable the DHCP server' },
|
|
{ key: 'address-pool', label: 'Address Pool', type: 'text' },
|
|
],
|
|
},
|
|
{
|
|
label: 'DHCP Network',
|
|
routerosPath: '/ip/dhcp-server/network',
|
|
isSingleton: false,
|
|
fields: [
|
|
{ key: 'gateway', label: 'Gateway', type: 'ip', placeholder: '192.168.88.1' },
|
|
{ key: 'dns-server', label: 'DNS Servers', type: 'text', placeholder: '192.168.88.1', help: 'DNS servers provided to DHCP clients' },
|
|
{ key: 'lease-time', label: 'Lease Time', type: 'text', placeholder: '10m', help: 'How long a DHCP lease is valid' },
|
|
],
|
|
},
|
|
{
|
|
label: 'Address Pool',
|
|
routerosPath: '/ip/pool',
|
|
isSingleton: false,
|
|
fields: [
|
|
{ key: 'ranges', label: 'IP Range', type: 'text', placeholder: '192.168.88.10-192.168.88.254', help: 'Range of IP addresses for DHCP clients' },
|
|
],
|
|
},
|
|
],
|
|
},
|
|
{
|
|
id: 'wifi',
|
|
label: 'WiFi',
|
|
icon: Wifi,
|
|
description: 'Wireless network names, passwords, and bands',
|
|
sections: [
|
|
{
|
|
label: 'Wireless Interface',
|
|
routerosPath: '/interface/wifi',
|
|
isSingleton: false,
|
|
fields: [
|
|
{ key: 'ssid', label: 'Network Name (SSID)', type: 'text', required: true, placeholder: 'MyNetwork' },
|
|
{ key: 'security.passphrase', label: 'Password', type: 'password', required: true, help: 'WPA2/WPA3 passphrase (min 8 characters)' },
|
|
{ key: 'configuration.band', label: 'Band', type: 'select', options: [
|
|
{ value: '2ghz-ax', label: '2.4 GHz' },
|
|
{ value: '5ghz-ax', label: '5 GHz' },
|
|
] },
|
|
{ key: 'disabled', label: 'Enabled', type: 'boolean' },
|
|
],
|
|
},
|
|
],
|
|
},
|
|
{
|
|
id: 'port-forwarding',
|
|
label: 'Port Forwarding',
|
|
icon: ArrowLeftRight,
|
|
description: 'Forward external ports to internal servers',
|
|
sections: [
|
|
{
|
|
label: 'NAT Rules',
|
|
routerosPath: '/ip/firewall/nat',
|
|
isSingleton: false,
|
|
fields: [
|
|
{ key: 'dst-port', label: 'External Port', type: 'number', required: true, placeholder: '80', validation: (v) => isValidPort(v) ? null : 'Port must be 1-65535' },
|
|
{ key: 'protocol', label: 'Protocol', type: 'select', required: true, options: [
|
|
{ value: 'tcp', label: 'TCP' },
|
|
{ value: 'udp', label: 'UDP' },
|
|
{ value: '6', label: 'TCP + UDP' },
|
|
] },
|
|
{ key: 'to-addresses', label: 'Internal IP Address', type: 'ip', required: true, placeholder: '192.168.88.100' },
|
|
{ key: 'to-ports', label: 'Internal Port', type: 'number', required: true, placeholder: '80', help: 'Leave same as external port if unchanged' },
|
|
{ key: 'comment', label: 'Description', type: 'text', placeholder: 'e.g., Web Server' },
|
|
],
|
|
},
|
|
],
|
|
},
|
|
{
|
|
id: 'firewall',
|
|
label: 'Firewall',
|
|
icon: Shield,
|
|
description: 'Basic firewall rules and address lists',
|
|
sections: [
|
|
{
|
|
label: 'Filter Rules',
|
|
routerosPath: '/ip/firewall/filter',
|
|
isSingleton: false,
|
|
fields: [
|
|
{ key: 'chain', label: 'Chain', type: 'select', required: true, options: [
|
|
{ value: 'input', label: 'Input' },
|
|
{ value: 'forward', label: 'Forward' },
|
|
] },
|
|
{ key: 'action', label: 'Action', type: 'select', required: true, options: [
|
|
{ value: 'accept', label: 'Accept' },
|
|
{ value: 'drop', label: 'Drop' },
|
|
{ value: 'reject', label: 'Reject' },
|
|
] },
|
|
{ key: 'protocol', label: 'Protocol', type: 'select', options: [
|
|
{ value: 'tcp', label: 'TCP' },
|
|
{ value: 'udp', label: 'UDP' },
|
|
{ value: 'icmp', label: 'ICMP' },
|
|
] },
|
|
{ key: 'dst-port', label: 'Destination Port', type: 'number', placeholder: '22' },
|
|
{ key: 'src-address', label: 'Source Address', type: 'text', placeholder: '192.168.88.0/24', help: 'Leave blank to match any source' },
|
|
{ key: 'comment', label: 'Comment', type: 'text', placeholder: 'e.g., Allow SSH from LAN' },
|
|
],
|
|
},
|
|
{
|
|
label: 'Address Lists',
|
|
routerosPath: '/ip/firewall/address-list',
|
|
isSingleton: false,
|
|
fields: [
|
|
{ key: 'list', label: 'List Name', type: 'text', required: true },
|
|
{ key: 'address', label: 'Address', type: 'text', required: true, placeholder: '192.168.88.0/24' },
|
|
{ key: 'comment', label: 'Comment', type: 'text' },
|
|
],
|
|
},
|
|
],
|
|
},
|
|
{
|
|
id: 'dns',
|
|
label: 'DNS',
|
|
icon: Server,
|
|
description: 'DNS servers and local name resolution',
|
|
sections: [
|
|
{
|
|
label: 'DNS Settings',
|
|
routerosPath: '/ip/dns',
|
|
isSingleton: true,
|
|
fields: [
|
|
{ key: 'servers', label: 'Upstream Servers', type: 'text', required: true, placeholder: '8.8.8.8,8.8.4.4', help: 'Comma-separated list of DNS server IPs used for name resolution' },
|
|
{ key: 'allow-remote-requests', label: 'Allow Remote Requests', type: 'boolean', help: 'Allow devices on your network to use this router as their DNS server' },
|
|
{ key: 'cache-size', label: 'Cache Size (KiB)', type: 'number', placeholder: '2048', help: 'DNS cache size in KiB' },
|
|
],
|
|
},
|
|
{
|
|
label: 'Static Entries',
|
|
routerosPath: '/ip/dns/static',
|
|
isSingleton: false,
|
|
fields: [
|
|
{ key: 'name', label: 'Name', type: 'text', required: true, placeholder: 'myserver.local' },
|
|
{ key: 'address', label: 'Address', type: 'ip', required: true, placeholder: '192.168.88.100' },
|
|
{ key: 'type', label: 'Type', type: 'select', options: [
|
|
{ value: 'A', label: 'A' },
|
|
{ value: 'AAAA', label: 'AAAA' },
|
|
{ value: 'CNAME', label: 'CNAME' },
|
|
] },
|
|
],
|
|
},
|
|
],
|
|
},
|
|
{
|
|
id: 'system',
|
|
label: 'System',
|
|
icon: Settings,
|
|
description: 'Device identity, time, passwords, and maintenance',
|
|
sections: [
|
|
{
|
|
label: 'Identity',
|
|
routerosPath: '/system/identity',
|
|
isSingleton: true,
|
|
fields: [
|
|
{ key: 'name', label: 'Hostname', type: 'text', required: true, placeholder: 'e.g., Office-Router-1', help: 'A friendly name for this router, visible in the fleet dashboard' },
|
|
],
|
|
},
|
|
{
|
|
label: 'Clock',
|
|
routerosPath: '/system/clock',
|
|
isSingleton: true,
|
|
fields: [
|
|
{ key: 'time-zone-name', label: 'Timezone', type: 'text', placeholder: 'America/New_York', help: 'IANA timezone identifier (e.g., America/New_York, Europe/London)' },
|
|
],
|
|
},
|
|
{
|
|
label: 'NTP Client',
|
|
routerosPath: '/system/ntp/client',
|
|
isSingleton: true,
|
|
fields: [
|
|
{ key: 'enabled', label: 'NTP Enabled', type: 'boolean' },
|
|
{ key: 'server-dns-names', label: 'NTP Servers', type: 'text', placeholder: 'pool.ntp.org', help: 'Comma-separated NTP server hostnames' },
|
|
],
|
|
},
|
|
{
|
|
label: 'System Resource',
|
|
routerosPath: '/system/resource',
|
|
isSingleton: true,
|
|
fields: [],
|
|
},
|
|
],
|
|
},
|
|
]
|