@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.
Files changed (72) hide show
  1. package/deno.json +1 -1
  2. package/dist_serve/bundle.js +768 -768
  3. package/dist_ts/00_commitinfo_data.js +1 -1
  4. package/dist_ts/classes.dcrouter.js +9 -1
  5. package/dist_ts_web/00_commitinfo_data.js +1 -1
  6. package/dist_ts_web/appstate/acme.d.ts +17 -0
  7. package/dist_ts_web/appstate/acme.js +64 -0
  8. package/dist_ts_web/appstate/certificates.d.ts +37 -0
  9. package/dist_ts_web/appstate/certificates.js +107 -0
  10. package/dist_ts_web/appstate/config.d.ts +9 -0
  11. package/dist_ts_web/appstate/config.js +35 -0
  12. package/dist_ts_web/appstate/domains.d.ts +80 -0
  13. package/dist_ts_web/appstate/domains.js +324 -0
  14. package/dist_ts_web/appstate/email-domains.d.ts +25 -0
  15. package/dist_ts_web/appstate/email-domains.js +104 -0
  16. package/dist_ts_web/appstate/email-ops.d.ts +10 -0
  17. package/dist_ts_web/appstate/email-ops.js +40 -0
  18. package/dist_ts_web/appstate/login.d.ts +30 -0
  19. package/dist_ts_web/appstate/login.js +83 -0
  20. package/dist_ts_web/appstate/logs.d.ts +16 -0
  21. package/dist_ts_web/appstate/logs.js +27 -0
  22. package/dist_ts_web/appstate/network.d.ts +50 -0
  23. package/dist_ts_web/appstate/network.js +122 -0
  24. package/dist_ts_web/appstate/profiles-targets.d.ts +45 -0
  25. package/dist_ts_web/appstate/profiles-targets.js +173 -0
  26. package/dist_ts_web/appstate/remoteingress.d.ts +47 -0
  27. package/dist_ts_web/appstate/remoteingress.js +204 -0
  28. package/dist_ts_web/appstate/routes.d.ts +76 -0
  29. package/dist_ts_web/appstate/routes.js +316 -0
  30. package/dist_ts_web/appstate/runtime.d.ts +1 -0
  31. package/dist_ts_web/appstate/runtime.js +276 -0
  32. package/dist_ts_web/appstate/security.d.ts +29 -0
  33. package/dist_ts_web/appstate/security.js +167 -0
  34. package/dist_ts_web/appstate/shared.d.ts +3 -0
  35. package/dist_ts_web/appstate/shared.js +13 -0
  36. package/dist_ts_web/appstate/stats.d.ts +15 -0
  37. package/dist_ts_web/appstate/stats.js +59 -0
  38. package/dist_ts_web/appstate/target-profiles.d.ts +37 -0
  39. package/dist_ts_web/appstate/target-profiles.js +118 -0
  40. package/dist_ts_web/appstate/ui.d.ts +11 -0
  41. package/dist_ts_web/appstate/ui.js +55 -0
  42. package/dist_ts_web/appstate/users.d.ts +27 -0
  43. package/dist_ts_web/appstate/users.js +85 -0
  44. package/dist_ts_web/appstate/vpn.d.ts +44 -0
  45. package/dist_ts_web/appstate/vpn.js +148 -0
  46. package/dist_ts_web/appstate.d.ts +20 -568
  47. package/dist_ts_web/appstate.js +24 -2418
  48. package/package.json +3 -3
  49. package/ts/00_commitinfo_data.ts +1 -1
  50. package/ts/classes.dcrouter.ts +10 -0
  51. package/ts_web/00_commitinfo_data.ts +1 -1
  52. package/ts_web/appstate/acme.ts +93 -0
  53. package/ts_web/appstate/certificates.ts +159 -0
  54. package/ts_web/appstate/config.ts +49 -0
  55. package/ts_web/appstate/domains.ts +429 -0
  56. package/ts_web/appstate/email-domains.ts +155 -0
  57. package/ts_web/appstate/email-ops.ts +57 -0
  58. package/ts_web/appstate/login.ts +128 -0
  59. package/ts_web/appstate/logs.ts +50 -0
  60. package/ts_web/appstate/network.ts +161 -0
  61. package/ts_web/appstate/profiles-targets.ts +240 -0
  62. package/ts_web/appstate/remoteingress.ts +300 -0
  63. package/ts_web/appstate/routes.ts +447 -0
  64. package/ts_web/appstate/runtime.ts +308 -0
  65. package/ts_web/appstate/security.ts +229 -0
  66. package/ts_web/appstate/shared.ts +15 -0
  67. package/ts_web/appstate/stats.ts +79 -0
  68. package/ts_web/appstate/target-profiles.ts +164 -0
  69. package/ts_web/appstate/ui.ts +75 -0
  70. package/ts_web/appstate/users.ts +133 -0
  71. package/ts_web/appstate/vpn.ts +234 -0
  72. package/ts_web/appstate.ts +24 -3403
@@ -0,0 +1,316 @@
1
+ import * as plugins from '../plugins.js';
2
+ import * as interfaces from '../../dist_ts_interfaces/index.js';
3
+ import { appState } from './shared.js';
4
+ import { getActionContext } from './login.js';
5
+ export const routeManagementStatePart = await appState.getStatePart('routeManagement', {
6
+ mergedRoutes: [],
7
+ warnings: [],
8
+ httpRedirects: [],
9
+ apiTokens: [],
10
+ gatewayClients: [],
11
+ isLoading: false,
12
+ error: null,
13
+ lastUpdated: 0,
14
+ }, 'soft');
15
+ // Route Management Actions
16
+ // ============================================================================
17
+ export const fetchMergedRoutesAction = routeManagementStatePart.createAction(async (statePartArg) => {
18
+ const context = getActionContext();
19
+ const currentState = statePartArg.getState();
20
+ if (!context.identity)
21
+ return currentState;
22
+ try {
23
+ const request = new plugins.domtools.plugins.typedrequest.TypedRequest('/typedrequest', 'getMergedRoutes');
24
+ const response = await request.fire({
25
+ identity: context.identity,
26
+ });
27
+ return {
28
+ ...currentState,
29
+ mergedRoutes: response.routes,
30
+ warnings: response.warnings,
31
+ isLoading: false,
32
+ error: null,
33
+ lastUpdated: Date.now(),
34
+ };
35
+ }
36
+ catch (error) {
37
+ return {
38
+ ...currentState,
39
+ isLoading: false,
40
+ error: error instanceof Error ? error.message : 'Failed to fetch routes',
41
+ };
42
+ }
43
+ });
44
+ export const fetchHttpRedirectsAction = routeManagementStatePart.createAction(async (statePartArg) => {
45
+ const context = getActionContext();
46
+ const currentState = statePartArg.getState();
47
+ if (!context.identity)
48
+ return currentState;
49
+ try {
50
+ const request = new plugins.domtools.plugins.typedrequest.TypedRequest('/typedrequest', 'getHttpRedirects');
51
+ const response = await request.fire({
52
+ identity: context.identity,
53
+ });
54
+ return {
55
+ ...currentState,
56
+ httpRedirects: response.redirects,
57
+ isLoading: false,
58
+ error: null,
59
+ lastUpdated: Date.now(),
60
+ };
61
+ }
62
+ catch (error) {
63
+ return {
64
+ ...currentState,
65
+ isLoading: false,
66
+ error: error instanceof Error ? error.message : 'Failed to fetch HTTP redirects',
67
+ };
68
+ }
69
+ });
70
+ export const createRouteAction = routeManagementStatePart.createAction(async (statePartArg, dataArg, actionContext) => {
71
+ const context = getActionContext();
72
+ const currentState = statePartArg.getState();
73
+ try {
74
+ const request = new plugins.domtools.plugins.typedrequest.TypedRequest('/typedrequest', 'createRoute');
75
+ await request.fire({
76
+ identity: context.identity,
77
+ route: dataArg.route,
78
+ enabled: dataArg.enabled,
79
+ metadata: dataArg.metadata,
80
+ });
81
+ return await actionContext.dispatch(fetchMergedRoutesAction, null);
82
+ }
83
+ catch (error) {
84
+ return {
85
+ ...currentState,
86
+ error: error instanceof Error ? error.message : 'Failed to create route',
87
+ };
88
+ }
89
+ });
90
+ export const updateRouteAction = routeManagementStatePart.createAction(async (statePartArg, dataArg, actionContext) => {
91
+ const context = getActionContext();
92
+ const currentState = statePartArg.getState();
93
+ try {
94
+ const request = new plugins.domtools.plugins.typedrequest.TypedRequest('/typedrequest', 'updateRoute');
95
+ const response = await request.fire({
96
+ identity: context.identity,
97
+ id: dataArg.id,
98
+ route: dataArg.route,
99
+ enabled: dataArg.enabled,
100
+ metadata: dataArg.metadata,
101
+ });
102
+ if (!response.success) {
103
+ throw new Error(response.message || 'Failed to update route');
104
+ }
105
+ return await actionContext.dispatch(fetchMergedRoutesAction, null);
106
+ }
107
+ catch (error) {
108
+ return {
109
+ ...currentState,
110
+ error: error instanceof Error ? error.message : 'Failed to update route',
111
+ };
112
+ }
113
+ });
114
+ export const deleteRouteAction = routeManagementStatePart.createAction(async (statePartArg, routeId, actionContext) => {
115
+ const context = getActionContext();
116
+ const currentState = statePartArg.getState();
117
+ try {
118
+ const request = new plugins.domtools.plugins.typedrequest.TypedRequest('/typedrequest', 'deleteRoute');
119
+ const response = await request.fire({
120
+ identity: context.identity,
121
+ id: routeId,
122
+ });
123
+ if (!response.success) {
124
+ throw new Error(response.message || 'Failed to delete route');
125
+ }
126
+ return await actionContext.dispatch(fetchMergedRoutesAction, null);
127
+ }
128
+ catch (error) {
129
+ return {
130
+ ...currentState,
131
+ error: error instanceof Error ? error.message : 'Failed to delete route',
132
+ };
133
+ }
134
+ });
135
+ export const toggleRouteAction = routeManagementStatePart.createAction(async (statePartArg, dataArg, actionContext) => {
136
+ const context = getActionContext();
137
+ const currentState = statePartArg.getState();
138
+ try {
139
+ const request = new plugins.domtools.plugins.typedrequest.TypedRequest('/typedrequest', 'toggleRoute');
140
+ const response = await request.fire({
141
+ identity: context.identity,
142
+ id: dataArg.id,
143
+ enabled: dataArg.enabled,
144
+ });
145
+ if (!response.success) {
146
+ throw new Error(response.message || 'Failed to toggle route');
147
+ }
148
+ return await actionContext.dispatch(fetchMergedRoutesAction, null);
149
+ }
150
+ catch (error) {
151
+ return {
152
+ ...currentState,
153
+ error: error instanceof Error ? error.message : 'Failed to toggle route',
154
+ };
155
+ }
156
+ });
157
+ // ============================================================================
158
+ // API Token Actions
159
+ // ============================================================================
160
+ export const fetchApiTokensAction = routeManagementStatePart.createAction(async (statePartArg) => {
161
+ const context = getActionContext();
162
+ const currentState = statePartArg.getState();
163
+ if (!context.identity)
164
+ return currentState;
165
+ try {
166
+ const request = new plugins.domtools.plugins.typedrequest.TypedRequest('/typedrequest', 'listApiTokens');
167
+ const response = await request.fire({
168
+ identity: context.identity,
169
+ });
170
+ return {
171
+ ...currentState,
172
+ apiTokens: response.tokens,
173
+ };
174
+ }
175
+ catch (error) {
176
+ return {
177
+ ...currentState,
178
+ error: error instanceof Error ? error.message : 'Failed to fetch tokens',
179
+ };
180
+ }
181
+ });
182
+ export const fetchGatewayClientsAction = routeManagementStatePart.createAction(async (statePartArg) => {
183
+ const context = getActionContext();
184
+ const currentState = statePartArg.getState();
185
+ if (!context.identity)
186
+ return currentState;
187
+ try {
188
+ const request = new plugins.domtools.plugins.typedrequest.TypedRequest('/typedrequest', 'listGatewayClients');
189
+ const response = await request.fire({ identity: context.identity });
190
+ return {
191
+ ...currentState,
192
+ gatewayClients: response.gatewayClients,
193
+ error: null,
194
+ lastUpdated: Date.now(),
195
+ };
196
+ }
197
+ catch (error) {
198
+ return {
199
+ ...currentState,
200
+ error: error instanceof Error ? error.message : 'Failed to fetch gateway clients',
201
+ };
202
+ }
203
+ });
204
+ export async function createGatewayClient(data) {
205
+ const context = getActionContext();
206
+ const request = new plugins.domtools.plugins.typedrequest.TypedRequest('/typedrequest', 'createGatewayClient');
207
+ return request.fire({
208
+ identity: context.identity,
209
+ capabilities: {
210
+ readDomains: true,
211
+ readDnsRecords: true,
212
+ syncRoutes: true,
213
+ syncDnsRecords: false,
214
+ requestCertificates: false,
215
+ },
216
+ ...data,
217
+ });
218
+ }
219
+ export const updateGatewayClientAction = routeManagementStatePart.createAction(async (statePartArg, dataArg, actionContext) => {
220
+ const context = getActionContext();
221
+ const currentState = statePartArg.getState();
222
+ try {
223
+ const request = new plugins.domtools.plugins.typedrequest.TypedRequest('/typedrequest', 'updateGatewayClient');
224
+ await request.fire({ identity: context.identity, ...dataArg });
225
+ return await actionContext.dispatch(fetchGatewayClientsAction, null);
226
+ }
227
+ catch (error) {
228
+ return {
229
+ ...currentState,
230
+ error: error instanceof Error ? error.message : 'Failed to update gateway client',
231
+ };
232
+ }
233
+ });
234
+ export const deleteGatewayClientAction = routeManagementStatePart.createAction(async (statePartArg, gatewayClientId, actionContext) => {
235
+ const context = getActionContext();
236
+ const currentState = statePartArg.getState();
237
+ try {
238
+ const request = new plugins.domtools.plugins.typedrequest.TypedRequest('/typedrequest', 'deleteGatewayClient');
239
+ await request.fire({ identity: context.identity, id: gatewayClientId });
240
+ return await actionContext.dispatch(fetchGatewayClientsAction, null);
241
+ }
242
+ catch (error) {
243
+ return {
244
+ ...currentState,
245
+ error: error instanceof Error ? error.message : 'Failed to delete gateway client',
246
+ };
247
+ }
248
+ });
249
+ export async function createGatewayClientToken(gatewayClientId, name, expiresInDays) {
250
+ const context = getActionContext();
251
+ const request = new plugins.domtools.plugins.typedrequest.TypedRequest('/typedrequest', 'createGatewayClientToken');
252
+ return request.fire({
253
+ identity: context.identity,
254
+ gatewayClientId,
255
+ name,
256
+ expiresInDays,
257
+ });
258
+ }
259
+ // Users
260
+ export async function createApiToken(name, scopes, expiresInDays, policy) {
261
+ const context = getActionContext();
262
+ const request = new plugins.domtools.plugins.typedrequest.TypedRequest('/typedrequest', 'createApiToken');
263
+ return request.fire({
264
+ identity: context.identity,
265
+ name,
266
+ scopes,
267
+ policy,
268
+ expiresInDays,
269
+ });
270
+ }
271
+ export async function rollApiToken(id) {
272
+ const context = getActionContext();
273
+ const request = new plugins.domtools.plugins.typedrequest.TypedRequest('/typedrequest', 'rollApiToken');
274
+ return request.fire({
275
+ identity: context.identity,
276
+ id,
277
+ });
278
+ }
279
+ export const revokeApiTokenAction = routeManagementStatePart.createAction(async (statePartArg, tokenId, actionContext) => {
280
+ const context = getActionContext();
281
+ const currentState = statePartArg.getState();
282
+ try {
283
+ const request = new plugins.domtools.plugins.typedrequest.TypedRequest('/typedrequest', 'revokeApiToken');
284
+ await request.fire({
285
+ identity: context.identity,
286
+ id: tokenId,
287
+ });
288
+ return await actionContext.dispatch(fetchApiTokensAction, null);
289
+ }
290
+ catch (error) {
291
+ return {
292
+ ...currentState,
293
+ error: error instanceof Error ? error.message : 'Failed to revoke token',
294
+ };
295
+ }
296
+ });
297
+ export const toggleApiTokenAction = routeManagementStatePart.createAction(async (statePartArg, dataArg, actionContext) => {
298
+ const context = getActionContext();
299
+ const currentState = statePartArg.getState();
300
+ try {
301
+ const request = new plugins.domtools.plugins.typedrequest.TypedRequest('/typedrequest', 'toggleApiToken');
302
+ await request.fire({
303
+ identity: context.identity,
304
+ id: dataArg.id,
305
+ enabled: dataArg.enabled,
306
+ });
307
+ return await actionContext.dispatch(fetchApiTokensAction, null);
308
+ }
309
+ catch (error) {
310
+ return {
311
+ ...currentState,
312
+ error: error instanceof Error ? error.message : 'Failed to toggle token',
313
+ };
314
+ }
315
+ });
316
+ //# sourceMappingURL=data:application/json;base64,eyJ2ZXJzaW9uIjozLCJmaWxlIjoicm91dGVzLmpzIiwic291cmNlUm9vdCI6IiIsInNvdXJjZXMiOlsiLi4vLi4vLi4vdHNfd2ViL2FwcHN0YXRlL3JvdXRlcy50cyJdLCJuYW1lcyI6W10sIm1hcHBpbmdzIjoiQUFBQSxPQUFPLEtBQUssT0FBTyxNQUFNLGVBQWUsQ0FBQztBQUN6QyxPQUFPLEtBQUssVUFBVSxNQUFNLDhCQUE4QixDQUFDO0FBQzNELE9BQU8sRUFBRSxRQUFRLEVBQUUsTUFBTSxhQUFhLENBQUM7QUFDdkMsT0FBTyxFQUFFLGdCQUFnQixFQUFFLE1BQU0sWUFBWSxDQUFDO0FBaUI5QyxNQUFNLENBQUMsTUFBTSx3QkFBd0IsR0FBRyxNQUFNLFFBQVEsQ0FBQyxZQUFZLENBQ2pFLGlCQUFpQixFQUNqQjtJQUNFLFlBQVksRUFBRSxFQUFFO0lBQ2hCLFFBQVEsRUFBRSxFQUFFO0lBQ1osYUFBYSxFQUFFLEVBQUU7SUFDakIsU0FBUyxFQUFFLEVBQUU7SUFDYixjQUFjLEVBQUUsRUFBRTtJQUNsQixTQUFTLEVBQUUsS0FBSztJQUNoQixLQUFLLEVBQUUsSUFBSTtJQUNYLFdBQVcsRUFBRSxDQUFDO0NBQ2YsRUFDRCxNQUFNLENBQ1AsQ0FBQztBQUVGLDJCQUEyQjtBQUMzQiwrRUFBK0U7QUFFL0UsTUFBTSxDQUFDLE1BQU0sdUJBQXVCLEdBQUcsd0JBQXdCLENBQUMsWUFBWSxDQUFDLEtBQUssRUFBRSxZQUFZLEVBQWtDLEVBQUU7SUFDbEksTUFBTSxPQUFPLEdBQUcsZ0JBQWdCLEVBQUUsQ0FBQztJQUNuQyxNQUFNLFlBQVksR0FBRyxZQUFZLENBQUMsUUFBUSxFQUFHLENBQUM7SUFDOUMsSUFBSSxDQUFDLE9BQU8sQ0FBQyxRQUFRO1FBQUUsT0FBTyxZQUFZLENBQUM7SUFFM0MsSUFBSSxDQUFDO1FBQ0gsTUFBTSxPQUFPLEdBQUcsSUFBSSxPQUFPLENBQUMsUUFBUSxDQUFDLE9BQU8sQ0FBQyxZQUFZLENBQUMsWUFBWSxDQUVwRSxlQUFlLEVBQUUsaUJBQWlCLENBQUMsQ0FBQztRQUV0QyxNQUFNLFFBQVEsR0FBRyxNQUFNLE9BQU8sQ0FBQyxJQUFJLENBQUM7WUFDbEMsUUFBUSxFQUFFLE9BQU8sQ0FBQyxRQUFRO1NBQzNCLENBQUMsQ0FBQztRQUVILE9BQU87WUFDTCxHQUFHLFlBQVk7WUFDZixZQUFZLEVBQUUsUUFBUSxDQUFDLE1BQU07WUFDN0IsUUFBUSxFQUFFLFFBQVEsQ0FBQyxRQUFRO1lBQzNCLFNBQVMsRUFBRSxLQUFLO1lBQ2hCLEtBQUssRUFBRSxJQUFJO1lBQ1gsV0FBVyxFQUFFLElBQUksQ0FBQyxHQUFHLEVBQUU7U0FDeEIsQ0FBQztJQUNKLENBQUM7SUFBQyxPQUFPLEtBQUssRUFBRSxDQUFDO1FBQ2YsT0FBTztZQUNMLEdBQUcsWUFBWTtZQUNmLFNBQVMsRUFBRSxLQUFLO1lBQ2hCLEtBQUssRUFBRSxLQUFLLFlBQVksS0FBSyxDQUFDLENBQUMsQ0FBQyxLQUFLLENBQUMsT0FBTyxDQUFDLENBQUMsQ0FBQyx3QkFBd0I7U0FDekUsQ0FBQztJQUNKLENBQUM7QUFDSCxDQUFDLENBQUMsQ0FBQztBQUVILE1BQU0sQ0FBQyxNQUFNLHdCQUF3QixHQUFHLHdCQUF3QixDQUFDLFlBQVksQ0FBQyxLQUFLLEVBQUUsWUFBWSxFQUFrQyxFQUFFO0lBQ25JLE1BQU0sT0FBTyxHQUFHLGdCQUFnQixFQUFFLENBQUM7SUFDbkMsTUFBTSxZQUFZLEdBQUcsWUFBWSxDQUFDLFFBQVEsRUFBRyxDQUFDO0lBQzlDLElBQUksQ0FBQyxPQUFPLENBQUMsUUFBUTtRQUFFLE9BQU8sWUFBWSxDQUFDO0lBRTNDLElBQUksQ0FBQztRQUNILE1BQU0sT0FBTyxHQUFHLElBQUksT0FBTyxDQUFDLFFBQVEsQ0FBQyxPQUFPLENBQUMsWUFBWSxDQUFDLFlBQVksQ0FFcEUsZUFBZSxFQUFFLGtCQUFrQixDQUFDLENBQUM7UUFFdkMsTUFBTSxRQUFRLEdBQUcsTUFBTSxPQUFPLENBQUMsSUFBSSxDQUFDO1lBQ2xDLFFBQVEsRUFBRSxPQUFPLENBQUMsUUFBUTtTQUMzQixDQUFDLENBQUM7UUFFSCxPQUFPO1lBQ0wsR0FBRyxZQUFZO1lBQ2YsYUFBYSxFQUFFLFFBQVEsQ0FBQyxTQUFTO1lBQ2pDLFNBQVMsRUFBRSxLQUFLO1lBQ2hCLEtBQUssRUFBRSxJQUFJO1lBQ1gsV0FBVyxFQUFFLElBQUksQ0FBQyxHQUFHLEVBQUU7U0FDeEIsQ0FBQztJQUNKLENBQUM7SUFBQyxPQUFPLEtBQUssRUFBRSxDQUFDO1FBQ2YsT0FBTztZQUNMLEdBQUcsWUFBWTtZQUNmLFNBQVMsRUFBRSxLQUFLO1lBQ2hCLEtBQUssRUFBRSxLQUFLLFlBQVksS0FBSyxDQUFDLENBQUMsQ0FBQyxLQUFLLENBQUMsT0FBTyxDQUFDLENBQUMsQ0FBQyxnQ0FBZ0M7U0FDakYsQ0FBQztJQUNKLENBQUM7QUFDSCxDQUFDLENBQUMsQ0FBQztBQUVILE1BQU0sQ0FBQyxNQUFNLGlCQUFpQixHQUFHLHdCQUF3QixDQUFDLFlBQVksQ0FJbkUsS0FBSyxFQUFFLFlBQVksRUFBRSxPQUFPLEVBQUUsYUFBYSxFQUFrQyxFQUFFO0lBQ2hGLE1BQU0sT0FBTyxHQUFHLGdCQUFnQixFQUFFLENBQUM7SUFDbkMsTUFBTSxZQUFZLEdBQUcsWUFBWSxDQUFDLFFBQVEsRUFBRyxDQUFDO0lBRTlDLElBQUksQ0FBQztRQUNILE1BQU0sT0FBTyxHQUFHLElBQUksT0FBTyxDQUFDLFFBQVEsQ0FBQyxPQUFPLENBQUMsWUFBWSxDQUFDLFlBQVksQ0FFcEUsZUFBZSxFQUFFLGFBQWEsQ0FBQyxDQUFDO1FBRWxDLE1BQU0sT0FBTyxDQUFDLElBQUksQ0FBQztZQUNqQixRQUFRLEVBQUUsT0FBTyxDQUFDLFFBQVM7WUFDM0IsS0FBSyxFQUFFLE9BQU8sQ0FBQyxLQUFLO1lBQ3BCLE9BQU8sRUFBRSxPQUFPLENBQUMsT0FBTztZQUN4QixRQUFRLEVBQUUsT0FBTyxDQUFDLFFBQVE7U0FDM0IsQ0FBQyxDQUFDO1FBRUgsT0FBTyxNQUFNLGFBQWMsQ0FBQyxRQUFRLENBQUMsdUJBQXVCLEVBQUUsSUFBSSxDQUFDLENBQUM7SUFDdEUsQ0FBQztJQUFDLE9BQU8sS0FBYyxFQUFFLENBQUM7UUFDeEIsT0FBTztZQUNMLEdBQUcsWUFBWTtZQUNmLEtBQUssRUFBRSxLQUFLLFlBQVksS0FBSyxDQUFDLENBQUMsQ0FBQyxLQUFLLENBQUMsT0FBTyxDQUFDLENBQUMsQ0FBQyx3QkFBd0I7U0FDekUsQ0FBQztJQUNKLENBQUM7QUFDSCxDQUFDLENBQUMsQ0FBQztBQUVILE1BQU0sQ0FBQyxNQUFNLGlCQUFpQixHQUFHLHdCQUF3QixDQUFDLFlBQVksQ0FLbkUsS0FBSyxFQUFFLFlBQVksRUFBRSxPQUFPLEVBQUUsYUFBYSxFQUFrQyxFQUFFO0lBQ2hGLE1BQU0sT0FBTyxHQUFHLGdCQUFnQixFQUFFLENBQUM7SUFDbkMsTUFBTSxZQUFZLEdBQUcsWUFBWSxDQUFDLFFBQVEsRUFBRyxDQUFDO0lBRTlDLElBQUksQ0FBQztRQUNILE1BQU0sT0FBTyxHQUFHLElBQUksT0FBTyxDQUFDLFFBQVEsQ0FBQyxPQUFPLENBQUMsWUFBWSxDQUFDLFlBQVksQ0FFcEUsZUFBZSxFQUFFLGFBQWEsQ0FBQyxDQUFDO1FBRWxDLE1BQU0sUUFBUSxHQUFHLE1BQU0sT0FBTyxDQUFDLElBQUksQ0FBQztZQUNsQyxRQUFRLEVBQUUsT0FBTyxDQUFDLFFBQVM7WUFDM0IsRUFBRSxFQUFFLE9BQU8sQ0FBQyxFQUFFO1lBQ2QsS0FBSyxFQUFFLE9BQU8sQ0FBQyxLQUFLO1lBQ3BCLE9BQU8sRUFBRSxPQUFPLENBQUMsT0FBTztZQUN4QixRQUFRLEVBQUUsT0FBTyxDQUFDLFFBQVE7U0FDM0IsQ0FBQyxDQUFDO1FBRUgsSUFBSSxDQUFDLFFBQVEsQ0FBQyxPQUFPLEVBQUUsQ0FBQztZQUN0QixNQUFNLElBQUksS0FBSyxDQUFDLFFBQVEsQ0FBQyxPQUFPLElBQUksd0JBQXdCLENBQUMsQ0FBQztRQUNoRSxDQUFDO1FBRUQsT0FBTyxNQUFNLGFBQWMsQ0FBQyxRQUFRLENBQUMsdUJBQXVCLEVBQUUsSUFBSSxDQUFDLENBQUM7SUFDdEUsQ0FBQztJQUFDLE9BQU8sS0FBYyxFQUFFLENBQUM7UUFDeEIsT0FBTztZQUNMLEdBQUcsWUFBWTtZQUNmLEtBQUssRUFBRSxLQUFLLFlBQVksS0FBSyxDQUFDLENBQUMsQ0FBQyxLQUFLLENBQUMsT0FBTyxDQUFDLENBQUMsQ0FBQyx3QkFBd0I7U0FDekUsQ0FBQztJQUNKLENBQUM7QUFDSCxDQUFDLENBQUMsQ0FBQztBQUVILE1BQU0sQ0FBQyxNQUFNLGlCQUFpQixHQUFHLHdCQUF3QixDQUFDLFlBQVksQ0FDcEUsS0FBSyxFQUFFLFlBQVksRUFBRSxPQUFPLEVBQUUsYUFBYSxFQUFrQyxFQUFFO0lBQzdFLE1BQU0sT0FBTyxHQUFHLGdCQUFnQixFQUFFLENBQUM7SUFDbkMsTUFBTSxZQUFZLEdBQUcsWUFBWSxDQUFDLFFBQVEsRUFBRyxDQUFDO0lBRTlDLElBQUksQ0FBQztRQUNILE1BQU0sT0FBTyxHQUFHLElBQUksT0FBTyxDQUFDLFFBQVEsQ0FBQyxPQUFPLENBQUMsWUFBWSxDQUFDLFlBQVksQ0FFcEUsZUFBZSxFQUFFLGFBQWEsQ0FBQyxDQUFDO1FBRWxDLE1BQU0sUUFBUSxHQUFHLE1BQU0sT0FBTyxDQUFDLElBQUksQ0FBQztZQUNsQyxRQUFRLEVBQUUsT0FBTyxDQUFDLFFBQVM7WUFDM0IsRUFBRSxFQUFFLE9BQU87U0FDWixDQUFDLENBQUM7UUFFSCxJQUFJLENBQUMsUUFBUSxDQUFDLE9BQU8sRUFBRSxDQUFDO1lBQ3RCLE1BQU0sSUFBSSxLQUFLLENBQUMsUUFBUSxDQUFDLE9BQU8sSUFBSSx3QkFBd0IsQ0FBQyxDQUFDO1FBQ2hFLENBQUM7UUFFRCxPQUFPLE1BQU0sYUFBYyxDQUFDLFFBQVEsQ0FBQyx1QkFBdUIsRUFBRSxJQUFJLENBQUMsQ0FBQztJQUN0RSxDQUFDO0lBQUMsT0FBTyxLQUFjLEVBQUUsQ0FBQztRQUN4QixPQUFPO1lBQ0wsR0FBRyxZQUFZO1lBQ2YsS0FBSyxFQUFFLEtBQUssWUFBWSxLQUFLLENBQUMsQ0FBQyxDQUFDLEtBQUssQ0FBQyxPQUFPLENBQUMsQ0FBQyxDQUFDLHdCQUF3QjtTQUN6RSxDQUFDO0lBQ0osQ0FBQztBQUNILENBQUMsQ0FDRixDQUFDO0FBRUYsTUFBTSxDQUFDLE1BQU0saUJBQWlCLEdBQUcsd0JBQXdCLENBQUMsWUFBWSxDQUduRSxLQUFLLEVBQUUsWUFBWSxFQUFFLE9BQU8sRUFBRSxhQUFhLEVBQWtDLEVBQUU7SUFDaEYsTUFBTSxPQUFPLEdBQUcsZ0JBQWdCLEVBQUUsQ0FBQztJQUNuQyxNQUFNLFlBQVksR0FBRyxZQUFZLENBQUMsUUFBUSxFQUFHLENBQUM7SUFFOUMsSUFBSSxDQUFDO1FBQ0gsTUFBTSxPQUFPLEdBQUcsSUFBSSxPQUFPLENBQUMsUUFBUSxDQUFDLE9BQU8sQ0FBQyxZQUFZLENBQUMsWUFBWSxDQUVwRSxlQUFlLEVBQUUsYUFBYSxDQUFDLENBQUM7UUFFbEMsTUFBTSxRQUFRLEdBQUcsTUFBTSxPQUFPLENBQUMsSUFBSSxDQUFDO1lBQ2xDLFFBQVEsRUFBRSxPQUFPLENBQUMsUUFBUztZQUMzQixFQUFFLEVBQUUsT0FBTyxDQUFDLEVBQUU7WUFDZCxPQUFPLEVBQUUsT0FBTyxDQUFDLE9BQU87U0FDekIsQ0FBQyxDQUFDO1FBRUgsSUFBSSxDQUFDLFFBQVEsQ0FBQyxPQUFPLEVBQUUsQ0FBQztZQUN0QixNQUFNLElBQUksS0FBSyxDQUFDLFFBQVEsQ0FBQyxPQUFPLElBQUksd0JBQXdCLENBQUMsQ0FBQztRQUNoRSxDQUFDO1FBRUQsT0FBTyxNQUFNLGFBQWMsQ0FBQyxRQUFRLENBQUMsdUJBQXVCLEVBQUUsSUFBSSxDQUFDLENBQUM7SUFDdEUsQ0FBQztJQUFDLE9BQU8sS0FBYyxFQUFFLENBQUM7UUFDeEIsT0FBTztZQUNMLEdBQUcsWUFBWTtZQUNmLEtBQUssRUFBRSxLQUFLLFlBQVksS0FBSyxDQUFDLENBQUMsQ0FBQyxLQUFLLENBQUMsT0FBTyxDQUFDLENBQUMsQ0FBQyx3QkFBd0I7U0FDekUsQ0FBQztJQUNKLENBQUM7QUFDSCxDQUFDLENBQUMsQ0FBQztBQUVILCtFQUErRTtBQUMvRSxvQkFBb0I7QUFDcEIsK0VBQStFO0FBRS9FLE1BQU0sQ0FBQyxNQUFNLG9CQUFvQixHQUFHLHdCQUF3QixDQUFDLFlBQVksQ0FBQyxLQUFLLEVBQUUsWUFBWSxFQUFrQyxFQUFFO0lBQy9ILE1BQU0sT0FBTyxHQUFHLGdCQUFnQixFQUFFLENBQUM7SUFDbkMsTUFBTSxZQUFZLEdBQUcsWUFBWSxDQUFDLFFBQVEsRUFBRyxDQUFDO0lBQzlDLElBQUksQ0FBQyxPQUFPLENBQUMsUUFBUTtRQUFFLE9BQU8sWUFBWSxDQUFDO0lBRTNDLElBQUksQ0FBQztRQUNILE1BQU0sT0FBTyxHQUFHLElBQUksT0FBTyxDQUFDLFFBQVEsQ0FBQyxPQUFPLENBQUMsWUFBWSxDQUFDLFlBQVksQ0FFcEUsZUFBZSxFQUFFLGVBQWUsQ0FBQyxDQUFDO1FBRXBDLE1BQU0sUUFBUSxHQUFHLE1BQU0sT0FBTyxDQUFDLElBQUksQ0FBQztZQUNsQyxRQUFRLEVBQUUsT0FBTyxDQUFDLFFBQVE7U0FDM0IsQ0FBQyxDQUFDO1FBRUgsT0FBTztZQUNMLEdBQUcsWUFBWTtZQUNmLFNBQVMsRUFBRSxRQUFRLENBQUMsTUFBTTtTQUMzQixDQUFDO0lBQ0osQ0FBQztJQUFDLE9BQU8sS0FBSyxFQUFFLENBQUM7UUFDZixPQUFPO1lBQ0wsR0FBRyxZQUFZO1lBQ2YsS0FBSyxFQUFFLEtBQUssWUFBWSxLQUFLLENBQUMsQ0FBQyxDQUFDLEtBQUssQ0FBQyxPQUFPLENBQUMsQ0FBQyxDQUFDLHdCQUF3QjtTQUN6RSxDQUFDO0lBQ0osQ0FBQztBQUNILENBQUMsQ0FBQyxDQUFDO0FBRUgsTUFBTSxDQUFDLE1BQU0seUJBQXlCLEdBQUcsd0JBQXdCLENBQUMsWUFBWSxDQUFDLEtBQUssRUFBRSxZQUFZLEVBQWtDLEVBQUU7SUFDcEksTUFBTSxPQUFPLEdBQUcsZ0JBQWdCLEVBQUUsQ0FBQztJQUNuQyxNQUFNLFlBQVksR0FBRyxZQUFZLENBQUMsUUFBUSxFQUFHLENBQUM7SUFDOUMsSUFBSSxDQUFDLE9BQU8sQ0FBQyxRQUFRO1FBQUUsT0FBTyxZQUFZLENBQUM7SUFFM0MsSUFBSSxDQUFDO1FBQ0gsTUFBTSxPQUFPLEdBQUcsSUFBSSxPQUFPLENBQUMsUUFBUSxDQUFDLE9BQU8sQ0FBQyxZQUFZLENBQUMsWUFBWSxDQUVwRSxlQUFlLEVBQUUsb0JBQW9CLENBQUMsQ0FBQztRQUN6QyxNQUFNLFFBQVEsR0FBRyxNQUFNLE9BQU8sQ0FBQyxJQUFJLENBQUMsRUFBRSxRQUFRLEVBQUUsT0FBTyxDQUFDLFFBQVEsRUFBRSxDQUFDLENBQUM7UUFDcEUsT0FBTztZQUNMLEdBQUcsWUFBWTtZQUNmLGNBQWMsRUFBRSxRQUFRLENBQUMsY0FBYztZQUN2QyxLQUFLLEVBQUUsSUFBSTtZQUNYLFdBQVcsRUFBRSxJQUFJLENBQUMsR0FBRyxFQUFFO1NBQ3hCLENBQUM7SUFDSixDQUFDO0lBQUMsT0FBTyxLQUFLLEVBQUUsQ0FBQztRQUNmLE9BQU87WUFDTCxHQUFHLFlBQVk7WUFDZixLQUFLLEVBQUUsS0FBSyxZQUFZLEtBQUssQ0FBQyxDQUFDLENBQUMsS0FBSyxDQUFDLE9BQU8sQ0FBQyxDQUFDLENBQUMsaUNBQWlDO1NBQ2xGLENBQUM7SUFDSixDQUFDO0FBQ0gsQ0FBQyxDQUFDLENBQUM7QUFFSCxNQUFNLENBQUMsS0FBSyxVQUFVLG1CQUFtQixDQUFDLElBT3pDO0lBQ0MsTUFBTSxPQUFPLEdBQUcsZ0JBQWdCLEVBQUUsQ0FBQztJQUNuQyxNQUFNLE9BQU8sR0FBRyxJQUFJLE9BQU8sQ0FBQyxRQUFRLENBQUMsT0FBTyxDQUFDLFlBQVksQ0FBQyxZQUFZLENBRXBFLGVBQWUsRUFBRSxxQkFBcUIsQ0FBQyxDQUFDO0lBQzFDLE9BQU8sT0FBTyxDQUFDLElBQUksQ0FBQztRQUNsQixRQUFRLEVBQUUsT0FBTyxDQUFDLFFBQVM7UUFDM0IsWUFBWSxFQUFFO1lBQ1osV0FBVyxFQUFFLElBQUk7WUFDakIsY0FBYyxFQUFFLElBQUk7WUFDcEIsVUFBVSxFQUFFLElBQUk7WUFDaEIsY0FBYyxFQUFFLEtBQUs7WUFDckIsbUJBQW1CLEVBQUUsS0FBSztTQUMzQjtRQUNELEdBQUcsSUFBSTtLQUNSLENBQUMsQ0FBQztBQUNMLENBQUM7QUFFRCxNQUFNLENBQUMsTUFBTSx5QkFBeUIsR0FBRyx3QkFBd0IsQ0FBQyxZQUFZLENBTzNFLEtBQUssRUFBRSxZQUFZLEVBQUUsT0FBTyxFQUFFLGFBQWEsRUFBa0MsRUFBRTtJQUNoRixNQUFNLE9BQU8sR0FBRyxnQkFBZ0IsRUFBRSxDQUFDO0lBQ25DLE1BQU0sWUFBWSxHQUFHLFlBQVksQ0FBQyxRQUFRLEVBQUcsQ0FBQztJQUM5QyxJQUFJLENBQUM7UUFDSCxNQUFNLE9BQU8sR0FBRyxJQUFJLE9BQU8sQ0FBQyxRQUFRLENBQUMsT0FBTyxDQUFDLFlBQVksQ0FBQyxZQUFZLENBRXBFLGVBQWUsRUFBRSxxQkFBcUIsQ0FBQyxDQUFDO1FBQzFDLE1BQU0sT0FBTyxDQUFDLElBQUksQ0FBQyxFQUFFLFFBQVEsRUFBRSxPQUFPLENBQUMsUUFBUyxFQUFFLEdBQUcsT0FBTyxFQUFFLENBQUMsQ0FBQztRQUNoRSxPQUFPLE1BQU0sYUFBYyxDQUFDLFFBQVEsQ0FBQyx5QkFBeUIsRUFBRSxJQUFJLENBQUMsQ0FBQztJQUN4RSxDQUFDO0lBQUMsT0FBTyxLQUFLLEVBQUUsQ0FBQztRQUNmLE9BQU87WUFDTCxHQUFHLFlBQVk7WUFDZixLQUFLLEVBQUUsS0FBSyxZQUFZLEtBQUssQ0FBQyxDQUFDLENBQUMsS0FBSyxDQUFDLE9BQU8sQ0FBQyxDQUFDLENBQUMsaUNBQWlDO1NBQ2xGLENBQUM7SUFDSixDQUFDO0FBQ0gsQ0FBQyxDQUFDLENBQUM7QUFFSCxNQUFNLENBQUMsTUFBTSx5QkFBeUIsR0FBRyx3QkFBd0IsQ0FBQyxZQUFZLENBQzVFLEtBQUssRUFBRSxZQUFZLEVBQUUsZUFBZSxFQUFFLGFBQWEsRUFBa0MsRUFBRTtJQUNyRixNQUFNLE9BQU8sR0FBRyxnQkFBZ0IsRUFBRSxDQUFDO0lBQ25DLE1BQU0sWUFBWSxHQUFHLFlBQVksQ0FBQyxRQUFRLEVBQUcsQ0FBQztJQUM5QyxJQUFJLENBQUM7UUFDSCxNQUFNLE9BQU8sR0FBRyxJQUFJLE9BQU8sQ0FBQyxRQUFRLENBQUMsT0FBTyxDQUFDLFlBQVksQ0FBQyxZQUFZLENBRXBFLGVBQWUsRUFBRSxxQkFBcUIsQ0FBQyxDQUFDO1FBQzFDLE1BQU0sT0FBTyxDQUFDLElBQUksQ0FBQyxFQUFFLFFBQVEsRUFBRSxPQUFPLENBQUMsUUFBUyxFQUFFLEVBQUUsRUFBRSxlQUFlLEVBQUUsQ0FBQyxDQUFDO1FBQ3pFLE9BQU8sTUFBTSxhQUFjLENBQUMsUUFBUSxDQUFDLHlCQUF5QixFQUFFLElBQUksQ0FBQyxDQUFDO0lBQ3hFLENBQUM7SUFBQyxPQUFPLEtBQUssRUFBRSxDQUFDO1FBQ2YsT0FBTztZQUNMLEdBQUcsWUFBWTtZQUNmLEtBQUssRUFBRSxLQUFLLFlBQVksS0FBSyxDQUFDLENBQUMsQ0FBQyxLQUFLLENBQUMsT0FBTyxDQUFDLENBQUMsQ0FBQyxpQ0FBaUM7U0FDbEYsQ0FBQztJQUNKLENBQUM7QUFDSCxDQUFDLENBQ0YsQ0FBQztBQUVGLE1BQU0sQ0FBQyxLQUFLLFVBQVUsd0JBQXdCLENBQzVDLGVBQXVCLEVBQ3ZCLElBQWEsRUFDYixhQUE2QjtJQUU3QixNQUFNLE9BQU8sR0FBRyxnQkFBZ0IsRUFBRSxDQUFDO0lBQ25DLE1BQU0sT0FBTyxHQUFHLElBQUksT0FBTyxDQUFDLFFBQVEsQ0FBQyxPQUFPLENBQUMsWUFBWSxDQUFDLFlBQVksQ0FFcEUsZUFBZSxFQUFFLDBCQUEwQixDQUFDLENBQUM7SUFDL0MsT0FBTyxPQUFPLENBQUMsSUFBSSxDQUFDO1FBQ2xCLFFBQVEsRUFBRSxPQUFPLENBQUMsUUFBUztRQUMzQixlQUFlO1FBQ2YsSUFBSTtRQUNKLGFBQWE7S0FDZCxDQUFDLENBQUM7QUFDTCxDQUFDO0FBRUQsUUFBUTtBQUVSLE1BQU0sQ0FBQyxLQUFLLFVBQVUsY0FBYyxDQUNsQyxJQUFZLEVBQ1osTUFBd0MsRUFDeEMsYUFBNkIsRUFDN0IsTUFBWTtJQUVaLE1BQU0sT0FBTyxHQUFHLGdCQUFnQixFQUFFLENBQUM7SUFDbkMsTUFBTSxPQUFPLEdBQUcsSUFBSSxPQUFPLENBQUMsUUFBUSxDQUFDLE9BQU8sQ0FBQyxZQUFZLENBQUMsWUFBWSxDQUVwRSxlQUFlLEVBQUUsZ0JBQWdCLENBQUMsQ0FBQztJQUVyQyxPQUFPLE9BQU8sQ0FBQyxJQUFJLENBQUM7UUFDbEIsUUFBUSxFQUFFLE9BQU8sQ0FBQyxRQUFTO1FBQzNCLElBQUk7UUFDSixNQUFNO1FBQ04sTUFBTTtRQUNOLGFBQWE7S0FDZCxDQUFDLENBQUM7QUFDTCxDQUFDO0FBRUQsTUFBTSxDQUFDLEtBQUssVUFBVSxZQUFZLENBQUMsRUFBVTtJQUMzQyxNQUFNLE9BQU8sR0FBRyxnQkFBZ0IsRUFBRSxDQUFDO0lBQ25DLE1BQU0sT0FBTyxHQUFHLElBQUksT0FBTyxDQUFDLFFBQVEsQ0FBQyxPQUFPLENBQUMsWUFBWSxDQUFDLFlBQVksQ0FFcEUsZUFBZSxFQUFFLGNBQWMsQ0FBQyxDQUFDO0lBRW5DLE9BQU8sT0FBTyxDQUFDLElBQUksQ0FBQztRQUNsQixRQUFRLEVBQUUsT0FBTyxDQUFDLFFBQVM7UUFDM0IsRUFBRTtLQUNILENBQUMsQ0FBQztBQUNMLENBQUM7QUFFRCxNQUFNLENBQUMsTUFBTSxvQkFBb0IsR0FBRyx3QkFBd0IsQ0FBQyxZQUFZLENBQ3ZFLEtBQUssRUFBRSxZQUFZLEVBQUUsT0FBTyxFQUFFLGFBQWEsRUFBa0MsRUFBRTtJQUM3RSxNQUFNLE9BQU8sR0FBRyxnQkFBZ0IsRUFBRSxDQUFDO0lBQ25DLE1BQU0sWUFBWSxHQUFHLFlBQVksQ0FBQyxRQUFRLEVBQUcsQ0FBQztJQUU5QyxJQUFJLENBQUM7UUFDSCxNQUFNLE9BQU8sR0FBRyxJQUFJLE9BQU8sQ0FBQyxRQUFRLENBQUMsT0FBTyxDQUFDLFlBQVksQ0FBQyxZQUFZLENBRXBFLGVBQWUsRUFBRSxnQkFBZ0IsQ0FBQyxDQUFDO1FBRXJDLE1BQU0sT0FBTyxDQUFDLElBQUksQ0FBQztZQUNqQixRQUFRLEVBQUUsT0FBTyxDQUFDLFFBQVM7WUFDM0IsRUFBRSxFQUFFLE9BQU87U0FDWixDQUFDLENBQUM7UUFFSCxPQUFPLE1BQU0sYUFBYyxDQUFDLFFBQVEsQ0FBQyxvQkFBb0IsRUFBRSxJQUFJLENBQUMsQ0FBQztJQUNuRSxDQUFDO0lBQUMsT0FBTyxLQUFjLEVBQUUsQ0FBQztRQUN4QixPQUFPO1lBQ0wsR0FBRyxZQUFZO1lBQ2YsS0FBSyxFQUFFLEtBQUssWUFBWSxLQUFLLENBQUMsQ0FBQyxDQUFDLEtBQUssQ0FBQyxPQUFPLENBQUMsQ0FBQyxDQUFDLHdCQUF3QjtTQUN6RSxDQUFDO0lBQ0osQ0FBQztBQUNILENBQUMsQ0FDRixDQUFDO0FBRUYsTUFBTSxDQUFDLE1BQU0sb0JBQW9CLEdBQUcsd0JBQXdCLENBQUMsWUFBWSxDQUd0RSxLQUFLLEVBQUUsWUFBWSxFQUFFLE9BQU8sRUFBRSxhQUFhLEVBQWtDLEVBQUU7SUFDaEYsTUFBTSxPQUFPLEdBQUcsZ0JBQWdCLEVBQUUsQ0FBQztJQUNuQyxNQUFNLFlBQVksR0FBRyxZQUFZLENBQUMsUUFBUSxFQUFHLENBQUM7SUFFOUMsSUFBSSxDQUFDO1FBQ0gsTUFBTSxPQUFPLEdBQUcsSUFBSSxPQUFPLENBQUMsUUFBUSxDQUFDLE9BQU8sQ0FBQyxZQUFZLENBQUMsWUFBWSxDQUVwRSxlQUFlLEVBQUUsZ0JBQWdCLENBQUMsQ0FBQztRQUVyQyxNQUFNLE9BQU8sQ0FBQyxJQUFJLENBQUM7WUFDakIsUUFBUSxFQUFFLE9BQU8sQ0FBQyxRQUFTO1lBQzNCLEVBQUUsRUFBRSxPQUFPLENBQUMsRUFBRTtZQUNkLE9BQU8sRUFBRSxPQUFPLENBQUMsT0FBTztTQUN6QixDQUFDLENBQUM7UUFFSCxPQUFPLE1BQU0sYUFBYyxDQUFDLFFBQVEsQ0FBQyxvQkFBb0IsRUFBRSxJQUFJLENBQUMsQ0FBQztJQUNuRSxDQUFDO0lBQUMsT0FBTyxLQUFjLEVBQUUsQ0FBQztRQUN4QixPQUFPO1lBQ0wsR0FBRyxZQUFZO1lBQ2YsS0FBSyxFQUFFLEtBQUssWUFBWSxLQUFLLENBQUMsQ0FBQyxDQUFDLEtBQUssQ0FBQyxPQUFPLENBQUMsQ0FBQyxDQUFDLHdCQUF3QjtTQUN6RSxDQUFDO0lBQ0osQ0FBQztBQUNILENBQUMsQ0FBQyxDQUFDIn0=
@@ -0,0 +1 @@
1
+ export {};
@@ -0,0 +1,276 @@
1
+ import * as plugins from '../plugins.js';
2
+ import * as interfaces from '../../dist_ts_interfaces/index.js';
3
+ import { runBackgroundRefresh } from './shared.js';
4
+ import { getActionContext, loginStatePart, logoutAction } from './login.js';
5
+ import { uiStatePart } from './ui.js';
6
+ import { statsStatePart } from './stats.js';
7
+ import { logStatePart } from './logs.js';
8
+ import { networkStatePart, refreshNetworkIpIntelligence } from './network.js';
9
+ import { securityPolicyStatePart, fetchSecurityPolicyAction } from './security.js';
10
+ import { certificateStatePart, fetchCertificateOverviewAction } from './certificates.js';
11
+ import { remoteIngressStatePart, fetchRemoteIngressAction } from './remoteingress.js';
12
+ import { vpnStatePart, fetchVpnAction } from './vpn.js';
13
+ // ============================================================================
14
+ // TypedSocket Client for Real-time Log Streaming
15
+ // ============================================================================
16
+ let socketClient = null;
17
+ const socketRouter = new plugins.domtools.plugins.typedrequest.TypedRouter();
18
+ // Batched log entry handler — buffers incoming entries and flushes once per animation frame
19
+ let logEntryBuffer = [];
20
+ let logFlushScheduled = false;
21
+ function flushLogEntries() {
22
+ logFlushScheduled = false;
23
+ if (logEntryBuffer.length === 0)
24
+ return;
25
+ const current = logStatePart.getState();
26
+ const updated = [...current.recentLogs, ...logEntryBuffer];
27
+ logEntryBuffer = [];
28
+ // Cap at 2000 entries
29
+ if (updated.length > 2000) {
30
+ updated.splice(0, updated.length - 2000);
31
+ }
32
+ logStatePart.setState({ ...current, recentLogs: updated });
33
+ }
34
+ // Register handler for pushed log entries from the server
35
+ socketRouter.addTypedHandler(new plugins.domtools.plugins.typedrequest.TypedHandler('pushLogEntry', async (dataArg) => {
36
+ logEntryBuffer.push(dataArg.entry);
37
+ if (!logFlushScheduled) {
38
+ logFlushScheduled = true;
39
+ requestAnimationFrame(flushLogEntries);
40
+ }
41
+ return {};
42
+ }));
43
+ async function connectSocket() {
44
+ if (socketClient)
45
+ return;
46
+ try {
47
+ socketClient = await plugins.typedsocket.TypedSocket.createClient(socketRouter, plugins.typedsocket.TypedSocket.useWindowLocationOriginUrl());
48
+ await socketClient.setTag('role', 'ops_dashboard');
49
+ }
50
+ catch (err) {
51
+ console.error('TypedSocket connection failed:', err);
52
+ socketClient = null;
53
+ }
54
+ }
55
+ async function disconnectSocket() {
56
+ if (socketClient) {
57
+ try {
58
+ await socketClient.stop();
59
+ }
60
+ catch {
61
+ // ignore disconnect errors
62
+ }
63
+ socketClient = null;
64
+ }
65
+ }
66
+ // In-flight guard to prevent concurrent refresh requests
67
+ let isRefreshing = false;
68
+ // Combined refresh action for efficient polling
69
+ async function dispatchCombinedRefreshAction() {
70
+ if (isRefreshing)
71
+ return;
72
+ isRefreshing = true;
73
+ try {
74
+ await dispatchCombinedRefreshActionInner();
75
+ }
76
+ finally {
77
+ isRefreshing = false;
78
+ }
79
+ }
80
+ async function dispatchCombinedRefreshActionInner() {
81
+ const context = getActionContext();
82
+ if (!context.identity)
83
+ return;
84
+ const currentView = uiStatePart.getState().activeView;
85
+ const currentSubview = uiStatePart.getState().activeSubview;
86
+ try {
87
+ // Always fetch basic stats for dashboard widgets
88
+ const combinedRequest = new plugins.domtools.plugins.typedrequest.TypedRequest('/typedrequest', 'getCombinedMetrics');
89
+ const combinedResponse = await combinedRequest.fire({
90
+ identity: context.identity,
91
+ sections: {
92
+ server: true,
93
+ email: true,
94
+ dns: true,
95
+ security: true,
96
+ network: currentView === 'network' && currentSubview === 'activity',
97
+ radius: true,
98
+ vpn: true,
99
+ },
100
+ });
101
+ // Update all stats from combined response
102
+ const currentStatsState = statsStatePart.getState();
103
+ statsStatePart.setState({
104
+ ...currentStatsState,
105
+ serverStats: combinedResponse.metrics.server || currentStatsState.serverStats,
106
+ emailStats: combinedResponse.metrics.email || currentStatsState.emailStats,
107
+ dnsStats: combinedResponse.metrics.dns || currentStatsState.dnsStats,
108
+ securityMetrics: combinedResponse.metrics.security || currentStatsState.securityMetrics,
109
+ radiusStats: combinedResponse.metrics.radius || currentStatsState.radiusStats,
110
+ vpnStats: combinedResponse.metrics.vpn || currentStatsState.vpnStats,
111
+ lastUpdated: Date.now(),
112
+ isLoading: false,
113
+ error: null,
114
+ });
115
+ // Update network stats if included
116
+ if (combinedResponse.metrics.network && currentView === 'network') {
117
+ const network = combinedResponse.metrics.network;
118
+ const connectionsByIP = {};
119
+ // Build connectionsByIP from connectionDetails (now populated with real per-IP data)
120
+ network.connectionDetails.forEach(conn => {
121
+ connectionsByIP[conn.remoteAddress] = (connectionsByIP[conn.remoteAddress] || 0) + (conn.connectionCount || 1);
122
+ });
123
+ // Build connections from connectionDetails (real per-IP aggregates)
124
+ const connections = network.connectionDetails.map((conn, i) => ({
125
+ id: `ip-${conn.remoteAddress}`,
126
+ remoteAddress: conn.remoteAddress,
127
+ localAddress: 'server',
128
+ startTime: conn.startTime,
129
+ protocol: conn.protocol,
130
+ state: conn.state,
131
+ bytesReceived: conn.bytesIn,
132
+ bytesSent: conn.bytesOut,
133
+ connectionCount: conn.connectionCount,
134
+ }));
135
+ networkStatePart.setState({
136
+ ...networkStatePart.getState(),
137
+ connections,
138
+ connectionsByIP,
139
+ throughputRate: {
140
+ bytesInPerSecond: network.totalBandwidth.in,
141
+ bytesOutPerSecond: network.totalBandwidth.out,
142
+ },
143
+ totalBytes: network.totalBytes || { in: 0, out: 0 },
144
+ topIPs: network.topEndpoints.map(e => ({ ip: e.endpoint, count: e.connections })),
145
+ topIPsByBandwidth: (network.topEndpointsByBandwidth || []).map(e => ({
146
+ ip: e.endpoint,
147
+ count: e.connections,
148
+ bwIn: e.bandwidth?.in || 0,
149
+ bwOut: e.bandwidth?.out || 0,
150
+ })),
151
+ topASNs: network.topASNs || [],
152
+ throughputByIP: network.topEndpoints.map(e => ({ ip: e.endpoint, in: e.bandwidth?.in || 0, out: e.bandwidth?.out || 0 })),
153
+ domainActivity: network.domainActivity || [],
154
+ throughputHistory: network.throughputHistory || [],
155
+ requestsPerSecond: network.requestsPerSecond || 0,
156
+ requestsTotal: network.requestsTotal || 0,
157
+ backends: network.backends || [],
158
+ frontendProtocols: network.frontendProtocols || null,
159
+ backendProtocols: network.backendProtocols || null,
160
+ lastUpdated: Date.now(),
161
+ isLoading: false,
162
+ error: null,
163
+ });
164
+ refreshNetworkIpIntelligence(context.identity, [
165
+ ...network.connectionDetails.map((conn) => conn.remoteAddress),
166
+ ...network.topEndpoints.map((endpoint) => endpoint.endpoint),
167
+ ...(network.topEndpointsByBandwidth || []).map((endpoint) => endpoint.endpoint),
168
+ ]);
169
+ }
170
+ if (currentView === 'security') {
171
+ runBackgroundRefresh('securityPolicy', 'Security policy refresh failed:', async () => {
172
+ await securityPolicyStatePart.dispatchAction(fetchSecurityPolicyAction, null);
173
+ });
174
+ }
175
+ // Refresh certificate data if on Domains > Certificates subview
176
+ if (currentView === 'domains' && currentSubview === 'certificates') {
177
+ runBackgroundRefresh('certificates', 'Certificate refresh failed:', async () => {
178
+ await certificateStatePart.dispatchAction(fetchCertificateOverviewAction, null);
179
+ });
180
+ }
181
+ // Refresh remote ingress data if on the Network → Remote Ingress subview
182
+ if (currentView === 'network' && currentSubview === 'remoteingress') {
183
+ runBackgroundRefresh('remoteIngress', 'Remote ingress refresh failed:', async () => {
184
+ await remoteIngressStatePart.dispatchAction(fetchRemoteIngressAction, null);
185
+ });
186
+ }
187
+ // Refresh VPN data if on the Network → VPN subview
188
+ if (currentView === 'network' && currentSubview === 'vpn') {
189
+ runBackgroundRefresh('vpn', 'VPN refresh failed:', async () => {
190
+ await vpnStatePart.dispatchAction(fetchVpnAction, null);
191
+ });
192
+ }
193
+ }
194
+ catch (error) {
195
+ console.error('Combined refresh failed:', error);
196
+ // If the error looks like an auth failure (invalid JWT), force re-login
197
+ const errMsg = String(error);
198
+ if (errMsg.includes('invalid') || errMsg.includes('unauthorized') || errMsg.includes('401')) {
199
+ await loginStatePart.dispatchAction(logoutAction, null);
200
+ window.location.reload();
201
+ }
202
+ }
203
+ }
204
+ // Create a proper action for the combined refresh so we can use createScheduledAction
205
+ const combinedRefreshAction = statsStatePart.createAction(async (statePartArg) => {
206
+ await dispatchCombinedRefreshAction();
207
+ // Return current state — dispatchCombinedRefreshAction already updates all state parts directly
208
+ return statePartArg.getState();
209
+ });
210
+ // Scheduled refresh process with autoPause: 'visibility' — automatically pauses when tab is hidden
211
+ let refreshProcess = null;
212
+ const startAutoRefresh = () => {
213
+ const uiState = uiStatePart.getState();
214
+ const loginState = loginStatePart.getState();
215
+ if (uiState.autoRefresh && loginState.isLoggedIn) {
216
+ // Dispose old process if interval changed or not running
217
+ if (refreshProcess) {
218
+ refreshProcess.dispose();
219
+ refreshProcess = null;
220
+ }
221
+ refreshProcess = statsStatePart.createScheduledAction({
222
+ action: combinedRefreshAction,
223
+ payload: undefined,
224
+ intervalMs: uiState.refreshInterval,
225
+ autoPause: 'visibility',
226
+ });
227
+ }
228
+ else {
229
+ if (refreshProcess) {
230
+ refreshProcess.dispose();
231
+ refreshProcess = null;
232
+ }
233
+ }
234
+ };
235
+ // Watch for relevant changes
236
+ let previousAutoRefresh = uiStatePart.getState().autoRefresh;
237
+ let previousRefreshInterval = uiStatePart.getState().refreshInterval;
238
+ let previousIsLoggedIn = loginStatePart.getState().isLoggedIn;
239
+ uiStatePart.select((s) => ({ autoRefresh: s.autoRefresh, refreshInterval: s.refreshInterval }))
240
+ .subscribe((state) => {
241
+ if (state.autoRefresh !== previousAutoRefresh ||
242
+ state.refreshInterval !== previousRefreshInterval) {
243
+ previousAutoRefresh = state.autoRefresh;
244
+ previousRefreshInterval = state.refreshInterval;
245
+ startAutoRefresh();
246
+ }
247
+ });
248
+ loginStatePart.select((s) => s.isLoggedIn).subscribe((isLoggedIn) => {
249
+ if (isLoggedIn !== previousIsLoggedIn) {
250
+ previousIsLoggedIn = isLoggedIn;
251
+ startAutoRefresh();
252
+ // Connect/disconnect TypedSocket based on login state
253
+ if (isLoggedIn) {
254
+ connectSocket();
255
+ }
256
+ else {
257
+ disconnectSocket();
258
+ }
259
+ }
260
+ });
261
+ // Pause/resume WebSocket when tab visibility changes
262
+ document.addEventListener('visibilitychange', () => {
263
+ if (document.hidden) {
264
+ disconnectSocket();
265
+ }
266
+ else if (loginStatePart.getState().isLoggedIn) {
267
+ connectSocket();
268
+ }
269
+ });
270
+ // Initial start
271
+ startAutoRefresh();
272
+ // Connect TypedSocket if already logged in (e.g., persistent session)
273
+ if (loginStatePart.getState().isLoggedIn) {
274
+ connectSocket();
275
+ }
276
+ //# sourceMappingURL=data:application/json;base64,eyJ2ZXJzaW9uIjozLCJmaWxlIjoicnVudGltZS5qcyIsInNvdXJjZVJvb3QiOiIiLCJzb3VyY2VzIjpbIi4uLy4uLy4uL3RzX3dlYi9hcHBzdGF0ZS9ydW50aW1lLnRzIl0sIm5hbWVzIjpbXSwibWFwcGluZ3MiOiJBQUFBLE9BQU8sS0FBSyxPQUFPLE1BQU0sZUFBZSxDQUFDO0FBQ3pDLE9BQU8sS0FBSyxVQUFVLE1BQU0sOEJBQThCLENBQUM7QUFDM0QsT0FBTyxFQUFFLG9CQUFvQixFQUFFLE1BQU0sYUFBYSxDQUFDO0FBQ25ELE9BQU8sRUFBRSxnQkFBZ0IsRUFBRSxjQUFjLEVBQUUsWUFBWSxFQUFFLE1BQU0sWUFBWSxDQUFDO0FBQzVFLE9BQU8sRUFBRSxXQUFXLEVBQUUsTUFBTSxTQUFTLENBQUM7QUFDdEMsT0FBTyxFQUFFLGNBQWMsRUFBRSxNQUFNLFlBQVksQ0FBQztBQUM1QyxPQUFPLEVBQUUsWUFBWSxFQUFrQixNQUFNLFdBQVcsQ0FBQztBQUN6RCxPQUFPLEVBQUUsZ0JBQWdCLEVBQUUsNEJBQTRCLEVBQUUsTUFBTSxjQUFjLENBQUM7QUFDOUUsT0FBTyxFQUFFLHVCQUF1QixFQUFFLHlCQUF5QixFQUFFLE1BQU0sZUFBZSxDQUFDO0FBQ25GLE9BQU8sRUFBRSxvQkFBb0IsRUFBRSw4QkFBOEIsRUFBRSxNQUFNLG1CQUFtQixDQUFDO0FBQ3pGLE9BQU8sRUFBRSxzQkFBc0IsRUFBRSx3QkFBd0IsRUFBRSxNQUFNLG9CQUFvQixDQUFDO0FBQ3RGLE9BQU8sRUFBRSxZQUFZLEVBQUUsY0FBYyxFQUFFLE1BQU0sVUFBVSxDQUFDO0FBR3hELCtFQUErRTtBQUMvRSxpREFBaUQ7QUFDakQsK0VBQStFO0FBRS9FLElBQUksWUFBWSxHQUEyQyxJQUFJLENBQUM7QUFDaEUsTUFBTSxZQUFZLEdBQUcsSUFBSSxPQUFPLENBQUMsUUFBUSxDQUFDLE9BQU8sQ0FBQyxZQUFZLENBQUMsV0FBVyxFQUFFLENBQUM7QUFFN0UsNEZBQTRGO0FBQzVGLElBQUksY0FBYyxHQUFnQyxFQUFFLENBQUM7QUFDckQsSUFBSSxpQkFBaUIsR0FBRyxLQUFLLENBQUM7QUFFOUIsU0FBUyxlQUFlO0lBQ3RCLGlCQUFpQixHQUFHLEtBQUssQ0FBQztJQUMxQixJQUFJLGNBQWMsQ0FBQyxNQUFNLEtBQUssQ0FBQztRQUFFLE9BQU87SUFDeEMsTUFBTSxPQUFPLEdBQUcsWUFBWSxDQUFDLFFBQVEsRUFBRyxDQUFDO0lBQ3pDLE1BQU0sT0FBTyxHQUFHLENBQUMsR0FBRyxPQUFPLENBQUMsVUFBVSxFQUFFLEdBQUcsY0FBYyxDQUFDLENBQUM7SUFDM0QsY0FBYyxHQUFHLEVBQUUsQ0FBQztJQUNwQixzQkFBc0I7SUFDdEIsSUFBSSxPQUFPLENBQUMsTUFBTSxHQUFHLElBQUksRUFBRSxDQUFDO1FBQzFCLE9BQU8sQ0FBQyxNQUFNLENBQUMsQ0FBQyxFQUFFLE9BQU8sQ0FBQyxNQUFNLEdBQUcsSUFBSSxDQUFDLENBQUM7SUFDM0MsQ0FBQztJQUNELFlBQVksQ0FBQyxRQUFRLENBQUMsRUFBRSxHQUFHLE9BQU8sRUFBRSxVQUFVLEVBQUUsT0FBTyxFQUFlLENBQUMsQ0FBQztBQUMxRSxDQUFDO0FBRUQsMERBQTBEO0FBQzFELFlBQVksQ0FBQyxlQUFlLENBQzFCLElBQUksT0FBTyxDQUFDLFFBQVEsQ0FBQyxPQUFPLENBQUMsWUFBWSxDQUFDLFlBQVksQ0FDcEQsY0FBYyxFQUNkLEtBQUssRUFBRSxPQUFPLEVBQUUsRUFBRTtJQUNoQixjQUFjLENBQUMsSUFBSSxDQUFDLE9BQU8sQ0FBQyxLQUFLLENBQUMsQ0FBQztJQUNuQyxJQUFJLENBQUMsaUJBQWlCLEVBQUUsQ0FBQztRQUN2QixpQkFBaUIsR0FBRyxJQUFJLENBQUM7UUFDekIscUJBQXFCLENBQUMsZUFBZSxDQUFDLENBQUM7SUFDekMsQ0FBQztJQUNELE9BQU8sRUFBRSxDQUFDO0FBQ1osQ0FBQyxDQUNGLENBQ0YsQ0FBQztBQUVGLEtBQUssVUFBVSxhQUFhO0lBQzFCLElBQUksWUFBWTtRQUFFLE9BQU87SUFDekIsSUFBSSxDQUFDO1FBQ0gsWUFBWSxHQUFHLE1BQU0sT0FBTyxDQUFDLFdBQVcsQ0FBQyxXQUFXLENBQUMsWUFBWSxDQUMvRCxZQUFZLEVBQ1osT0FBTyxDQUFDLFdBQVcsQ0FBQyxXQUFXLENBQUMsMEJBQTBCLEVBQUUsQ0FDN0QsQ0FBQztRQUNGLE1BQU0sWUFBWSxDQUFDLE1BQU0sQ0FBQyxNQUFNLEVBQUUsZUFBZSxDQUFDLENBQUM7SUFDckQsQ0FBQztJQUFDLE9BQU8sR0FBRyxFQUFFLENBQUM7UUFDYixPQUFPLENBQUMsS0FBSyxDQUFDLGdDQUFnQyxFQUFFLEdBQUcsQ0FBQyxDQUFDO1FBQ3JELFlBQVksR0FBRyxJQUFJLENBQUM7SUFDdEIsQ0FBQztBQUNILENBQUM7QUFFRCxLQUFLLFVBQVUsZ0JBQWdCO0lBQzdCLElBQUksWUFBWSxFQUFFLENBQUM7UUFDakIsSUFBSSxDQUFDO1lBQ0gsTUFBTSxZQUFZLENBQUMsSUFBSSxFQUFFLENBQUM7UUFDNUIsQ0FBQztRQUFDLE1BQU0sQ0FBQztZQUNQLDJCQUEyQjtRQUM3QixDQUFDO1FBQ0QsWUFBWSxHQUFHLElBQUksQ0FBQztJQUN0QixDQUFDO0FBQ0gsQ0FBQztBQUVELHlEQUF5RDtBQUN6RCxJQUFJLFlBQVksR0FBRyxLQUFLLENBQUM7QUFFekIsZ0RBQWdEO0FBQ2hELEtBQUssVUFBVSw2QkFBNkI7SUFDMUMsSUFBSSxZQUFZO1FBQUUsT0FBTztJQUN6QixZQUFZLEdBQUcsSUFBSSxDQUFDO0lBQ3BCLElBQUksQ0FBQztRQUNILE1BQU0sa0NBQWtDLEVBQUUsQ0FBQztJQUM3QyxDQUFDO1lBQVMsQ0FBQztRQUNULFlBQVksR0FBRyxLQUFLLENBQUM7SUFDdkIsQ0FBQztBQUNILENBQUM7QUFFRCxLQUFLLFVBQVUsa0NBQWtDO0lBQy9DLE1BQU0sT0FBTyxHQUFHLGdCQUFnQixFQUFFLENBQUM7SUFDbkMsSUFBSSxDQUFDLE9BQU8sQ0FBQyxRQUFRO1FBQUUsT0FBTztJQUM5QixNQUFNLFdBQVcsR0FBRyxXQUFXLENBQUMsUUFBUSxFQUFHLENBQUMsVUFBVSxDQUFDO0lBQ3ZELE1BQU0sY0FBYyxHQUFHLFdBQVcsQ0FBQyxRQUFRLEVBQUcsQ0FBQyxhQUFhLENBQUM7SUFFN0QsSUFBSSxDQUFDO1FBQ0gsaURBQWlEO1FBQ2pELE1BQU0sZUFBZSxHQUFHLElBQUksT0FBTyxDQUFDLFFBQVEsQ0FBQyxPQUFPLENBQUMsWUFBWSxDQUFDLFlBQVksQ0FFNUUsZUFBZSxFQUFFLG9CQUFvQixDQUFDLENBQUM7UUFFekMsTUFBTSxnQkFBZ0IsR0FBRyxNQUFNLGVBQWUsQ0FBQyxJQUFJLENBQUM7WUFDbEQsUUFBUSxFQUFFLE9BQU8sQ0FBQyxRQUFRO1lBQzFCLFFBQVEsRUFBRTtnQkFDUixNQUFNLEVBQUUsSUFBSTtnQkFDWixLQUFLLEVBQUUsSUFBSTtnQkFDWCxHQUFHLEVBQUUsSUFBSTtnQkFDVCxRQUFRLEVBQUUsSUFBSTtnQkFDZCxPQUFPLEVBQUUsV0FBVyxLQUFLLFNBQVMsSUFBSSxjQUFjLEtBQUssVUFBVTtnQkFDbkUsTUFBTSxFQUFFLElBQUk7Z0JBQ1osR0FBRyxFQUFFLElBQUk7YUFDVjtTQUNGLENBQUMsQ0FBQztRQUVILDBDQUEwQztRQUMxQyxNQUFNLGlCQUFpQixHQUFHLGNBQWMsQ0FBQyxRQUFRLEVBQUcsQ0FBQztRQUNyRCxjQUFjLENBQUMsUUFBUSxDQUFDO1lBQ3RCLEdBQUcsaUJBQWlCO1lBQ3BCLFdBQVcsRUFBRSxnQkFBZ0IsQ0FBQyxPQUFPLENBQUMsTUFBTSxJQUFJLGlCQUFpQixDQUFDLFdBQVc7WUFDN0UsVUFBVSxFQUFFLGdCQUFnQixDQUFDLE9BQU8sQ0FBQyxLQUFLLElBQUksaUJBQWlCLENBQUMsVUFBVTtZQUMxRSxRQUFRLEVBQUUsZ0JBQWdCLENBQUMsT0FBTyxDQUFDLEdBQUcsSUFBSSxpQkFBaUIsQ0FBQyxRQUFRO1lBQ3BFLGVBQWUsRUFBRSxnQkFBZ0IsQ0FBQyxPQUFPLENBQUMsUUFBUSxJQUFJLGlCQUFpQixDQUFDLGVBQWU7WUFDdkYsV0FBVyxFQUFFLGdCQUFnQixDQUFDLE9BQU8sQ0FBQyxNQUFNLElBQUksaUJBQWlCLENBQUMsV0FBVztZQUM3RSxRQUFRLEVBQUUsZ0JBQWdCLENBQUMsT0FBTyxDQUFDLEdBQUcsSUFBSSxpQkFBaUIsQ0FBQyxRQUFRO1lBQ3BFLFdBQVcsRUFBRSxJQUFJLENBQUMsR0FBRyxFQUFFO1lBQ3ZCLFNBQVMsRUFBRSxLQUFLO1lBQ2hCLEtBQUssRUFBRSxJQUFJO1NBQ1osQ0FBQyxDQUFDO1FBRUgsbUNBQW1DO1FBQ25DLElBQUksZ0JBQWdCLENBQUMsT0FBTyxDQUFDLE9BQU8sSUFBSSxXQUFXLEtBQUssU0FBUyxFQUFFLENBQUM7WUFDbEUsTUFBTSxPQUFPLEdBQUcsZ0JBQWdCLENBQUMsT0FBTyxDQUFDLE9BQU8sQ0FBQztZQUNqRCxNQUFNLGVBQWUsR0FBNkIsRUFBRSxDQUFDO1lBRXJELHFGQUFxRjtZQUNyRixPQUFPLENBQUMsaUJBQWlCLENBQUMsT0FBTyxDQUFDLElBQUksQ0FBQyxFQUFFO2dCQUN2QyxlQUFlLENBQUMsSUFBSSxDQUFDLGFBQWEsQ0FBQyxHQUFHLENBQUMsZUFBZSxDQUFDLElBQUksQ0FBQyxhQUFhLENBQUMsSUFBSSxDQUFDLENBQUMsR0FBRyxDQUFDLElBQUksQ0FBQyxlQUFlLElBQUksQ0FBQyxDQUFDLENBQUM7WUFDakgsQ0FBQyxDQUFDLENBQUM7WUFFSCxvRUFBb0U7WUFDcEUsTUFBTSxXQUFXLEdBQXNDLE9BQU8sQ0FBQyxpQkFBaUIsQ0FBQyxHQUFHLENBQUMsQ0FBQyxJQUFJLEVBQUUsQ0FBQyxFQUFFLEVBQUUsQ0FBQyxDQUFDO2dCQUNqRyxFQUFFLEVBQUUsTUFBTSxJQUFJLENBQUMsYUFBYSxFQUFFO2dCQUM5QixhQUFhLEVBQUUsSUFBSSxDQUFDLGFBQWE7Z0JBQ2pDLFlBQVksRUFBRSxRQUFRO2dCQUN0QixTQUFTLEVBQUUsSUFBSSxDQUFDLFNBQVM7Z0JBQ3pCLFFBQVEsRUFBRSxJQUFJLENBQUMsUUFBZTtnQkFDOUIsS0FBSyxFQUFFLElBQUksQ0FBQyxLQUFZO2dCQUN4QixhQUFhLEVBQUUsSUFBSSxDQUFDLE9BQU87Z0JBQzNCLFNBQVMsRUFBRSxJQUFJLENBQUMsUUFBUTtnQkFDeEIsZUFBZSxFQUFFLElBQUksQ0FBQyxlQUFlO2FBQ3RDLENBQUMsQ0FBQyxDQUFDO1lBRUosZ0JBQWdCLENBQUMsUUFBUSxDQUFDO2dCQUN4QixHQUFHLGdCQUFnQixDQUFDLFFBQVEsRUFBRztnQkFDL0IsV0FBVztnQkFDWCxlQUFlO2dCQUNmLGNBQWMsRUFBRTtvQkFDZCxnQkFBZ0IsRUFBRSxPQUFPLENBQUMsY0FBYyxDQUFDLEVBQUU7b0JBQzNDLGlCQUFpQixFQUFFLE9BQU8sQ0FBQyxjQUFjLENBQUMsR0FBRztpQkFDOUM7Z0JBQ0QsVUFBVSxFQUFFLE9BQU8sQ0FBQyxVQUFVLElBQUksRUFBRSxFQUFFLEVBQUUsQ0FBQyxFQUFFLEdBQUcsRUFBRSxDQUFDLEVBQUU7Z0JBQ25ELE1BQU0sRUFBRSxPQUFPLENBQUMsWUFBWSxDQUFDLEdBQUcsQ0FBQyxDQUFDLENBQUMsRUFBRSxDQUFDLENBQUMsRUFBRSxFQUFFLEVBQUUsQ0FBQyxDQUFDLFFBQVEsRUFBRSxLQUFLLEVBQUUsQ0FBQyxDQUFDLFdBQVcsRUFBRSxDQUFDLENBQUM7Z0JBQ2pGLGlCQUFpQixFQUFFLENBQUMsT0FBTyxDQUFDLHVCQUF1QixJQUFJLEVBQUUsQ0FBQyxDQUFDLEdBQUcsQ0FBQyxDQUFDLENBQUMsRUFBRSxDQUFDLENBQUM7b0JBQ25FLEVBQUUsRUFBRSxDQUFDLENBQUMsUUFBUTtvQkFDZCxLQUFLLEVBQUUsQ0FBQyxDQUFDLFdBQVc7b0JBQ3BCLElBQUksRUFBRSxDQUFDLENBQUMsU0FBUyxFQUFFLEVBQUUsSUFBSSxDQUFDO29CQUMxQixLQUFLLEVBQUUsQ0FBQyxDQUFDLFNBQVMsRUFBRSxHQUFHLElBQUksQ0FBQztpQkFDN0IsQ0FBQyxDQUFDO2dCQUNILE9BQU8sRUFBRSxPQUFPLENBQUMsT0FBTyxJQUFJLEVBQUU7Z0JBQzlCLGNBQWMsRUFBRSxPQUFPLENBQUMsWUFBWSxDQUFDLEdBQUcsQ0FBQyxDQUFDLENBQUMsRUFBRSxDQUFDLENBQUMsRUFBRSxFQUFFLEVBQUUsQ0FBQyxDQUFDLFFBQVEsRUFBRSxFQUFFLEVBQUUsQ0FBQyxDQUFDLFNBQVMsRUFBRSxFQUFFLElBQUksQ0FBQyxFQUFFLEdBQUcsRUFBRSxDQUFDLENBQUMsU0FBUyxFQUFFLEdBQUcsSUFBSSxDQUFDLEVBQUUsQ0FBQyxDQUFDO2dCQUN6SCxjQUFjLEVBQUUsT0FBTyxDQUFDLGNBQWMsSUFBSSxFQUFFO2dCQUM1QyxpQkFBaUIsRUFBRSxPQUFPLENBQUMsaUJBQWlCLElBQUksRUFBRTtnQkFDbEQsaUJBQWlCLEVBQUUsT0FBTyxDQUFDLGlCQUFpQixJQUFJLENBQUM7Z0JBQ2pELGFBQWEsRUFBRSxPQUFPLENBQUMsYUFBYSxJQUFJLENBQUM7Z0JBQ3pDLFFBQVEsRUFBRSxPQUFPLENBQUMsUUFBUSxJQUFJLEVBQUU7Z0JBQ2hDLGlCQUFpQixFQUFFLE9BQU8sQ0FBQyxpQkFBaUIsSUFBSSxJQUFJO2dCQUNwRCxnQkFBZ0IsRUFBRSxPQUFPLENBQUMsZ0JBQWdCLElBQUksSUFBSTtnQkFDbEQsV0FBVyxFQUFFLElBQUksQ0FBQyxHQUFHLEVBQUU7Z0JBQ3ZCLFNBQVMsRUFBRSxLQUFLO2dCQUNoQixLQUFLLEVBQUUsSUFBSTthQUNaLENBQUMsQ0FBQztZQUVILDRCQUE0QixDQUFDLE9BQU8sQ0FBQyxRQUFRLEVBQUU7Z0JBQzdDLEdBQUcsT0FBTyxDQUFDLGlCQUFpQixDQUFDLEdBQUcsQ0FBQyxDQUFDLElBQUksRUFBRSxFQUFFLENBQUMsSUFBSSxDQUFDLGFBQWEsQ0FBQztnQkFDOUQsR0FBRyxPQUFPLENBQUMsWUFBWSxDQUFDLEdBQUcsQ0FBQyxDQUFDLFFBQVEsRUFBRSxFQUFFLENBQUMsUUFBUSxDQUFDLFFBQVEsQ0FBQztnQkFDNUQsR0FBRyxDQUFDLE9BQU8sQ0FBQyx1QkFBdUIsSUFBSSxFQUFFLENBQUMsQ0FBQyxHQUFHLENBQUMsQ0FBQyxRQUFRLEVBQUUsRUFBRSxDQUFDLFFBQVEsQ0FBQyxRQUFRLENBQUM7YUFDaEYsQ0FBQyxDQUFDO1FBQ0wsQ0FBQztRQUVELElBQUksV0FBVyxLQUFLLFVBQVUsRUFBRSxDQUFDO1lBQy9CLG9CQUFvQixDQUFDLGdCQUFnQixFQUFFLGlDQUFpQyxFQUFFLEtBQUssSUFBSSxFQUFFO2dCQUNuRixNQUFNLHVCQUF1QixDQUFDLGNBQWMsQ0FBQyx5QkFBeUIsRUFBRSxJQUFJLENBQUMsQ0FBQztZQUNoRixDQUFDLENBQUMsQ0FBQztRQUNMLENBQUM7UUFFRCxnRUFBZ0U7UUFDaEUsSUFBSSxXQUFXLEtBQUssU0FBUyxJQUFJLGNBQWMsS0FBSyxjQUFjLEVBQUUsQ0FBQztZQUNuRSxvQkFBb0IsQ0FBQyxjQUFjLEVBQUUsNkJBQTZCLEVBQUUsS0FBSyxJQUFJLEVBQUU7Z0JBQzdFLE1BQU0sb0JBQW9CLENBQUMsY0FBYyxDQUFDLDhCQUE4QixFQUFFLElBQUksQ0FBQyxDQUFDO1lBQ2xGLENBQUMsQ0FBQyxDQUFDO1FBQ0wsQ0FBQztRQUVELHlFQUF5RTtRQUN6RSxJQUFJLFdBQVcsS0FBSyxTQUFTLElBQUksY0FBYyxLQUFLLGVBQWUsRUFBRSxDQUFDO1lBQ3BFLG9CQUFvQixDQUFDLGVBQWUsRUFBRSxnQ0FBZ0MsRUFBRSxLQUFLLElBQUksRUFBRTtnQkFDakYsTUFBTSxzQkFBc0IsQ0FBQyxjQUFjLENBQUMsd0JBQXdCLEVBQUUsSUFBSSxDQUFDLENBQUM7WUFDOUUsQ0FBQyxDQUFDLENBQUM7UUFDTCxDQUFDO1FBRUQsbURBQW1EO1FBQ25ELElBQUksV0FBVyxLQUFLLFNBQVMsSUFBSSxjQUFjLEtBQUssS0FBSyxFQUFFLENBQUM7WUFDMUQsb0JBQW9CLENBQUMsS0FBSyxFQUFFLHFCQUFxQixFQUFFLEtBQUssSUFBSSxFQUFFO2dCQUM1RCxNQUFNLFlBQVksQ0FBQyxjQUFjLENBQUMsY0FBYyxFQUFFLElBQUksQ0FBQyxDQUFDO1lBQzFELENBQUMsQ0FBQyxDQUFDO1FBQ0wsQ0FBQztJQUNILENBQUM7SUFBQyxPQUFPLEtBQUssRUFBRSxDQUFDO1FBQ2YsT0FBTyxDQUFDLEtBQUssQ0FBQywwQkFBMEIsRUFBRSxLQUFLLENBQUMsQ0FBQztRQUNqRCx3RUFBd0U7UUFDeEUsTUFBTSxNQUFNLEdBQUcsTUFBTSxDQUFDLEtBQUssQ0FBQyxDQUFDO1FBQzdCLElBQUksTUFBTSxDQUFDLFFBQVEsQ0FBQyxTQUFTLENBQUMsSUFBSSxNQUFNLENBQUMsUUFBUSxDQUFDLGNBQWMsQ0FBQyxJQUFJLE1BQU0sQ0FBQyxRQUFRLENBQUMsS0FBSyxDQUFDLEVBQUUsQ0FBQztZQUM1RixNQUFNLGNBQWMsQ0FBQyxjQUFjLENBQUMsWUFBWSxFQUFFLElBQUksQ0FBQyxDQUFDO1lBQ3hELE1BQU0sQ0FBQyxRQUFRLENBQUMsTUFBTSxFQUFFLENBQUM7UUFDM0IsQ0FBQztJQUNILENBQUM7QUFDSCxDQUFDO0FBRUQsc0ZBQXNGO0FBQ3RGLE1BQU0scUJBQXFCLEdBQUcsY0FBYyxDQUFDLFlBQVksQ0FBTyxLQUFLLEVBQUUsWUFBWSxFQUFFLEVBQUU7SUFDckYsTUFBTSw2QkFBNkIsRUFBRSxDQUFDO0lBQ3RDLGdHQUFnRztJQUNoRyxPQUFPLFlBQVksQ0FBQyxRQUFRLEVBQUcsQ0FBQztBQUNsQyxDQUFDLENBQUMsQ0FBQztBQUVILG1HQUFtRztBQUNuRyxJQUFJLGNBQWMsR0FBbUUsSUFBSSxDQUFDO0FBRTFGLE1BQU0sZ0JBQWdCLEdBQUcsR0FBRyxFQUFFO0lBQzVCLE1BQU0sT0FBTyxHQUFHLFdBQVcsQ0FBQyxRQUFRLEVBQUcsQ0FBQztJQUN4QyxNQUFNLFVBQVUsR0FBRyxjQUFjLENBQUMsUUFBUSxFQUFHLENBQUM7SUFFOUMsSUFBSSxPQUFPLENBQUMsV0FBVyxJQUFJLFVBQVUsQ0FBQyxVQUFVLEVBQUUsQ0FBQztRQUNqRCx5REFBeUQ7UUFDekQsSUFBSSxjQUFjLEVBQUUsQ0FBQztZQUNuQixjQUFjLENBQUMsT0FBTyxFQUFFLENBQUM7WUFDekIsY0FBYyxHQUFHLElBQUksQ0FBQztRQUN4QixDQUFDO1FBQ0QsY0FBYyxHQUFHLGNBQWMsQ0FBQyxxQkFBcUIsQ0FBQztZQUNwRCxNQUFNLEVBQUUscUJBQXFCO1lBQzdCLE9BQU8sRUFBRSxTQUFTO1lBQ2xCLFVBQVUsRUFBRSxPQUFPLENBQUMsZUFBZTtZQUNuQyxTQUFTLEVBQUUsWUFBWTtTQUN4QixDQUFDLENBQUM7SUFDTCxDQUFDO1NBQU0sQ0FBQztRQUNOLElBQUksY0FBYyxFQUFFLENBQUM7WUFDbkIsY0FBYyxDQUFDLE9BQU8sRUFBRSxDQUFDO1lBQ3pCLGNBQWMsR0FBRyxJQUFJLENBQUM7UUFDeEIsQ0FBQztJQUNILENBQUM7QUFDSCxDQUFDLENBQUM7QUFFRiw2QkFBNkI7QUFDN0IsSUFBSSxtQkFBbUIsR0FBRyxXQUFXLENBQUMsUUFBUSxFQUFHLENBQUMsV0FBVyxDQUFDO0FBQzlELElBQUksdUJBQXVCLEdBQUcsV0FBVyxDQUFDLFFBQVEsRUFBRyxDQUFDLGVBQWUsQ0FBQztBQUN0RSxJQUFJLGtCQUFrQixHQUFHLGNBQWMsQ0FBQyxRQUFRLEVBQUcsQ0FBQyxVQUFVLENBQUM7QUFFL0QsV0FBVyxDQUFDLE1BQU0sQ0FBQyxDQUFDLENBQUMsRUFBRSxFQUFFLENBQUMsQ0FBQyxFQUFFLFdBQVcsRUFBRSxDQUFDLENBQUMsV0FBVyxFQUFFLGVBQWUsRUFBRSxDQUFDLENBQUMsZUFBZSxFQUFFLENBQUMsQ0FBQztLQUM1RixTQUFTLENBQUMsQ0FBQyxLQUFLLEVBQUUsRUFBRTtJQUNuQixJQUFJLEtBQUssQ0FBQyxXQUFXLEtBQUssbUJBQW1CO1FBQ3pDLEtBQUssQ0FBQyxlQUFlLEtBQUssdUJBQXVCLEVBQUUsQ0FBQztRQUN0RCxtQkFBbUIsR0FBRyxLQUFLLENBQUMsV0FBVyxDQUFDO1FBQ3hDLHVCQUF1QixHQUFHLEtBQUssQ0FBQyxlQUFlLENBQUM7UUFDaEQsZ0JBQWdCLEVBQUUsQ0FBQztJQUNyQixDQUFDO0FBQ0gsQ0FBQyxDQUFDLENBQUM7QUFFTCxjQUFjLENBQUMsTUFBTSxDQUFDLENBQUMsQ0FBQyxFQUFFLEVBQUUsQ0FBQyxDQUFDLENBQUMsVUFBVSxDQUFDLENBQUMsU0FBUyxDQUFDLENBQUMsVUFBVSxFQUFFLEVBQUU7SUFDbEUsSUFBSSxVQUFVLEtBQUssa0JBQWtCLEVBQUUsQ0FBQztRQUN0QyxrQkFBa0IsR0FBRyxVQUFVLENBQUM7UUFDaEMsZ0JBQWdCLEVBQUUsQ0FBQztRQUVuQixzREFBc0Q7UUFDdEQsSUFBSSxVQUFVLEVBQUUsQ0FBQztZQUNmLGFBQWEsRUFBRSxDQUFDO1FBQ2xCLENBQUM7YUFBTSxDQUFDO1lBQ04sZ0JBQWdCLEVBQUUsQ0FBQztRQUNyQixDQUFDO0lBQ0gsQ0FBQztBQUNILENBQUMsQ0FBQyxDQUFDO0FBRUgscURBQXFEO0FBQ3JELFFBQVEsQ0FBQyxnQkFBZ0IsQ0FBQyxrQkFBa0IsRUFBRSxHQUFHLEVBQUU7SUFDakQsSUFBSSxRQUFRLENBQUMsTUFBTSxFQUFFLENBQUM7UUFDcEIsZ0JBQWdCLEVBQUUsQ0FBQztJQUNyQixDQUFDO1NBQU0sSUFBSSxjQUFjLENBQUMsUUFBUSxFQUFHLENBQUMsVUFBVSxFQUFFLENBQUM7UUFDakQsYUFBYSxFQUFFLENBQUM7SUFDbEIsQ0FBQztBQUNILENBQUMsQ0FBQyxDQUFDO0FBRUgsZ0JBQWdCO0FBQ2hCLGdCQUFnQixFQUFFLENBQUM7QUFFbkIsc0VBQXNFO0FBQ3RFLElBQUksY0FBYyxDQUFDLFFBQVEsRUFBRyxDQUFDLFVBQVUsRUFBRSxDQUFDO0lBQzFDLGFBQWEsRUFBRSxDQUFDO0FBQ2xCLENBQUMifQ==