363 lines
9.3 KiB
TypeScript
363 lines
9.3 KiB
TypeScript
import {
|
|
DeesElement,
|
|
customElement,
|
|
html,
|
|
css,
|
|
cssManager,
|
|
state,
|
|
type TemplateResult,
|
|
} from '@design.estate/dees-element';
|
|
import type { DeesAppui } from '@design.estate/dees-catalog';
|
|
import type { IRouteConfig } from './sz-route-card.js';
|
|
import './index.js';
|
|
|
|
declare global {
|
|
interface HTMLElementTagNameMap {
|
|
'sz-demo-view-routes': SzDemoViewRoutes;
|
|
}
|
|
}
|
|
|
|
@customElement('sz-demo-view-routes')
|
|
export class SzDemoViewRoutes extends DeesElement {
|
|
private appui: DeesAppui | null = null;
|
|
|
|
@state()
|
|
private accessor currentTab: 'all' | 'https' | 'email' | 'dns' = 'all';
|
|
|
|
private demoRoutes: IRouteConfig[] = [
|
|
// 1. HTTPS with TLS termination + auto cert
|
|
{
|
|
id: 'route-1',
|
|
name: 'Web Frontend',
|
|
description: 'Main website with TLS termination and automatic certificates',
|
|
enabled: true,
|
|
priority: 10,
|
|
tags: ['web', 'https', 'production'],
|
|
match: {
|
|
ports: 443,
|
|
domains: ['serve.zone', 'www.serve.zone'],
|
|
protocol: 'http',
|
|
},
|
|
action: {
|
|
type: 'forward',
|
|
targets: [{ host: '10.0.0.10', port: 3000 }],
|
|
tls: { mode: 'terminate', certificate: 'auto' },
|
|
},
|
|
},
|
|
// 2. HTTP to HTTPS redirect
|
|
{
|
|
id: 'route-2',
|
|
name: 'HTTP Redirect',
|
|
description: 'Redirects all HTTP traffic to HTTPS',
|
|
enabled: true,
|
|
priority: 100,
|
|
tags: ['web', 'http', 'redirect'],
|
|
match: {
|
|
ports: 80,
|
|
domains: ['serve.zone', 'www.serve.zone'],
|
|
protocol: 'http',
|
|
},
|
|
action: {
|
|
type: 'socket-handler',
|
|
},
|
|
},
|
|
// 3. Email SMTP route
|
|
{
|
|
id: 'route-3',
|
|
name: 'SMTP Inbound',
|
|
description: 'Inbound email relay for serve.zone domain',
|
|
enabled: true,
|
|
tags: ['email', 'smtp', 'production'],
|
|
match: {
|
|
ports: 25,
|
|
domains: 'mail.serve.zone',
|
|
},
|
|
action: {
|
|
type: 'forward',
|
|
targets: [{ host: '10.0.1.5', port: 25 }],
|
|
tls: { mode: 'terminate', certificate: 'auto' },
|
|
},
|
|
},
|
|
// 4. API gateway with path matching, rate limiting, CORS
|
|
{
|
|
id: 'route-4',
|
|
name: 'API Gateway',
|
|
description: 'API gateway with rate limiting, CORS headers, and load balancing',
|
|
enabled: true,
|
|
priority: 20,
|
|
tags: ['web', 'api', 'https', 'production'],
|
|
match: {
|
|
ports: 443,
|
|
domains: 'api.serve.zone',
|
|
path: '/v2/*',
|
|
protocol: 'http',
|
|
},
|
|
action: {
|
|
type: 'forward',
|
|
targets: [
|
|
{ host: ['10.0.0.20', '10.0.0.21', '10.0.0.22'], port: 8080 },
|
|
],
|
|
tls: { mode: 'terminate', certificate: 'auto' },
|
|
loadBalancing: { algorithm: 'round-robin' },
|
|
},
|
|
security: {
|
|
rateLimit: { enabled: true, maxRequests: 200, window: 60 },
|
|
maxConnections: 5000,
|
|
},
|
|
headers: {
|
|
response: {
|
|
'Access-Control-Allow-Origin': '*',
|
|
'X-Request-Id': '{{requestId}}',
|
|
},
|
|
},
|
|
},
|
|
// 5. WebSocket route
|
|
{
|
|
id: 'route-5',
|
|
name: 'WebSocket Realtime',
|
|
description: 'Real-time WebSocket connections for live updates',
|
|
enabled: true,
|
|
tags: ['web', 'https', 'websocket'],
|
|
match: {
|
|
ports: 443,
|
|
domains: 'ws.serve.zone',
|
|
path: '/ws/*',
|
|
protocol: 'http',
|
|
},
|
|
action: {
|
|
type: 'forward',
|
|
targets: [{ host: '10.0.0.30', port: 9090 }],
|
|
tls: { mode: 'terminate', certificate: 'auto' },
|
|
websocket: { enabled: true },
|
|
},
|
|
},
|
|
// 6. Wildcard domain route
|
|
{
|
|
id: 'route-6',
|
|
name: 'Tenant Wildcard',
|
|
description: 'Multi-tenant wildcard routing for customer subdomains',
|
|
enabled: true,
|
|
priority: 50,
|
|
tags: ['web', 'https', 'multi-tenant'],
|
|
match: {
|
|
ports: 443,
|
|
domains: '*.customers.serve.zone',
|
|
protocol: 'http',
|
|
},
|
|
action: {
|
|
type: 'forward',
|
|
targets: [{ host: '10.0.0.40', port: 8080 }],
|
|
tls: { mode: 'terminate', certificate: 'auto' },
|
|
},
|
|
security: {
|
|
ipAllowList: ['10.0.0.0/8', '172.16.0.0/12'],
|
|
},
|
|
},
|
|
// 7. Load-balanced route with health check
|
|
{
|
|
id: 'route-7',
|
|
name: 'Microservices LB',
|
|
description: 'Load-balanced microservices backend with IP-hash affinity',
|
|
enabled: true,
|
|
tags: ['web', 'https', 'production'],
|
|
match: {
|
|
ports: [443, 8443],
|
|
domains: 'services.serve.zone',
|
|
protocol: 'http',
|
|
},
|
|
action: {
|
|
type: 'forward',
|
|
targets: [
|
|
{ host: ['10.0.2.1', '10.0.2.2', '10.0.2.3', '10.0.2.4'], port: 3000 },
|
|
],
|
|
tls: { mode: 'terminate-and-reencrypt', certificate: 'auto' },
|
|
loadBalancing: { algorithm: 'ip-hash' },
|
|
},
|
|
},
|
|
// 8. DNS-over-HTTPS route
|
|
{
|
|
id: 'route-8',
|
|
name: 'DNS over HTTPS',
|
|
description: 'DNS-over-HTTPS resolver endpoint',
|
|
enabled: true,
|
|
tags: ['dns', 'https'],
|
|
match: {
|
|
ports: 443,
|
|
domains: 'dns.serve.zone',
|
|
path: '/dns-query',
|
|
protocol: 'http',
|
|
},
|
|
action: {
|
|
type: 'forward',
|
|
targets: [{ host: '10.0.3.1', port: 8053 }],
|
|
tls: { mode: 'terminate', certificate: 'auto' },
|
|
},
|
|
},
|
|
// 9. NFTables high-performance route
|
|
{
|
|
id: 'route-9',
|
|
name: 'High-Perf TCP Proxy',
|
|
description: 'NFTables-accelerated TCP proxy for game servers',
|
|
enabled: true,
|
|
tags: ['tcp', 'nftables', 'production'],
|
|
match: {
|
|
ports: [{ from: 27000, to: 27050 }],
|
|
protocol: 'tcp',
|
|
},
|
|
action: {
|
|
type: 'forward',
|
|
targets: [{ host: '10.0.4.1', port: 'preserve' }],
|
|
forwardingEngine: 'nftables',
|
|
},
|
|
},
|
|
// 10. Disabled maintenance route
|
|
{
|
|
id: 'route-10',
|
|
name: 'Legacy Admin Panel',
|
|
description: 'Deprecated admin panel — disabled for maintenance',
|
|
enabled: false,
|
|
tags: ['web', 'https', 'deprecated'],
|
|
match: {
|
|
ports: 443,
|
|
domains: 'admin-old.serve.zone',
|
|
protocol: 'http',
|
|
},
|
|
action: {
|
|
type: 'socket-handler',
|
|
},
|
|
security: {
|
|
ipBlockList: ['0.0.0.0/0'],
|
|
},
|
|
},
|
|
];
|
|
|
|
private get filteredRoutes(): IRouteConfig[] {
|
|
if (this.currentTab === 'all') return this.demoRoutes;
|
|
if (this.currentTab === 'https') {
|
|
return this.demoRoutes.filter((r) =>
|
|
r.tags?.some((t) => ['web', 'https', 'http'].includes(t))
|
|
);
|
|
}
|
|
if (this.currentTab === 'email') {
|
|
return this.demoRoutes.filter((r) =>
|
|
r.tags?.some((t) => ['email', 'smtp'].includes(t))
|
|
);
|
|
}
|
|
if (this.currentTab === 'dns') {
|
|
return this.demoRoutes.filter((r) =>
|
|
r.tags?.some((t) => ['dns'].includes(t))
|
|
);
|
|
}
|
|
return this.demoRoutes;
|
|
}
|
|
|
|
async onActivate(context: { appui: DeesAppui; viewId: string }) {
|
|
this.appui = context.appui;
|
|
|
|
this.appui.setContentTabs([
|
|
{
|
|
key: 'All Routes',
|
|
action: () => {
|
|
this.currentTab = 'all';
|
|
this.updateSecondaryMenu();
|
|
},
|
|
},
|
|
{
|
|
key: 'HTTP/S',
|
|
action: () => {
|
|
this.currentTab = 'https';
|
|
this.updateSecondaryMenu();
|
|
},
|
|
},
|
|
{
|
|
key: 'Email',
|
|
action: () => {
|
|
this.currentTab = 'email';
|
|
this.updateSecondaryMenu();
|
|
},
|
|
},
|
|
{
|
|
key: 'DNS',
|
|
action: () => {
|
|
this.currentTab = 'dns';
|
|
this.updateSecondaryMenu();
|
|
},
|
|
},
|
|
]);
|
|
|
|
this.updateSecondaryMenu();
|
|
}
|
|
|
|
private updateSecondaryMenu() {
|
|
if (!this.appui) return;
|
|
|
|
const total = this.demoRoutes.length;
|
|
const active = this.demoRoutes.filter((r) => r.enabled !== false).length;
|
|
const forwardCount = this.demoRoutes.filter((r) => r.action.type === 'forward').length;
|
|
|
|
this.appui.setSecondaryMenu({
|
|
heading: 'Routes',
|
|
groups: [
|
|
{
|
|
name: 'Actions',
|
|
items: [
|
|
{
|
|
type: 'action',
|
|
key: 'Refresh',
|
|
iconName: 'lucide:RefreshCw',
|
|
action: () => {
|
|
console.log('Refresh routes');
|
|
},
|
|
},
|
|
{
|
|
type: 'action',
|
|
key: 'Add Route',
|
|
iconName: 'lucide:Plus',
|
|
action: () => {
|
|
console.log('Add route');
|
|
},
|
|
},
|
|
],
|
|
},
|
|
{
|
|
name: 'Statistics',
|
|
items: [
|
|
{ type: 'header' as const, label: `${total} Total Routes` },
|
|
{ type: 'header' as const, label: `${active} Active` },
|
|
{ type: 'header' as const, label: `${forwardCount} Forward` },
|
|
{ type: 'header' as const, label: `${total - forwardCount} Socket Handler` },
|
|
],
|
|
},
|
|
],
|
|
});
|
|
}
|
|
|
|
onDeactivate() {
|
|
// Cleanup if needed
|
|
}
|
|
|
|
public static styles = [
|
|
cssManager.defaultStyles,
|
|
css`
|
|
:host {
|
|
display: block;
|
|
padding: 24px;
|
|
height: 100%;
|
|
overflow-y: auto;
|
|
box-sizing: border-box;
|
|
}
|
|
`,
|
|
];
|
|
|
|
public render(): TemplateResult {
|
|
return html`
|
|
<sz-route-list-view
|
|
.routes=${this.filteredRoutes}
|
|
@route-click=${(e: CustomEvent<IRouteConfig>) => {
|
|
console.log('Route clicked:', e.detail.name);
|
|
}}
|
|
></sz-route-list-view>
|
|
`;
|
|
}
|
|
}
|