@serve.zone/catalog 2.2.0 → 2.4.0

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,164 @@
1
+ import {
2
+ DeesElement,
3
+ customElement,
4
+ html,
5
+ css,
6
+ cssManager,
7
+ type TemplateResult,
8
+ } from '@design.estate/dees-element';
9
+ import type { IConfigField } from './sz-config-section.js';
10
+ import './index.js';
11
+
12
+ declare global {
13
+ interface HTMLElementTagNameMap {
14
+ 'sz-demo-view-config': SzDemoViewConfig;
15
+ }
16
+ }
17
+
18
+ @customElement('sz-demo-view-config')
19
+ export class SzDemoViewConfig extends DeesElement {
20
+ public static styles = [
21
+ cssManager.defaultStyles,
22
+ css`
23
+ :host {
24
+ display: block;
25
+ padding: 24px;
26
+ height: 100%;
27
+ overflow-y: auto;
28
+ box-sizing: border-box;
29
+ }
30
+ `,
31
+ ];
32
+
33
+ public render(): TemplateResult {
34
+ const systemFields: IConfigField[] = [
35
+ { key: 'Base Directory', value: '/home/user/.serve.zone/dcrouter' },
36
+ { key: 'Data Directory', value: '/home/user/.serve.zone/dcrouter/data' },
37
+ { key: 'Public IP', value: '203.0.113.50' },
38
+ { key: 'Proxy IPs', value: ['203.0.113.10', '203.0.113.11'], type: 'pills' },
39
+ { key: 'Uptime', value: '3d 14h 22m' },
40
+ { key: 'Storage Backend', value: 'filesystem', type: 'badge' },
41
+ ];
42
+
43
+ const proxyFields: IConfigField[] = [
44
+ { key: 'Route Count', value: 12 },
45
+ { key: 'ACME Enabled', value: true, type: 'boolean' },
46
+ { key: 'Account Email', value: 'admin@serve.zone' },
47
+ { key: 'Use Production', value: true, type: 'boolean' },
48
+ { key: 'Auto Renew', value: true, type: 'boolean' },
49
+ { key: 'Renew Threshold', value: '30 days' },
50
+ ];
51
+
52
+ const emailFields: IConfigField[] = [
53
+ { key: 'Ports', value: ['25', '465', '587'], type: 'pills' },
54
+ { key: 'Hostname', value: 'mail.serve.zone' },
55
+ { key: 'Domains', value: ['serve.zone', 'mail.serve.zone'], type: 'pills' },
56
+ { key: 'Email Routes', value: 5 },
57
+ { key: 'Received Path', value: '/data/emails' },
58
+ ];
59
+
60
+ const dnsFields: IConfigField[] = [
61
+ { key: 'Port', value: 53 },
62
+ { key: 'NS Domains', value: ['ns1.serve.zone', 'ns2.serve.zone'], type: 'pills' },
63
+ { key: 'Scopes', value: ['serve.zone', 'example.com'], type: 'pills' },
64
+ { key: 'Record Count', value: 24 },
65
+ { key: 'DNS Challenge', value: true, type: 'boolean' },
66
+ ];
67
+
68
+ const tlsFields: IConfigField[] = [
69
+ { key: 'Contact Email', value: 'admin@serve.zone' },
70
+ { key: 'Domain', value: 'serve.zone' },
71
+ { key: 'Source', value: 'acme', type: 'badge' },
72
+ { key: 'Certificate Path', value: null },
73
+ { key: 'Key Path', value: null },
74
+ ];
75
+
76
+ const cacheFields: IConfigField[] = [
77
+ { key: 'Storage Path', value: '/home/user/.serve.zone/dcrouter/tsmdb' },
78
+ { key: 'DB Name', value: 'dcrouter' },
79
+ { key: 'Default TTL', value: '30 days' },
80
+ { key: 'Cleanup Interval', value: '1 hour' },
81
+ ];
82
+
83
+ const radiusFields: IConfigField[] = [
84
+ { key: 'Auth Port', value: null },
85
+ { key: 'Accounting Port', value: null },
86
+ ];
87
+
88
+ const remoteIngressFields: IConfigField[] = [
89
+ { key: 'Tunnel Port', value: 8443 },
90
+ { key: 'Hub Domain', value: 'hub.serve.zone' },
91
+ { key: 'TLS Configured', value: true, type: 'boolean' },
92
+ ];
93
+
94
+ return html`
95
+ <sz-config-overview
96
+ infoText="This view displays the current running configuration. DcRouter is configured through code or remote management."
97
+ >
98
+ <sz-config-section
99
+ title="System"
100
+ subtitle="Base paths and infrastructure"
101
+ icon="lucide:server"
102
+ status="enabled"
103
+ .fields=${systemFields}
104
+ ></sz-config-section>
105
+
106
+ <sz-config-section
107
+ title="SmartProxy"
108
+ subtitle="HTTP/HTTPS and TCP/SNI reverse proxy"
109
+ icon="lucide:network"
110
+ status="enabled"
111
+ .fields=${proxyFields}
112
+ ></sz-config-section>
113
+
114
+ <sz-config-section
115
+ title="Email Server"
116
+ subtitle="SMTP email handling with smartmta"
117
+ icon="lucide:mail"
118
+ status="enabled"
119
+ .fields=${emailFields}
120
+ ></sz-config-section>
121
+
122
+ <sz-config-section
123
+ title="DNS Server"
124
+ subtitle="Authoritative DNS with smartdns"
125
+ icon="lucide:globe"
126
+ status="enabled"
127
+ .fields=${dnsFields}
128
+ ></sz-config-section>
129
+
130
+ <sz-config-section
131
+ title="TLS / Certificates"
132
+ subtitle="Certificate management and ACME"
133
+ icon="lucide:shield-check"
134
+ status="enabled"
135
+ .fields=${tlsFields}
136
+ ></sz-config-section>
137
+
138
+ <sz-config-section
139
+ title="Cache Database"
140
+ subtitle="Persistent caching with smartdata"
141
+ icon="lucide:database"
142
+ status="enabled"
143
+ .fields=${cacheFields}
144
+ ></sz-config-section>
145
+
146
+ <sz-config-section
147
+ title="RADIUS Server"
148
+ subtitle="Network authentication and VLAN assignment"
149
+ icon="lucide:wifi"
150
+ status="not-configured"
151
+ .fields=${radiusFields}
152
+ ></sz-config-section>
153
+
154
+ <sz-config-section
155
+ title="Remote Ingress"
156
+ subtitle="Edge tunnel nodes"
157
+ icon="lucide:cloud"
158
+ status="enabled"
159
+ .fields=${remoteIngressFields}
160
+ ></sz-config-section>
161
+ </sz-config-overview>
162
+ `;
163
+ }
164
+ }
@@ -0,0 +1,362 @@
1
+ import {
2
+ DeesElement,
3
+ customElement,
4
+ html,
5
+ css,
6
+ cssManager,
7
+ state,
8
+ type TemplateResult,
9
+ } from '@design.estate/dees-element';
10
+ import type { DeesAppui } from '@design.estate/dees-catalog';
11
+ import type { IRouteConfig } from './sz-route-card.js';
12
+ import './index.js';
13
+
14
+ declare global {
15
+ interface HTMLElementTagNameMap {
16
+ 'sz-demo-view-routes': SzDemoViewRoutes;
17
+ }
18
+ }
19
+
20
+ @customElement('sz-demo-view-routes')
21
+ export class SzDemoViewRoutes extends DeesElement {
22
+ private appui: DeesAppui | null = null;
23
+
24
+ @state()
25
+ private accessor currentTab: 'all' | 'https' | 'email' | 'dns' = 'all';
26
+
27
+ private demoRoutes: IRouteConfig[] = [
28
+ // 1. HTTPS with TLS termination + auto cert
29
+ {
30
+ id: 'route-1',
31
+ name: 'Web Frontend',
32
+ description: 'Main website with TLS termination and automatic certificates',
33
+ enabled: true,
34
+ priority: 10,
35
+ tags: ['web', 'https', 'production'],
36
+ match: {
37
+ ports: 443,
38
+ domains: ['serve.zone', 'www.serve.zone'],
39
+ protocol: 'http',
40
+ },
41
+ action: {
42
+ type: 'forward',
43
+ targets: [{ host: '10.0.0.10', port: 3000 }],
44
+ tls: { mode: 'terminate', certificate: 'auto' },
45
+ },
46
+ },
47
+ // 2. HTTP to HTTPS redirect
48
+ {
49
+ id: 'route-2',
50
+ name: 'HTTP Redirect',
51
+ description: 'Redirects all HTTP traffic to HTTPS',
52
+ enabled: true,
53
+ priority: 100,
54
+ tags: ['web', 'http', 'redirect'],
55
+ match: {
56
+ ports: 80,
57
+ domains: ['serve.zone', 'www.serve.zone'],
58
+ protocol: 'http',
59
+ },
60
+ action: {
61
+ type: 'socket-handler',
62
+ },
63
+ },
64
+ // 3. Email SMTP route
65
+ {
66
+ id: 'route-3',
67
+ name: 'SMTP Inbound',
68
+ description: 'Inbound email relay for serve.zone domain',
69
+ enabled: true,
70
+ tags: ['email', 'smtp', 'production'],
71
+ match: {
72
+ ports: 25,
73
+ domains: 'mail.serve.zone',
74
+ },
75
+ action: {
76
+ type: 'forward',
77
+ targets: [{ host: '10.0.1.5', port: 25 }],
78
+ tls: { mode: 'terminate', certificate: 'auto' },
79
+ },
80
+ },
81
+ // 4. API gateway with path matching, rate limiting, CORS
82
+ {
83
+ id: 'route-4',
84
+ name: 'API Gateway',
85
+ description: 'API gateway with rate limiting, CORS headers, and load balancing',
86
+ enabled: true,
87
+ priority: 20,
88
+ tags: ['web', 'api', 'https', 'production'],
89
+ match: {
90
+ ports: 443,
91
+ domains: 'api.serve.zone',
92
+ path: '/v2/*',
93
+ protocol: 'http',
94
+ },
95
+ action: {
96
+ type: 'forward',
97
+ targets: [
98
+ { host: ['10.0.0.20', '10.0.0.21', '10.0.0.22'], port: 8080 },
99
+ ],
100
+ tls: { mode: 'terminate', certificate: 'auto' },
101
+ loadBalancing: { algorithm: 'round-robin' },
102
+ },
103
+ security: {
104
+ rateLimit: { enabled: true, maxRequests: 200, window: 60 },
105
+ maxConnections: 5000,
106
+ },
107
+ headers: {
108
+ response: {
109
+ 'Access-Control-Allow-Origin': '*',
110
+ 'X-Request-Id': '{{requestId}}',
111
+ },
112
+ },
113
+ },
114
+ // 5. WebSocket route
115
+ {
116
+ id: 'route-5',
117
+ name: 'WebSocket Realtime',
118
+ description: 'Real-time WebSocket connections for live updates',
119
+ enabled: true,
120
+ tags: ['web', 'https', 'websocket'],
121
+ match: {
122
+ ports: 443,
123
+ domains: 'ws.serve.zone',
124
+ path: '/ws/*',
125
+ protocol: 'http',
126
+ },
127
+ action: {
128
+ type: 'forward',
129
+ targets: [{ host: '10.0.0.30', port: 9090 }],
130
+ tls: { mode: 'terminate', certificate: 'auto' },
131
+ websocket: { enabled: true },
132
+ },
133
+ },
134
+ // 6. Wildcard domain route
135
+ {
136
+ id: 'route-6',
137
+ name: 'Tenant Wildcard',
138
+ description: 'Multi-tenant wildcard routing for customer subdomains',
139
+ enabled: true,
140
+ priority: 50,
141
+ tags: ['web', 'https', 'multi-tenant'],
142
+ match: {
143
+ ports: 443,
144
+ domains: '*.customers.serve.zone',
145
+ protocol: 'http',
146
+ },
147
+ action: {
148
+ type: 'forward',
149
+ targets: [{ host: '10.0.0.40', port: 8080 }],
150
+ tls: { mode: 'terminate', certificate: 'auto' },
151
+ },
152
+ security: {
153
+ ipAllowList: ['10.0.0.0/8', '172.16.0.0/12'],
154
+ },
155
+ },
156
+ // 7. Load-balanced route with health check
157
+ {
158
+ id: 'route-7',
159
+ name: 'Microservices LB',
160
+ description: 'Load-balanced microservices backend with IP-hash affinity',
161
+ enabled: true,
162
+ tags: ['web', 'https', 'production'],
163
+ match: {
164
+ ports: [443, 8443],
165
+ domains: 'services.serve.zone',
166
+ protocol: 'http',
167
+ },
168
+ action: {
169
+ type: 'forward',
170
+ targets: [
171
+ { host: ['10.0.2.1', '10.0.2.2', '10.0.2.3', '10.0.2.4'], port: 3000 },
172
+ ],
173
+ tls: { mode: 'terminate-and-reencrypt', certificate: 'auto' },
174
+ loadBalancing: { algorithm: 'ip-hash' },
175
+ },
176
+ },
177
+ // 8. DNS-over-HTTPS route
178
+ {
179
+ id: 'route-8',
180
+ name: 'DNS over HTTPS',
181
+ description: 'DNS-over-HTTPS resolver endpoint',
182
+ enabled: true,
183
+ tags: ['dns', 'https'],
184
+ match: {
185
+ ports: 443,
186
+ domains: 'dns.serve.zone',
187
+ path: '/dns-query',
188
+ protocol: 'http',
189
+ },
190
+ action: {
191
+ type: 'forward',
192
+ targets: [{ host: '10.0.3.1', port: 8053 }],
193
+ tls: { mode: 'terminate', certificate: 'auto' },
194
+ },
195
+ },
196
+ // 9. NFTables high-performance route
197
+ {
198
+ id: 'route-9',
199
+ name: 'High-Perf TCP Proxy',
200
+ description: 'NFTables-accelerated TCP proxy for game servers',
201
+ enabled: true,
202
+ tags: ['tcp', 'nftables', 'production'],
203
+ match: {
204
+ ports: [{ from: 27000, to: 27050 }],
205
+ protocol: 'tcp',
206
+ },
207
+ action: {
208
+ type: 'forward',
209
+ targets: [{ host: '10.0.4.1', port: 'preserve' }],
210
+ forwardingEngine: 'nftables',
211
+ },
212
+ },
213
+ // 10. Disabled maintenance route
214
+ {
215
+ id: 'route-10',
216
+ name: 'Legacy Admin Panel',
217
+ description: 'Deprecated admin panel — disabled for maintenance',
218
+ enabled: false,
219
+ tags: ['web', 'https', 'deprecated'],
220
+ match: {
221
+ ports: 443,
222
+ domains: 'admin-old.serve.zone',
223
+ protocol: 'http',
224
+ },
225
+ action: {
226
+ type: 'socket-handler',
227
+ },
228
+ security: {
229
+ ipBlockList: ['0.0.0.0/0'],
230
+ },
231
+ },
232
+ ];
233
+
234
+ private get filteredRoutes(): IRouteConfig[] {
235
+ if (this.currentTab === 'all') return this.demoRoutes;
236
+ if (this.currentTab === 'https') {
237
+ return this.demoRoutes.filter((r) =>
238
+ r.tags?.some((t) => ['web', 'https', 'http'].includes(t))
239
+ );
240
+ }
241
+ if (this.currentTab === 'email') {
242
+ return this.demoRoutes.filter((r) =>
243
+ r.tags?.some((t) => ['email', 'smtp'].includes(t))
244
+ );
245
+ }
246
+ if (this.currentTab === 'dns') {
247
+ return this.demoRoutes.filter((r) =>
248
+ r.tags?.some((t) => ['dns'].includes(t))
249
+ );
250
+ }
251
+ return this.demoRoutes;
252
+ }
253
+
254
+ async onActivate(context: { appui: DeesAppui; viewId: string }) {
255
+ this.appui = context.appui;
256
+
257
+ this.appui.setContentTabs([
258
+ {
259
+ key: 'All Routes',
260
+ action: () => {
261
+ this.currentTab = 'all';
262
+ this.updateSecondaryMenu();
263
+ },
264
+ },
265
+ {
266
+ key: 'HTTP/S',
267
+ action: () => {
268
+ this.currentTab = 'https';
269
+ this.updateSecondaryMenu();
270
+ },
271
+ },
272
+ {
273
+ key: 'Email',
274
+ action: () => {
275
+ this.currentTab = 'email';
276
+ this.updateSecondaryMenu();
277
+ },
278
+ },
279
+ {
280
+ key: 'DNS',
281
+ action: () => {
282
+ this.currentTab = 'dns';
283
+ this.updateSecondaryMenu();
284
+ },
285
+ },
286
+ ]);
287
+
288
+ this.updateSecondaryMenu();
289
+ }
290
+
291
+ private updateSecondaryMenu() {
292
+ if (!this.appui) return;
293
+
294
+ const total = this.demoRoutes.length;
295
+ const active = this.demoRoutes.filter((r) => r.enabled !== false).length;
296
+ const forwardCount = this.demoRoutes.filter((r) => r.action.type === 'forward').length;
297
+
298
+ this.appui.setSecondaryMenu({
299
+ heading: 'Routes',
300
+ groups: [
301
+ {
302
+ name: 'Actions',
303
+ items: [
304
+ {
305
+ type: 'action',
306
+ key: 'Refresh',
307
+ iconName: 'lucide:RefreshCw',
308
+ action: () => {
309
+ console.log('Refresh routes');
310
+ },
311
+ },
312
+ {
313
+ type: 'action',
314
+ key: 'Add Route',
315
+ iconName: 'lucide:Plus',
316
+ action: () => {
317
+ console.log('Add route');
318
+ },
319
+ },
320
+ ],
321
+ },
322
+ {
323
+ name: 'Statistics',
324
+ items: [
325
+ { type: 'header' as const, label: `${total} Total Routes` },
326
+ { type: 'header' as const, label: `${active} Active` },
327
+ { type: 'header' as const, label: `${forwardCount} Forward` },
328
+ { type: 'header' as const, label: `${total - forwardCount} Socket Handler` },
329
+ ],
330
+ },
331
+ ],
332
+ });
333
+ }
334
+
335
+ onDeactivate() {
336
+ // Cleanup if needed
337
+ }
338
+
339
+ public static styles = [
340
+ cssManager.defaultStyles,
341
+ css`
342
+ :host {
343
+ display: block;
344
+ padding: 24px;
345
+ height: 100%;
346
+ overflow-y: auto;
347
+ box-sizing: border-box;
348
+ }
349
+ `,
350
+ ];
351
+
352
+ public render(): TemplateResult {
353
+ return html`
354
+ <sz-route-list-view
355
+ .routes=${this.filteredRoutes}
356
+ @route-click=${(e: CustomEvent<IRouteConfig>) => {
357
+ console.log('Route clicked:', e.detail.name);
358
+ }}
359
+ ></sz-route-list-view>
360
+ `;
361
+ }
362
+ }