@alauda-fe/network 1.0.0-beta.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (46) hide show
  1. package/esm2022/alauda-fe-network.mjs +5 -0
  2. package/esm2022/index.mjs +19 -0
  3. package/esm2022/lib/components/certificate-status/component.mjs +37 -0
  4. package/esm2022/lib/components/fixed-ip/component.mjs +503 -0
  5. package/esm2022/lib/components/loadbalancer-spec-form/component.mjs +251 -0
  6. package/esm2022/lib/components/service-annotations-form/annotations.component.mjs +681 -0
  7. package/esm2022/lib/components/service-annotations-form-item/annotations.component.mjs +106 -0
  8. package/esm2022/lib/components/service-form/component.mjs +307 -0
  9. package/esm2022/lib/components/service-form/fieldset/component.mjs +407 -0
  10. package/esm2022/lib/directives/subnet-validator.directive.mjs +111 -0
  11. package/esm2022/lib/services/alb-api.service.mjs +48 -0
  12. package/esm2022/lib/services/certificate-api.service.mjs +111 -0
  13. package/esm2022/lib/services/network-util.service.mjs +116 -0
  14. package/esm2022/lib/types/alb-exports.mjs +14 -0
  15. package/esm2022/lib/types/k8s-exports.mjs +13 -0
  16. package/esm2022/lib/types/resource-definition.mjs +16 -0
  17. package/esm2022/lib/utils/alb-exports.mjs +108 -0
  18. package/esm2022/lib/utils/alb-internals.mjs +2 -0
  19. package/esm2022/lib/utils/cidr-exports.mjs +359 -0
  20. package/esm2022/lib/utils/cluster-exports.mjs +18 -0
  21. package/esm2022/lib/utils/service-exports.mjs +58 -0
  22. package/esm2022/lib/utils/service-internals.mjs +7 -0
  23. package/esm2022/lib/utils/subnet-exports.mjs +18 -0
  24. package/index.d.ts +18 -0
  25. package/lib/components/certificate-status/component.d.ts +17 -0
  26. package/lib/components/fixed-ip/component.d.ts +67 -0
  27. package/lib/components/loadbalancer-spec-form/component.d.ts +34 -0
  28. package/lib/components/service-annotations-form/annotations.component.d.ts +74 -0
  29. package/lib/components/service-annotations-form-item/annotations.component.d.ts +14 -0
  30. package/lib/components/service-form/component.d.ts +56 -0
  31. package/lib/components/service-form/fieldset/component.d.ts +46 -0
  32. package/lib/directives/subnet-validator.directive.d.ts +34 -0
  33. package/lib/services/alb-api.service.d.ts +16 -0
  34. package/lib/services/certificate-api.service.d.ts +38 -0
  35. package/lib/services/network-util.service.d.ts +21 -0
  36. package/lib/types/alb-exports.d.ts +29 -0
  37. package/lib/types/k8s-exports.d.ts +130 -0
  38. package/lib/types/resource-definition.d.ts +25 -0
  39. package/lib/utils/alb-exports.d.ts +16 -0
  40. package/lib/utils/alb-internals.d.ts +10 -0
  41. package/lib/utils/cidr-exports.d.ts +85 -0
  42. package/lib/utils/cluster-exports.d.ts +14 -0
  43. package/lib/utils/service-exports.d.ts +18 -0
  44. package/lib/utils/service-internals.d.ts +2 -0
  45. package/lib/utils/subnet-exports.d.ts +20 -0
  46. package/package.json +31 -0
@@ -0,0 +1,407 @@
1
+ import { __decorate, __metadata } from "tslib";
2
+ import { AutocompleteModule, IconModule, InputModule, SelectModule, TooltipModule, coerceAttrBoolean, } from '@alauda/ui';
3
+ import { SERVICE_PORT_BASE_PROTOCOLS, SERVICE_PORT_PROTOCOLS, ValueHook, TranslateModule, ArrayFormTableModule, PurePipeModule, ErrorsMapperModule, isEqual, ValidateRowDuplicateService, K8S_RESOURCE_NAME_START_WITH_CHARS_ONLY, } from '@alauda-fe/common';
4
+ import { NgFor, NgIf, LowerCasePipe } from '@angular/common';
5
+ import { ChangeDetectionStrategy, Component, Injector, Input, Optional, } from '@angular/core';
6
+ import { ControlContainer, ReactiveFormsModule, Validators, } from '@angular/forms';
7
+ import { uniqBy } from 'lodash-es';
8
+ import { BaseResourceFormArrayComponent } from 'ng-resource-form-util';
9
+ import { debounceTime, distinctUntilChanged, takeUntil } from 'rxjs';
10
+ import { getServiceDefaultName } from '../../../utils/service-internals';
11
+ import * as i0 from "@angular/core";
12
+ import * as i1 from "@angular/forms";
13
+ import * as i2 from "@alauda-fe/common";
14
+ import * as i3 from "@alauda/ui";
15
+ const _c0 = function (a0) { return { type: a0 }; };
16
+ function ServicePortsFieldsetComponent_ng_container_1_Template(rf, ctx) { if (rf & 1) {
17
+ i0.ɵɵelementContainerStart(0);
18
+ i0.ɵɵelementStart(1, "th");
19
+ i0.ɵɵtext(2);
20
+ i0.ɵɵpipe(3, "translate");
21
+ i0.ɵɵelementEnd();
22
+ i0.ɵɵelementStart(4, "th")(5, "span", 4);
23
+ i0.ɵɵtext(6, "*");
24
+ i0.ɵɵelementEnd();
25
+ i0.ɵɵtext(7);
26
+ i0.ɵɵpipe(8, "translate");
27
+ i0.ɵɵelementEnd();
28
+ i0.ɵɵelementStart(9, "th")(10, "span", 4);
29
+ i0.ɵɵtext(11, "*");
30
+ i0.ɵɵelementEnd();
31
+ i0.ɵɵtext(12);
32
+ i0.ɵɵpipe(13, "translate");
33
+ i0.ɵɵpipe(14, "pure");
34
+ i0.ɵɵelementEnd();
35
+ i0.ɵɵelementStart(15, "th");
36
+ i0.ɵɵtext(16);
37
+ i0.ɵɵpipe(17, "translate");
38
+ i0.ɵɵelement(18, "aui-icon", 5);
39
+ i0.ɵɵpipe(19, "translate");
40
+ i0.ɵɵpipe(20, "translate");
41
+ i0.ɵɵpipe(21, "pure");
42
+ i0.ɵɵelementEnd();
43
+ i0.ɵɵelementContainerEnd();
44
+ } if (rf & 2) {
45
+ const ctx_r0 = i0.ɵɵnextContext();
46
+ i0.ɵɵadvance(2);
47
+ i0.ɵɵtextInterpolate(i0.ɵɵpipeBind1(3, 5, "protocol"));
48
+ i0.ɵɵadvance(5);
49
+ i0.ɵɵtextInterpolate1(" ", i0.ɵɵpipeBind1(8, 7, "service_port"), " ");
50
+ i0.ɵɵadvance(5);
51
+ i0.ɵɵtextInterpolate1(" ", i0.ɵɵpipeBind1(13, 9, i0.ɵɵpipeBind2(14, 11, ctx_r0.targetComponent, ctx_r0.getContainerPortTranslateKey)), " ");
52
+ i0.ɵɵadvance(4);
53
+ i0.ɵɵtextInterpolate1(" ", i0.ɵɵpipeBind1(17, 14, "service_port_name"), " ");
54
+ i0.ɵɵadvance(2);
55
+ i0.ɵɵproperty("auiTooltip", i0.ɵɵpipeBind2(19, 16, "service_name_default_tips", i0.ɵɵpureFunction1(24, _c0, i0.ɵɵpipeBind1(20, 19, i0.ɵɵpipeBind2(21, 21, ctx_r0.targetComponent, ctx_r0.getContainerPortTranslateKey)))));
56
+ } }
57
+ function ServicePortsFieldsetComponent_ng_container_2_aui_option_3_Template(rf, ctx) { if (rf & 1) {
58
+ i0.ɵɵelementStart(0, "aui-option", 17);
59
+ i0.ɵɵpipe(1, "lowercase");
60
+ i0.ɵɵtext(2);
61
+ i0.ɵɵelementEnd();
62
+ } if (rf & 2) {
63
+ const protocol_r10 = ctx.$implicit;
64
+ i0.ɵɵproperty("value", i0.ɵɵpipeBind1(1, 3, protocol_r10))("label", protocol_r10);
65
+ i0.ɵɵadvance(2);
66
+ i0.ɵɵtextInterpolate1(" ", protocol_r10, " ");
67
+ } }
68
+ function ServicePortsFieldsetComponent_ng_container_2_acl_errors_mapper_6_Template(rf, ctx) { if (rf & 1) {
69
+ i0.ɵɵelement(0, "acl-errors-mapper", 18);
70
+ i0.ɵɵpipe(1, "translate");
71
+ } if (rf & 2) {
72
+ const control_r3 = i0.ɵɵnextContext().$implicit;
73
+ i0.ɵɵproperty("errors", control_r3.get("port").errors)("controlName", i0.ɵɵpipeBind1(1, 2, "service_port"));
74
+ } }
75
+ function ServicePortsFieldsetComponent_ng_container_2_ng_container_11_aui_suggestion_1_Template(rf, ctx) { if (rf & 1) {
76
+ i0.ɵɵelementStart(0, "aui-suggestion", 20);
77
+ i0.ɵɵtext(1);
78
+ i0.ɵɵelementEnd();
79
+ } if (rf & 2) {
80
+ const suggestion_r14 = ctx.ngIf;
81
+ i0.ɵɵproperty("value", suggestion_r14);
82
+ i0.ɵɵadvance(1);
83
+ i0.ɵɵtextInterpolate(suggestion_r14);
84
+ } }
85
+ function ServicePortsFieldsetComponent_ng_container_2_ng_container_11_Template(rf, ctx) { if (rf & 1) {
86
+ i0.ɵɵelementContainerStart(0);
87
+ i0.ɵɵtemplate(1, ServicePortsFieldsetComponent_ng_container_2_ng_container_11_aui_suggestion_1_Template, 2, 2, "aui-suggestion", 19);
88
+ i0.ɵɵelementContainerEnd();
89
+ } if (rf & 2) {
90
+ const port_r12 = ctx.$implicit;
91
+ i0.ɵɵadvance(1);
92
+ i0.ɵɵproperty("ngIf", port_r12.containerPort + (port_r12.name ? "-" + port_r12.name : ""));
93
+ } }
94
+ const _c1 = function (a0) { return { controlName: a0 }; };
95
+ const _c2 = function (a0, a1) { return { characters: a0, start_end_character: a1 }; };
96
+ function ServicePortsFieldsetComponent_ng_container_2_acl_errors_mapper_13_Template(rf, ctx) { if (rf & 1) {
97
+ i0.ɵɵelement(0, "acl-errors-mapper", 16);
98
+ i0.ɵɵpipe(1, "translate");
99
+ i0.ɵɵpipe(2, "pure");
100
+ i0.ɵɵpipe(3, "translate");
101
+ i0.ɵɵpipe(4, "translate");
102
+ i0.ɵɵpipe(5, "pure");
103
+ i0.ɵɵpipe(6, "translate");
104
+ i0.ɵɵpipe(7, "translate");
105
+ i0.ɵɵpipe(8, "pure");
106
+ } if (rf & 2) {
107
+ const control_r3 = i0.ɵɵnextContext().$implicit;
108
+ const ctx_r9 = i0.ɵɵnextContext();
109
+ i0.ɵɵproperty("controlName", i0.ɵɵpipeBind1(1, 3, i0.ɵɵpipeBind2(2, 5, ctx_r9.targetComponent, ctx_r9.getContainerPortTranslateKey)))("errors", control_r3.get("targetPort").errors)("errorsMapper", i0.ɵɵpureFunction2(28, _c2, i0.ɵɵpipeBind2(3, 8, "port_name_error_characters_tip", i0.ɵɵpureFunction1(24, _c1, i0.ɵɵpipeBind1(4, 11, i0.ɵɵpipeBind2(5, 13, ctx_r9.targetComponent, ctx_r9.getContainerPortTranslateKey)))), i0.ɵɵpipeBind2(6, 16, "port_name_error_start_end_character_tip", i0.ɵɵpureFunction1(26, _c1, i0.ɵɵpipeBind1(7, 19, i0.ɵɵpipeBind2(8, 21, ctx_r9.targetComponent, ctx_r9.getContainerPortTranslateKey))))));
110
+ } }
111
+ const _c3 = function (a0) { return { pattern: a0 }; };
112
+ function ServicePortsFieldsetComponent_ng_container_2_Template(rf, ctx) { if (rf & 1) {
113
+ const _r17 = i0.ɵɵgetCurrentView();
114
+ i0.ɵɵelementContainerStart(0, 6);
115
+ i0.ɵɵelementStart(1, "td")(2, "aui-select", 7);
116
+ i0.ɵɵlistener("valueChange", function ServicePortsFieldsetComponent_ng_container_2_Template_aui_select_valueChange_2_listener() { const restoredCtx = i0.ɵɵrestoreView(_r17); const control_r3 = restoredCtx.$implicit; const ctx_r16 = i0.ɵɵnextContext(); return i0.ɵɵresetView(ctx_r16.updateAppProtocol(control_r3)); });
117
+ i0.ɵɵtemplate(3, ServicePortsFieldsetComponent_ng_container_2_aui_option_3_Template, 3, 5, "aui-option", 8);
118
+ i0.ɵɵelementEnd()();
119
+ i0.ɵɵelementStart(4, "td")(5, "input", 9);
120
+ i0.ɵɵlistener("ngModelChange", function ServicePortsFieldsetComponent_ng_container_2_Template_input_ngModelChange_5_listener($event) { const restoredCtx = i0.ɵɵrestoreView(_r17); const control_r3 = restoredCtx.$implicit; const ctx_r18 = i0.ɵɵnextContext(); return i0.ɵɵresetView(ctx_r18.autoCompleteContainerPort(control_r3, $event)); });
121
+ i0.ɵɵelementEnd();
122
+ i0.ɵɵtemplate(6, ServicePortsFieldsetComponent_ng_container_2_acl_errors_mapper_6_Template, 2, 4, "acl-errors-mapper", 10);
123
+ i0.ɵɵelementEnd();
124
+ i0.ɵɵelementStart(7, "td")(8, "input", 11);
125
+ i0.ɵɵlistener("auiAutocompleteSelected", function ServicePortsFieldsetComponent_ng_container_2_Template_input_auiAutocompleteSelected_8_listener($event) { const restoredCtx = i0.ɵɵrestoreView(_r17); const control_r3 = restoredCtx.$implicit; const ctx_r19 = i0.ɵɵnextContext(); return i0.ɵɵresetView(ctx_r19.updateContainerPort(control_r3, $event)); });
126
+ i0.ɵɵelementEnd();
127
+ i0.ɵɵelementStart(9, "aui-autocomplete", null, 12);
128
+ i0.ɵɵtemplate(11, ServicePortsFieldsetComponent_ng_container_2_ng_container_11_Template, 2, 1, "ng-container", 13);
129
+ i0.ɵɵpipe(12, "pure");
130
+ i0.ɵɵelementEnd();
131
+ i0.ɵɵtemplate(13, ServicePortsFieldsetComponent_ng_container_2_acl_errors_mapper_13_Template, 9, 31, "acl-errors-mapper", 14);
132
+ i0.ɵɵelementEnd();
133
+ i0.ɵɵelementStart(14, "td");
134
+ i0.ɵɵelement(15, "input", 15)(16, "acl-errors-mapper", 16);
135
+ i0.ɵɵpipe(17, "translate");
136
+ i0.ɵɵpipe(18, "translate");
137
+ i0.ɵɵelementEnd();
138
+ i0.ɵɵelementContainerEnd();
139
+ } if (rf & 2) {
140
+ const control_r3 = ctx.$implicit;
141
+ const index_r4 = ctx.index;
142
+ const _r7 = i0.ɵɵreference(10);
143
+ const ctx_r1 = i0.ɵɵnextContext();
144
+ let tmp_2_0;
145
+ let tmp_5_0;
146
+ i0.ɵɵproperty("formGroupName", index_r4);
147
+ i0.ɵɵadvance(3);
148
+ i0.ɵɵproperty("ngForOf", ctx_r1.servicePortProtocols);
149
+ i0.ɵɵadvance(3);
150
+ i0.ɵɵproperty("ngIf", control_r3.get("port").dirty || ((tmp_2_0 = ctx_r1.controlContainer == null ? null : ctx_r1.controlContainer.formDirective) == null ? null : tmp_2_0.submitted));
151
+ i0.ɵɵadvance(2);
152
+ i0.ɵɵproperty("auiAutocomplete", _r7);
153
+ i0.ɵɵadvance(3);
154
+ i0.ɵɵproperty("ngForOf", i0.ɵɵpipeBind3(12, 9, ctx_r1.containerPortSuggestions, ctx_r1.getContainerPortSuggestions, control_r3.get("appProtocol").value));
155
+ i0.ɵɵadvance(2);
156
+ i0.ɵɵproperty("ngIf", control_r3.get("targetPort").dirty || ((tmp_5_0 = ctx_r1.controlContainer == null ? null : ctx_r1.controlContainer.formDirective) == null ? null : tmp_5_0.submitted));
157
+ i0.ɵɵadvance(3);
158
+ i0.ɵɵproperty("controlName", i0.ɵɵpipeBind1(17, 13, "service_port_name"))("errors", control_r3.get("name").errors)("errorsMapper", i0.ɵɵpureFunction1(17, _c3, i0.ɵɵpipeBind1(18, 15, ctx_r1.namePattern.tip)));
159
+ } }
160
+ const _c4 = function (a0) { return { port: a0 }; };
161
+ const _c5 = function (a0) { return { name: a0 }; };
162
+ const _c6 = function (a0, a1) { return { port: a0, name: a1 }; };
163
+ function ServicePortsFieldsetComponent_ng_container_3_acl_errors_mapper_2_Template(rf, ctx) { if (rf & 1) {
164
+ i0.ɵɵelement(0, "acl-errors-mapper", 24);
165
+ i0.ɵɵpipe(1, "translate");
166
+ i0.ɵɵpipe(2, "translate");
167
+ } if (rf & 2) {
168
+ const duplicateError_r24 = ctx.ngIf;
169
+ i0.ɵɵproperty("errors", duplicateError_r24)("errorsMapper", i0.ɵɵpureFunction2(12, _c6, i0.ɵɵpipeBind2(1, 2, "duplicate_service_port", i0.ɵɵpureFunction1(8, _c4, duplicateError_r24.port == null ? null : duplicateError_r24.port.port)), i0.ɵɵpipeBind2(2, 5, "duplicate_service_name", i0.ɵɵpureFunction1(10, _c5, duplicateError_r24.name == null ? null : duplicateError_r24.name.name))));
170
+ } }
171
+ const _c7 = function (a0) { return { protocol: a0 }; };
172
+ function ServicePortsFieldsetComponent_ng_container_3_ng_template_3_Template(rf, ctx) { if (rf & 1) {
173
+ i0.ɵɵelement(0, "acl-errors-mapper", 24);
174
+ i0.ɵɵpipe(1, "translate");
175
+ } if (rf & 2) {
176
+ const control_r20 = i0.ɵɵnextContext().$implicit;
177
+ i0.ɵɵproperty("errors", control_r20.errors)("errorsMapper", i0.ɵɵpureFunction1(4, _c7, i0.ɵɵpipeBind1(1, 2, "lb_service_protocol_hint")));
178
+ } }
179
+ function ServicePortsFieldsetComponent_ng_container_3_Template(rf, ctx) { if (rf & 1) {
180
+ i0.ɵɵelementContainerStart(0);
181
+ i0.ɵɵelementStart(1, "td", 21);
182
+ i0.ɵɵtemplate(2, ServicePortsFieldsetComponent_ng_container_3_acl_errors_mapper_2_Template, 3, 15, "acl-errors-mapper", 22);
183
+ i0.ɵɵtemplate(3, ServicePortsFieldsetComponent_ng_container_3_ng_template_3_Template, 2, 6, "ng-template", null, 23, i0.ɵɵtemplateRefExtractor);
184
+ i0.ɵɵelementEnd();
185
+ i0.ɵɵelementContainerEnd();
186
+ } if (rf & 2) {
187
+ const control_r20 = ctx.$implicit;
188
+ const _r22 = i0.ɵɵreference(4);
189
+ i0.ɵɵadvance(2);
190
+ i0.ɵɵproperty("ngIf", control_r20.errors == null ? null : control_r20.errors.duplicateError)("ngIfElse", _r22);
191
+ } }
192
+ const MAX_PORT_NUMBER = 65535;
193
+ function getNormalizedTargetPort(targetPort) {
194
+ return isNaN(+targetPort) ? targetPort : +targetPort;
195
+ }
196
+ const targetPortValidator = (ctrl) => {
197
+ const targetPort = ctrl.value;
198
+ if (!targetPort) {
199
+ return;
200
+ }
201
+ if (!/^[\da-z-]+$/.test(targetPort)) {
202
+ return {
203
+ characters: true,
204
+ };
205
+ }
206
+ if (/^\d+$/.test(targetPort)) {
207
+ const portValue = parseInt(targetPort, 10);
208
+ if (portValue < 1) {
209
+ return { min: { min: 1 } };
210
+ }
211
+ if (portValue > MAX_PORT_NUMBER) {
212
+ return { max: { max: MAX_PORT_NUMBER } };
213
+ }
214
+ }
215
+ else if (/(^[^a-z]+$)|(^-)|(-$)|(-{2,})/.test(targetPort)) {
216
+ return {
217
+ start_end_character: true,
218
+ };
219
+ }
220
+ };
221
+ export class ServicePortsFieldsetComponent extends BaseResourceFormArrayComponent {
222
+ get required() {
223
+ return this._required;
224
+ }
225
+ set required(required) {
226
+ this._required = coerceAttrBoolean(required);
227
+ }
228
+ constructor(injector, controlContainer, rowDupService) {
229
+ super(injector);
230
+ this.injector = injector;
231
+ this.controlContainer = controlContainer;
232
+ this.rowDupService = rowDupService;
233
+ this.containerPortSuggestions = [];
234
+ this.existedPorts = [];
235
+ this.targetComponent = 'workload';
236
+ this.servicePortProtocols = SERVICE_PORT_PROTOCOLS;
237
+ this.namePattern = K8S_RESOURCE_NAME_START_WITH_CHARS_ONLY;
238
+ this.validateServiceType = this.validateServiceType.bind(this);
239
+ }
240
+ ngOnInit() {
241
+ super.ngOnInit();
242
+ this.form.valueChanges
243
+ .pipe(debounceTime(0), distinctUntilChanged(isEqual), takeUntil(this.destroy$))
244
+ .subscribe(() => this.updateValueAndValidity());
245
+ }
246
+ getOnFormArrayResizeFn() {
247
+ return () => this.createNewControl();
248
+ }
249
+ getResourceMergeStrategy() {
250
+ return true;
251
+ }
252
+ createNewControl() {
253
+ return this.fb.group({
254
+ name: [
255
+ '',
256
+ [
257
+ Validators.pattern(this.namePattern.pattern),
258
+ Validators.maxLength(63),
259
+ ],
260
+ ],
261
+ protocol: [SERVICE_PORT_BASE_PROTOCOLS[0]],
262
+ appProtocol: [SERVICE_PORT_PROTOCOLS[0].toLowerCase()],
263
+ port: [
264
+ '',
265
+ [Validators.required, Validators.min(1), Validators.max(65535)],
266
+ ],
267
+ targetPort: [
268
+ '',
269
+ [Validators.required, Validators.maxLength(15), targetPortValidator],
270
+ ],
271
+ }, {
272
+ validators: [
273
+ this.rowDupService.createFormArrayValidator({
274
+ rowKeys: [{ port: ['port', 'protocol'] }, { name: ['name'] }],
275
+ formArray: this.form,
276
+ valueMapFn: (data, prop) => {
277
+ if (prop === 'name') {
278
+ return data[prop] || getServiceDefaultName(data);
279
+ }
280
+ return data[prop];
281
+ },
282
+ initData: this.existedPorts.map(({ port, protocol }) => ({
283
+ port: {
284
+ port,
285
+ protocol,
286
+ },
287
+ })),
288
+ }),
289
+ this.validateServiceType,
290
+ ],
291
+ });
292
+ }
293
+ validateServiceType(_ctrl) {
294
+ if (this.serviceType !== 'LoadBalancer') {
295
+ return null;
296
+ }
297
+ for (let i = 1, servicePorts = this.formModel, len = servicePorts.length; i < len; i++) {
298
+ const prev = servicePorts[i - 1];
299
+ const curr = servicePorts[i];
300
+ if (prev.protocol !== curr.protocol) {
301
+ return {
302
+ protocol: true,
303
+ };
304
+ }
305
+ }
306
+ }
307
+ adaptResourceModel(ports) {
308
+ return ports?.map(port => {
309
+ port.appProtocol =
310
+ port.appProtocol ||
311
+ port.protocol?.toLowerCase() ||
312
+ 'tcp';
313
+ return port;
314
+ });
315
+ }
316
+ adaptFormModel(ports) {
317
+ return ports.map(item => {
318
+ if (item.targetPort) {
319
+ item.targetPort = getNormalizedTargetPort(item.targetPort);
320
+ }
321
+ else {
322
+ delete item.targetPort;
323
+ }
324
+ if (/^\d+$/.test(String(item.nodePort))) {
325
+ item.nodePort = +item.nodePort;
326
+ }
327
+ else {
328
+ delete item.nodePort;
329
+ }
330
+ return item;
331
+ });
332
+ }
333
+ updateAppProtocol(group) {
334
+ const protocol = group.get('appProtocol').value;
335
+ group
336
+ .get('protocol')
337
+ .setValue(protocol === 'UDP'.toLowerCase() ? 'UDP' : 'TCP');
338
+ }
339
+ updateValueAndValidity() {
340
+ this.form?.controls.forEach(ctrl => ctrl.updateValueAndValidity());
341
+ }
342
+ getContainerPortSuggestions(containerPortSuggestions = [], appProtocol) {
343
+ const _protocol = appProtocol === 'udp' ? 'UDP' : 'TCP';
344
+ return uniqBy(containerPortSuggestions?.filter(containerPort => (containerPort.protocol ?? 'TCP') === _protocol), port => port.containerPort + (port.name ? '-' + port.name : ''));
345
+ }
346
+ // 点击带名称的容器端口时也只设置端口号
347
+ updateContainerPort(control, value) {
348
+ control.get('targetPort').patchValue(value.split('-')[0]);
349
+ }
350
+ autoCompleteContainerPort(control, value) {
351
+ control.get('targetPort').patchValue(value ? String(value) : null);
352
+ }
353
+ getContainerPortTranslateKey(targetComponent) {
354
+ return targetComponent === 'vm' ? 'vm_port' : 'container_port';
355
+ }
356
+ static { this.ɵfac = function ServicePortsFieldsetComponent_Factory(t) { return new (t || ServicePortsFieldsetComponent)(i0.ɵɵdirectiveInject(i0.Injector), i0.ɵɵdirectiveInject(i1.ControlContainer, 8), i0.ɵɵdirectiveInject(i2.ValidateRowDuplicateService)); }; }
357
+ static { this.ɵcmp = /*@__PURE__*/ i0.ɵɵdefineComponent({ type: ServicePortsFieldsetComponent, selectors: [["acl-service-ports-fieldset"]], inputs: { required: "required", serviceType: "serviceType", containerPortSuggestions: "containerPortSuggestions", existedPorts: "existedPorts", targetComponent: "targetComponent" }, standalone: true, features: [i0.ɵɵProvidersFeature([ValidateRowDuplicateService]), i0.ɵɵInheritDefinitionFeature, i0.ɵɵStandaloneFeature], decls: 4, vars: 3, consts: [[1, "form-table__flex-layout", "inline-action-col", 3, "minRow", "rows", "formGroup", "add", "remove"], [4, "aclArrayFormTableHeader"], [3, "formGroupName", 4, "aclArrayFormTableRow"], [4, "aclArrayFormTableRowError"], [1, "required-mark"], ["icon", "question_circle", 1, "ml-4", "icon--help", 3, "auiTooltip"], [3, "formGroupName"], ["formControlName", "appProtocol", 3, "valueChange"], [3, "value", "label", 4, "ngFor", "ngForOf"], ["aui-input", "", "type", "number", "formControlName", "port", "required", "", 3, "ngModelChange"], [3, "errors", "controlName", 4, "ngIf"], ["aui-input", "", "formControlName", "targetPort", 3, "auiAutocomplete", "auiAutocompleteSelected"], ["suggestions", ""], [4, "ngFor", "ngForOf"], [3, "controlName", "errors", "errorsMapper", 4, "ngIf"], ["aui-input", "", "formControlName", "name"], [3, "controlName", "errors", "errorsMapper"], [3, "value", "label"], [3, "errors", "controlName"], [3, "value", 4, "ngIf"], [3, "value"], ["colspan", "5", 1, "acl-table-form-error-hint"], [3, "errors", "errorsMapper", 4, "ngIf", "ngIfElse"], ["otherErrors", ""], [3, "errors", "errorsMapper"]], template: function ServicePortsFieldsetComponent_Template(rf, ctx) { if (rf & 1) {
358
+ i0.ɵɵelementStart(0, "acl-array-form-table", 0);
359
+ i0.ɵɵlistener("add", function ServicePortsFieldsetComponent_Template_acl_array_form_table_add_0_listener() { return ctx.add(ctx.form.length); })("remove", function ServicePortsFieldsetComponent_Template_acl_array_form_table_remove_0_listener($event) { return ctx.remove($event); });
360
+ i0.ɵɵtemplate(1, ServicePortsFieldsetComponent_ng_container_1_Template, 22, 26, "ng-container", 1);
361
+ i0.ɵɵtemplate(2, ServicePortsFieldsetComponent_ng_container_2_Template, 19, 19, "ng-container", 2);
362
+ i0.ɵɵtemplate(3, ServicePortsFieldsetComponent_ng_container_3_Template, 5, 2, "ng-container", 3);
363
+ i0.ɵɵelementEnd();
364
+ } if (rf & 2) {
365
+ i0.ɵɵproperty("minRow", ctx.required ? 1 : 0)("rows", ctx.form.controls)("formGroup", ctx.form);
366
+ } }, dependencies: [AutocompleteModule, i3.AutoCompleteDirective, i3.AutocompleteComponent, i3.SuggestionComponent, InputModule, i3.InputComponent, NgIf,
367
+ NgFor,
368
+ LowerCasePipe,
369
+ ReactiveFormsModule, i1.DefaultValueAccessor, i1.NumberValueAccessor, i1.NgControlStatus, i1.NgControlStatusGroup, i1.RequiredValidator, i1.FormGroupDirective, i1.FormControlName, i1.FormGroupName, TranslateModule, i2.TranslatePipe, IconModule, i3.IconComponent, TooltipModule, i3.TooltipDirective, PurePipeModule, i2.PurePipe, SelectModule, i3.SelectComponent, i3.OptionComponent, ArrayFormTableModule, i2.ArrayFormTableComponent, i2.ArrayFormTableHeaderDirective, i2.ArrayFormTableRowDirective, i2.ArrayFormTableRowErrorDirective, ErrorsMapperModule, i2.ErrorsMapperComponent], encapsulation: 2, changeDetection: 0 }); }
370
+ }
371
+ __decorate([
372
+ ValueHook(null, null, function () {
373
+ this.updateValueAndValidity();
374
+ }),
375
+ __metadata("design:type", String)
376
+ ], ServicePortsFieldsetComponent.prototype, "serviceType", void 0);
377
+ (function () { (typeof ngDevMode === "undefined" || ngDevMode) && i0.ɵsetClassMetadata(ServicePortsFieldsetComponent, [{
378
+ type: Component,
379
+ args: [{ standalone: true, selector: 'acl-service-ports-fieldset', preserveWhitespaces: false, changeDetection: ChangeDetectionStrategy.OnPush, providers: [ValidateRowDuplicateService], imports: [
380
+ AutocompleteModule,
381
+ InputModule,
382
+ NgIf,
383
+ NgFor,
384
+ LowerCasePipe,
385
+ ReactiveFormsModule,
386
+ TranslateModule,
387
+ IconModule,
388
+ TooltipModule,
389
+ PurePipeModule,
390
+ SelectModule,
391
+ ArrayFormTableModule,
392
+ ErrorsMapperModule,
393
+ ], template: "<acl-array-form-table\n (add)=\"add(form.length)\"\n (remove)=\"remove($event)\"\n [minRow]=\"required ? 1 : 0\"\n [rows]=\"form.controls\"\n [formGroup]=\"$any(form)\"\n class=\"form-table__flex-layout inline-action-col\"\n>\n <ng-container *aclArrayFormTableHeader>\n <th>{{ 'protocol' | translate }}</th>\n <th>\n <span class=\"required-mark\">*</span>\n {{ 'service_port' | translate }}\n </th>\n <th>\n <span class=\"required-mark\">*</span>\n {{ targetComponent | pure: getContainerPortTranslateKey | translate }}\n </th>\n <th>\n {{ 'service_port_name' | translate }}\n <aui-icon\n class=\"ml-4 icon--help\"\n icon=\"question_circle\"\n [auiTooltip]=\"\n 'service_name_default_tips'\n | translate\n : {\n type:\n targetComponent\n | pure: getContainerPortTranslateKey\n | translate\n }\n \"\n ></aui-icon>\n </th>\n </ng-container>\n\n <ng-container\n *aclArrayFormTableRow=\"let control; let index = index\"\n [formGroupName]=\"index\"\n >\n <td>\n <aui-select\n formControlName=\"appProtocol\"\n (valueChange)=\"updateAppProtocol(control)\"\n >\n <aui-option\n *ngFor=\"let protocol of servicePortProtocols\"\n [value]=\"protocol | lowercase\"\n [label]=\"protocol\"\n >\n {{ protocol }}\n </aui-option>\n </aui-select>\n </td>\n <td>\n <input\n aui-input\n type=\"number\"\n formControlName=\"port\"\n (ngModelChange)=\"autoCompleteContainerPort(control, $event)\"\n required\n />\n <acl-errors-mapper\n *ngIf=\"\n control.get('port').dirty ||\n $any(controlContainer?.formDirective)?.submitted\n \"\n [errors]=\"control.get('port').errors\"\n [controlName]=\"'service_port' | translate\"\n ></acl-errors-mapper>\n </td>\n <td>\n <input\n aui-input\n formControlName=\"targetPort\"\n [auiAutocomplete]=\"suggestions\"\n (auiAutocompleteSelected)=\"updateContainerPort(control, $event)\"\n />\n <aui-autocomplete #suggestions>\n <ng-container\n *ngFor=\"\n let port of containerPortSuggestions\n | pure\n : getContainerPortSuggestions\n : control.get('appProtocol').value\n \"\n >\n <aui-suggestion\n *ngIf=\"\n port.containerPort +\n (port.name ? '-' + port.name : '') as suggestion\n \"\n [value]=\"suggestion\"\n >{{ suggestion }}</aui-suggestion\n >\n </ng-container>\n </aui-autocomplete>\n <acl-errors-mapper\n *ngIf=\"\n control.get('targetPort').dirty ||\n $any(controlContainer?.formDirective)?.submitted\n \"\n [controlName]=\"\n targetComponent | pure: getContainerPortTranslateKey | translate\n \"\n [errors]=\"control.get('targetPort').errors\"\n [errorsMapper]=\"{\n characters:\n 'port_name_error_characters_tip'\n | translate\n : {\n controlName:\n targetComponent\n | pure: getContainerPortTranslateKey\n | translate\n },\n start_end_character:\n 'port_name_error_start_end_character_tip'\n | translate\n : {\n controlName:\n targetComponent\n | pure: getContainerPortTranslateKey\n | translate\n }\n }\"\n ></acl-errors-mapper>\n </td>\n <td>\n <input\n aui-input\n formControlName=\"name\"\n />\n <acl-errors-mapper\n [controlName]=\"'service_port_name' | translate\"\n [errors]=\"control.get('name').errors\"\n [errorsMapper]=\"{\n pattern: namePattern.tip | translate\n }\"\n ></acl-errors-mapper>\n </td>\n </ng-container>\n\n <!-- Input error row -->\n <ng-container *aclArrayFormTableRowError=\"let control\">\n <td\n class=\"acl-table-form-error-hint\"\n colspan=\"5\"\n >\n <acl-errors-mapper\n *ngIf=\"\n control.errors?.duplicateError as duplicateError;\n else otherErrors\n \"\n [errors]=\"duplicateError\"\n [errorsMapper]=\"{\n port:\n 'duplicate_service_port'\n | translate: { port: duplicateError.port?.port },\n name:\n 'duplicate_service_name'\n | translate: { name: duplicateError.name?.name }\n }\"\n ></acl-errors-mapper>\n <ng-template #otherErrors>\n <acl-errors-mapper\n [errors]=\"control.errors\"\n [errorsMapper]=\"{\n protocol: 'lb_service_protocol_hint' | translate\n }\"\n ></acl-errors-mapper>\n </ng-template>\n </td>\n </ng-container>\n</acl-array-form-table>\n" }]
394
+ }], function () { return [{ type: i0.Injector }, { type: i1.ControlContainer, decorators: [{
395
+ type: Optional
396
+ }] }, { type: i2.ValidateRowDuplicateService }]; }, { required: [{
397
+ type: Input
398
+ }], serviceType: [{
399
+ type: Input
400
+ }], containerPortSuggestions: [{
401
+ type: Input
402
+ }], existedPorts: [{
403
+ type: Input
404
+ }], targetComponent: [{
405
+ type: Input
406
+ }] }); })();
407
+ //# sourceMappingURL=data:application/json;base64,eyJ2ZXJzaW9uIjozLCJmaWxlIjoiY29tcG9uZW50LmpzIiwic291cmNlUm9vdCI6IiIsInNvdXJjZXMiOlsiLi4vLi4vLi4vLi4vLi4vLi4vLi4vLi4vbW9kdWxlcy9uZXR3b3JrL3NyYy9saWIvY29tcG9uZW50cy9zZXJ2aWNlLWZvcm0vZmllbGRzZXQvY29tcG9uZW50LnRzIiwiLi4vLi4vLi4vLi4vLi4vLi4vLi4vLi4vbW9kdWxlcy9uZXR3b3JrL3NyYy9saWIvY29tcG9uZW50cy9zZXJ2aWNlLWZvcm0vZmllbGRzZXQvdGVtcGxhdGUuaHRtbCJdLCJuYW1lcyI6W10sIm1hcHBpbmdzIjoiO0FBQUEsT0FBTyxFQUNMLGtCQUFrQixFQUNsQixVQUFVLEVBQ1YsV0FBVyxFQUNYLFlBQVksRUFDWixhQUFhLEVBQ2IsaUJBQWlCLEdBQ2xCLE1BQU0sWUFBWSxDQUFDO0FBQ3BCLE9BQU8sRUFLTCwyQkFBMkIsRUFDM0Isc0JBQXNCLEVBQ3RCLFNBQVMsRUFDVCxlQUFlLEVBQ2Ysb0JBQW9CLEVBQ3BCLGNBQWMsRUFDZCxrQkFBa0IsRUFDbEIsT0FBTyxFQUNQLDJCQUEyQixFQUMzQix1Q0FBdUMsR0FDeEMsTUFBTSxtQkFBbUIsQ0FBQztBQUMzQixPQUFPLEVBQUUsS0FBSyxFQUFFLElBQUksRUFBRSxhQUFhLEVBQUUsTUFBTSxpQkFBaUIsQ0FBQztBQUM3RCxPQUFPLEVBQ0wsdUJBQXVCLEVBQ3ZCLFNBQVMsRUFDVCxRQUFRLEVBQ1IsS0FBSyxFQUVMLFFBQVEsR0FDVCxNQUFNLGVBQWUsQ0FBQztBQUN2QixPQUFPLEVBRUwsZ0JBQWdCLEVBRWhCLG1CQUFtQixFQUNuQixVQUFVLEdBQ1gsTUFBTSxnQkFBZ0IsQ0FBQztBQUN4QixPQUFPLEVBQUUsTUFBTSxFQUFFLE1BQU0sV0FBVyxDQUFDO0FBQ25DLE9BQU8sRUFBRSw4QkFBOEIsRUFBRSxNQUFNLHVCQUF1QixDQUFDO0FBQ3ZFLE9BQU8sRUFBRSxZQUFZLEVBQUUsb0JBQW9CLEVBQUUsU0FBUyxFQUFFLE1BQU0sTUFBTSxDQUFDO0FBRXJFLE9B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LGVBQWU7b0JBQ2YsVUFBVTtvQkFDVixhQUFhO29CQUNiLGNBQWM7b0JBQ2QsWUFBWTtvQkFDWixvQkFBb0I7b0JBQ3BCLGtCQUFrQjtpQkFDbkI7O3NCQWtDRSxRQUFRO2tFQXpCUCxRQUFRO2tCQURYLEtBQUs7WUFhTixXQUFXO2tCQURWLEtBQUs7WUFJTix3QkFBd0I7a0JBRHZCLEtBQUs7WUFJTixZQUFZO2tCQURYLEtBQUs7WUFJTixlQUFlO2tCQURkLEtBQUsiLCJzb3VyY2VzQ29udGVudCI6WyJpbXBvcnQge1xuICBBdXRvY29tcGxldGVNb2R1bGUsXG4gIEljb25Nb2R1bGUsXG4gIElucHV0TW9kdWxlLFxuICBTZWxlY3RNb2R1bGUsXG4gIFRvb2x0aXBNb2R1bGUsXG4gIGNvZXJjZUF0dHJCb29sZWFuLFxufSBmcm9tICdAYWxhdWRhL3VpJztcbmltcG9ydCB7XG4gIENvbnRhaW5lclBvcnQsXG4gIFNlcnZpY2VQb3J0LFxuICBTZXJ2aWNlUG9ydFByb3RvY29sLFxuICBTZXJ2aWNlVHlwZSxcbiAgU0VSVklDRV9QT1JUX0JBU0VfUFJPVE9DT0xTLFxuICBTRVJWSUNFX1BPUlRfUFJPVE9DT0xTLFxuICBWYWx1ZUhvb2ssXG4gIFRyYW5zbGF0ZU1vZHVsZSxcbiAgQXJyYXlGb3JtVGFibGVNb2R1bGUsXG4gIFB1cmVQaXBlTW9kdWxlLFxuICBFcnJvcnNNYXBwZXJNb2R1bGUsXG4gIGlzRXF1YWwsXG4gIFZhbGlkYXRlUm93RHVwbGljYXRlU2VydmljZSxcbiAgSzhTX1JFU09VUkNFX05BTUVfU1RBUlRfV0lUSF9DSEFSU19PTkxZLFxufSBmcm9tICdAYWxhdWRhLWZlL2NvbW1vbic7XG5pbXBvcnQgeyBOZ0ZvciwgTmdJZiwgTG93ZXJDYXNlUGlwZSB9IGZyb20gJ0Bhbmd1bGFyL2NvbW1vbic7XG5pbXBvcnQge1xuICBDaGFuZ2VEZXRlY3Rpb25TdHJhdGVneSxcbiAgQ29tcG9uZW50LFxuICBJbmplY3RvcixcbiAgSW5wdXQsXG4gIE9uSW5pdCxcbiAgT3B0aW9uYWwsXG59IGZyb20gJ0Bhbmd1bGFyL2NvcmUnO1xuaW1wb3J0IHtcbiAgQWJzdHJhY3RDb250cm9sLFxuICBDb250cm9sQ29udGFpbmVyLFxuICBGb3JtR3JvdXAsXG4gIFJlYWN0aXZlRm9ybXNNb2R1bGUsXG4gIFZhbGlkYXRvcnMsXG59IGZyb20gJ0Bhbmd1bGFyL2Zvcm1zJztcbmltcG9ydCB7IHVuaXFCeSB9IGZyb20gJ2xvZGFzaC1lcyc7XG5pbXBvcnQgeyBCYXNlUmVzb3VyY2VGb3JtQXJyYXlDb21wb25lbnQgfSBmcm9tICduZy1yZXNvdXJjZS1mb3JtLXV0aWwnO1xuaW1wb3J0IHsgZGVib3VuY2VUaW1lLCBkaXN0aW5jdFVudGlsQ2hhbmdlZCwgdGFrZVVudGlsIH0gZnJvbSAncnhqcyc7XG5cbmltcG9ydCB7IGdldFNlcnZpY2VEZWZhdWx0TmFtZSB9IGZyb20gJy4uLy4uLy4uL3V0aWxzL3NlcnZpY2UtaW50ZXJuYWxzJztcblxuY29uc3QgTUFYX1BPUlRfTlVNQkVSID0gNjVfNTM1O1xuXG5mdW5jdGlvbiBnZXROb3JtYWxpemVkVGFyZ2V0UG9ydCh0YXJnZXRQb3J0OiBudW1iZXIgfCBzdHJpbmcpIHtcbiAgcmV0dXJuIGlzTmFOKCt0YXJnZXRQb3J0KSA/IHRhcmdldFBvcnQgOiArdGFyZ2V0UG9ydDtcbn1cblxuY29uc3QgdGFyZ2V0UG9ydFZhbGlkYXRvciA9IChjdHJsOiBBYnN0cmFjdENvbnRyb2wpID0+IHtcbiAgY29uc3QgdGFyZ2V0UG9ydDogc3RyaW5nID0gY3RybC52YWx1ZTtcblxuICBpZiAoIXRhcmdldFBvcnQpIHtcbiAgICByZXR1cm47XG4gIH1cblxuICBpZiAoIS9eW1xcZGEtei1dKyQvLnRlc3QodGFyZ2V0UG9ydCkpIHtcbiAgICByZXR1cm4ge1xuICAgICAgY2hhcmFjdGVyczogdHJ1ZSxcbiAgICB9O1xuICB9XG5cbiAgaWYgKC9eXFxkKyQvLnRlc3QodGFyZ2V0UG9ydCkpIHtcbiAgICBjb25zdCBwb3J0VmFsdWUgPSBwYXJzZUludCh0YXJnZXRQb3J0LCAxMCk7XG4gICAgaWYgKHBvcnRWYWx1ZSA8IDEpIHtcbiAgICAgIHJldHVybiB7IG1pbjogeyBtaW46IDEgfSB9O1xuICAgIH1cbiAgICBpZiAocG9ydFZhbHVlID4gTUFYX1BPUlRfTlVNQkVSKSB7XG4gICAgICByZXR1cm4geyBtYXg6IHsgbWF4OiBNQVhfUE9SVF9OVU1CRVIgfSB9O1xuICAgIH1cbiAgfSBlbHNlIGlmICgvKF5bXmEtel0rJCl8KF4tKXwoLSQpfCgtezIsfSkvLnRlc3QodGFyZ2V0UG9ydCkpIHtcbiAgICByZXR1cm4ge1xuICAgICAgc3RhcnRfZW5kX2NoYXJhY3RlcjogdHJ1ZSxcbiAgICB9O1xuICB9XG59O1xuXG5AQ29tcG9uZW50KHtcbiAgc3RhbmRhbG9uZTogdHJ1ZSxcbiAgc2VsZWN0b3I6ICdhY2wtc2VydmljZS1wb3J0cy1maWVsZHNldCcsXG4gIHRlbXBsYXRlVXJsOiAnLi90ZW1wbGF0ZS5odG1sJyxcbiAgcHJlc2VydmVXaGl0ZXNwYWNlczogZmFsc2UsXG4gIGNoYW5nZURldGVjdGlvbjogQ2hhbmdlRGV0ZWN0aW9uU3RyYXRlZ3kuT25QdXNoLFxuICBwcm92aWRlcnM6IFtWYWxpZGF0ZVJvd0R1cGxpY2F0ZVNlcnZpY2VdLFxuICBpbXBvcnRzOiBbXG4gICAgQXV0b2NvbXBsZXRlTW9kdWxlLFxuICAgIElucHV0TW9kdWxlLFxuICAgIE5nSWYsXG4gICAgTmdGb3IsXG4gICAgTG93ZXJDYXNlUGlwZSxcbiAgICBSZWFjdGl2ZUZvcm1zTW9kdWxlLFxuICAgIFRyYW5zbGF0ZU1vZHVsZSxcbiAgICBJY29uTW9kdWxlLFxuICAgIFRvb2x0aXBNb2R1bGUsXG4gICAgUHVyZVBpcGVNb2R1bGUsXG4gICAgU2VsZWN0TW9kdWxlLFxuICAgIEFycmF5Rm9ybVRhYmxlTW9kdWxlLFxuICAgIEVycm9yc01hcHBlck1vZHVsZSxcbiAgXSxcbn0pXG5leHBvcnQgY2xhc3MgU2VydmljZVBvcnRzRmllbGRzZXRDb21wb25lbnRcbiAgZXh0ZW5kcyBCYXNlUmVzb3VyY2VGb3JtQXJyYXlDb21wb25lbnQ8U2VydmljZVBvcnQ+XG4gIGltcGxlbWVudHMgT25Jbml0XG57XG4gIF9yZXF1aXJlZDogYm9vbGVhbjtcblxuICBASW5wdXQoKVxuICBnZXQgcmVxdWlyZWQoKSB7XG4gICAgcmV0dXJuIHRoaXMuX3JlcXVpcmVkO1xuICB9XG5cbiAgc2V0IHJlcXVpcmVkKHJlcXVpcmVkOiBib29sZWFuIHwgJycpIHtcbiAgICB0aGlzLl9yZXF1aXJlZCA9IGNvZXJjZUF0dHJCb29sZWFuKHJlcXVpcmVkKTtcbiAgfVxuXG4gIEBWYWx1ZUhvb2sobnVsbCwgbnVsbCwgZnVuY3Rpb24gKHRoaXM6IFNlcnZpY2VQb3J0c0ZpZWxkc2V0Q29tcG9uZW50KSB7XG4gICAgdGhpcy51cGRhdGVWYWx1ZUFuZFZhbGlkaXR5KCk7XG4gIH0pXG4gIEBJbnB1dCgpXG4gIHNlcnZpY2VUeXBlOiBTZXJ2aWNlVHlwZTtcblxuICBASW5wdXQoKVxuICBjb250YWluZXJQb3J0U3VnZ2VzdGlvbnM6IENvbnRhaW5lclBvcnRbXSA9IFtdO1xuXG4gIEBJbnB1dCgpXG4gIGV4aXN0ZWRQb3J0czogU2VydmljZVBvcnRbXSA9IFtdO1xuXG4gIEBJbnB1dCgpXG4gIHRhcmdldENvbXBvbmVudDogJ3dvcmtsb2FkJyB8ICd2bScgfCAnbGFiZWwtc2VsZWN0b3JzJyA9ICd3b3JrbG9hZCc7XG5cbiAgY29uc3RydWN0b3IoXG4gICAgcHVibGljIG92ZXJyaWRlIGluamVjdG9yOiBJbmplY3RvcixcbiAgICBAT3B0aW9uYWwoKSBwdWJsaWMgcmVhZG9ubHkgY29udHJvbENvbnRhaW5lcjogQ29udHJvbENvbnRhaW5lcixcbiAgICBwcml2YXRlIHJlYWRvbmx5IHJvd0R1cFNlcnZpY2U6IFZhbGlkYXRlUm93RHVwbGljYXRlU2VydmljZSxcbiAgKSB7XG4gICAgc3VwZXIoaW5qZWN0b3IpO1xuICAgIHRoaXMudmFsaWRhdGVTZXJ2aWNlVHlwZSA9IHRoaXMudmFsaWRhdGVTZXJ2aWNlVHlwZS5iaW5kKHRoaXMpO1xuICB9XG5cbiAgc2VydmljZVBvcnRQcm90b2NvbHMgPSBTRVJWSUNFX1BPUlRfUFJPVE9DT0xTO1xuICBuYW1lUGF0dGVybiA9IEs4U19SRVNPVVJDRV9OQU1FX1NUQVJUX1dJVEhfQ0hBUlNfT05MWTtcblxuICBvdmVycmlkZSBuZ09uSW5pdCgpOiB2b2lkIHtcbiAgICBzdXBlci5uZ09uSW5pdCgpO1xuXG4gICAgdGhpcy5mb3JtLnZhbHVlQ2hhbmdlc1xuICAgICAgLnBpcGUoXG4gICAgICAgIGRlYm91bmNlVGltZSgwKSxcbiAgICAgICAgZGlzdGluY3RVbnRpbENoYW5nZWQoaXNFcXVhbCksXG4gICAgICAgIHRha2VVbnRpbCh0aGlzLmRlc3Ryb3kkKSxcbiAgICAgIClcbiAgICAgIC5zdWJzY3JpYmUoKCkgPT4gdGhpcy51cGRhdGVWYWx1ZUFuZFZhbGlkaXR5KCkpO1xuICB9XG5cbiAgb3ZlcnJpZGUgZ2V0T25Gb3JtQXJyYXlSZXNpemVGbigpIHtcbiAgICByZXR1cm4gKCkgPT4gdGhpcy5jcmVhdGVOZXdDb250cm9sKCk7XG4gIH1cblxuICBvdmVycmlkZSBnZXRSZXNvdXJjZU1lcmdlU3RyYXRlZ3koKTogYm9vbGVhbiB7XG4gICAgcmV0dXJuIHRydWU7XG4gIH1cblxuICBwcml2YXRlIGNyZWF0ZU5ld0NvbnRyb2woKSB7XG4gICAgcmV0dXJuIHRoaXMuZmIuZ3JvdXAoXG4gICAgICB7XG4gICAgICAgIG5hbWU6IFtcbiAgICAgICAgICAnJyxcbiAgICAgICAgICBbXG4gICAgICAgICAgICBWYWxpZGF0b3JzLnBhdHRlcm4odGhpcy5uYW1lUGF0dGVybi5wYXR0ZXJuKSxcbiAgICAgICAgICAgIFZhbGlkYXRvcnMubWF4TGVuZ3RoKDYzKSxcbiAgICAgICAgICBdLFxuICAgICAgICBdLFxuICAgICAgICBwcm90b2NvbDogW1NFUlZJQ0VfUE9SVF9CQVNFX1BST1RPQ09MU1swXV0sXG4gICAgICAgIGFwcFByb3RvY29sOiBbU0VSVklDRV9QT1JUX1BST1RPQ09MU1swXS50b0xvd2VyQ2FzZSgpXSxcbiAgICAgICAgcG9ydDogW1xuICAgICAgICAgICcnLFxuICAgICAgICAgIFtWYWxpZGF0b3JzLnJlcXVpcmVkLCBWYWxpZGF0b3JzLm1pbigxKSwgVmFsaWRhdG9ycy5tYXgoNjVfNTM1KV0sXG4gICAgICAgIF0sXG4gICAgICAgIHRhcmdldFBvcnQ6IFtcbiAgICAgICAgICAnJyxcbiAgICAgICAgICBbVmFsaWRhdG9ycy5yZXF1aXJlZCwgVmFsaWRhdG9ycy5tYXhMZW5ndGgoMTUpLCB0YXJnZXRQb3J0VmFsaWRhdG9yXSxcbiAgICAgICAgXSxcbiAgICAgIH0sXG4gICAgICB7XG4gICAgICAgIHZhbGlkYXRvcnM6IFtcbiAgICAgICAgICB0aGlzLnJvd0R1cFNlcnZpY2UuY3JlYXRlRm9ybUFycmF5VmFsaWRhdG9yKHtcbiAgICAgICAgICAgIHJvd0tleXM6IFt7IHBvcnQ6IFsncG9ydCcsICdwcm90b2NvbCddIH0sIHsgbmFtZTogWyduYW1lJ10gfV0sXG4gICAgICAgICAgICBmb3JtQXJyYXk6IHRoaXMuZm9ybSxcbiAgICAgICAgICAgIHZhbHVlTWFwRm46IChkYXRhOiBTZXJ2aWNlUG9ydCwgcHJvcDoga2V5b2YgU2VydmljZVBvcnQpID0+IHtcbiAgICAgICAgICAgICAgaWYgKHByb3AgPT09ICduYW1lJykge1xuICAgICAgICAgICAgICAgIHJldHVybiBkYXRhW3Byb3BdIHx8IGdldFNlcnZpY2VEZWZhdWx0TmFtZShkYXRhKTtcbiAgICAgICAgICAgICAgfVxuICAgICAgICAgICAgICByZXR1cm4gZGF0YVtwcm9wXTtcbiAgICAgICAgICAgIH0sXG4gICAgICAgICAgICBpbml0RGF0YTogdGhpcy5leGlzdGVkUG9ydHMubWFwKCh7IHBvcnQsIHByb3RvY29sIH0pID0+ICh7XG4gICAgICAgICAgICAgIHBvcnQ6IHtcbiAgICAgICAgICAgICAgICBwb3J0LFxuICAgICAgICAgICAgICAgIHByb3RvY29sLFxuICAgICAgICAgICAgICB9LFxuICAgICAgICAgICAgfSkpLFxuICAgICAgICAgIH0pLFxuICAgICAgICAgIHRoaXMudmFsaWRhdGVTZXJ2aWNlVHlwZSxcbiAgICAgICAgXSxcbiAgICAgIH0sXG4gICAgKTtcbiAgfVxuXG4gIHZhbGlkYXRlU2VydmljZVR5cGUoX2N0cmw/OiBBYnN0cmFjdENvbnRyb2wpIHtcbiAgICBpZiAodGhpcy5zZXJ2aWNlVHlwZSAhPT0gJ0xvYWRCYWxhbmNlcicpIHtcbiAgICAgIHJldHVybiBudWxsO1xuICAgIH1cbiAgICBmb3IgKFxuICAgICAgbGV0IGkgPSAxLCBzZXJ2aWNlUG9ydHMgPSB0aGlzLmZvcm1Nb2RlbCwgbGVuID0gc2VydmljZVBvcnRzLmxlbmd0aDtcbiAgICAgIGkgPCBsZW47XG4gICAgICBpKytcbiAgICApIHtcbiAgICAgIGNvbnN0IHByZXYgPSBzZXJ2aWNlUG9ydHNbaSAtIDFdO1xuICAgICAgY29uc3QgY3VyciA9IHNlcnZpY2VQb3J0c1tpXTtcbiAgICAgIGlmIChwcmV2LnByb3RvY29sICE9PSBjdXJyLnByb3RvY29sKSB7XG4gICAgICAgIHJldHVybiB7XG4gICAgICAgICAgcHJvdG9jb2w6IHRydWUsXG4gICAgICAgIH07XG4gICAgICB9XG4gICAgfVxuICB9XG5cbiAgb3ZlcnJpZGUgYWRhcHRSZXNvdXJjZU1vZGVsKHBvcnRzOiBTZXJ2aWNlUG9ydFtdKTogU2VydmljZVBvcnRbXSB7XG4gICAgcmV0dXJuIHBvcnRzPy5tYXAocG9ydCA9PiB7XG4gICAgICBwb3J0LmFwcFByb3RvY29sID1cbiAgICAgICAgcG9ydC5hcHBQcm90b2NvbCB8fFxuICAgICAgICAocG9ydC5wcm90b2NvbD8udG9Mb3dlckNhc2UoKSBhcyAndGNwJyB8ICd1ZHAnKSB8fFxuICAgICAgICAndGNwJztcbiAgICAgIHJldHVybiBwb3J0O1xuICAgIH0pO1xuICB9XG5cbiAgb3ZlcnJpZGUgYWRhcHRGb3JtTW9kZWwocG9ydHM6IFNlcnZpY2VQb3J0W10pOiBTZXJ2aWNlUG9ydFtdIHtcbiAgICByZXR1cm4gcG9ydHMubWFwKGl0ZW0gPT4ge1xuICAgICAgaWYgKGl0ZW0udGFyZ2V0UG9ydCkge1xuICAgICAgICBpdGVtLnRhcmdldFBvcnQgPSBnZXROb3JtYWxpemVkVGFyZ2V0UG9ydChpdGVtLnRhcmdldFBvcnQpO1xuICAgICAgfSBlbHNlIHtcbiAgICAgICAgZGVsZXRlIGl0ZW0udGFyZ2V0UG9ydDtcbiAgICAgIH1cblxuICAgICAgaWYgKC9eXFxkKyQvLnRlc3QoU3RyaW5nKGl0ZW0ubm9kZVBvcnQpKSkge1xuICAgICAgICBpdGVtLm5vZGVQb3J0ID0gK2l0ZW0ubm9kZVBvcnQ7XG4gICAgICB9IGVsc2Uge1xuICAgICAgICBkZWxldGUgaXRlbS5ub2RlUG9ydDtcbiAgICAgIH1cbiAgICAgIHJldHVybiBpdGVtO1xuICAgIH0pO1xuICB9XG5cbiAgdXBkYXRlQXBwUHJvdG9jb2woZ3JvdXA6IEZvcm1Hcm91cCkge1xuICAgIGNvbnN0IHByb3RvY29sID0gZ3JvdXAuZ2V0KCdhcHBQcm90b2NvbCcpLnZhbHVlO1xuICAgIGdyb3VwXG4gICAgICAuZ2V0KCdwcm90b2NvbCcpXG4gICAgICAuc2V0VmFsdWUocHJvdG9jb2wgPT09ICdVRFAnLnRvTG93ZXJDYXNlKCkgPyAnVURQJyA6ICdUQ1AnKTtcbiAgfVxuXG4gIHVwZGF0ZVZhbHVlQW5kVmFsaWRpdHkoKSB7XG4gICAgdGhpcy5mb3JtPy5jb250cm9scy5mb3JFYWNoKGN0cmwgPT4gY3RybC51cGRhdGVWYWx1ZUFuZFZhbGlkaXR5KCkpO1xuICB9XG5cbiAgZ2V0Q29udGFpbmVyUG9ydFN1Z2dlc3Rpb25zKFxuICAgIGNvbnRhaW5lclBvcnRTdWdnZXN0aW9uczogQ29udGFpbmVyUG9ydFtdID0gW10sXG4gICAgYXBwUHJvdG9jb2w6IExvd2VyY2FzZTxTZXJ2aWNlUG9ydFByb3RvY29sPixcbiAgKSB7XG4gICAgY29uc3QgX3Byb3RvY29sID0gYXBwUHJvdG9jb2wgPT09ICd1ZHAnID8gJ1VEUCcgOiAnVENQJztcbiAgICByZXR1cm4gdW5pcUJ5KFxuICAgICAgY29udGFpbmVyUG9ydFN1Z2dlc3Rpb25zPy5maWx0ZXIoXG4gICAgICAgIGNvbnRhaW5lclBvcnQgPT4gKGNvbnRhaW5lclBvcnQucHJvdG9jb2wgPz8gJ1RDUCcpID09PSBfcHJvdG9jb2wsXG4gICAgICApLFxuICAgICAgcG9ydCA9PiBwb3J0LmNvbnRhaW5lclBvcnQgKyAocG9ydC5uYW1lID8gJy0nICsgcG9ydC5uYW1lIDogJycpLFxuICAgICk7XG4gIH1cblxuICAvLyDngrnlh7vluKblkI3np7DnmoTlrrnlmajnq6/lj6Pml7bkuZ/lj6rorr7nva7nq6/lj6Plj7dcbiAgdXBkYXRlQ29udGFpbmVyUG9ydChjb250cm9sOiBBYnN0cmFjdENvbnRyb2wsIHZhbHVlOiBzdHJpbmcpIHtcbiAgICBjb250cm9sLmdldCgndGFyZ2V0UG9ydCcpLnBhdGNoVmFsdWUodmFsdWUuc3BsaXQoJy0nKVswXSk7XG4gIH1cblxuICBhdXRvQ29tcGxldGVDb250YWluZXJQb3J0KGNvbnRyb2w6IEFic3RyYWN0Q29udHJvbCwgdmFsdWU6IG51bWJlcikge1xuICAgIGNvbnRyb2wuZ2V0KCd0YXJnZXRQb3J0JykucGF0Y2hWYWx1ZSh2YWx1ZSA/IFN0cmluZyh2YWx1ZSkgOiBudWxsKTtcbiAgfVxuXG4gIGdldENvbnRhaW5lclBvcnRUcmFuc2xhdGVLZXkoXG4gICAgdGFyZ2V0Q29tcG9uZW50OiAndm0nIHwgJ3dvcmtsb2FkJyB8ICdsYWJlbC1zZWxlY3RvcnMnLFxuICApIHtcbiAgICByZXR1cm4gdGFyZ2V0Q29tcG9uZW50ID09PSAndm0nID8gJ3ZtX3BvcnQnIDogJ2NvbnRhaW5lcl9wb3J0JztcbiAgfVxufVxuIiwiPGFjbC1hcnJheS1mb3JtLXRhYmxlXG4gIChhZGQpPVwiYWRkKGZvcm0ubGVuZ3RoKVwiXG4gIChyZW1vdmUpPVwicmVtb3ZlKCRldmVudClcIlxuICBbbWluUm93XT1cInJlcXVpcmVkID8gMSA6IDBcIlxuICBbcm93c109XCJmb3JtLmNvbnRyb2xzXCJcbiAgW2Zvcm1Hcm91cF09XCIkYW55KGZvcm0pXCJcbiAgY2xhc3M9XCJmb3JtLXRhYmxlX19mbGV4LWxheW91dCBpbmxpbmUtYWN0aW9uLWNvbFwiXG4+XG4gIDxuZy1jb250YWluZXIgKmFjbEFycmF5Rm9ybVRhYmxlSGVhZGVyPlxuICAgIDx0aD57eyAncHJvdG9jb2wnIHwgdHJhbnNsYXRlIH19PC90aD5cbiAgICA8dGg+XG4gICAgICA8c3BhbiBjbGFzcz1cInJlcXVpcmVkLW1hcmtcIj4qPC9zcGFuPlxuICAgICAge3sgJ3NlcnZpY2VfcG9ydCcgfCB0cmFuc2xhdGUgfX1cbiAgICA8L3RoPlxuICAgIDx0aD5cbiAgICAgIDxzcGFuIGNsYXNzPVwicmVxdWlyZWQtbWFya1wiPio8L3NwYW4+XG4gICAgICB7eyB0YXJnZXRDb21wb25lbnQgfCBwdXJlOiBnZXRDb250YWluZXJQb3J0VHJhbnNsYXRlS2V5IHwgdHJhbnNsYXRlIH19XG4gICAgPC90aD5cbiAgICA8dGg+XG4gICAgICB7eyAnc2VydmljZV9wb3J0X25hbWUnIHwgdHJhbnNsYXRlIH19XG4gICAgICA8YXVpLWljb25cbiAgICAgICAgY2xhc3M9XCJtbC00IGljb24tLWhlbHBcIlxuICAgICAgICBpY29uPVwicXVlc3Rpb25fY2lyY2xlXCJcbiAgICAgICAgW2F1aVRvb2x0aXBdPVwiXG4gICAgICAgICAgJ3NlcnZpY2VfbmFtZV9kZWZhdWx0X3RpcHMnXG4gICAgICAgICAgICB8IHRyYW5zbGF0ZVxuICAgICAgICAgICAgICA6IHtcbiAgICAgICAgICAgICAgICAgIHR5cGU6XG4gICAgICAgICAgICAgICAgICAgIHRhcmdldENvbXBvbmVudFxuICAgICAgICAgICAgICAgICAgICB8IHB1cmU6IGdldENvbnRhaW5lclBvcnRUcmFuc2xhdGVLZXlcbiAgICAgICAgICAgICAgICAgICAgfCB0cmFuc2xhdGVcbiAgICAgICAgICAgICAgICB9XG4gICAgICAgIFwiXG4gICAgICA+PC9hdWktaWNvbj5cbiAgICA8L3RoPlxuICA8L25nLWNvbnRhaW5lcj5cblxuICA8bmctY29udGFpbmVyXG4gICAgKmFjbEFycmF5Rm9ybVRhYmxlUm93PVwibGV0IGNvbnRyb2w7IGxldCBpbmRleCA9IGluZGV4XCJcbiAgICBbZm9ybUdyb3VwTmFtZV09XCJpbmRleFwiXG4gID5cbiAgICA8dGQ+XG4gICAgICA8YXVpLXNlbGVjdFxuICAgICAgICBmb3JtQ29udHJvbE5hbWU9XCJhcHBQcm90b2NvbFwiXG4gICAgICAgICh2YWx1ZUNoYW5nZSk9XCJ1cGRhdGVBcHBQcm90b2NvbChjb250cm9sKVwiXG4gICAgICA+XG4gICAgICAgIDxhdWktb3B0aW9uXG4gICAgICAgICAgKm5nRm9yPVwibGV0IHByb3RvY29sIG9mIHNlcnZpY2VQb3J0UHJvdG9jb2xzXCJcbiAgICAgICAgICBbdmFsdWVdPVwicHJvdG9jb2wgfCBsb3dlcmNhc2VcIlxuICAgICAgICAgIFtsYWJlbF09XCJwcm90b2NvbFwiXG4gICAgICAgID5cbiAgICAgICAgICB7eyBwcm90b2NvbCB9fVxuICAgICAgICA8L2F1aS1vcHRpb24+XG4gICAgICA8L2F1aS1zZWxlY3Q+XG4gICAgPC90ZD5cbiAgICA8dGQ+XG4gICAgICA8aW5wdXRcbiAgICAgICAgYXVpLWlucHV0XG4gICAgICAgIHR5cGU9XCJudW1iZXJcIlxuICAgICAgICBmb3JtQ29udHJvbE5hbWU9XCJwb3J0XCJcbiAgICAgICAgKG5nTW9kZWxDaGFuZ2UpPVwiYXV0b0NvbXBsZXRlQ29udGFpbmVyUG9ydChjb250cm9sLCAkZXZlbnQpXCJcbiAgICAgICAgcmVxdWlyZWRcbiAgICAgIC8+XG4gICAgICA8YWNsLWVycm9ycy1tYXBwZXJcbiAgICAgICAgKm5nSWY9XCJcbiAgICAgICAgICBjb250cm9sLmdldCgncG9ydCcpLmRpcnR5IHx8XG4gICAgICAgICAgJGFueShjb250cm9sQ29udGFpbmVyPy5mb3JtRGlyZWN0aXZlKT8uc3VibWl0dGVkXG4gICAgICAgIFwiXG4gICAgICAgIFtlcnJvcnNdPVwiY29udHJvbC5nZXQoJ3BvcnQnKS5lcnJvcnNcIlxuICAgICAgICBbY29udHJvbE5hbWVdPVwiJ3NlcnZpY2VfcG9ydCcgfCB0cmFuc2xhdGVcIlxuICAgICAgPjwvYWNsLWVycm9ycy1tYXBwZXI+XG4gICAgPC90ZD5cbiAgICA8dGQ+XG4gICAgICA8aW5wdXRcbiAgICAgICAgYXVpLWlucHV0XG4gICAgICAgIGZvcm1Db250cm9sTmFtZT1cInRhcmdldFBvcnRcIlxuICAgICAgICBbYXVpQXV0b2NvbXBsZXRlXT1cInN1Z2dlc3Rpb25zXCJcbiAgICAgICAgKGF1aUF1dG9jb21wbGV0ZVNlbGVjdGVkKT1cInVwZGF0ZUNvbnRhaW5lclBvcnQoY29udHJvbCwgJGV2ZW50KVwiXG4gICAgICAvPlxuICAgICAgPGF1aS1hdXRvY29tcGxldGUgI3N1Z2dlc3Rpb25zPlxuICAgICAgICA8bmctY29udGFpbmVyXG4gICAgICAgICAgKm5nRm9yPVwiXG4gICAgICAgICAgICBsZXQgcG9ydCBvZiBjb250YWluZXJQb3J0U3VnZ2VzdGlvbnNcbiAgICAgICAgICAgICAgfCBwdXJlXG4gICAgICAgICAgICAgICAgOiBnZXRDb250YWluZXJQb3J0U3VnZ2VzdGlvbnNcbiAgICAgICAgICAgICAgICA6IGNvbnRyb2wuZ2V0KCdhcHBQcm90b2NvbCcpLnZhbHVlXG4gICAgICAgICAgXCJcbiAgICAgICAgPlxuICAgICAgICAgIDxhdWktc3VnZ2VzdGlvblxuICAgICAgICAgICAgKm5nSWY9XCJcbiAgICAgICAgICAgICAgcG9ydC5jb250YWluZXJQb3J0ICtcbiAgICAgICAgICAgICAgKHBvcnQubmFtZSA/ICctJyArIHBvcnQubmFtZSA6ICcnKSBhcyBzdWdnZXN0aW9uXG4gICAgICAgICAgICBcIlxuICAgICAgICAgICAgW3ZhbHVlXT1cInN1Z2dlc3Rpb25cIlxuICAgICAgICAgICAgPnt7IHN1Z2dlc3Rpb24gfX08L2F1aS1zdWdnZXN0aW9uXG4gICAgICAgICAgPlxuICAgICAgICA8L25nLWNvbnRhaW5lcj5cbiAgICAgIDwvYXVpLWF1dG9jb21wbGV0ZT5cbiAgICAgIDxhY2wtZXJyb3JzLW1hcHBlclxuICAgICAgICAqbmdJZj1cIlxuICAgICAgICAgIGNvbnRyb2wuZ2V0KCd0YXJnZXRQb3J0JykuZGlydHkgfHxcbiAgICAgICAgICAkYW55KGNvbnRyb2xDb250YWluZXI/LmZvcm1EaXJlY3RpdmUpPy5zdWJtaXR0ZWRcbiAgICAgICAgXCJcbiAgICAgICAgW2NvbnRyb2xOYW1lXT1cIlxuICAgICAgICAgIHRhcmdldENvbXBvbmVudCB8IHB1cmU6IGdldENvbnRhaW5lclBvcnRUcmFuc2xhdGVLZXkgfCB0cmFuc2xhdGVcbiAgICAgICAgXCJcbiAgICAgICAgW2Vycm9yc109XCJjb250cm9sLmdldCgndGFyZ2V0UG9ydCcpLmVycm9yc1wiXG4gICAgICAgIFtlcnJvcnNNYXBwZXJdPVwie1xuICAgICAgICAgIGNoYXJhY3RlcnM6XG4gICAgICAgICAgICAncG9ydF9uYW1lX2Vycm9yX2NoYXJhY3RlcnNfdGlwJ1xuICAgICAgICAgICAgfCB0cmFuc2xhdGVcbiAgICAgICAgICAgICAgOiB7XG4gICAgICAgICAgICAgICAgICBjb250cm9sTmFtZTpcbiAgICAgICAgICAgICAgICAgICAgdGFyZ2V0Q29tcG9uZW50XG4gICAgICAgICAgICAgICAgICAgIHwgcHVyZTogZ2V0Q29udGFpbmVyUG9ydFRyYW5zbGF0ZUtleVxuICAgICAgICAgICAgICAgICAgICB8IHRyYW5zbGF0ZVxuICAgICAgICAgICAgICAgIH0sXG4gICAgICAgICAgc3RhcnRfZW5kX2NoYXJhY3RlcjpcbiAgICAgICAgICAgICdwb3J0X25hbWVfZXJyb3Jfc3RhcnRfZW5kX2NoYXJhY3Rlcl90aXAnXG4gICAgICAgICAgICB8IHRyYW5zbGF0ZVxuICAgICAgICAgICAgICA6IHtcbiAgICAgICAgICAgICAgICAgIGNvbnRyb2xOYW1lOlxuICAgICAgICAgICAgICAgICAgICB0YXJnZXRDb21wb25lbnRcbiAgICAgICAgICAgICAgICAgICAgfCBwdXJlOiBnZXRDb250YWluZXJQb3J0VHJhbnNsYXRlS2V5XG4gICAgICAgICAgICAgICAgICAgIHwgdHJhbnNsYXRlXG4gICAgICAgICAgICAgICAgfVxuICAgICAgICB9XCJcbiAgICAgID48L2FjbC1lcnJvcnMtbWFwcGVyPlxuICAgIDwvdGQ+XG4gICAgPHRkPlxuICAgICAgPGlucHV0XG4gICAgICAgIGF1aS1pbnB1dFxuICAgICAgICBmb3JtQ29udHJvbE5hbWU9XCJuYW1lXCJcbiAgICAgIC8+XG4gICAgICA8YWNsLWVycm9ycy1tYXBwZXJcbiAgICAgICAgW2NvbnRyb2xOYW1lXT1cIidzZXJ2aWNlX3BvcnRfbmFtZScgfCB0cmFuc2xhdGVcIlxuICAgICAgICBbZXJyb3JzXT1cImNvbnRyb2wuZ2V0KCduYW1lJykuZXJyb3JzXCJcbiAgICAgICAgW2Vycm9yc01hcHBlcl09XCJ7XG4gICAgICAgICAgcGF0dGVybjogbmFtZVBhdHRlcm4udGlwIHwgdHJhbnNsYXRlXG4gICAgICAgIH1cIlxuICAgICAgPjwvYWNsLWVycm9ycy1tYXBwZXI+XG4gICAgPC90ZD5cbiAgPC9uZy1jb250YWluZXI+XG5cbiAgPCEtLSBJbnB1dCBlcnJvciByb3cgLS0+XG4gIDxuZy1jb250YWluZXIgKmFjbEFycmF5Rm9ybVRhYmxlUm93RXJyb3I9XCJsZXQgY29udHJvbFwiPlxuICAgIDx0ZFxuICAgICAgY2xhc3M9XCJhY2wtdGFibGUtZm9ybS1lcnJvci1oaW50XCJcbiAgICAgIGNvbHNwYW49XCI1XCJcbiAgICA+XG4gICAgICA8YWNsLWVycm9ycy1tYXBwZXJcbiAgICAgICAgKm5nSWY9XCJcbiAgICAgICAgICBjb250cm9sLmVycm9ycz8uZHVwbGljYXRlRXJyb3IgYXMgZHVwbGljYXRlRXJyb3I7XG4gICAgICAgICAgZWxzZSBvdGhlckVycm9yc1xuICAgICAgICBcIlxuICAgICAgICBbZXJyb3JzXT1cImR1cGxpY2F0ZUVycm9yXCJcbiAgICAgICAgW2Vycm9yc01hcHBlcl09XCJ7XG4gICAgICAgICAgcG9ydDpcbiAgICAgICAgICAgICdkdXBsaWNhdGVfc2VydmljZV9wb3J0J1xuICAgICAgICAgICAgfCB0cmFuc2xhdGU6IHsgcG9ydDogZHVwbGljYXRlRXJyb3IucG9ydD8ucG9ydCB9LFxuICAgICAgICAgIG5hbWU6XG4gICAgICAgICAgICAnZHVwbGljYXRlX3NlcnZpY2VfbmFtZSdcbiAgICAgICAgICAgIHwgdHJhbnNsYXRlOiB7IG5hbWU6IGR1cGxpY2F0ZUVycm9yLm5hbWU/Lm5hbWUgfVxuICAgICAgICB9XCJcbiAgICAgID48L2FjbC1lcnJvcnMtbWFwcGVyPlxuICAgICAgPG5nLXRlbXBsYXRlICNvdGhlckVycm9ycz5cbiAgICAgICAgPGFjbC1lcnJvcnMtbWFwcGVyXG4gICAgICAgICAgW2Vycm9yc109XCJjb250cm9sLmVycm9yc1wiXG4gICAgICAgICAgW2Vycm9yc01hcHBlcl09XCJ7XG4gICAgICAgICAgICBwcm90b2NvbDogJ2xiX3NlcnZpY2VfcHJvdG9jb2xfaGludCcgfCB0cmFuc2xhdGVcbiAgICAgICAgICB9XCJcbiAgICAgICAgPjwvYWNsLWVycm9ycy1tYXBwZXI+XG4gICAgICA8L25nLXRlbXBsYXRlPlxuICAgIDwvdGQ+XG4gIDwvbmctY29udGFpbmVyPlxuPC9hY2wtYXJyYXktZm9ybS10YWJsZT5cbiJdfQ==
@@ -0,0 +1,111 @@
1
+ import { __decorate, __metadata } from "tslib";
2
+ import { ValueHook } from '@alauda-fe/common';
3
+ import { Directive, Input } from '@angular/core';
4
+ import { NG_VALIDATORS } from '@angular/forms';
5
+ import { IPMode, isCidrAddressValid, isCidrContain, isIpAddressValid, isBelongCidr, parseSegment, } from '../utils/cidr-exports';
6
+ import * as i0 from "@angular/core";
7
+ export class CidrIpDirective {
8
+ validate(control) {
9
+ this.control = control;
10
+ const { value } = control;
11
+ if (!value || !this.info) {
12
+ return null;
13
+ }
14
+ const { ipMode, segment } = this.info;
15
+ if (!isIpAddressValid(value, ipMode)) {
16
+ return { pattern: true };
17
+ }
18
+ if (!segment) {
19
+ return null;
20
+ }
21
+ const { ipV4Segment, ipV6Segment } = parseSegment(segment);
22
+ const activeSegment = ipMode === IPMode.IPV6 ? ipV6Segment : ipV4Segment;
23
+ if (!isCidrAddressValid(activeSegment, ipMode)) {
24
+ return null;
25
+ }
26
+ return isBelongCidr(activeSegment, value, ipMode)
27
+ ? null
28
+ : { ipNotInCidr: activeSegment };
29
+ }
30
+ static { this.ɵfac = function CidrIpDirective_Factory(t) { return new (t || CidrIpDirective)(); }; }
31
+ static { this.ɵdir = /*@__PURE__*/ i0.ɵɵdefineDirective({ type: CidrIpDirective, selectors: [["", "rcCidrIp", ""]], inputs: { info: ["rcCidrIp", "info"] }, standalone: true, features: [i0.ɵɵProvidersFeature([
32
+ {
33
+ provide: NG_VALIDATORS,
34
+ useExisting: CidrIpDirective,
35
+ multi: true,
36
+ },
37
+ ])] }); }
38
+ }
39
+ __decorate([
40
+ ValueHook(null, null, function () {
41
+ this.control?.updateValueAndValidity();
42
+ }),
43
+ __metadata("design:type", Object)
44
+ ], CidrIpDirective.prototype, "info", void 0);
45
+ (function () { (typeof ngDevMode === "undefined" || ngDevMode) && i0.ɵsetClassMetadata(CidrIpDirective, [{
46
+ type: Directive,
47
+ args: [{
48
+ selector: '[rcCidrIp]',
49
+ providers: [
50
+ {
51
+ provide: NG_VALIDATORS,
52
+ useExisting: CidrIpDirective,
53
+ multi: true,
54
+ },
55
+ ],
56
+ standalone: true,
57
+ }]
58
+ }], null, { info: [{
59
+ type: Input,
60
+ args: ['rcCidrIp']
61
+ }] }); })();
62
+ export class CidrScaleSubnetDirective {
63
+ validate(control) {
64
+ const { value } = control;
65
+ if (!value || !this.info) {
66
+ return null;
67
+ }
68
+ const { ipMode, segment } = this.info;
69
+ if (!isCidrAddressValid(value, ipMode)) {
70
+ return { pattern: true };
71
+ }
72
+ if (!segment) {
73
+ return null;
74
+ }
75
+ const { ipV4Segment, ipV6Segment } = parseSegment(segment);
76
+ const activeSegment = ipMode === IPMode.IPV6 ? ipV6Segment : ipV4Segment;
77
+ if (!isCidrAddressValid(activeSegment, ipMode)) {
78
+ return null;
79
+ }
80
+ // 新的 cidr 包含旧的 cidr
81
+ return isCidrContain(value, activeSegment, ipMode)
82
+ ? null
83
+ : { cidrContain: activeSegment };
84
+ }
85
+ static { this.ɵfac = function CidrScaleSubnetDirective_Factory(t) { return new (t || CidrScaleSubnetDirective)(); }; }
86
+ static { this.ɵdir = /*@__PURE__*/ i0.ɵɵdefineDirective({ type: CidrScaleSubnetDirective, selectors: [["", "rcCidrScaleSubnet", ""]], inputs: { info: ["rcCidrScaleSubnet", "info"] }, standalone: true, features: [i0.ɵɵProvidersFeature([
87
+ {
88
+ provide: NG_VALIDATORS,
89
+ useExisting: CidrScaleSubnetDirective,
90
+ multi: true,
91
+ },
92
+ ])] }); }
93
+ }
94
+ (function () { (typeof ngDevMode === "undefined" || ngDevMode) && i0.ɵsetClassMetadata(CidrScaleSubnetDirective, [{
95
+ type: Directive,
96
+ args: [{
97
+ selector: '[rcCidrScaleSubnet]',
98
+ providers: [
99
+ {
100
+ provide: NG_VALIDATORS,
101
+ useExisting: CidrScaleSubnetDirective,
102
+ multi: true,
103
+ },
104
+ ],
105
+ standalone: true,
106
+ }]
107
+ }], null, { info: [{
108
+ type: Input,
109
+ args: ['rcCidrScaleSubnet']
110
+ }] }); })();
111
+ //# sourceMappingURL=data:application/json;base64,eyJ2ZXJzaW9uIjozLCJmaWxlIjoic3VibmV0LXZhbGlkYXRvci5kaXJlY3RpdmUuanMiLCJzb3VyY2VSb290IjoiIiwic291cmNlcyI6WyIuLi8uLi8uLi8uLi8uLi8uLi9tb2R1bGVzL25ldHdvcmsvc3JjL2xpYi9kaXJlY3RpdmVzL3N1Ym5ldC12YWxpZGF0b3IuZGlyZWN0aXZlLnRzIl0sIm5hbWVzIjpbXSwibWFwcGluZ3MiOiI7QUFBQSxPQUFPLEVBQUUsU0FBUyxFQUFFLE1BQU0sbUJBQW1CLENBQUM7QUFDOUMsT0FBTyxFQUFFLFNBQVMsRUFBRSxLQUFLLEVBQUUsTUFBTSxlQUFlLENBQUM7QUFDakQsT0FBTyxFQUFtQixhQUFhLEVBQWEsTUFBTSxnQkFBZ0IsQ0FBQztBQUUzRSxPQUFPLEVBQ0wsTUFBTSxFQUNOLGtCQUFrQixFQUNsQixhQUFhLEVBQ2IsZ0JBQWdCLEVBQ2hCLFlBQVksRUFDWixZQUFZLEdBQ2IsTUFBTSx1QkFBdUIsQ0FBQzs7QUFhL0IsTUFBTSxPQUFPLGVBQWU7SUFZMUIsUUFBUSxDQUFDLE9BQXdCO1FBQy9CLElBQUksQ0FBQyxPQUFPLEdBQUcsT0FBTyxDQUFDO1FBQ3ZCLE1BQU0sRUFBRSxLQUFLLEVBQUUsR0FBRyxPQUFPLENBQUM7UUFDMUIsSUFBSSxDQUFDLEtBQUssSUFBSSxDQUFDLElBQUksQ0FBQyxJQUFJLEVBQUU7WUFDeEIsT0FBTyxJQUFJLENBQUM7U0FDYjtRQUNELE1BQU0sRUFBRSxNQUFNLEVBQUUsT0FBTyxFQUFFLEdBQUcsSUFBSSxDQUFDLElBQUksQ0FBQztRQUN0QyxJQUFJLENBQUMsZ0JBQWdCLENBQUMsS0FBSyxFQUFFLE1BQU0sQ0FBQyxFQUFFO1lBQ3BDLE9BQU8sRUFBRSxPQUFPLEVBQUUsSUFBSSxFQUFFLENBQUM7U0FDMUI7UUFDRCxJQUFJLENBQUMsT0FBTyxFQUFFO1lBQ1osT0FBTyxJQUFJLENBQUM7U0FDYjtRQUNELE1BQU0sRUFBRSxXQUFXLEVBQUUsV0FBVyxFQUFFLEdBQUcsWUFBWSxDQUFDLE9BQU8sQ0FBQyxDQUFDO1FBQzNELE1BQU0sYUFBYSxHQUFHLE1BQU0sS0FBSyxNQUFNLENBQUMsSUFBSSxDQUFDLENBQUMsQ0FBQyxXQUFXLENBQUMsQ0FBQyxDQUFDLFdBQVcsQ0FBQztRQUN6RSxJQUFJLENBQUMsa0JBQWtCLENBQUMsYUFBYSxFQUFFLE1BQU0sQ0FBQyxFQUFFO1lBQzlDLE9BQU8sSUFBSSxDQUFDO1NBQ2I7UUFDRCxPQUFPLFlBQVksQ0FBQyxhQUFhLEVBQUUsS0FBSyxFQUFFLE1BQU0sQ0FBQztZQUMvQyxDQUFDLENBQUMsSUFBSTtZQUNOLENBQUMsQ0FBQyxFQUFFLFdBQVcsRUFBRSxhQUFhLEVBQUUsQ0FBQztJQUNyQyxDQUFDO2dGQWpDVSxlQUFlO29FQUFmLGVBQWUsZ0lBVGY7Z0JBQ1Q7b0JBQ0UsT0FBTyxFQUFFLGFBQWE7b0JBQ3RCLFdBQVcsRUFBRSxlQUFlO29CQUM1QixLQUFLLEVBQUUsSUFBSTtpQkFDWjthQUNGOztBQVFEO0lBSkMsU0FBUyxDQUFDLElBQUksRUFBRSxJQUFJLEVBQUU7UUFDckIsSUFBSSxDQUFDLE9BQU8sRUFBRSxzQkFBc0IsRUFBRSxDQUFDO0lBQ3pDLENBQUMsQ0FBQzs7NkNBS0E7dUZBUlMsZUFBZTtjQVgzQixTQUFTO2VBQUM7Z0JBQ1QsUUFBUSxFQUFFLFlBQVk7Z0JBQ3RCLFNBQVMsRUFBRTtvQkFDVDt3QkFDRSxPQUFPLEVBQUUsYUFBYTt3QkFDdEIsV0FBVyxpQkFBaUI7d0JBQzVCLEtBQUssRUFBRSxJQUFJO3FCQUNaO2lCQUNGO2dCQUNELFVBQVUsRUFBRSxJQUFJO2FBQ2pCO2dCQU1DLElBQUk7a0JBREgsS0FBSzttQkFBQyxVQUFVOztBQTJDbkIsTUFBTSxPQUFPLHdCQUF3QjtJQU9uQyxRQUFRLENBQUMsT0FBd0I7UUFDL0IsTUFBTSxFQUFFLEtBQUssRUFBRSxHQUFHLE9BQU8sQ0FBQztRQUMxQixJQUFJLENBQUMsS0FBSyxJQUFJLENBQUMsSUFBSSxDQUFDLElBQUksRUFBRTtZQUN4QixPQUFPLElBQUksQ0FBQztTQUNiO1FBQ0QsTUFBTSxFQUFFLE1BQU0sRUFBRSxPQUFPLEVBQUUsR0FBRyxJQUFJLENBQUMsSUFBSSxDQUFDO1FBQ3RDLElBQUksQ0FBQyxrQkFBa0IsQ0FBQyxLQUFLLEVBQUUsTUFBTSxDQUFDLEVBQUU7WUFDdEMsT0FBTyxFQUFFLE9BQU8sRUFBRSxJQUFJLEVBQUUsQ0FBQztTQUMxQjtRQUNELElBQUksQ0FBQyxPQUFPLEVBQUU7WUFDWixPQUFPLElBQUksQ0FBQztTQUNiO1FBQ0QsTUFBTSxFQUFFLFdBQVcsRUFBRSxXQUFXLEVBQUUsR0FBRyxZQUFZLENBQUMsT0FBTyxDQUFDLENBQUM7UUFDM0QsTUFBTSxhQUFhLEdBQUcsTUFBTSxLQUFLLE1BQU0sQ0FBQyxJQUFJLENBQUMsQ0FBQyxDQUFDLFdBQVcsQ0FBQyxDQUFDLENBQUMsV0FBVyxDQUFDO1FBQ3pFLElBQUksQ0FBQyxrQkFBa0IsQ0FBQyxhQUFhLEVBQUUsTUFBTSxDQUFDLEVBQUU7WUFDOUMsT0FBTyxJQUFJLENBQUM7U0FDYjtRQUNELG9CQUFvQjtRQUNwQixPQUFPLGFBQWEsQ0FBQyxLQUFLLEVBQUUsYUFBYSxFQUFFLE1BQU0sQ0FBQztZQUNoRCxDQUFDLENBQUMsSUFBSTtZQUNOLENBQUMsQ0FBQyxFQUFFLFdBQVcsRUFBRSxhQUFhLEVBQUUsQ0FBQztJQUNyQyxDQUFDO3lGQTVCVSx3QkFBd0I7b0VBQXhCLHdCQUF3QixrSkFUeEI7Z0JBQ1Q7b0JBQ0UsT0FBTyxFQUFFLGFBQWE7b0JBQ3RCLFdBQVcsRUFBRSx3QkFBd0I7b0JBQ3JDLEtBQUssRUFBRSxJQUFJO2lCQUNaO2FBQ0Y7O3VGQUdVLHdCQUF3QjtjQVhwQyxTQUFTO2VBQUM7Z0JBQ1QsUUFBUSxFQUFFLHFCQUFxQjtnQkFDL0IsU0FBUyxFQUFFO29CQUNUO3dCQUNFLE9BQU8sRUFBRSxhQUFhO3dCQUN0QixXQUFXLDBCQUEwQjt3QkFDckMsS0FBSyxFQUFFLElBQUk7cUJBQ1o7aUJBQ0Y7Z0JBQ0QsVUFBVSxFQUFFLElBQUk7YUFDakI7Z0JBR0MsSUFBSTtrQkFESCxLQUFLO21CQUFDLG1CQUFtQiIsInNvdXJjZXNDb250ZW50IjpbImltcG9ydCB7IFZhbHVlSG9vayB9IGZyb20gJ0BhbGF1ZGEtZmUvY29tbW9uJztcbmltcG9ydCB7IERpcmVjdGl2ZSwgSW5wdXQgfSBmcm9tICdAYW5ndWxhci9jb3JlJztcbmltcG9ydCB7IEFic3RyYWN0Q29udHJvbCwgTkdfVkFMSURBVE9SUywgVmFsaWRhdG9yIH0gZnJvbSAnQGFuZ3VsYXIvZm9ybXMnO1xuXG5pbXBvcnQge1xuICBJUE1vZGUsXG4gIGlzQ2lkckFkZHJlc3NWYWxpZCxcbiAgaXNDaWRyQ29udGFpbixcbiAgaXNJcEFkZHJlc3NWYWxpZCxcbiAgaXNCZWxvbmdDaWRyLFxuICBwYXJzZVNlZ21lbnQsXG59IGZyb20gJy4uL3V0aWxzL2NpZHItZXhwb3J0cyc7XG5cbkBEaXJlY3RpdmUoe1xuICBzZWxlY3RvcjogJ1tyY0NpZHJJcF0nLFxuICBwcm92aWRlcnM6IFtcbiAgICB7XG4gICAgICBwcm92aWRlOiBOR19WQUxJREFUT1JTLFxuICAgICAgdXNlRXhpc3Rpbmc6IENpZHJJcERpcmVjdGl2ZSxcbiAgICAgIG11bHRpOiB0cnVlLFxuICAgIH0sXG4gIF0sXG4gIHN0YW5kYWxvbmU6IHRydWUsXG59KVxuZXhwb3J0IGNsYXNzIENpZHJJcERpcmVjdGl2ZSBpbXBsZW1lbnRzIFZhbGlkYXRvciB7XG4gIEBWYWx1ZUhvb2sobnVsbCwgbnVsbCwgZnVuY3Rpb24gKHRoaXM6IENpZHJJcERpcmVjdGl2ZSkge1xuICAgIHRoaXMuY29udHJvbD8udXBkYXRlVmFsdWVBbmRWYWxpZGl0eSgpO1xuICB9KVxuICBASW5wdXQoJ3JjQ2lkcklwJylcbiAgaW5mbz86IHtcbiAgICBpcE1vZGU6IElQTW9kZTtcbiAgICBzZWdtZW50OiBzdHJpbmc7XG4gIH07XG5cbiAgY29udHJvbDogQWJzdHJhY3RDb250cm9sO1xuXG4gIHZhbGlkYXRlKGNvbnRyb2w6IEFic3RyYWN0Q29udHJvbCkge1xuICAgIHRoaXMuY29udHJvbCA9IGNvbnRyb2w7XG4gICAgY29uc3QgeyB2YWx1ZSB9ID0gY29udHJvbDtcbiAgICBpZiAoIXZhbHVlIHx8ICF0aGlzLmluZm8pIHtcbiAgICAgIHJldHVybiBudWxsO1xuICAgIH1cbiAgICBjb25zdCB7IGlwTW9kZSwgc2VnbWVudCB9ID0gdGhpcy5pbmZvO1xuICAgIGlmICghaXNJcEFkZHJlc3NWYWxpZCh2YWx1ZSwgaXBNb2RlKSkge1xuICAgICAgcmV0dXJuIHsgcGF0dGVybjogdHJ1ZSB9O1xuICAgIH1cbiAgICBpZiAoIXNlZ21lbnQpIHtcbiAgICAgIHJldHVybiBudWxsO1xuICAgIH1cbiAgICBjb25zdCB7IGlwVjRTZWdtZW50LCBpcFY2U2VnbWVudCB9ID0gcGFyc2VTZWdtZW50KHNlZ21lbnQpO1xuICAgIGNvbnN0IGFjdGl2ZVNlZ21lbnQgPSBpcE1vZGUgPT09IElQTW9kZS5JUFY2ID8gaXBWNlNlZ21lbnQgOiBpcFY0U2VnbWVudDtcbiAgICBpZiAoIWlzQ2lkckFkZHJlc3NWYWxpZChhY3RpdmVTZWdtZW50LCBpcE1vZGUpKSB7XG4gICAgICByZXR1cm4gbnVsbDtcbiAgICB9XG4gICAgcmV0dXJuIGlzQmVsb25nQ2lkcihhY3RpdmVTZWdtZW50LCB2YWx1ZSwgaXBNb2RlKVxuICAgICAgPyBudWxsXG4gICAgICA6IHsgaXBOb3RJbkNpZHI6IGFjdGl2ZVNlZ21lbnQgfTtcbiAgfVxufVxuXG5ARGlyZWN0aXZlKHtcbiAgc2VsZWN0b3I6ICdbcmNDaWRyU2NhbGVTdWJuZXRdJyxcbiAgcHJvdmlkZXJzOiBbXG4gICAge1xuICAgICAgcHJvdmlkZTogTkdfVkFMSURBVE9SUyxcbiAgICAgIHVzZUV4aXN0aW5nOiBDaWRyU2NhbGVTdWJuZXREaXJlY3RpdmUsXG4gICAgICBtdWx0aTogdHJ1ZSxcbiAgICB9LFxuICBdLFxuICBzdGFuZGFsb25lOiB0cnVlLFxufSlcbmV4cG9ydCBjbGFzcyBDaWRyU2NhbGVTdWJuZXREaXJlY3RpdmUgaW1wbGVtZW50cyBWYWxpZGF0b3Ige1xuICBASW5wdXQoJ3JjQ2lkclNjYWxlU3VibmV0JylcbiAgaW5mbz86IHtcbiAgICBpcE1vZGU6IElQTW9kZTtcbiAgICBzZWdtZW50OiBzdHJpbmc7XG4gIH07XG5cbiAgdmFsaWRhdGUoY29udHJvbDogQWJzdHJhY3RDb250cm9sKSB7XG4gICAgY29uc3QgeyB2YWx1ZSB9ID0gY29udHJvbDtcbiAgICBpZiAoIXZhbHVlIHx8ICF0aGlzLmluZm8pIHtcbiAgICAgIHJldHVybiBudWxsO1xuICAgIH1cbiAgICBjb25zdCB7IGlwTW9kZSwgc2VnbWVudCB9ID0gdGhpcy5pbmZvO1xuICAgIGlmICghaXNDaWRyQWRkcmVzc1ZhbGlkKHZhbHVlLCBpcE1vZGUpKSB7XG4gICAgICByZXR1cm4geyBwYXR0ZXJuOiB0cnVlIH07XG4gICAgfVxuICAgIGlmICghc2VnbWVudCkge1xuICAgICAgcmV0dXJuIG51bGw7XG4gICAgfVxuICAgIGNvbnN0IHsgaXBWNFNlZ21lbnQsIGlwVjZTZWdtZW50IH0gPSBwYXJzZVNlZ21lbnQoc2VnbWVudCk7XG4gICAgY29uc3QgYWN0aXZlU2VnbWVudCA9IGlwTW9kZSA9PT0gSVBNb2RlLklQVjYgPyBpcFY2U2VnbWVudCA6IGlwVjRTZWdtZW50O1xuICAgIGlmICghaXNDaWRyQWRkcmVzc1ZhbGlkKGFjdGl2ZVNlZ21lbnQsIGlwTW9kZSkpIHtcbiAgICAgIHJldHVybiBudWxsO1xuICAgIH1cbiAgICAvLyDmlrDnmoQgY2lkciDljIXlkKvml6fnmoQgY2lkclxuICAgIHJldHVybiBpc0NpZHJDb250YWluKHZhbHVlLCBhY3RpdmVTZWdtZW50LCBpcE1vZGUpXG4gICAgICA/IG51bGxcbiAgICAgIDogeyBjaWRyQ29udGFpbjogYWN0aXZlU2VnbWVudCB9O1xuICB9XG59XG4iXX0=