@serve.zone/dcrouter 15.0.2 → 15.0.4
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/deno.json +1 -1
- package/dist_serve/bundle.js +768 -768
- package/dist_ts/00_commitinfo_data.js +1 -1
- package/dist_ts/classes.dcrouter.js +9 -1
- package/dist_ts_web/00_commitinfo_data.js +1 -1
- package/dist_ts_web/appstate/acme.d.ts +17 -0
- package/dist_ts_web/appstate/acme.js +64 -0
- package/dist_ts_web/appstate/certificates.d.ts +37 -0
- package/dist_ts_web/appstate/certificates.js +107 -0
- package/dist_ts_web/appstate/config.d.ts +9 -0
- package/dist_ts_web/appstate/config.js +35 -0
- package/dist_ts_web/appstate/domains.d.ts +80 -0
- package/dist_ts_web/appstate/domains.js +324 -0
- package/dist_ts_web/appstate/email-domains.d.ts +25 -0
- package/dist_ts_web/appstate/email-domains.js +104 -0
- package/dist_ts_web/appstate/email-ops.d.ts +10 -0
- package/dist_ts_web/appstate/email-ops.js +40 -0
- package/dist_ts_web/appstate/login.d.ts +30 -0
- package/dist_ts_web/appstate/login.js +83 -0
- package/dist_ts_web/appstate/logs.d.ts +16 -0
- package/dist_ts_web/appstate/logs.js +27 -0
- package/dist_ts_web/appstate/network.d.ts +50 -0
- package/dist_ts_web/appstate/network.js +122 -0
- package/dist_ts_web/appstate/profiles-targets.d.ts +45 -0
- package/dist_ts_web/appstate/profiles-targets.js +173 -0
- package/dist_ts_web/appstate/remoteingress.d.ts +47 -0
- package/dist_ts_web/appstate/remoteingress.js +204 -0
- package/dist_ts_web/appstate/routes.d.ts +76 -0
- package/dist_ts_web/appstate/routes.js +316 -0
- package/dist_ts_web/appstate/runtime.d.ts +1 -0
- package/dist_ts_web/appstate/runtime.js +276 -0
- package/dist_ts_web/appstate/security.d.ts +29 -0
- package/dist_ts_web/appstate/security.js +167 -0
- package/dist_ts_web/appstate/shared.d.ts +3 -0
- package/dist_ts_web/appstate/shared.js +13 -0
- package/dist_ts_web/appstate/stats.d.ts +15 -0
- package/dist_ts_web/appstate/stats.js +59 -0
- package/dist_ts_web/appstate/target-profiles.d.ts +37 -0
- package/dist_ts_web/appstate/target-profiles.js +118 -0
- package/dist_ts_web/appstate/ui.d.ts +11 -0
- package/dist_ts_web/appstate/ui.js +55 -0
- package/dist_ts_web/appstate/users.d.ts +27 -0
- package/dist_ts_web/appstate/users.js +85 -0
- package/dist_ts_web/appstate/vpn.d.ts +44 -0
- package/dist_ts_web/appstate/vpn.js +148 -0
- package/dist_ts_web/appstate.d.ts +20 -568
- package/dist_ts_web/appstate.js +24 -2418
- package/package.json +3 -3
- package/ts/00_commitinfo_data.ts +1 -1
- package/ts/classes.dcrouter.ts +10 -0
- package/ts_web/00_commitinfo_data.ts +1 -1
- package/ts_web/appstate/acme.ts +93 -0
- package/ts_web/appstate/certificates.ts +159 -0
- package/ts_web/appstate/config.ts +49 -0
- package/ts_web/appstate/domains.ts +429 -0
- package/ts_web/appstate/email-domains.ts +155 -0
- package/ts_web/appstate/email-ops.ts +57 -0
- package/ts_web/appstate/login.ts +128 -0
- package/ts_web/appstate/logs.ts +50 -0
- package/ts_web/appstate/network.ts +161 -0
- package/ts_web/appstate/profiles-targets.ts +240 -0
- package/ts_web/appstate/remoteingress.ts +300 -0
- package/ts_web/appstate/routes.ts +447 -0
- package/ts_web/appstate/runtime.ts +308 -0
- package/ts_web/appstate/security.ts +229 -0
- package/ts_web/appstate/shared.ts +15 -0
- package/ts_web/appstate/stats.ts +79 -0
- package/ts_web/appstate/target-profiles.ts +164 -0
- package/ts_web/appstate/ui.ts +75 -0
- package/ts_web/appstate/users.ts +133 -0
- package/ts_web/appstate/vpn.ts +234 -0
- package/ts_web/appstate.ts +24 -3403
|
@@ -0,0 +1,429 @@
|
|
|
1
|
+
import * as plugins from '../plugins.js';
|
|
2
|
+
import * as interfaces from '../../ts_interfaces/index.js';
|
|
3
|
+
import { appState } from './shared.js';
|
|
4
|
+
import { getActionContext } from './login.js';
|
|
5
|
+
|
|
6
|
+
// ============================================================================
|
|
7
|
+
// Domains State (DNS providers + domains + records)
|
|
8
|
+
// ============================================================================
|
|
9
|
+
|
|
10
|
+
export interface IDomainsState {
|
|
11
|
+
providers: interfaces.data.IDnsProviderPublic[];
|
|
12
|
+
domains: interfaces.data.IDomain[];
|
|
13
|
+
records: interfaces.data.IDnsRecord[];
|
|
14
|
+
/** id of the currently-selected domain in the DNS records subview. */
|
|
15
|
+
selectedDomainId: string | null;
|
|
16
|
+
isLoading: boolean;
|
|
17
|
+
error: string | null;
|
|
18
|
+
lastUpdated: number;
|
|
19
|
+
}
|
|
20
|
+
|
|
21
|
+
export const domainsStatePart = await appState.getStatePart<IDomainsState>(
|
|
22
|
+
'domains',
|
|
23
|
+
{
|
|
24
|
+
providers: [],
|
|
25
|
+
domains: [],
|
|
26
|
+
records: [],
|
|
27
|
+
selectedDomainId: null,
|
|
28
|
+
isLoading: false,
|
|
29
|
+
error: null,
|
|
30
|
+
lastUpdated: 0,
|
|
31
|
+
},
|
|
32
|
+
'soft',
|
|
33
|
+
);
|
|
34
|
+
|
|
35
|
+
export const fetchDomainsAndProvidersAction = domainsStatePart.createAction(
|
|
36
|
+
async (statePartArg): Promise<IDomainsState> => {
|
|
37
|
+
const context = getActionContext();
|
|
38
|
+
const currentState = statePartArg.getState()!;
|
|
39
|
+
if (!context.identity) return currentState;
|
|
40
|
+
|
|
41
|
+
try {
|
|
42
|
+
const providersRequest = new plugins.domtools.plugins.typedrequest.TypedRequest<
|
|
43
|
+
interfaces.requests.IReq_GetDnsProviders
|
|
44
|
+
>('/typedrequest', 'getDnsProviders');
|
|
45
|
+
const domainsRequest = new plugins.domtools.plugins.typedrequest.TypedRequest<
|
|
46
|
+
interfaces.requests.IReq_GetDomains
|
|
47
|
+
>('/typedrequest', 'getDomains');
|
|
48
|
+
|
|
49
|
+
const [providersResponse, domainsResponse] = await Promise.all([
|
|
50
|
+
providersRequest.fire({ identity: context.identity }),
|
|
51
|
+
domainsRequest.fire({ identity: context.identity }),
|
|
52
|
+
]);
|
|
53
|
+
|
|
54
|
+
return {
|
|
55
|
+
...currentState,
|
|
56
|
+
providers: providersResponse.providers,
|
|
57
|
+
domains: domainsResponse.domains,
|
|
58
|
+
isLoading: false,
|
|
59
|
+
error: null,
|
|
60
|
+
lastUpdated: Date.now(),
|
|
61
|
+
};
|
|
62
|
+
} catch (error: unknown) {
|
|
63
|
+
return {
|
|
64
|
+
...currentState,
|
|
65
|
+
isLoading: false,
|
|
66
|
+
error: error instanceof Error ? error.message : 'Failed to fetch domains/providers',
|
|
67
|
+
};
|
|
68
|
+
}
|
|
69
|
+
},
|
|
70
|
+
);
|
|
71
|
+
|
|
72
|
+
export const fetchDnsRecordsForDomainAction = domainsStatePart.createAction<{ domainId: string }>(
|
|
73
|
+
async (statePartArg, dataArg): Promise<IDomainsState> => {
|
|
74
|
+
const context = getActionContext();
|
|
75
|
+
const currentState = statePartArg.getState()!;
|
|
76
|
+
if (!context.identity) return currentState;
|
|
77
|
+
|
|
78
|
+
try {
|
|
79
|
+
const request = new plugins.domtools.plugins.typedrequest.TypedRequest<
|
|
80
|
+
interfaces.requests.IReq_GetDnsRecords
|
|
81
|
+
>('/typedrequest', 'getDnsRecords');
|
|
82
|
+
const response = await request.fire({
|
|
83
|
+
identity: context.identity,
|
|
84
|
+
domainId: dataArg.domainId,
|
|
85
|
+
});
|
|
86
|
+
return {
|
|
87
|
+
...currentState,
|
|
88
|
+
records: response.records,
|
|
89
|
+
selectedDomainId: dataArg.domainId,
|
|
90
|
+
error: null,
|
|
91
|
+
};
|
|
92
|
+
} catch (error: unknown) {
|
|
93
|
+
return {
|
|
94
|
+
...currentState,
|
|
95
|
+
error: error instanceof Error ? error.message : 'Failed to fetch DNS records',
|
|
96
|
+
};
|
|
97
|
+
}
|
|
98
|
+
},
|
|
99
|
+
);
|
|
100
|
+
|
|
101
|
+
export const createDnsProviderAction = domainsStatePart.createAction<{
|
|
102
|
+
name: string;
|
|
103
|
+
type: interfaces.data.TDnsProviderType;
|
|
104
|
+
credentials: interfaces.data.TDnsProviderCredentials;
|
|
105
|
+
}>(async (statePartArg, dataArg, actionContext): Promise<IDomainsState> => {
|
|
106
|
+
const context = getActionContext();
|
|
107
|
+
try {
|
|
108
|
+
const request = new plugins.domtools.plugins.typedrequest.TypedRequest<
|
|
109
|
+
interfaces.requests.IReq_CreateDnsProvider
|
|
110
|
+
>('/typedrequest', 'createDnsProvider');
|
|
111
|
+
const response = await request.fire({
|
|
112
|
+
identity: context.identity!,
|
|
113
|
+
name: dataArg.name,
|
|
114
|
+
type: dataArg.type,
|
|
115
|
+
credentials: dataArg.credentials,
|
|
116
|
+
});
|
|
117
|
+
if (!response.success) {
|
|
118
|
+
return {
|
|
119
|
+
...statePartArg.getState()!,
|
|
120
|
+
error: response.message || 'Failed to create provider',
|
|
121
|
+
};
|
|
122
|
+
}
|
|
123
|
+
return await actionContext!.dispatch(fetchDomainsAndProvidersAction, null);
|
|
124
|
+
} catch (error: unknown) {
|
|
125
|
+
return {
|
|
126
|
+
...statePartArg.getState()!,
|
|
127
|
+
error: error instanceof Error ? error.message : 'Failed to create provider',
|
|
128
|
+
};
|
|
129
|
+
}
|
|
130
|
+
});
|
|
131
|
+
|
|
132
|
+
export const updateDnsProviderAction = domainsStatePart.createAction<{
|
|
133
|
+
id: string;
|
|
134
|
+
name?: string;
|
|
135
|
+
credentials?: interfaces.data.TDnsProviderCredentials;
|
|
136
|
+
}>(async (statePartArg, dataArg, actionContext): Promise<IDomainsState> => {
|
|
137
|
+
const context = getActionContext();
|
|
138
|
+
try {
|
|
139
|
+
const request = new plugins.domtools.plugins.typedrequest.TypedRequest<
|
|
140
|
+
interfaces.requests.IReq_UpdateDnsProvider
|
|
141
|
+
>('/typedrequest', 'updateDnsProvider');
|
|
142
|
+
const response = await request.fire({
|
|
143
|
+
identity: context.identity!,
|
|
144
|
+
id: dataArg.id,
|
|
145
|
+
name: dataArg.name,
|
|
146
|
+
credentials: dataArg.credentials,
|
|
147
|
+
});
|
|
148
|
+
if (!response.success) {
|
|
149
|
+
return {
|
|
150
|
+
...statePartArg.getState()!,
|
|
151
|
+
error: response.message || 'Failed to update provider',
|
|
152
|
+
};
|
|
153
|
+
}
|
|
154
|
+
return await actionContext!.dispatch(fetchDomainsAndProvidersAction, null);
|
|
155
|
+
} catch (error: unknown) {
|
|
156
|
+
return {
|
|
157
|
+
...statePartArg.getState()!,
|
|
158
|
+
error: error instanceof Error ? error.message : 'Failed to update provider',
|
|
159
|
+
};
|
|
160
|
+
}
|
|
161
|
+
});
|
|
162
|
+
|
|
163
|
+
export const deleteDnsProviderAction = domainsStatePart.createAction<{ id: string; force?: boolean }>(
|
|
164
|
+
async (statePartArg, dataArg, actionContext): Promise<IDomainsState> => {
|
|
165
|
+
const context = getActionContext();
|
|
166
|
+
try {
|
|
167
|
+
const request = new plugins.domtools.plugins.typedrequest.TypedRequest<
|
|
168
|
+
interfaces.requests.IReq_DeleteDnsProvider
|
|
169
|
+
>('/typedrequest', 'deleteDnsProvider');
|
|
170
|
+
const response = await request.fire({
|
|
171
|
+
identity: context.identity!,
|
|
172
|
+
id: dataArg.id,
|
|
173
|
+
force: dataArg.force,
|
|
174
|
+
});
|
|
175
|
+
if (!response.success) {
|
|
176
|
+
return {
|
|
177
|
+
...statePartArg.getState()!,
|
|
178
|
+
error: response.message || 'Failed to delete provider',
|
|
179
|
+
};
|
|
180
|
+
}
|
|
181
|
+
return await actionContext!.dispatch(fetchDomainsAndProvidersAction, null);
|
|
182
|
+
} catch (error: unknown) {
|
|
183
|
+
return {
|
|
184
|
+
...statePartArg.getState()!,
|
|
185
|
+
error: error instanceof Error ? error.message : 'Failed to delete provider',
|
|
186
|
+
};
|
|
187
|
+
}
|
|
188
|
+
},
|
|
189
|
+
);
|
|
190
|
+
|
|
191
|
+
export const testDnsProviderAction = domainsStatePart.createAction<{ id: string }>(
|
|
192
|
+
async (statePartArg, dataArg, actionContext): Promise<IDomainsState> => {
|
|
193
|
+
const context = getActionContext();
|
|
194
|
+
try {
|
|
195
|
+
const request = new plugins.domtools.plugins.typedrequest.TypedRequest<
|
|
196
|
+
interfaces.requests.IReq_TestDnsProvider
|
|
197
|
+
>('/typedrequest', 'testDnsProvider');
|
|
198
|
+
await request.fire({ identity: context.identity!, id: dataArg.id });
|
|
199
|
+
return await actionContext!.dispatch(fetchDomainsAndProvidersAction, null);
|
|
200
|
+
} catch (error: unknown) {
|
|
201
|
+
return {
|
|
202
|
+
...statePartArg.getState()!,
|
|
203
|
+
error: error instanceof Error ? error.message : 'Failed to test provider',
|
|
204
|
+
};
|
|
205
|
+
}
|
|
206
|
+
},
|
|
207
|
+
);
|
|
208
|
+
|
|
209
|
+
/** One-shot fetch for the import-domain modal. Does NOT modify state. */
|
|
210
|
+
export async function fetchProviderDomains(
|
|
211
|
+
providerId: string,
|
|
212
|
+
): Promise<{ success: boolean; domains?: interfaces.data.IProviderDomainListing[]; message?: string }> {
|
|
213
|
+
const context = getActionContext();
|
|
214
|
+
if (!context.identity) return { success: false, message: 'Not authenticated' };
|
|
215
|
+
const request = new plugins.domtools.plugins.typedrequest.TypedRequest<
|
|
216
|
+
interfaces.requests.IReq_ListProviderDomains
|
|
217
|
+
>('/typedrequest', 'listProviderDomains');
|
|
218
|
+
return await request.fire({ identity: context.identity, providerId });
|
|
219
|
+
}
|
|
220
|
+
|
|
221
|
+
export const createDcrouterDomainAction = domainsStatePart.createAction<{
|
|
222
|
+
name: string;
|
|
223
|
+
description?: string;
|
|
224
|
+
}>(async (statePartArg, dataArg, actionContext): Promise<IDomainsState> => {
|
|
225
|
+
const context = getActionContext();
|
|
226
|
+
try {
|
|
227
|
+
const request = new plugins.domtools.plugins.typedrequest.TypedRequest<
|
|
228
|
+
interfaces.requests.IReq_CreateDomain
|
|
229
|
+
>('/typedrequest', 'createDomain');
|
|
230
|
+
const response = await request.fire({
|
|
231
|
+
identity: context.identity!,
|
|
232
|
+
name: dataArg.name,
|
|
233
|
+
description: dataArg.description,
|
|
234
|
+
});
|
|
235
|
+
if (!response.success) {
|
|
236
|
+
return { ...statePartArg.getState()!, error: response.message || 'Failed to create domain' };
|
|
237
|
+
}
|
|
238
|
+
return await actionContext!.dispatch(fetchDomainsAndProvidersAction, null);
|
|
239
|
+
} catch (error: unknown) {
|
|
240
|
+
return {
|
|
241
|
+
...statePartArg.getState()!,
|
|
242
|
+
error: error instanceof Error ? error.message : 'Failed to create domain',
|
|
243
|
+
};
|
|
244
|
+
}
|
|
245
|
+
});
|
|
246
|
+
|
|
247
|
+
export const importDomainsFromProviderAction = domainsStatePart.createAction<{
|
|
248
|
+
providerId: string;
|
|
249
|
+
domainNames: string[];
|
|
250
|
+
}>(async (statePartArg, dataArg, actionContext): Promise<IDomainsState> => {
|
|
251
|
+
const context = getActionContext();
|
|
252
|
+
try {
|
|
253
|
+
const request = new plugins.domtools.plugins.typedrequest.TypedRequest<
|
|
254
|
+
interfaces.requests.IReq_ImportDomain
|
|
255
|
+
>('/typedrequest', 'importDomain');
|
|
256
|
+
const response = await request.fire({
|
|
257
|
+
identity: context.identity!,
|
|
258
|
+
providerId: dataArg.providerId,
|
|
259
|
+
domainNames: dataArg.domainNames,
|
|
260
|
+
});
|
|
261
|
+
if (!response.success) {
|
|
262
|
+
return { ...statePartArg.getState()!, error: response.message || 'Failed to import domains' };
|
|
263
|
+
}
|
|
264
|
+
return await actionContext!.dispatch(fetchDomainsAndProvidersAction, null);
|
|
265
|
+
} catch (error: unknown) {
|
|
266
|
+
return {
|
|
267
|
+
...statePartArg.getState()!,
|
|
268
|
+
error: error instanceof Error ? error.message : 'Failed to import domains',
|
|
269
|
+
};
|
|
270
|
+
}
|
|
271
|
+
});
|
|
272
|
+
|
|
273
|
+
export const deleteDomainAction = domainsStatePart.createAction<{ id: string }>(
|
|
274
|
+
async (statePartArg, dataArg, actionContext): Promise<IDomainsState> => {
|
|
275
|
+
const context = getActionContext();
|
|
276
|
+
try {
|
|
277
|
+
const request = new plugins.domtools.plugins.typedrequest.TypedRequest<
|
|
278
|
+
interfaces.requests.IReq_DeleteDomain
|
|
279
|
+
>('/typedrequest', 'deleteDomain');
|
|
280
|
+
const response = await request.fire({ identity: context.identity!, id: dataArg.id });
|
|
281
|
+
if (!response.success) {
|
|
282
|
+
return { ...statePartArg.getState()!, error: response.message || 'Failed to delete domain' };
|
|
283
|
+
}
|
|
284
|
+
return await actionContext!.dispatch(fetchDomainsAndProvidersAction, null);
|
|
285
|
+
} catch (error: unknown) {
|
|
286
|
+
return {
|
|
287
|
+
...statePartArg.getState()!,
|
|
288
|
+
error: error instanceof Error ? error.message : 'Failed to delete domain',
|
|
289
|
+
};
|
|
290
|
+
}
|
|
291
|
+
},
|
|
292
|
+
);
|
|
293
|
+
|
|
294
|
+
export const syncDomainAction = domainsStatePart.createAction<{ id: string }>(
|
|
295
|
+
async (statePartArg, dataArg, actionContext): Promise<IDomainsState> => {
|
|
296
|
+
const context = getActionContext();
|
|
297
|
+
try {
|
|
298
|
+
const request = new plugins.domtools.plugins.typedrequest.TypedRequest<
|
|
299
|
+
interfaces.requests.IReq_SyncDomain
|
|
300
|
+
>('/typedrequest', 'syncDomain');
|
|
301
|
+
const response = await request.fire({ identity: context.identity!, id: dataArg.id });
|
|
302
|
+
if (!response.success) {
|
|
303
|
+
return { ...statePartArg.getState()!, error: response.message || 'Failed to sync domain' };
|
|
304
|
+
}
|
|
305
|
+
return await actionContext!.dispatch(fetchDomainsAndProvidersAction, null);
|
|
306
|
+
} catch (error: unknown) {
|
|
307
|
+
return {
|
|
308
|
+
...statePartArg.getState()!,
|
|
309
|
+
error: error instanceof Error ? error.message : 'Failed to sync domain',
|
|
310
|
+
};
|
|
311
|
+
}
|
|
312
|
+
},
|
|
313
|
+
);
|
|
314
|
+
|
|
315
|
+
export const migrateDomainAction = domainsStatePart.createAction<{
|
|
316
|
+
id: string;
|
|
317
|
+
targetSource: interfaces.data.TDomainSource;
|
|
318
|
+
targetProviderId?: string;
|
|
319
|
+
deleteExistingProviderRecords?: boolean;
|
|
320
|
+
}>(
|
|
321
|
+
async (statePartArg, dataArg, actionContext): Promise<IDomainsState> => {
|
|
322
|
+
const context = getActionContext();
|
|
323
|
+
try {
|
|
324
|
+
const request = new plugins.domtools.plugins.typedrequest.TypedRequest<
|
|
325
|
+
interfaces.requests.IReq_MigrateDomain
|
|
326
|
+
>('/typedrequest', 'migrateDomain');
|
|
327
|
+
const response = await request.fire({ identity: context.identity!, ...dataArg });
|
|
328
|
+
if (!response.success) {
|
|
329
|
+
return { ...statePartArg.getState()!, error: response.message || 'Migration failed' };
|
|
330
|
+
}
|
|
331
|
+
return await actionContext!.dispatch(fetchDomainsAndProvidersAction, null);
|
|
332
|
+
} catch (error: unknown) {
|
|
333
|
+
return {
|
|
334
|
+
...statePartArg.getState()!,
|
|
335
|
+
error: error instanceof Error ? error.message : 'Migration failed',
|
|
336
|
+
};
|
|
337
|
+
}
|
|
338
|
+
},
|
|
339
|
+
);
|
|
340
|
+
|
|
341
|
+
export const createDnsRecordAction = domainsStatePart.createAction<{
|
|
342
|
+
domainId: string;
|
|
343
|
+
name: string;
|
|
344
|
+
type: interfaces.data.TDnsRecordType;
|
|
345
|
+
value: string;
|
|
346
|
+
ttl?: number;
|
|
347
|
+
proxied?: boolean;
|
|
348
|
+
}>(async (statePartArg, dataArg, actionContext): Promise<IDomainsState> => {
|
|
349
|
+
const context = getActionContext();
|
|
350
|
+
try {
|
|
351
|
+
const request = new plugins.domtools.plugins.typedrequest.TypedRequest<
|
|
352
|
+
interfaces.requests.IReq_CreateDnsRecord
|
|
353
|
+
>('/typedrequest', 'createDnsRecord');
|
|
354
|
+
const response = await request.fire({
|
|
355
|
+
identity: context.identity!,
|
|
356
|
+
domainId: dataArg.domainId,
|
|
357
|
+
name: dataArg.name,
|
|
358
|
+
type: dataArg.type,
|
|
359
|
+
value: dataArg.value,
|
|
360
|
+
ttl: dataArg.ttl,
|
|
361
|
+
proxied: dataArg.proxied,
|
|
362
|
+
});
|
|
363
|
+
if (!response.success) {
|
|
364
|
+
return { ...statePartArg.getState()!, error: response.message || 'Failed to create record' };
|
|
365
|
+
}
|
|
366
|
+
return await actionContext!.dispatch(fetchDnsRecordsForDomainAction, { domainId: dataArg.domainId });
|
|
367
|
+
} catch (error: unknown) {
|
|
368
|
+
return {
|
|
369
|
+
...statePartArg.getState()!,
|
|
370
|
+
error: error instanceof Error ? error.message : 'Failed to create record',
|
|
371
|
+
};
|
|
372
|
+
}
|
|
373
|
+
});
|
|
374
|
+
|
|
375
|
+
export const updateDnsRecordAction = domainsStatePart.createAction<{
|
|
376
|
+
id: string;
|
|
377
|
+
domainId: string;
|
|
378
|
+
name?: string;
|
|
379
|
+
value?: string;
|
|
380
|
+
ttl?: number;
|
|
381
|
+
proxied?: boolean;
|
|
382
|
+
}>(async (statePartArg, dataArg, actionContext): Promise<IDomainsState> => {
|
|
383
|
+
const context = getActionContext();
|
|
384
|
+
try {
|
|
385
|
+
const request = new plugins.domtools.plugins.typedrequest.TypedRequest<
|
|
386
|
+
interfaces.requests.IReq_UpdateDnsRecord
|
|
387
|
+
>('/typedrequest', 'updateDnsRecord');
|
|
388
|
+
const response = await request.fire({
|
|
389
|
+
identity: context.identity!,
|
|
390
|
+
id: dataArg.id,
|
|
391
|
+
name: dataArg.name,
|
|
392
|
+
value: dataArg.value,
|
|
393
|
+
ttl: dataArg.ttl,
|
|
394
|
+
proxied: dataArg.proxied,
|
|
395
|
+
});
|
|
396
|
+
if (!response.success) {
|
|
397
|
+
return { ...statePartArg.getState()!, error: response.message || 'Failed to update record' };
|
|
398
|
+
}
|
|
399
|
+
return await actionContext!.dispatch(fetchDnsRecordsForDomainAction, { domainId: dataArg.domainId });
|
|
400
|
+
} catch (error: unknown) {
|
|
401
|
+
return {
|
|
402
|
+
...statePartArg.getState()!,
|
|
403
|
+
error: error instanceof Error ? error.message : 'Failed to update record',
|
|
404
|
+
};
|
|
405
|
+
}
|
|
406
|
+
});
|
|
407
|
+
|
|
408
|
+
export const deleteDnsRecordAction = domainsStatePart.createAction<{ id: string; domainId: string }>(
|
|
409
|
+
async (statePartArg, dataArg, actionContext): Promise<IDomainsState> => {
|
|
410
|
+
const context = getActionContext();
|
|
411
|
+
try {
|
|
412
|
+
const request = new plugins.domtools.plugins.typedrequest.TypedRequest<
|
|
413
|
+
interfaces.requests.IReq_DeleteDnsRecord
|
|
414
|
+
>('/typedrequest', 'deleteDnsRecord');
|
|
415
|
+
const response = await request.fire({ identity: context.identity!, id: dataArg.id });
|
|
416
|
+
if (!response.success) {
|
|
417
|
+
return { ...statePartArg.getState()!, error: response.message || 'Failed to delete record' };
|
|
418
|
+
}
|
|
419
|
+
return await actionContext!.dispatch(fetchDnsRecordsForDomainAction, { domainId: dataArg.domainId });
|
|
420
|
+
} catch (error: unknown) {
|
|
421
|
+
return {
|
|
422
|
+
...statePartArg.getState()!,
|
|
423
|
+
error: error instanceof Error ? error.message : 'Failed to delete record',
|
|
424
|
+
};
|
|
425
|
+
}
|
|
426
|
+
},
|
|
427
|
+
);
|
|
428
|
+
|
|
429
|
+
// ============================================================================
|
|
@@ -0,0 +1,155 @@
|
|
|
1
|
+
import * as plugins from '../plugins.js';
|
|
2
|
+
import * as interfaces from '../../ts_interfaces/index.js';
|
|
3
|
+
import { appState } from './shared.js';
|
|
4
|
+
import { getActionContext } from './login.js';
|
|
5
|
+
|
|
6
|
+
|
|
7
|
+
// ============================================================================
|
|
8
|
+
// Email Domains State
|
|
9
|
+
// ============================================================================
|
|
10
|
+
|
|
11
|
+
export interface IEmailDomainsState {
|
|
12
|
+
domains: interfaces.data.IEmailDomain[];
|
|
13
|
+
settings: interfaces.data.IEmailServerSettings | null;
|
|
14
|
+
isLoading: boolean;
|
|
15
|
+
lastUpdated: number;
|
|
16
|
+
}
|
|
17
|
+
|
|
18
|
+
export const emailDomainsStatePart = await appState.getStatePart<IEmailDomainsState>(
|
|
19
|
+
'emailDomains',
|
|
20
|
+
{
|
|
21
|
+
domains: [],
|
|
22
|
+
settings: null,
|
|
23
|
+
isLoading: false,
|
|
24
|
+
lastUpdated: 0,
|
|
25
|
+
},
|
|
26
|
+
'soft',
|
|
27
|
+
);
|
|
28
|
+
|
|
29
|
+
export const fetchEmailDomainsAction = emailDomainsStatePart.createAction(
|
|
30
|
+
async (statePartArg): Promise<IEmailDomainsState> => {
|
|
31
|
+
const context = getActionContext();
|
|
32
|
+
const currentState = statePartArg.getState()!;
|
|
33
|
+
if (!context.identity) return currentState;
|
|
34
|
+
|
|
35
|
+
try {
|
|
36
|
+
const request = new plugins.domtools.plugins.typedrequest.TypedRequest<
|
|
37
|
+
interfaces.requests.IReq_GetEmailDomains
|
|
38
|
+
>('/typedrequest', 'getEmailDomains');
|
|
39
|
+
const settingsRequest = new plugins.domtools.plugins.typedrequest.TypedRequest<
|
|
40
|
+
interfaces.requests.IReq_GetEmailServerSettings
|
|
41
|
+
>('/typedrequest', 'getEmailServerSettings');
|
|
42
|
+
const response = await request.fire({ identity: context.identity });
|
|
43
|
+
const settingsResponse = await settingsRequest.fire({ identity: context.identity });
|
|
44
|
+
return {
|
|
45
|
+
...currentState,
|
|
46
|
+
domains: response.domains,
|
|
47
|
+
settings: settingsResponse.settings,
|
|
48
|
+
isLoading: false,
|
|
49
|
+
lastUpdated: Date.now(),
|
|
50
|
+
};
|
|
51
|
+
} catch {
|
|
52
|
+
return { ...currentState, isLoading: false };
|
|
53
|
+
}
|
|
54
|
+
},
|
|
55
|
+
);
|
|
56
|
+
|
|
57
|
+
export const createEmailDomainAction = emailDomainsStatePart.createAction<{
|
|
58
|
+
linkedDomainId: string;
|
|
59
|
+
subdomain?: string;
|
|
60
|
+
dkimSelector?: string;
|
|
61
|
+
dkimKeySize?: number;
|
|
62
|
+
rotateKeys?: boolean;
|
|
63
|
+
rotationIntervalDays?: number;
|
|
64
|
+
}>(async (statePartArg, args, actionContext) => {
|
|
65
|
+
const context = getActionContext();
|
|
66
|
+
const currentState = statePartArg.getState()!;
|
|
67
|
+
try {
|
|
68
|
+
const request = new plugins.domtools.plugins.typedrequest.TypedRequest<
|
|
69
|
+
interfaces.requests.IReq_CreateEmailDomain
|
|
70
|
+
>('/typedrequest', 'createEmailDomain');
|
|
71
|
+
await request.fire({ identity: context.identity!, ...args });
|
|
72
|
+
return await actionContext!.dispatch(fetchEmailDomainsAction, null);
|
|
73
|
+
} catch {
|
|
74
|
+
return currentState;
|
|
75
|
+
}
|
|
76
|
+
});
|
|
77
|
+
|
|
78
|
+
export const updateEmailServerSettingsAction = emailDomainsStatePart.createAction<
|
|
79
|
+
interfaces.data.TEmailServerSettingsUpdate
|
|
80
|
+
>(async (statePartArg, settings, actionContext) => {
|
|
81
|
+
const context = getActionContext();
|
|
82
|
+
const currentState = statePartArg.getState()!;
|
|
83
|
+
try {
|
|
84
|
+
const request = new plugins.domtools.plugins.typedrequest.TypedRequest<
|
|
85
|
+
interfaces.requests.IReq_UpdateEmailServerSettings
|
|
86
|
+
>('/typedrequest', 'updateEmailServerSettings');
|
|
87
|
+
const response = await request.fire({ identity: context.identity!, settings });
|
|
88
|
+
if (!response.success) {
|
|
89
|
+
return currentState;
|
|
90
|
+
}
|
|
91
|
+
return await actionContext!.dispatch(fetchEmailDomainsAction, null);
|
|
92
|
+
} catch {
|
|
93
|
+
return currentState;
|
|
94
|
+
}
|
|
95
|
+
});
|
|
96
|
+
|
|
97
|
+
export const deleteEmailDomainAction = emailDomainsStatePart.createAction<string>(
|
|
98
|
+
async (statePartArg, id, actionContext) => {
|
|
99
|
+
const context = getActionContext();
|
|
100
|
+
const currentState = statePartArg.getState()!;
|
|
101
|
+
try {
|
|
102
|
+
const request = new plugins.domtools.plugins.typedrequest.TypedRequest<
|
|
103
|
+
interfaces.requests.IReq_DeleteEmailDomain
|
|
104
|
+
>('/typedrequest', 'deleteEmailDomain');
|
|
105
|
+
await request.fire({ identity: context.identity!, id });
|
|
106
|
+
return await actionContext!.dispatch(fetchEmailDomainsAction, null);
|
|
107
|
+
} catch {
|
|
108
|
+
return currentState;
|
|
109
|
+
}
|
|
110
|
+
},
|
|
111
|
+
);
|
|
112
|
+
|
|
113
|
+
export const validateEmailDomainAction = emailDomainsStatePart.createAction<string>(
|
|
114
|
+
async (statePartArg, id, actionContext) => {
|
|
115
|
+
const context = getActionContext();
|
|
116
|
+
const currentState = statePartArg.getState()!;
|
|
117
|
+
try {
|
|
118
|
+
const request = new plugins.domtools.plugins.typedrequest.TypedRequest<
|
|
119
|
+
interfaces.requests.IReq_ValidateEmailDomain
|
|
120
|
+
>('/typedrequest', 'validateEmailDomain');
|
|
121
|
+
await request.fire({ identity: context.identity!, id });
|
|
122
|
+
return await actionContext!.dispatch(fetchEmailDomainsAction, null);
|
|
123
|
+
} catch {
|
|
124
|
+
return currentState;
|
|
125
|
+
}
|
|
126
|
+
},
|
|
127
|
+
);
|
|
128
|
+
|
|
129
|
+
export const provisionEmailDomainDnsAction = emailDomainsStatePart.createAction<string>(
|
|
130
|
+
async (statePartArg, id, actionContext) => {
|
|
131
|
+
const context = getActionContext();
|
|
132
|
+
const currentState = statePartArg.getState()!;
|
|
133
|
+
try {
|
|
134
|
+
const request = new plugins.domtools.plugins.typedrequest.TypedRequest<
|
|
135
|
+
interfaces.requests.IReq_ProvisionEmailDomainDns
|
|
136
|
+
>('/typedrequest', 'provisionEmailDomainDns');
|
|
137
|
+
await request.fire({ identity: context.identity!, id });
|
|
138
|
+
return await actionContext!.dispatch(fetchEmailDomainsAction, null);
|
|
139
|
+
} catch {
|
|
140
|
+
return currentState;
|
|
141
|
+
}
|
|
142
|
+
},
|
|
143
|
+
);
|
|
144
|
+
|
|
145
|
+
// ============================================================================
|
|
146
|
+
// Email Domain Standalone Functions
|
|
147
|
+
// ============================================================================
|
|
148
|
+
|
|
149
|
+
export async function fetchEmailDomainDnsRecords(id: string) {
|
|
150
|
+
const context = getActionContext();
|
|
151
|
+
const request = new plugins.domtools.plugins.typedrequest.TypedRequest<
|
|
152
|
+
interfaces.requests.IReq_GetEmailDomainDnsRecords
|
|
153
|
+
>('/typedrequest', 'getEmailDomainDnsRecords');
|
|
154
|
+
return request.fire({ identity: context.identity!, id });
|
|
155
|
+
}
|
|
@@ -0,0 +1,57 @@
|
|
|
1
|
+
import * as plugins from '../plugins.js';
|
|
2
|
+
import * as interfaces from '../../ts_interfaces/index.js';
|
|
3
|
+
import { appState } from './shared.js';
|
|
4
|
+
import { getActionContext } from './login.js';
|
|
5
|
+
|
|
6
|
+
export interface IEmailOpsState {
|
|
7
|
+
emails: interfaces.requests.IEmail[];
|
|
8
|
+
isLoading: boolean;
|
|
9
|
+
error: string | null;
|
|
10
|
+
lastUpdated: number;
|
|
11
|
+
}
|
|
12
|
+
|
|
13
|
+
export const emailOpsStatePart = await appState.getStatePart<IEmailOpsState>(
|
|
14
|
+
'emailOps',
|
|
15
|
+
{
|
|
16
|
+
emails: [],
|
|
17
|
+
isLoading: false,
|
|
18
|
+
error: null,
|
|
19
|
+
lastUpdated: 0,
|
|
20
|
+
},
|
|
21
|
+
'soft'
|
|
22
|
+
);
|
|
23
|
+
|
|
24
|
+
// Email Operations Actions
|
|
25
|
+
// ============================================================================
|
|
26
|
+
|
|
27
|
+
// Fetch All Emails Action
|
|
28
|
+
export const fetchAllEmailsAction = emailOpsStatePart.createAction(async (statePartArg): Promise<IEmailOpsState> => {
|
|
29
|
+
const context = getActionContext();
|
|
30
|
+
const currentState = statePartArg.getState()!;
|
|
31
|
+
if (!context.identity) return currentState;
|
|
32
|
+
|
|
33
|
+
try {
|
|
34
|
+
const request = new plugins.domtools.plugins.typedrequest.TypedRequest<
|
|
35
|
+
interfaces.requests.IReq_GetAllEmails
|
|
36
|
+
>('/typedrequest', 'getAllEmails');
|
|
37
|
+
|
|
38
|
+
const response = await request.fire({
|
|
39
|
+
identity: context.identity,
|
|
40
|
+
});
|
|
41
|
+
|
|
42
|
+
return {
|
|
43
|
+
emails: response.emails,
|
|
44
|
+
isLoading: false,
|
|
45
|
+
error: null,
|
|
46
|
+
lastUpdated: Date.now(),
|
|
47
|
+
};
|
|
48
|
+
} catch (error) {
|
|
49
|
+
return {
|
|
50
|
+
...currentState,
|
|
51
|
+
isLoading: false,
|
|
52
|
+
error: error instanceof Error ? error.message : 'Failed to fetch emails',
|
|
53
|
+
};
|
|
54
|
+
}
|
|
55
|
+
});
|
|
56
|
+
|
|
57
|
+
// ============================================================================
|