@serve.zone/dcrouter 11.10.3 → 11.10.7

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.
Files changed (76) hide show
  1. package/dist_serve/bundle.js +5102 -5102
  2. package/dist_ts/00_commitinfo_data.js +1 -1
  3. package/dist_ts/cache/classes.cache.cleaner.js +1 -1
  4. package/dist_ts/cache/classes.cached.document.js +1 -1
  5. package/dist_ts/cache/classes.cachedb.js +1 -1
  6. package/dist_ts/cache/documents/classes.cached.email.js +1 -1
  7. package/dist_ts/cache/documents/classes.cached.ip.reputation.js +1 -1
  8. package/dist_ts/classes.dcrouter.js +3 -3
  9. package/dist_ts/config/classes.route-config-manager.d.ts +1 -1
  10. package/dist_ts/config/validator.js +1 -1
  11. package/dist_ts/errors/base.errors.js +2 -2
  12. package/dist_ts/monitoring/classes.metricsmanager.d.ts +6 -1
  13. package/dist_ts/monitoring/classes.metricsmanager.js +69 -31
  14. package/dist_ts/opsserver/classes.opsserver.js +2 -2
  15. package/dist_ts/opsserver/handlers/admin.handler.js +1 -1
  16. package/dist_ts/opsserver/handlers/certificate.handler.js +1 -1
  17. package/dist_ts/opsserver/handlers/radius.handler.js +1 -1
  18. package/dist_ts/opsserver/handlers/stats.handler.js +1 -1
  19. package/dist_ts/radius/classes.accounting.manager.js +1 -1
  20. package/dist_ts/radius/classes.radius.server.js +1 -1
  21. package/dist_ts/radius/classes.vlan.manager.js +1 -1
  22. package/dist_ts/security/classes.contentscanner.js +3 -3
  23. package/dist_ts/security/classes.ipreputationchecker.js +4 -4
  24. package/dist_ts/security/classes.securitylogger.js +5 -3
  25. package/dist_ts/sms/classes.smsservice.js +2 -2
  26. package/dist_ts/storage/classes.storagemanager.d.ts +1 -1
  27. package/dist_ts/storage/classes.storagemanager.js +2 -4
  28. package/dist_ts_web/00_commitinfo_data.js +1 -1
  29. package/dist_ts_web/appstate.js +9 -6
  30. package/dist_ts_web/elements/ops-dashboard.js +3 -2
  31. package/dist_ts_web/elements/ops-view-certificates.js +1 -1
  32. package/dist_ts_web/elements/ops-view-config.js +1 -1
  33. package/dist_ts_web/elements/ops-view-emails.js +1 -1
  34. package/dist_ts_web/elements/ops-view-network.js +1 -1
  35. package/dist_ts_web/elements/ops-view-remoteingress.js +1 -1
  36. package/dist_ts_web/router.js +1 -1
  37. package/license +21 -0
  38. package/package.json +15 -15
  39. package/readme.hints.md +1 -1
  40. package/readme.md +1 -1
  41. package/ts/00_commitinfo_data.ts +1 -1
  42. package/ts/cache/classes.cache.cleaner.ts +10 -10
  43. package/ts/cache/classes.cached.document.ts +1 -1
  44. package/ts/cache/classes.cachedb.ts +6 -6
  45. package/ts/cache/documents/classes.cached.email.ts +14 -14
  46. package/ts/cache/documents/classes.cached.ip.reputation.ts +10 -10
  47. package/ts/classes.dcrouter.ts +31 -31
  48. package/ts/config/validator.ts +5 -5
  49. package/ts/errors/base.errors.ts +1 -1
  50. package/ts/monitoring/classes.metricsmanager.ts +70 -33
  51. package/ts/opsserver/classes.opsserver.ts +13 -13
  52. package/ts/opsserver/handlers/admin.handler.ts +1 -1
  53. package/ts/opsserver/handlers/certificate.handler.ts +6 -6
  54. package/ts/opsserver/handlers/radius.handler.ts +4 -4
  55. package/ts/opsserver/handlers/stats.handler.ts +1 -1
  56. package/ts/radius/classes.accounting.manager.ts +10 -10
  57. package/ts/radius/classes.radius.server.ts +2 -2
  58. package/ts/radius/classes.vlan.manager.ts +5 -5
  59. package/ts/readme.md +1 -1
  60. package/ts/security/classes.contentscanner.ts +12 -12
  61. package/ts/security/classes.ipreputationchecker.ts +26 -26
  62. package/ts/security/classes.securitylogger.ts +6 -4
  63. package/ts/sms/classes.smsservice.ts +3 -3
  64. package/ts/storage/classes.storagemanager.ts +23 -25
  65. package/ts_apiclient/readme.md +1 -1
  66. package/ts_web/00_commitinfo_data.ts +1 -1
  67. package/ts_web/appstate.ts +136 -133
  68. package/ts_web/elements/ops-dashboard.ts +15 -14
  69. package/ts_web/elements/ops-view-certificates.ts +10 -10
  70. package/ts_web/elements/ops-view-config.ts +8 -8
  71. package/ts_web/elements/ops-view-emails.ts +2 -2
  72. package/ts_web/elements/ops-view-network.ts +2 -2
  73. package/ts_web/elements/ops-view-remoteingress.ts +6 -6
  74. package/ts_web/readme.md +1 -1
  75. package/ts_web/router.ts +3 -3
  76. /package/{npmextra.json → .smartconfig.json} +0 -0
@@ -240,7 +240,7 @@ interface IActionContext {
240
240
  }
241
241
 
242
242
  const getActionContext = (): IActionContext => {
243
- const identity = loginStatePart.getState().identity;
243
+ const identity = loginStatePart.getState()!.identity;
244
244
  // Treat expired JWTs as no identity — prevents stale persisted sessions from firing requests
245
245
  if (identity && identity.expiresAt && identity.expiresAt < Date.now()) {
246
246
  return { identity: null };
@@ -252,7 +252,7 @@ const getActionContext = (): IActionContext => {
252
252
  export const loginAction = loginStatePart.createAction<{
253
253
  username: string;
254
254
  password: string;
255
- }>(async (statePartArg, dataArg) => {
255
+ }>(async (statePartArg, dataArg): Promise<ILoginState> => {
256
256
  const typedRequest = new plugins.domtools.plugins.typedrequest.TypedRequest<
257
257
  interfaces.requests.IReq_AdminLoginWithUsernameAndPassword
258
258
  >('/typedrequest', 'adminLoginWithUsernameAndPassword');
@@ -269,10 +269,10 @@ export const loginAction = loginStatePart.createAction<{
269
269
  isLoggedIn: true,
270
270
  };
271
271
  }
272
- return statePartArg.getState();
273
- } catch (error) {
272
+ return statePartArg.getState()!;
273
+ } catch (error: unknown) {
274
274
  console.error('Login failed:', error);
275
- return statePartArg.getState();
275
+ return statePartArg.getState()!;
276
276
  }
277
277
  });
278
278
 
@@ -300,9 +300,9 @@ export const logoutAction = loginStatePart.createAction(async (statePartArg) =>
300
300
  });
301
301
 
302
302
  // Fetch All Stats Action - Using combined endpoint for efficiency
303
- export const fetchAllStatsAction = statsStatePart.createAction(async (statePartArg) => {
303
+ export const fetchAllStatsAction = statsStatePart.createAction(async (statePartArg): Promise<IStatsState> => {
304
304
  const context = getActionContext();
305
- const currentState = statePartArg.getState();
305
+ const currentState = statePartArg.getState()!;
306
306
  if (!context.identity) return currentState;
307
307
 
308
308
  try {
@@ -310,7 +310,7 @@ export const fetchAllStatsAction = statsStatePart.createAction(async (statePartA
310
310
  const combinedRequest = new plugins.domtools.plugins.typedrequest.TypedRequest<
311
311
  interfaces.requests.IReq_GetCombinedMetrics
312
312
  >('/typedrequest', 'getCombinedMetrics');
313
-
313
+
314
314
  const combinedResponse = await combinedRequest.fire({
315
315
  identity: context.identity,
316
316
  sections: {
@@ -332,19 +332,19 @@ export const fetchAllStatsAction = statsStatePart.createAction(async (statePartA
332
332
  isLoading: false,
333
333
  error: null,
334
334
  };
335
- } catch (error) {
335
+ } catch (error: unknown) {
336
336
  return {
337
337
  ...currentState,
338
338
  isLoading: false,
339
- error: error.message || 'Failed to fetch statistics',
339
+ error: (error as Error).message || 'Failed to fetch statistics',
340
340
  };
341
341
  }
342
342
  });
343
343
 
344
344
  // Fetch Configuration Action (read-only)
345
- export const fetchConfigurationAction = configStatePart.createAction(async (statePartArg) => {
345
+ export const fetchConfigurationAction = configStatePart.createAction(async (statePartArg): Promise<IConfigState> => {
346
346
  const context = getActionContext();
347
- const currentState = statePartArg.getState();
347
+ const currentState = statePartArg.getState()!;
348
348
  if (!context.identity) return currentState;
349
349
 
350
350
  try {
@@ -361,11 +361,11 @@ export const fetchConfigurationAction = configStatePart.createAction(async (stat
361
361
  isLoading: false,
362
362
  error: null,
363
363
  };
364
- } catch (error) {
364
+ } catch (error: unknown) {
365
365
  return {
366
366
  ...currentState,
367
367
  isLoading: false,
368
- error: error.message || 'Failed to fetch configuration',
368
+ error: (error as Error).message || 'Failed to fetch configuration',
369
369
  };
370
370
  }
371
371
  });
@@ -375,9 +375,9 @@ export const fetchRecentLogsAction = logStatePart.createAction<{
375
375
  limit?: number;
376
376
  level?: 'debug' | 'info' | 'warn' | 'error';
377
377
  category?: 'smtp' | 'dns' | 'security' | 'system' | 'email';
378
- }>(async (statePartArg, dataArg) => {
378
+ }>(async (statePartArg, dataArg): Promise<ILogState> => {
379
379
  const context = getActionContext();
380
- if (!context.identity) return statePartArg.getState();
380
+ if (!context.identity) return statePartArg.getState()!;
381
381
 
382
382
  const logsRequest = new plugins.domtools.plugins.typedrequest.TypedRequest<
383
383
  interfaces.requests.IReq_GetRecentLogs
@@ -391,14 +391,14 @@ export const fetchRecentLogsAction = logStatePart.createAction<{
391
391
  });
392
392
 
393
393
  return {
394
- ...statePartArg.getState(),
394
+ ...statePartArg.getState()!,
395
395
  recentLogs: response.logs,
396
396
  };
397
397
  });
398
398
 
399
399
  // Toggle Auto Refresh Action
400
- export const toggleAutoRefreshAction = uiStatePart.createAction(async (statePartArg) => {
401
- const currentState = statePartArg.getState();
400
+ export const toggleAutoRefreshAction = uiStatePart.createAction(async (statePartArg): Promise<IUiState> => {
401
+ const currentState = statePartArg.getState()!;
402
402
  return {
403
403
  ...currentState,
404
404
  autoRefresh: !currentState.autoRefresh,
@@ -406,9 +406,9 @@ export const toggleAutoRefreshAction = uiStatePart.createAction(async (statePart
406
406
  });
407
407
 
408
408
  // Set Active View Action
409
- export const setActiveViewAction = uiStatePart.createAction<string>(async (statePartArg, viewName) => {
410
- const currentState = statePartArg.getState();
411
-
409
+ export const setActiveViewAction = uiStatePart.createAction<string>(async (statePartArg, viewName): Promise<IUiState> => {
410
+ const currentState = statePartArg.getState()!;
411
+
412
412
  // If switching to network view, ensure we fetch network data
413
413
  if (viewName === 'network' && currentState.activeView !== 'network') {
414
414
  setTimeout(() => {
@@ -451,9 +451,9 @@ export const setActiveViewAction = uiStatePart.createAction<string>(async (state
451
451
  });
452
452
 
453
453
  // Fetch Network Stats Action
454
- export const fetchNetworkStatsAction = networkStatePart.createAction(async (statePartArg) => {
454
+ export const fetchNetworkStatsAction = networkStatePart.createAction(async (statePartArg): Promise<INetworkState> => {
455
455
  const context = getActionContext();
456
- const currentState = statePartArg.getState();
456
+ const currentState = statePartArg.getState()!;
457
457
  if (!context.identity) return currentState;
458
458
 
459
459
  try {
@@ -525,9 +525,9 @@ export const fetchNetworkStatsAction = networkStatePart.createAction(async (stat
525
525
  // ============================================================================
526
526
 
527
527
  // Fetch All Emails Action
528
- export const fetchAllEmailsAction = emailOpsStatePart.createAction(async (statePartArg) => {
528
+ export const fetchAllEmailsAction = emailOpsStatePart.createAction(async (statePartArg): Promise<IEmailOpsState> => {
529
529
  const context = getActionContext();
530
- const currentState = statePartArg.getState();
530
+ const currentState = statePartArg.getState()!;
531
531
  if (!context.identity) return currentState;
532
532
 
533
533
  try {
@@ -558,9 +558,9 @@ export const fetchAllEmailsAction = emailOpsStatePart.createAction(async (stateP
558
558
  // Certificate Actions
559
559
  // ============================================================================
560
560
 
561
- export const fetchCertificateOverviewAction = certificateStatePart.createAction(async (statePartArg) => {
561
+ export const fetchCertificateOverviewAction = certificateStatePart.createAction(async (statePartArg): Promise<ICertificateState> => {
562
562
  const context = getActionContext();
563
- const currentState = statePartArg.getState();
563
+ const currentState = statePartArg.getState()!;
564
564
  if (!context.identity) return currentState;
565
565
 
566
566
  try {
@@ -589,9 +589,9 @@ export const fetchCertificateOverviewAction = certificateStatePart.createAction(
589
589
  });
590
590
 
591
591
  export const reprovisionCertificateAction = certificateStatePart.createAction<string>(
592
- async (statePartArg, domain, actionContext) => {
592
+ async (statePartArg, domain, actionContext): Promise<ICertificateState> => {
593
593
  const context = getActionContext();
594
- const currentState = statePartArg.getState();
594
+ const currentState = statePartArg.getState()!;
595
595
 
596
596
  try {
597
597
  const request = new plugins.domtools.plugins.typedrequest.TypedRequest<
@@ -599,13 +599,13 @@ export const reprovisionCertificateAction = certificateStatePart.createAction<st
599
599
  >('/typedrequest', 'reprovisionCertificateDomain');
600
600
 
601
601
  await request.fire({
602
- identity: context.identity,
602
+ identity: context.identity!,
603
603
  domain,
604
604
  });
605
605
 
606
606
  // Re-fetch overview after reprovisioning
607
- return await actionContext.dispatch(fetchCertificateOverviewAction, null);
608
- } catch (error) {
607
+ return await actionContext!.dispatch(fetchCertificateOverviewAction, null);
608
+ } catch (error: unknown) {
609
609
  return {
610
610
  ...currentState,
611
611
  error: error instanceof Error ? error.message : 'Failed to reprovision certificate',
@@ -615,9 +615,9 @@ export const reprovisionCertificateAction = certificateStatePart.createAction<st
615
615
  );
616
616
 
617
617
  export const deleteCertificateAction = certificateStatePart.createAction<string>(
618
- async (statePartArg, domain, actionContext) => {
618
+ async (statePartArg, domain, actionContext): Promise<ICertificateState> => {
619
619
  const context = getActionContext();
620
- const currentState = statePartArg.getState();
620
+ const currentState = statePartArg.getState()!;
621
621
 
622
622
  try {
623
623
  const request = new plugins.domtools.plugins.typedrequest.TypedRequest<
@@ -625,13 +625,13 @@ export const deleteCertificateAction = certificateStatePart.createAction<string>
625
625
  >('/typedrequest', 'deleteCertificate');
626
626
 
627
627
  await request.fire({
628
- identity: context.identity,
628
+ identity: context.identity!,
629
629
  domain,
630
630
  });
631
631
 
632
632
  // Re-fetch overview after deletion
633
- return await actionContext.dispatch(fetchCertificateOverviewAction, null);
634
- } catch (error) {
633
+ return await actionContext!.dispatch(fetchCertificateOverviewAction, null);
634
+ } catch (error: unknown) {
635
635
  return {
636
636
  ...currentState,
637
637
  error: error instanceof Error ? error.message : 'Failed to delete certificate',
@@ -649,9 +649,9 @@ export const importCertificateAction = certificateStatePart.createAction<{
649
649
  publicKey: string;
650
650
  csr: string;
651
651
  }>(
652
- async (statePartArg, cert, actionContext) => {
652
+ async (statePartArg, cert, actionContext): Promise<ICertificateState> => {
653
653
  const context = getActionContext();
654
- const currentState = statePartArg.getState();
654
+ const currentState = statePartArg.getState()!;
655
655
 
656
656
  try {
657
657
  const request = new plugins.domtools.plugins.typedrequest.TypedRequest<
@@ -659,13 +659,13 @@ export const importCertificateAction = certificateStatePart.createAction<{
659
659
  >('/typedrequest', 'importCertificate');
660
660
 
661
661
  await request.fire({
662
- identity: context.identity,
662
+ identity: context.identity!,
663
663
  cert,
664
664
  });
665
665
 
666
666
  // Re-fetch overview after import
667
- return await actionContext.dispatch(fetchCertificateOverviewAction, null);
668
- } catch (error) {
667
+ return await actionContext!.dispatch(fetchCertificateOverviewAction, null);
668
+ } catch (error: unknown) {
669
669
  return {
670
670
  ...currentState,
671
671
  error: error instanceof Error ? error.message : 'Failed to import certificate',
@@ -681,7 +681,7 @@ export async function fetchCertificateExport(domain: string) {
681
681
  >('/typedrequest', 'exportCertificate');
682
682
 
683
683
  return request.fire({
684
- identity: context.identity,
684
+ identity: context.identity!,
685
685
  domain,
686
686
  });
687
687
  }
@@ -695,16 +695,16 @@ export async function fetchConnectionToken(edgeId: string) {
695
695
  const request = new plugins.domtools.plugins.typedrequest.TypedRequest<
696
696
  interfaces.requests.IReq_GetRemoteIngressConnectionToken
697
697
  >('/typedrequest', 'getRemoteIngressConnectionToken');
698
- return request.fire({ identity: context.identity, edgeId });
698
+ return request.fire({ identity: context.identity!, edgeId });
699
699
  }
700
700
 
701
701
  // ============================================================================
702
702
  // Remote Ingress Actions
703
703
  // ============================================================================
704
704
 
705
- export const fetchRemoteIngressAction = remoteIngressStatePart.createAction(async (statePartArg) => {
705
+ export const fetchRemoteIngressAction = remoteIngressStatePart.createAction(async (statePartArg): Promise<IRemoteIngressState> => {
706
706
  const context = getActionContext();
707
- const currentState = statePartArg.getState();
707
+ const currentState = statePartArg.getState()!;
708
708
  if (!context.identity) return currentState;
709
709
 
710
710
  try {
@@ -743,9 +743,9 @@ export const createRemoteIngressAction = remoteIngressStatePart.createAction<{
743
743
  listenPorts?: number[];
744
744
  autoDerivePorts?: boolean;
745
745
  tags?: string[];
746
- }>(async (statePartArg, dataArg, actionContext) => {
746
+ }>(async (statePartArg, dataArg, actionContext): Promise<IRemoteIngressState> => {
747
747
  const context = getActionContext();
748
- const currentState = statePartArg.getState();
748
+ const currentState = statePartArg.getState()!;
749
749
 
750
750
  try {
751
751
  const request = new plugins.domtools.plugins.typedrequest.TypedRequest<
@@ -753,7 +753,7 @@ export const createRemoteIngressAction = remoteIngressStatePart.createAction<{
753
753
  >('/typedrequest', 'createRemoteIngress');
754
754
 
755
755
  const response = await request.fire({
756
- identity: context.identity,
756
+ identity: context.identity!,
757
757
  name: dataArg.name,
758
758
  listenPorts: dataArg.listenPorts,
759
759
  autoDerivePorts: dataArg.autoDerivePorts,
@@ -762,16 +762,16 @@ export const createRemoteIngressAction = remoteIngressStatePart.createAction<{
762
762
 
763
763
  if (response.success) {
764
764
  // Refresh the list
765
- await actionContext.dispatch(fetchRemoteIngressAction, null);
765
+ await actionContext!.dispatch(fetchRemoteIngressAction, null);
766
766
 
767
767
  return {
768
- ...statePartArg.getState(),
768
+ ...statePartArg.getState()!,
769
769
  newEdgeId: response.edge.id,
770
770
  };
771
771
  }
772
772
 
773
773
  return currentState;
774
- } catch (error) {
774
+ } catch (error: unknown) {
775
775
  return {
776
776
  ...currentState,
777
777
  error: error instanceof Error ? error.message : 'Failed to create edge',
@@ -780,9 +780,9 @@ export const createRemoteIngressAction = remoteIngressStatePart.createAction<{
780
780
  });
781
781
 
782
782
  export const deleteRemoteIngressAction = remoteIngressStatePart.createAction<string>(
783
- async (statePartArg, edgeId, actionContext) => {
783
+ async (statePartArg, edgeId, actionContext): Promise<IRemoteIngressState> => {
784
784
  const context = getActionContext();
785
- const currentState = statePartArg.getState();
785
+ const currentState = statePartArg.getState()!;
786
786
 
787
787
  try {
788
788
  const request = new plugins.domtools.plugins.typedrequest.TypedRequest<
@@ -790,12 +790,12 @@ export const deleteRemoteIngressAction = remoteIngressStatePart.createAction<str
790
790
  >('/typedrequest', 'deleteRemoteIngress');
791
791
 
792
792
  await request.fire({
793
- identity: context.identity,
793
+ identity: context.identity!,
794
794
  id: edgeId,
795
795
  });
796
796
 
797
- return await actionContext.dispatch(fetchRemoteIngressAction, null);
798
- } catch (error) {
797
+ return await actionContext!.dispatch(fetchRemoteIngressAction, null);
798
+ } catch (error: unknown) {
799
799
  return {
800
800
  ...currentState,
801
801
  error: error instanceof Error ? error.message : 'Failed to delete edge',
@@ -810,9 +810,9 @@ export const updateRemoteIngressAction = remoteIngressStatePart.createAction<{
810
810
  listenPorts?: number[];
811
811
  autoDerivePorts?: boolean;
812
812
  tags?: string[];
813
- }>(async (statePartArg, dataArg, actionContext) => {
813
+ }>(async (statePartArg, dataArg, actionContext): Promise<IRemoteIngressState> => {
814
814
  const context = getActionContext();
815
- const currentState = statePartArg.getState();
815
+ const currentState = statePartArg.getState()!;
816
816
 
817
817
  try {
818
818
  const request = new plugins.domtools.plugins.typedrequest.TypedRequest<
@@ -820,7 +820,7 @@ export const updateRemoteIngressAction = remoteIngressStatePart.createAction<{
820
820
  >('/typedrequest', 'updateRemoteIngress');
821
821
 
822
822
  await request.fire({
823
- identity: context.identity,
823
+ identity: context.identity!,
824
824
  id: dataArg.id,
825
825
  name: dataArg.name,
826
826
  listenPorts: dataArg.listenPorts,
@@ -828,8 +828,8 @@ export const updateRemoteIngressAction = remoteIngressStatePart.createAction<{
828
828
  tags: dataArg.tags,
829
829
  });
830
830
 
831
- return await actionContext.dispatch(fetchRemoteIngressAction, null);
832
- } catch (error) {
831
+ return await actionContext!.dispatch(fetchRemoteIngressAction, null);
832
+ } catch (error: unknown) {
833
833
  return {
834
834
  ...currentState,
835
835
  error: error instanceof Error ? error.message : 'Failed to update edge',
@@ -838,9 +838,9 @@ export const updateRemoteIngressAction = remoteIngressStatePart.createAction<{
838
838
  });
839
839
 
840
840
  export const regenerateRemoteIngressSecretAction = remoteIngressStatePart.createAction<string>(
841
- async (statePartArg, edgeId) => {
841
+ async (statePartArg, edgeId): Promise<IRemoteIngressState> => {
842
842
  const context = getActionContext();
843
- const currentState = statePartArg.getState();
843
+ const currentState = statePartArg.getState()!;
844
844
 
845
845
  try {
846
846
  const request = new plugins.domtools.plugins.typedrequest.TypedRequest<
@@ -848,7 +848,7 @@ export const regenerateRemoteIngressSecretAction = remoteIngressStatePart.create
848
848
  >('/typedrequest', 'regenerateRemoteIngressSecret');
849
849
 
850
850
  const response = await request.fire({
851
- identity: context.identity,
851
+ identity: context.identity!,
852
852
  id: edgeId,
853
853
  });
854
854
 
@@ -870,9 +870,9 @@ export const regenerateRemoteIngressSecretAction = remoteIngressStatePart.create
870
870
  );
871
871
 
872
872
  export const clearNewEdgeIdAction = remoteIngressStatePart.createAction(
873
- async (statePartArg) => {
873
+ async (statePartArg): Promise<IRemoteIngressState> => {
874
874
  return {
875
- ...statePartArg.getState(),
875
+ ...statePartArg.getState()!,
876
876
  newEdgeId: null,
877
877
  };
878
878
  }
@@ -881,9 +881,9 @@ export const clearNewEdgeIdAction = remoteIngressStatePart.createAction(
881
881
  export const toggleRemoteIngressAction = remoteIngressStatePart.createAction<{
882
882
  id: string;
883
883
  enabled: boolean;
884
- }>(async (statePartArg, dataArg, actionContext) => {
884
+ }>(async (statePartArg, dataArg, actionContext): Promise<IRemoteIngressState> => {
885
885
  const context = getActionContext();
886
- const currentState = statePartArg.getState();
886
+ const currentState = statePartArg.getState()!;
887
887
 
888
888
  try {
889
889
  const request = new plugins.domtools.plugins.typedrequest.TypedRequest<
@@ -891,13 +891,13 @@ export const toggleRemoteIngressAction = remoteIngressStatePart.createAction<{
891
891
  >('/typedrequest', 'updateRemoteIngress');
892
892
 
893
893
  await request.fire({
894
- identity: context.identity,
894
+ identity: context.identity!,
895
895
  id: dataArg.id,
896
896
  enabled: dataArg.enabled,
897
897
  });
898
898
 
899
- return await actionContext.dispatch(fetchRemoteIngressAction, null);
900
- } catch (error) {
899
+ return await actionContext!.dispatch(fetchRemoteIngressAction, null);
900
+ } catch (error: unknown) {
901
901
  return {
902
902
  ...currentState,
903
903
  error: error instanceof Error ? error.message : 'Failed to toggle edge',
@@ -909,9 +909,9 @@ export const toggleRemoteIngressAction = remoteIngressStatePart.createAction<{
909
909
  // Route Management Actions
910
910
  // ============================================================================
911
911
 
912
- export const fetchMergedRoutesAction = routeManagementStatePart.createAction(async (statePartArg) => {
912
+ export const fetchMergedRoutesAction = routeManagementStatePart.createAction(async (statePartArg): Promise<IRouteManagementState> => {
913
913
  const context = getActionContext();
914
- const currentState = statePartArg.getState();
914
+ const currentState = statePartArg.getState()!;
915
915
  if (!context.identity) return currentState;
916
916
 
917
917
  try {
@@ -943,9 +943,9 @@ export const fetchMergedRoutesAction = routeManagementStatePart.createAction(asy
943
943
  export const createRouteAction = routeManagementStatePart.createAction<{
944
944
  route: any;
945
945
  enabled?: boolean;
946
- }>(async (statePartArg, dataArg, actionContext) => {
946
+ }>(async (statePartArg, dataArg, actionContext): Promise<IRouteManagementState> => {
947
947
  const context = getActionContext();
948
- const currentState = statePartArg.getState();
948
+ const currentState = statePartArg.getState()!;
949
949
 
950
950
  try {
951
951
  const request = new plugins.domtools.plugins.typedrequest.TypedRequest<
@@ -953,13 +953,13 @@ export const createRouteAction = routeManagementStatePart.createAction<{
953
953
  >('/typedrequest', 'createRoute');
954
954
 
955
955
  await request.fire({
956
- identity: context.identity,
956
+ identity: context.identity!,
957
957
  route: dataArg.route,
958
958
  enabled: dataArg.enabled,
959
959
  });
960
960
 
961
- return await actionContext.dispatch(fetchMergedRoutesAction, null);
962
- } catch (error) {
961
+ return await actionContext!.dispatch(fetchMergedRoutesAction, null);
962
+ } catch (error: unknown) {
963
963
  return {
964
964
  ...currentState,
965
965
  error: error instanceof Error ? error.message : 'Failed to create route',
@@ -968,9 +968,9 @@ export const createRouteAction = routeManagementStatePart.createAction<{
968
968
  });
969
969
 
970
970
  export const deleteRouteAction = routeManagementStatePart.createAction<string>(
971
- async (statePartArg, routeId, actionContext) => {
971
+ async (statePartArg, routeId, actionContext): Promise<IRouteManagementState> => {
972
972
  const context = getActionContext();
973
- const currentState = statePartArg.getState();
973
+ const currentState = statePartArg.getState()!;
974
974
 
975
975
  try {
976
976
  const request = new plugins.domtools.plugins.typedrequest.TypedRequest<
@@ -978,12 +978,12 @@ export const deleteRouteAction = routeManagementStatePart.createAction<string>(
978
978
  >('/typedrequest', 'deleteRoute');
979
979
 
980
980
  await request.fire({
981
- identity: context.identity,
981
+ identity: context.identity!,
982
982
  id: routeId,
983
983
  });
984
984
 
985
- return await actionContext.dispatch(fetchMergedRoutesAction, null);
986
- } catch (error) {
985
+ return await actionContext!.dispatch(fetchMergedRoutesAction, null);
986
+ } catch (error: unknown) {
987
987
  return {
988
988
  ...currentState,
989
989
  error: error instanceof Error ? error.message : 'Failed to delete route',
@@ -995,9 +995,9 @@ export const deleteRouteAction = routeManagementStatePart.createAction<string>(
995
995
  export const toggleRouteAction = routeManagementStatePart.createAction<{
996
996
  id: string;
997
997
  enabled: boolean;
998
- }>(async (statePartArg, dataArg, actionContext) => {
998
+ }>(async (statePartArg, dataArg, actionContext): Promise<IRouteManagementState> => {
999
999
  const context = getActionContext();
1000
- const currentState = statePartArg.getState();
1000
+ const currentState = statePartArg.getState()!;
1001
1001
 
1002
1002
  try {
1003
1003
  const request = new plugins.domtools.plugins.typedrequest.TypedRequest<
@@ -1005,13 +1005,13 @@ export const toggleRouteAction = routeManagementStatePart.createAction<{
1005
1005
  >('/typedrequest', 'toggleRoute');
1006
1006
 
1007
1007
  await request.fire({
1008
- identity: context.identity,
1008
+ identity: context.identity!,
1009
1009
  id: dataArg.id,
1010
1010
  enabled: dataArg.enabled,
1011
1011
  });
1012
1012
 
1013
- return await actionContext.dispatch(fetchMergedRoutesAction, null);
1014
- } catch (error) {
1013
+ return await actionContext!.dispatch(fetchMergedRoutesAction, null);
1014
+ } catch (error: unknown) {
1015
1015
  return {
1016
1016
  ...currentState,
1017
1017
  error: error instanceof Error ? error.message : 'Failed to toggle route',
@@ -1022,9 +1022,9 @@ export const toggleRouteAction = routeManagementStatePart.createAction<{
1022
1022
  export const setRouteOverrideAction = routeManagementStatePart.createAction<{
1023
1023
  routeName: string;
1024
1024
  enabled: boolean;
1025
- }>(async (statePartArg, dataArg, actionContext) => {
1025
+ }>(async (statePartArg, dataArg, actionContext): Promise<IRouteManagementState> => {
1026
1026
  const context = getActionContext();
1027
- const currentState = statePartArg.getState();
1027
+ const currentState = statePartArg.getState()!;
1028
1028
 
1029
1029
  try {
1030
1030
  const request = new plugins.domtools.plugins.typedrequest.TypedRequest<
@@ -1032,13 +1032,13 @@ export const setRouteOverrideAction = routeManagementStatePart.createAction<{
1032
1032
  >('/typedrequest', 'setRouteOverride');
1033
1033
 
1034
1034
  await request.fire({
1035
- identity: context.identity,
1035
+ identity: context.identity!,
1036
1036
  routeName: dataArg.routeName,
1037
1037
  enabled: dataArg.enabled,
1038
1038
  });
1039
1039
 
1040
- return await actionContext.dispatch(fetchMergedRoutesAction, null);
1041
- } catch (error) {
1040
+ return await actionContext!.dispatch(fetchMergedRoutesAction, null);
1041
+ } catch (error: unknown) {
1042
1042
  return {
1043
1043
  ...currentState,
1044
1044
  error: error instanceof Error ? error.message : 'Failed to set override',
@@ -1047,9 +1047,9 @@ export const setRouteOverrideAction = routeManagementStatePart.createAction<{
1047
1047
  });
1048
1048
 
1049
1049
  export const removeRouteOverrideAction = routeManagementStatePart.createAction<string>(
1050
- async (statePartArg, routeName, actionContext) => {
1050
+ async (statePartArg, routeName, actionContext): Promise<IRouteManagementState> => {
1051
1051
  const context = getActionContext();
1052
- const currentState = statePartArg.getState();
1052
+ const currentState = statePartArg.getState()!;
1053
1053
 
1054
1054
  try {
1055
1055
  const request = new plugins.domtools.plugins.typedrequest.TypedRequest<
@@ -1057,12 +1057,12 @@ export const removeRouteOverrideAction = routeManagementStatePart.createAction<s
1057
1057
  >('/typedrequest', 'removeRouteOverride');
1058
1058
 
1059
1059
  await request.fire({
1060
- identity: context.identity,
1060
+ identity: context.identity!,
1061
1061
  routeName,
1062
1062
  });
1063
1063
 
1064
- return await actionContext.dispatch(fetchMergedRoutesAction, null);
1065
- } catch (error) {
1064
+ return await actionContext!.dispatch(fetchMergedRoutesAction, null);
1065
+ } catch (error: unknown) {
1066
1066
  return {
1067
1067
  ...currentState,
1068
1068
  error: error instanceof Error ? error.message : 'Failed to remove override',
@@ -1075,9 +1075,9 @@ export const removeRouteOverrideAction = routeManagementStatePart.createAction<s
1075
1075
  // API Token Actions
1076
1076
  // ============================================================================
1077
1077
 
1078
- export const fetchApiTokensAction = routeManagementStatePart.createAction(async (statePartArg) => {
1078
+ export const fetchApiTokensAction = routeManagementStatePart.createAction(async (statePartArg): Promise<IRouteManagementState> => {
1079
1079
  const context = getActionContext();
1080
- const currentState = statePartArg.getState();
1080
+ const currentState = statePartArg.getState()!;
1081
1081
  if (!context.identity) return currentState;
1082
1082
 
1083
1083
  try {
@@ -1108,7 +1108,7 @@ export async function createApiToken(name: string, scopes: interfaces.data.TApiT
1108
1108
  >('/typedrequest', 'createApiToken');
1109
1109
 
1110
1110
  return request.fire({
1111
- identity: context.identity,
1111
+ identity: context.identity!,
1112
1112
  name,
1113
1113
  scopes,
1114
1114
  expiresInDays,
@@ -1122,15 +1122,15 @@ export async function rollApiToken(id: string) {
1122
1122
  >('/typedrequest', 'rollApiToken');
1123
1123
 
1124
1124
  return request.fire({
1125
- identity: context.identity,
1125
+ identity: context.identity!,
1126
1126
  id,
1127
1127
  });
1128
1128
  }
1129
1129
 
1130
1130
  export const revokeApiTokenAction = routeManagementStatePart.createAction<string>(
1131
- async (statePartArg, tokenId, actionContext) => {
1131
+ async (statePartArg, tokenId, actionContext): Promise<IRouteManagementState> => {
1132
1132
  const context = getActionContext();
1133
- const currentState = statePartArg.getState();
1133
+ const currentState = statePartArg.getState()!;
1134
1134
 
1135
1135
  try {
1136
1136
  const request = new plugins.domtools.plugins.typedrequest.TypedRequest<
@@ -1138,12 +1138,12 @@ export const revokeApiTokenAction = routeManagementStatePart.createAction<string
1138
1138
  >('/typedrequest', 'revokeApiToken');
1139
1139
 
1140
1140
  await request.fire({
1141
- identity: context.identity,
1141
+ identity: context.identity!,
1142
1142
  id: tokenId,
1143
1143
  });
1144
1144
 
1145
- return await actionContext.dispatch(fetchApiTokensAction, null);
1146
- } catch (error) {
1145
+ return await actionContext!.dispatch(fetchApiTokensAction, null);
1146
+ } catch (error: unknown) {
1147
1147
  return {
1148
1148
  ...currentState,
1149
1149
  error: error instanceof Error ? error.message : 'Failed to revoke token',
@@ -1155,9 +1155,9 @@ export const revokeApiTokenAction = routeManagementStatePart.createAction<string
1155
1155
  export const toggleApiTokenAction = routeManagementStatePart.createAction<{
1156
1156
  id: string;
1157
1157
  enabled: boolean;
1158
- }>(async (statePartArg, dataArg, actionContext) => {
1158
+ }>(async (statePartArg, dataArg, actionContext): Promise<IRouteManagementState> => {
1159
1159
  const context = getActionContext();
1160
- const currentState = statePartArg.getState();
1160
+ const currentState = statePartArg.getState()!;
1161
1161
 
1162
1162
  try {
1163
1163
  const request = new plugins.domtools.plugins.typedrequest.TypedRequest<
@@ -1165,13 +1165,13 @@ export const toggleApiTokenAction = routeManagementStatePart.createAction<{
1165
1165
  >('/typedrequest', 'toggleApiToken');
1166
1166
 
1167
1167
  await request.fire({
1168
- identity: context.identity,
1168
+ identity: context.identity!,
1169
1169
  id: dataArg.id,
1170
1170
  enabled: dataArg.enabled,
1171
1171
  });
1172
1172
 
1173
- return await actionContext.dispatch(fetchApiTokensAction, null);
1174
- } catch (error) {
1173
+ return await actionContext!.dispatch(fetchApiTokensAction, null);
1174
+ } catch (error: unknown) {
1175
1175
  return {
1176
1176
  ...currentState,
1177
1177
  error: error instanceof Error ? error.message : 'Failed to toggle token',
@@ -1191,13 +1191,13 @@ socketRouter.addTypedHandler(
1191
1191
  new plugins.domtools.plugins.typedrequest.TypedHandler<interfaces.requests.IReq_PushLogEntry>(
1192
1192
  'pushLogEntry',
1193
1193
  async (dataArg) => {
1194
- const current = logStatePart.getState();
1194
+ const current = logStatePart.getState()!;
1195
1195
  const updated = [...current.recentLogs, dataArg.entry];
1196
1196
  // Cap at 2000 entries
1197
1197
  if (updated.length > 2000) {
1198
1198
  updated.splice(0, updated.length - 2000);
1199
1199
  }
1200
- logStatePart.setState({ ...current, recentLogs: updated });
1200
+ logStatePart.setState({ ...current, recentLogs: updated } as ILogState);
1201
1201
  return {};
1202
1202
  }
1203
1203
  )
@@ -1232,14 +1232,14 @@ async function disconnectSocket() {
1232
1232
  async function dispatchCombinedRefreshAction() {
1233
1233
  const context = getActionContext();
1234
1234
  if (!context.identity) return;
1235
- const currentView = uiStatePart.getState().activeView;
1235
+ const currentView = uiStatePart.getState()!.activeView;
1236
1236
 
1237
1237
  try {
1238
1238
  // Always fetch basic stats for dashboard widgets
1239
1239
  const combinedRequest = new plugins.domtools.plugins.typedrequest.TypedRequest<
1240
1240
  interfaces.requests.IReq_GetCombinedMetrics
1241
1241
  >('/typedrequest', 'getCombinedMetrics');
1242
-
1242
+
1243
1243
  const combinedResponse = await combinedRequest.fire({
1244
1244
  identity: context.identity,
1245
1245
  sections: {
@@ -1252,12 +1252,13 @@ async function dispatchCombinedRefreshAction() {
1252
1252
  });
1253
1253
 
1254
1254
  // Update all stats from combined response
1255
+ const currentStatsState = statsStatePart.getState()!;
1255
1256
  statsStatePart.setState({
1256
- ...statsStatePart.getState(),
1257
- serverStats: combinedResponse.metrics.server || statsStatePart.getState().serverStats,
1258
- emailStats: combinedResponse.metrics.email || statsStatePart.getState().emailStats,
1259
- dnsStats: combinedResponse.metrics.dns || statsStatePart.getState().dnsStats,
1260
- securityMetrics: combinedResponse.metrics.security || statsStatePart.getState().securityMetrics,
1257
+ ...currentStatsState,
1258
+ serverStats: combinedResponse.metrics.server || currentStatsState.serverStats,
1259
+ emailStats: combinedResponse.metrics.email || currentStatsState.emailStats,
1260
+ dnsStats: combinedResponse.metrics.dns || currentStatsState.dnsStats,
1261
+ securityMetrics: combinedResponse.metrics.security || currentStatsState.securityMetrics,
1261
1262
  lastUpdated: Date.now(),
1262
1263
  isLoading: false,
1263
1264
  error: null,
@@ -1284,7 +1285,7 @@ async function dispatchCombinedRefreshAction() {
1284
1285
  });
1285
1286
 
1286
1287
  networkStatePart.setState({
1287
- ...networkStatePart.getState(),
1288
+ ...networkStatePart.getState()!,
1288
1289
  connections: connectionsResponse.connections,
1289
1290
  connectionsByIP,
1290
1291
  throughputRate: {
@@ -1297,14 +1298,15 @@ async function dispatchCombinedRefreshAction() {
1297
1298
  throughputHistory: network.throughputHistory || [],
1298
1299
  requestsPerSecond: network.requestsPerSecond || 0,
1299
1300
  requestsTotal: network.requestsTotal || 0,
1301
+ backends: network.backends || [],
1300
1302
  lastUpdated: Date.now(),
1301
1303
  isLoading: false,
1302
1304
  error: null,
1303
1305
  });
1304
- } catch (error) {
1306
+ } catch (error: unknown) {
1305
1307
  console.error('Failed to fetch connections:', error);
1306
1308
  networkStatePart.setState({
1307
- ...networkStatePart.getState(),
1309
+ ...networkStatePart.getState()!,
1308
1310
  connections: [],
1309
1311
  connectionsByIP,
1310
1312
  throughputRate: {
@@ -1317,6 +1319,7 @@ async function dispatchCombinedRefreshAction() {
1317
1319
  throughputHistory: network.throughputHistory || [],
1318
1320
  requestsPerSecond: network.requestsPerSecond || 0,
1319
1321
  requestsTotal: network.requestsTotal || 0,
1322
+ backends: network.backends || [],
1320
1323
  lastUpdated: Date.now(),
1321
1324
  isLoading: false,
1322
1325
  error: null,
@@ -1359,9 +1362,9 @@ let currentRefreshRate = 1000; // Track current refresh rate to avoid unnecessar
1359
1362
  // Initialize auto-refresh when UI state is ready
1360
1363
  (() => {
1361
1364
  const startAutoRefresh = () => {
1362
- const uiState = uiStatePart.getState();
1363
- const loginState = loginStatePart.getState();
1364
-
1365
+ const uiState = uiStatePart.getState()!;
1366
+ const loginState = loginStatePart.getState()!;
1367
+
1365
1368
  // Only start if conditions are met and not already running at the same rate
1366
1369
  if (uiState.autoRefresh && loginState.isLoggedIn) {
1367
1370
  // Check if we need to restart the interval (rate changed or not running)
@@ -1387,9 +1390,9 @@ let currentRefreshRate = 1000; // Track current refresh rate to avoid unnecessar
1387
1390
  };
1388
1391
 
1389
1392
  // Watch for relevant changes only
1390
- let previousAutoRefresh = uiStatePart.getState().autoRefresh;
1391
- let previousRefreshInterval = uiStatePart.getState().refreshInterval;
1392
- let previousIsLoggedIn = loginStatePart.getState().isLoggedIn;
1393
+ let previousAutoRefresh = uiStatePart.getState()!.autoRefresh;
1394
+ let previousRefreshInterval = uiStatePart.getState()!.refreshInterval;
1395
+ let previousIsLoggedIn = loginStatePart.getState()!.isLoggedIn;
1393
1396
 
1394
1397
  uiStatePart.state.subscribe((state) => {
1395
1398
  // Only restart if relevant values changed
@@ -1420,7 +1423,7 @@ let currentRefreshRate = 1000; // Track current refresh rate to avoid unnecessar
1420
1423
  startAutoRefresh();
1421
1424
 
1422
1425
  // Connect TypedSocket if already logged in (e.g., persistent session)
1423
- if (loginStatePart.getState().isLoggedIn) {
1426
+ if (loginStatePart.getState()!.isLoggedIn) {
1424
1427
  connectSocket();
1425
1428
  }
1426
1429
  })();