@serve.zone/dcrouter 13.8.0 → 13.9.1
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.
- package/dist_serve/bundle.js +1632 -1522
- package/dist_ts/00_commitinfo_data.js +1 -1
- package/dist_ts/classes.dcrouter.js +3 -2
- package/dist_ts/dns/manager.dns.d.ts +17 -15
- package/dist_ts/dns/manager.dns.js +33 -27
- package/dist_ts/dns/providers/factory.js +10 -1
- package/dist_ts/opsserver/handlers/dns-provider.handler.js +42 -5
- package/dist_ts/opsserver/handlers/domain.handler.js +3 -3
- package/dist_ts_interfaces/data/dns-provider.d.ts +28 -4
- package/dist_ts_interfaces/data/dns-provider.js +15 -1
- package/dist_ts_interfaces/data/dns-record.d.ts +9 -7
- package/dist_ts_interfaces/data/domain.d.ts +8 -7
- package/dist_ts_interfaces/requests/dns-records.d.ts +1 -1
- package/dist_ts_interfaces/requests/domains.d.ts +3 -3
- package/dist_ts_migrations/index.js +17 -1
- package/dist_ts_web/00_commitinfo_data.js +1 -1
- package/dist_ts_web/appstate.d.ts +1 -1
- package/dist_ts_web/appstate.js +2 -2
- package/dist_ts_web/elements/domains/dns-provider-form.d.ts +4 -2
- package/dist_ts_web/elements/domains/dns-provider-form.js +11 -5
- package/dist_ts_web/elements/domains/ops-view-dns.js +3 -3
- package/dist_ts_web/elements/domains/ops-view-domains.d.ts +1 -1
- package/dist_ts_web/elements/domains/ops-view-domains.js +10 -10
- package/dist_ts_web/elements/domains/ops-view-providers.js +19 -5
- package/dist_ts_web/elements/network/ops-view-network-activity.js +25 -31
- package/dist_ts_web/elements/network/ops-view-remoteingress.js +3 -1
- package/dist_ts_web/elements/network/ops-view-vpn.js +3 -1
- package/package.json +3 -3
- package/ts/00_commitinfo_data.ts +1 -1
- package/ts/classes.dcrouter.ts +2 -1
- package/ts/dns/manager.dns.ts +38 -27
- package/ts/dns/providers/factory.ts +11 -0
- package/ts/opsserver/handlers/dns-provider.handler.ts +41 -3
- package/ts/opsserver/handlers/domain.handler.ts +2 -2
- package/ts_web/00_commitinfo_data.ts +1 -1
- package/ts_web/appstate.ts +1 -1
- package/ts_web/elements/domains/dns-provider-form.ts +12 -4
- package/ts_web/elements/domains/ops-view-dns.ts +2 -2
- package/ts_web/elements/domains/ops-view-domains.ts +9 -9
- package/ts_web/elements/domains/ops-view-providers.ts +18 -4
- package/ts_web/elements/network/ops-view-network-activity.ts +24 -31
- package/ts_web/elements/network/ops-view-remoteingress.ts +2 -0
- package/ts_web/elements/network/ops-view-vpn.ts +2 -0
package/ts_web/appstate.ts
CHANGED
|
@@ -1793,7 +1793,7 @@ export async function fetchProviderDomains(
|
|
|
1793
1793
|
return await request.fire({ identity: context.identity, providerId });
|
|
1794
1794
|
}
|
|
1795
1795
|
|
|
1796
|
-
export const
|
|
1796
|
+
export const createDcrouterDomainAction = domainsStatePart.createAction<{
|
|
1797
1797
|
name: string;
|
|
1798
1798
|
description?: string;
|
|
1799
1799
|
}>(async (statePartArg, dataArg, actionContext): Promise<IDomainsState> => {
|
|
@@ -44,12 +44,15 @@ export class DnsProviderForm extends DeesElement {
|
|
|
44
44
|
accessor providerName: string = '';
|
|
45
45
|
|
|
46
46
|
/**
|
|
47
|
-
* Currently selected provider type. Initialized to the first
|
|
48
|
-
* caller can override before mounting (e.g. for edit dialogs).
|
|
47
|
+
* Currently selected provider type. Initialized to the first user-creatable
|
|
48
|
+
* descriptor; caller can override before mounting (e.g. for edit dialogs).
|
|
49
|
+
* The built-in 'dcrouter' pseudo-provider is excluded from the picker —
|
|
50
|
+
* operators cannot create another one.
|
|
49
51
|
*/
|
|
50
52
|
@state()
|
|
51
53
|
accessor selectedType: interfaces.data.TDnsProviderType =
|
|
52
|
-
interfaces.data.dnsProviderTypeDescriptors
|
|
54
|
+
interfaces.data.dnsProviderTypeDescriptors.find((d) => d.type !== 'dcrouter')?.type ??
|
|
55
|
+
'cloudflare';
|
|
53
56
|
|
|
54
57
|
/** When true, hide the type picker — used in edit dialogs. */
|
|
55
58
|
@property({ type: Boolean })
|
|
@@ -102,7 +105,12 @@ export class DnsProviderForm extends DeesElement {
|
|
|
102
105
|
];
|
|
103
106
|
|
|
104
107
|
public render(): TemplateResult {
|
|
105
|
-
|
|
108
|
+
// Exclude the built-in 'dcrouter' pseudo-provider from the type picker —
|
|
109
|
+
// operators cannot create another one, it's surfaced at read time by the
|
|
110
|
+
// backend handler instead.
|
|
111
|
+
const descriptors = interfaces.data.dnsProviderTypeDescriptors.filter(
|
|
112
|
+
(d) => d.type !== 'dcrouter',
|
|
113
|
+
);
|
|
106
114
|
const descriptor = interfaces.data.getDnsProviderTypeDescriptor(this.selectedType);
|
|
107
115
|
|
|
108
116
|
return html`
|
|
@@ -80,7 +80,7 @@ export class OpsViewDns extends DeesElement {
|
|
|
80
80
|
font-weight: 500;
|
|
81
81
|
}
|
|
82
82
|
|
|
83
|
-
.sourceBadge.
|
|
83
|
+
.sourceBadge.local {
|
|
84
84
|
background: ${cssManager.bdTheme('#e0e7ff', '#1e1b4b')};
|
|
85
85
|
color: ${cssManager.bdTheme('#3730a3', '#a5b4fc')};
|
|
86
86
|
}
|
|
@@ -184,7 +184,7 @@ export class OpsViewDns extends DeesElement {
|
|
|
184
184
|
private domainHint(domainId: string): string {
|
|
185
185
|
const domain = this.domainsState.domains.find((d) => d.id === domainId);
|
|
186
186
|
if (!domain) return '';
|
|
187
|
-
if (domain.source === '
|
|
187
|
+
if (domain.source === 'dcrouter') {
|
|
188
188
|
return 'Records are served by dcrouter (authoritative).';
|
|
189
189
|
}
|
|
190
190
|
return 'Records are stored at the provider — changes here are pushed via the provider API.';
|
|
@@ -55,7 +55,7 @@ export class OpsViewDomains extends DeesElement {
|
|
|
55
55
|
font-weight: 500;
|
|
56
56
|
}
|
|
57
57
|
|
|
58
|
-
.sourceBadge.
|
|
58
|
+
.sourceBadge.dcrouter {
|
|
59
59
|
background: ${cssManager.bdTheme('#e0e7ff', '#1e1b4b')};
|
|
60
60
|
color: ${cssManager.bdTheme('#3730a3', '#a5b4fc')};
|
|
61
61
|
}
|
|
@@ -76,7 +76,7 @@ export class OpsViewDomains extends DeesElement {
|
|
|
76
76
|
<div class="domainsContainer">
|
|
77
77
|
<dees-table
|
|
78
78
|
.heading1=${'Domains'}
|
|
79
|
-
.heading2=${'Domains under management —
|
|
79
|
+
.heading2=${'Domains under management — served by dcrouter (authoritative) or imported from a provider'}
|
|
80
80
|
.data=${domains}
|
|
81
81
|
.showColumnFilters=${true}
|
|
82
82
|
.displayFunction=${(d: interfaces.data.IDomain) => ({
|
|
@@ -90,11 +90,11 @@ export class OpsViewDomains extends DeesElement {
|
|
|
90
90
|
})}
|
|
91
91
|
.dataActions=${[
|
|
92
92
|
{
|
|
93
|
-
name: 'Add
|
|
93
|
+
name: 'Add DcRouter Domain',
|
|
94
94
|
iconName: 'lucide:plus',
|
|
95
95
|
type: ['header' as const],
|
|
96
96
|
actionFunc: async () => {
|
|
97
|
-
await this.
|
|
97
|
+
await this.showCreateDcrouterDialog();
|
|
98
98
|
},
|
|
99
99
|
},
|
|
100
100
|
{
|
|
@@ -168,17 +168,17 @@ export class OpsViewDomains extends DeesElement {
|
|
|
168
168
|
d: interfaces.data.IDomain,
|
|
169
169
|
providersById: Map<string, interfaces.data.IDnsProviderPublic>,
|
|
170
170
|
): TemplateResult {
|
|
171
|
-
if (d.source === '
|
|
172
|
-
return html`<span class="sourceBadge
|
|
171
|
+
if (d.source === 'dcrouter') {
|
|
172
|
+
return html`<span class="sourceBadge dcrouter">DcRouter</span>`;
|
|
173
173
|
}
|
|
174
174
|
const provider = d.providerId ? providersById.get(d.providerId) : undefined;
|
|
175
175
|
return html`<span class="sourceBadge provider">${provider?.name || 'Provider'}</span>`;
|
|
176
176
|
}
|
|
177
177
|
|
|
178
|
-
private async
|
|
178
|
+
private async showCreateDcrouterDialog() {
|
|
179
179
|
const { DeesModal } = await import('@design.estate/dees-catalog');
|
|
180
180
|
DeesModal.createAndShow({
|
|
181
|
-
heading: 'Add
|
|
181
|
+
heading: 'Add DcRouter Domain',
|
|
182
182
|
content: html`
|
|
183
183
|
<dees-form>
|
|
184
184
|
<dees-input-text .key=${'name'} .label=${'FQDN (e.g. example.com)'} .required=${true}></dees-input-text>
|
|
@@ -199,7 +199,7 @@ export class OpsViewDomains extends DeesElement {
|
|
|
199
199
|
?.querySelector('dees-form');
|
|
200
200
|
if (!form) return;
|
|
201
201
|
const data = await form.collectFormData();
|
|
202
|
-
await appstate.domainsStatePart.dispatchAction(appstate.
|
|
202
|
+
await appstate.domainsStatePart.dispatchAction(appstate.createDcrouterDomainAction, {
|
|
203
203
|
name: String(data.name),
|
|
204
204
|
description: data.description ? String(data.description) : undefined,
|
|
205
205
|
});
|
|
@@ -71,6 +71,11 @@ export class OpsViewProviders extends DeesElement {
|
|
|
71
71
|
background: ${cssManager.bdTheme('#f3f4f6', '#1f2937')};
|
|
72
72
|
color: ${cssManager.bdTheme('#4b5563', '#9ca3af')};
|
|
73
73
|
}
|
|
74
|
+
|
|
75
|
+
.statusBadge.builtin {
|
|
76
|
+
background: ${cssManager.bdTheme('#e0e7ff', '#1e1b4b')};
|
|
77
|
+
color: ${cssManager.bdTheme('#3730a3', '#a5b4fc')};
|
|
78
|
+
}
|
|
74
79
|
`,
|
|
75
80
|
];
|
|
76
81
|
|
|
@@ -82,15 +87,21 @@ export class OpsViewProviders extends DeesElement {
|
|
|
82
87
|
<div class="providersContainer">
|
|
83
88
|
<dees-table
|
|
84
89
|
.heading1=${'Providers'}
|
|
85
|
-
.heading2=${'
|
|
90
|
+
.heading2=${'Built-in dcrouter + external DNS provider accounts'}
|
|
86
91
|
.data=${providers}
|
|
87
92
|
.showColumnFilters=${true}
|
|
88
93
|
.displayFunction=${(p: interfaces.data.IDnsProviderPublic) => ({
|
|
89
94
|
Name: p.name,
|
|
90
95
|
Type: this.providerTypeLabel(p.type),
|
|
91
|
-
Status:
|
|
92
|
-
|
|
93
|
-
|
|
96
|
+
Status: p.builtIn
|
|
97
|
+
? html`<span class="statusBadge builtin">built-in</span>`
|
|
98
|
+
: this.renderStatusBadge(p.status),
|
|
99
|
+
'Last Tested': p.builtIn
|
|
100
|
+
? '—'
|
|
101
|
+
: p.lastTestedAt
|
|
102
|
+
? new Date(p.lastTestedAt).toLocaleString()
|
|
103
|
+
: 'never',
|
|
104
|
+
Error: p.builtIn ? '—' : p.lastError || '-',
|
|
94
105
|
})}
|
|
95
106
|
.dataActions=${[
|
|
96
107
|
{
|
|
@@ -116,6 +127,7 @@ export class OpsViewProviders extends DeesElement {
|
|
|
116
127
|
name: 'Test Connection',
|
|
117
128
|
iconName: 'lucide:plug',
|
|
118
129
|
type: ['inRow', 'contextmenu'] as any,
|
|
130
|
+
actionRelevancyCheckFunc: (p: interfaces.data.IDnsProviderPublic) => !p.builtIn,
|
|
119
131
|
actionFunc: async (actionData: any) => {
|
|
120
132
|
const provider = actionData.item as interfaces.data.IDnsProviderPublic;
|
|
121
133
|
await this.testProvider(provider);
|
|
@@ -125,6 +137,7 @@ export class OpsViewProviders extends DeesElement {
|
|
|
125
137
|
name: 'Edit',
|
|
126
138
|
iconName: 'lucide:pencil',
|
|
127
139
|
type: ['inRow', 'contextmenu'] as any,
|
|
140
|
+
actionRelevancyCheckFunc: (p: interfaces.data.IDnsProviderPublic) => !p.builtIn,
|
|
128
141
|
actionFunc: async (actionData: any) => {
|
|
129
142
|
const provider = actionData.item as interfaces.data.IDnsProviderPublic;
|
|
130
143
|
await this.showEditDialog(provider);
|
|
@@ -134,6 +147,7 @@ export class OpsViewProviders extends DeesElement {
|
|
|
134
147
|
name: 'Delete',
|
|
135
148
|
iconName: 'lucide:trash2',
|
|
136
149
|
type: ['inRow', 'contextmenu'] as any,
|
|
150
|
+
actionRelevancyCheckFunc: (p: interfaces.data.IDnsProviderPublic) => !p.builtIn,
|
|
137
151
|
actionFunc: async (actionData: any) => {
|
|
138
152
|
const provider = actionData.item as interfaces.data.IDnsProviderPublic;
|
|
139
153
|
await this.deleteProvider(provider);
|
|
@@ -323,6 +323,8 @@ export class OpsViewNetworkActivity extends DeesElement {
|
|
|
323
323
|
<!-- Requests Table -->
|
|
324
324
|
<dees-table
|
|
325
325
|
.data=${this.networkRequests}
|
|
326
|
+
.rowKey=${'id'}
|
|
327
|
+
.highlightUpdates=${'flash'}
|
|
326
328
|
.displayFunction=${(req: INetworkRequest) => ({
|
|
327
329
|
Time: new Date(req.timestamp).toLocaleTimeString(),
|
|
328
330
|
Protocol: html`<span class="protocolBadge ${req.protocol}">${req.protocol.toUpperCase()}</span>`,
|
|
@@ -595,6 +597,8 @@ export class OpsViewNetworkActivity extends DeesElement {
|
|
|
595
597
|
return html`
|
|
596
598
|
<dees-table
|
|
597
599
|
.data=${this.networkState.topIPs}
|
|
600
|
+
.rowKey=${'ip'}
|
|
601
|
+
.highlightUpdates=${'flash'}
|
|
598
602
|
.displayFunction=${(ipData: { ip: string; count: number }) => {
|
|
599
603
|
const bw = bandwidthByIP.get(ipData.ip);
|
|
600
604
|
return {
|
|
@@ -624,6 +628,8 @@ export class OpsViewNetworkActivity extends DeesElement {
|
|
|
624
628
|
return html`
|
|
625
629
|
<dees-table
|
|
626
630
|
.data=${backends}
|
|
631
|
+
.rowKey=${'backend'}
|
|
632
|
+
.highlightUpdates=${'flash'}
|
|
627
633
|
.displayFunction=${(item: interfaces.data.IBackendInfo) => {
|
|
628
634
|
const totalErrors = item.connectErrors + item.handshakeErrors + item.requestErrors;
|
|
629
635
|
const protocolClass = item.protocol.toLowerCase().replace(/[^a-z0-9]/g, '');
|
|
@@ -724,37 +730,24 @@ export class OpsViewNetworkActivity extends DeesElement {
|
|
|
724
730
|
this.requestsPerSecHistory.shift();
|
|
725
731
|
}
|
|
726
732
|
|
|
727
|
-
//
|
|
728
|
-
|
|
729
|
-
|
|
730
|
-
|
|
731
|
-
|
|
732
|
-
|
|
733
|
-
|
|
734
|
-
|
|
735
|
-
|
|
736
|
-
|
|
737
|
-
|
|
738
|
-
|
|
739
|
-
|
|
740
|
-
|
|
741
|
-
|
|
742
|
-
|
|
743
|
-
|
|
744
|
-
|
|
745
|
-
port: conn.protocol === 'https' ? 443 : 80,
|
|
746
|
-
protocol: conn.protocol === 'https' || conn.protocol === 'http' ? conn.protocol : 'tcp',
|
|
747
|
-
statusCode: conn.state === 'connected' ? 200 : undefined,
|
|
748
|
-
duration: Date.now() - conn.startTime,
|
|
749
|
-
bytesIn: conn.bytesReceived,
|
|
750
|
-
bytesOut: conn.bytesSent,
|
|
751
|
-
remoteIp: conn.remoteAddress,
|
|
752
|
-
route: 'proxy',
|
|
753
|
-
}));
|
|
754
|
-
} else {
|
|
755
|
-
this.networkRequests = [];
|
|
756
|
-
}
|
|
757
|
-
}
|
|
733
|
+
// Reassign unconditionally so dees-table's flash diff can compare per-cell
|
|
734
|
+
// values against the previous snapshot. Row identity is preserved via
|
|
735
|
+
// rowKey='id', so DOM nodes are reused across ticks.
|
|
736
|
+
this.networkRequests = this.networkState.connections.map((conn) => ({
|
|
737
|
+
id: conn.id,
|
|
738
|
+
timestamp: conn.startTime,
|
|
739
|
+
method: 'GET', // Default method for proxy connections
|
|
740
|
+
url: '/',
|
|
741
|
+
hostname: conn.remoteAddress,
|
|
742
|
+
port: conn.protocol === 'https' ? 443 : 80,
|
|
743
|
+
protocol: conn.protocol === 'https' || conn.protocol === 'http' ? conn.protocol : 'tcp',
|
|
744
|
+
statusCode: conn.state === 'connected' ? 200 : undefined,
|
|
745
|
+
duration: Date.now() - conn.startTime,
|
|
746
|
+
bytesIn: conn.bytesReceived,
|
|
747
|
+
bytesOut: conn.bytesSent,
|
|
748
|
+
remoteIp: conn.remoteAddress,
|
|
749
|
+
route: 'proxy',
|
|
750
|
+
}));
|
|
758
751
|
|
|
759
752
|
// Load server-side throughput history into chart (once)
|
|
760
753
|
if (!this.historyLoaded && this.networkState.throughputHistory && this.networkState.throughputHistory.length > 0) {
|
|
@@ -220,6 +220,8 @@ export class OpsViewRemoteIngress extends DeesElement {
|
|
|
220
220
|
.heading1=${'Edge Nodes'}
|
|
221
221
|
.heading2=${'Manage remote ingress edge registrations'}
|
|
222
222
|
.data=${this.riState.edges}
|
|
223
|
+
.rowKey=${'id'}
|
|
224
|
+
.highlightUpdates=${'flash'}
|
|
223
225
|
.showColumnFilters=${true}
|
|
224
226
|
.displayFunction=${(edge: interfaces.data.IRemoteIngress) => ({
|
|
225
227
|
name: edge.name,
|
|
@@ -305,6 +305,8 @@ export class OpsViewVpn extends DeesElement {
|
|
|
305
305
|
.heading1=${'VPN Clients'}
|
|
306
306
|
.heading2=${'Manage WireGuard and SmartVPN client registrations'}
|
|
307
307
|
.data=${clients}
|
|
308
|
+
.rowKey=${'clientId'}
|
|
309
|
+
.highlightUpdates=${'flash'}
|
|
308
310
|
.showColumnFilters=${true}
|
|
309
311
|
.displayFunction=${(client: interfaces.data.IVpnClient) => {
|
|
310
312
|
const conn = this.getConnectedInfo(client);
|