@almatar/smart-booking-dashboard 0.0.2-alpha.2 → 0.0.2-alpha.3

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 (50) hide show
  1. package/esm2022/lib/components/almatar-aside/aside.component.mjs +6 -7
  2. package/esm2022/lib/components/hotel-cancel/almatar-hotel-auto-cancellation.component.mjs +2 -2
  3. package/esm2022/lib/components/hotel-cancel/components/almatar-hotel-auto-cancellation-select-rooms/components/almatar-hotel-auto-cancellation-non-refundable-room/almatar-hotel-auto-cancellation-non-refundable-room.component.mjs +2 -2
  4. package/esm2022/lib/components/hotel-cancel/services/almatar-hotel-auto-cancellation-endpoints.service.mjs +13 -4
  5. package/esm2022/lib/components/reissue-dialog/reissue-dialog.component.mjs +135 -0
  6. package/esm2022/lib/components/reissue-dialog/reissue-upgrade.store.mjs +305 -0
  7. package/esm2022/lib/components/reissue-dialog/reissue.store.mjs +349 -0
  8. package/esm2022/lib/components/reissue-dialog/steps/reissue-date-step/reissue-date-step.component.mjs +45 -0
  9. package/esm2022/lib/components/reissue-dialog/steps/reissue-legs-step/reissue-legs-step.component.mjs +140 -0
  10. package/esm2022/lib/components/reissue-dialog/steps/reissue-notice/reissue-notice.component.mjs +16 -0
  11. package/esm2022/lib/components/reissue-dialog/steps/reissue-route-step/reissue-route-step.component.mjs +104 -0
  12. package/esm2022/lib/components/reissue-dialog/steps/reissue-service-step/reissue-service-step.component.mjs +44 -0
  13. package/esm2022/lib/components/reissue-dialog/steps/reissue-upgrade-confirm-step/reissue-upgrade-confirm-step.component.mjs +193 -0
  14. package/esm2022/lib/components/reissue-dialog/steps/reissue-upgrade-step/reissue-upgrade-step.component.mjs +88 -0
  15. package/esm2022/lib/components/workflow-actions/workflow-actions.component.mjs +5 -3
  16. package/esm2022/lib/config/dashboard.config.mjs +3 -1
  17. package/esm2022/lib/models/reissue.types.mjs +2 -0
  18. package/esm2022/lib/pages/smart-booking-dashboard/smart-booking-dashboard.component.mjs +9 -3
  19. package/esm2022/lib/services/reissue.service.mjs +142 -0
  20. package/esm2022/lib/services/toast.service.mjs +15 -7
  21. package/esm2022/lib/utils/reissue-format.mjs +64 -0
  22. package/esm2022/lib/utils/reissue-url.builder.mjs +314 -0
  23. package/esm2022/public-api.mjs +3 -1
  24. package/fesm2022/almatar-smart-booking-dashboard.mjs +1919 -25
  25. package/fesm2022/almatar-smart-booking-dashboard.mjs.map +1 -1
  26. package/lib/components/action-dialog/action-dialog.component.d.ts +1 -1
  27. package/lib/components/almatar-aside/aside.component.d.ts +1 -2
  28. package/lib/components/hotel-cancel/components/hotel-content/hotel-content.component.d.ts +1 -1
  29. package/lib/components/hotel-cancel/services/almatar-hotel-auto-cancellation-endpoints.service.d.ts +6 -0
  30. package/lib/components/reissue-dialog/reissue-dialog.component.d.ts +34 -0
  31. package/lib/components/reissue-dialog/reissue-upgrade.store.d.ts +96 -0
  32. package/lib/components/reissue-dialog/reissue.store.d.ts +124 -0
  33. package/lib/components/reissue-dialog/steps/reissue-date-step/reissue-date-step.component.d.ts +11 -0
  34. package/lib/components/reissue-dialog/steps/reissue-legs-step/reissue-legs-step.component.d.ts +16 -0
  35. package/lib/components/reissue-dialog/steps/reissue-notice/reissue-notice.component.d.ts +8 -0
  36. package/lib/components/reissue-dialog/steps/reissue-route-step/reissue-route-step.component.d.ts +21 -0
  37. package/lib/components/reissue-dialog/steps/reissue-service-step/reissue-service-step.component.d.ts +17 -0
  38. package/lib/components/reissue-dialog/steps/reissue-upgrade-confirm-step/reissue-upgrade-confirm-step.component.d.ts +28 -0
  39. package/lib/components/reissue-dialog/steps/reissue-upgrade-step/reissue-upgrade-step.component.d.ts +13 -0
  40. package/lib/components/result-panel/result-panel.component.d.ts +1 -1
  41. package/lib/components/workflow-actions/workflow-actions.component.d.ts +3 -1
  42. package/lib/config/dashboard.config.d.ts +29 -0
  43. package/lib/models/reissue.types.d.ts +147 -0
  44. package/lib/pages/smart-booking-dashboard/smart-booking-dashboard.component.d.ts +4 -1
  45. package/lib/services/reissue.service.d.ts +45 -0
  46. package/lib/services/toast.service.d.ts +14 -1
  47. package/lib/utils/reissue-format.d.ts +28 -0
  48. package/lib/utils/reissue-url.builder.d.ts +24 -0
  49. package/package.json +9 -7
  50. package/public-api.d.ts +5 -1
@@ -0,0 +1,305 @@
1
+ import { DestroyRef, Injectable, computed, effect, inject, signal, untracked } from '@angular/core';
2
+ import { takeUntilDestroyed } from '@angular/core/rxjs-interop';
3
+ import { finalize } from 'rxjs/operators';
4
+ import { SbdReissueService } from '../../services/reissue.service';
5
+ import { formatMoney } from '../../utils/reissue-format';
6
+ import { SbdReissueStore, buildLegRow } from './reissue.store';
7
+ import * as i0 from "@angular/core";
8
+ const extraOf = (o) => o.fareDetails?.totalAdditionalFare ?? o.priceDifference ?? 0;
9
+ const routeOf = (l) => `${l.origin} → ${l.destination}`;
10
+ const currentOf = (l) => {
11
+ if (!l)
12
+ return '';
13
+ const cabin = [l.class, l.fareBrand?.name].filter(Boolean).join(' · ');
14
+ return cabin ? `Current: ${cabin}` : '';
15
+ };
16
+ /**
17
+ * Upgrade Class flow: pick the new class -> price it (choose-flight) -> confirm (book-now when nothing to pay,
18
+ * otherwise a backend-generated payment link). Reads the options the main store already loaded.
19
+ */
20
+ export class SbdReissueUpgradeStore {
21
+ constructor() {
22
+ this.main = inject(SbdReissueStore);
23
+ this.api = inject(SbdReissueService);
24
+ this.destroyRef = inject(DestroyRef);
25
+ this.submitting = signal(false);
26
+ this.error = signal(null);
27
+ this.priceChanged = signal(false);
28
+ /** `book-now` succeeded (nothing to pay): the reissue is being placed with the supplier. */
29
+ this.booked = signal(false);
30
+ this.paymentLink = signal(null);
31
+ this.selected = signal({}); // sectionId -> referenceKey
32
+ this.unavailableKeys = signal(new Set());
33
+ /** Legs the agent chose to upgrade (the "select leg" step; a one-way preselects its only leg). */
34
+ this.legIds = signal([]);
35
+ /** Options fetched for a partial leg selection; `null` = the options loaded when the dialog opened (all legs) apply. */
36
+ this.freshOptions = signal(null);
37
+ this.legsStepSkipped = signal(false);
38
+ // ── derived ───────────────────────────────────────────────────────────────
39
+ this.currency = computed(() => this.main.ctx()?.currency ?? '');
40
+ /** The options to show: for a partial leg selection the fresh response, otherwise the one loaded with the dialog. */
41
+ this.options = computed(() => this.freshOptions() ?? this.main.upgradeOptions());
42
+ this.legRows = computed(() => {
43
+ const chosen = new Set(this.legIds());
44
+ return this.main
45
+ .legs()
46
+ .map((leg, i) => buildLegRow(leg, this.legUpgradable(leg.legId, i), chosen.has(leg.legId), this.main.isLegOnline(leg.legId) ? 'no-options' : 'offline'));
47
+ });
48
+ this.anyLegUpgradable = computed(() => this.legRows().some(r => r.available));
49
+ this.canContinueFromLegs = computed(() => this.legIds().length > 0 && !this.submitting());
50
+ /** Legs the options on screen were requested for (all of them, or just the selected ones after a partial fetch). */
51
+ this.optionLegs = computed(() => {
52
+ const all = this.main.legs();
53
+ return this.freshOptions() ? all.filter(l => this.legIds().includes(l.legId)) : all;
54
+ });
55
+ this.rawSections = computed(() => {
56
+ const data = this.options();
57
+ if (!data)
58
+ return [];
59
+ if (data.fareOptionScope === 'leg') {
60
+ return (data.legs ?? []).map(leg => ({
61
+ id: String(leg.legIndex),
62
+ title: routeOf({ origin: leg.origin ?? leg.existingLeg.origin, destination: leg.destination ?? leg.existingLeg.destination }),
63
+ current: currentOf(leg.existingLeg),
64
+ options: leg.options ?? [],
65
+ }));
66
+ }
67
+ const originals = data.existingLegs ?? data.originalLegs ?? [];
68
+ return [
69
+ {
70
+ id: 'booking',
71
+ title: originals.map(routeOf).join(' · ') || 'Whole booking',
72
+ current: currentOf(originals[0]),
73
+ options: data.options ?? [],
74
+ },
75
+ ];
76
+ });
77
+ this.sections = computed(() => {
78
+ const selected = this.selected();
79
+ const unavailable = this.unavailableKeys();
80
+ const currency = this.currency();
81
+ return this.rawSections().map(s => ({
82
+ id: s.id,
83
+ title: s.title,
84
+ current: s.current,
85
+ options: s.options.map(o => {
86
+ const extra = extraOf(o);
87
+ return {
88
+ key: o.referenceKey,
89
+ name: o.name,
90
+ code: o.code,
91
+ extraLabel: extra > 0 ? `+${formatMoney(extra, currency)}` : 'No extra cost',
92
+ selected: selected[s.id] === o.referenceKey,
93
+ unavailable: unavailable.has(o.referenceKey),
94
+ };
95
+ }),
96
+ }));
97
+ });
98
+ this.picks = computed(() => {
99
+ const selected = this.selected();
100
+ return this.rawSections().flatMap(section => {
101
+ const option = section.options.find(o => o.referenceKey === selected[section.id]);
102
+ return option ? [{ section, option }] : [];
103
+ });
104
+ });
105
+ this.canContinue = computed(() => this.picks().length > 0 && !this.submitting());
106
+ /**
107
+ * Amount to pay: the sum of the picked options' additional fare (same as the web's `getTotalToPay`).
108
+ * choose-flight's own `price` is deliberately not used — it is not known whether it is the difference or the full fare.
109
+ */
110
+ this.total = computed(() => this.picks().reduce((sum, p) => sum + extraOf(p.option), 0));
111
+ this.totalLabel = computed(() => (this.total() > 0 ? formatMoney(this.total(), this.currency()) : 'Nothing to pay'));
112
+ this.summary = computed(() => this.picks().map(({ section, option }) => ({
113
+ title: section.title,
114
+ from: section.current.replace(/^Current:\s*/, ''),
115
+ to: option.name,
116
+ extraLabel: extraOf(option) > 0 ? `+${formatMoney(extraOf(option), this.currency())}` : 'No extra cost',
117
+ })));
118
+ this.action = computed(() => {
119
+ if (this.booked() || this.paymentLink())
120
+ return 'done';
121
+ return this.total() > 0 ? 'link' : 'book';
122
+ });
123
+ /** Nothing can be changed any more once the upgrade is placed or a link was generated. */
124
+ this.locked = computed(() => this.booked() || !!this.paymentLink() || this.submitting());
125
+ // A fresh options response (new dialog visit / retry) starts the flow over.
126
+ effect(() => {
127
+ this.main.upgradeOptions();
128
+ untracked(() => this.reset());
129
+ }, { allowSignalWrites: true });
130
+ }
131
+ // ── leg selection ─────────────────────────────────────────────────────────
132
+ /** A leg can be upgraded only if it is online AND has upgrade options (per leg for leg scope; booking scope applies to all). */
133
+ legUpgradable(legId, index) {
134
+ if (!this.main.isLegOnline(legId))
135
+ return false;
136
+ const data = this.main.upgradeOptions();
137
+ if (!data)
138
+ return false;
139
+ if (data.fareOptionScope === 'leg') {
140
+ return (data.legs?.find(l => l.legIndex === index)?.options?.length ?? 0) > 0;
141
+ }
142
+ return (data.options?.length ?? 0) > 0;
143
+ }
144
+ // ── actions ───────────────────────────────────────────────────────────────
145
+ /**
146
+ * Service picked: go to "select leg", unless there is nothing to choose (one-way with its only leg upgradable),
147
+ * which goes straight to the options like the web.
148
+ */
149
+ start() {
150
+ if (this.main.loading() || this.main.error())
151
+ return;
152
+ this.main.service.set('upgrade_class');
153
+ this.freshOptions.set(null);
154
+ this.selected.set({});
155
+ this.error.set(null);
156
+ const upgradable = this.legRows().filter(r => r.available);
157
+ if (this.legRows().length === 1 && upgradable.length === 1) {
158
+ this.legIds.set([upgradable[0].leg.legId]);
159
+ this.legsStepSkipped.set(true);
160
+ this.main.goTo('upgrade');
161
+ return;
162
+ }
163
+ this.legsStepSkipped.set(false);
164
+ // "Upgrade as a whole" bookings: every upgradable leg is preselected and cannot be unticked.
165
+ this.legIds.set(this.main.allowSingleLegSelection() ? [] : upgradable.map(r => r.leg.legId));
166
+ this.main.goTo('upgrade-legs');
167
+ }
168
+ toggleLeg(legId) {
169
+ const row = this.legRows().find(r => r.leg.legId === legId);
170
+ if (!row?.available || !this.main.allowSingleLegSelection())
171
+ return;
172
+ this.error.set(null);
173
+ this.legIds.update(ids => (ids.includes(legId) ? ids.filter(i => i !== legId) : [...ids, legId]));
174
+ }
175
+ /**
176
+ * Select leg -> options. All legs selected: reuse the options loaded with the dialog. A subset: fetch the options
177
+ * again for just those legs (the earlier response covers the whole booking, so it would price the wrong legs).
178
+ */
179
+ continueFromLegs() {
180
+ const ctx = this.main.ctx();
181
+ const chosen = this.main.legs().filter(l => this.legIds().includes(l.legId));
182
+ if (!ctx || !chosen.length || !this.canContinueFromLegs())
183
+ return;
184
+ this.selected.set({});
185
+ this.unavailableKeys.set(new Set());
186
+ if (chosen.length === this.main.legs().length) {
187
+ this.freshOptions.set(null);
188
+ this.main.goTo('upgrade');
189
+ return;
190
+ }
191
+ this.submitting.set(true);
192
+ this.error.set(null);
193
+ this.api
194
+ .getUpgradeClassOptions(ctx.bookingId, this.main.postBookingId(), { ...ctx, legs: chosen })
195
+ .pipe(finalize(() => this.submitting.set(false)), takeUntilDestroyed(this.destroyRef))
196
+ .subscribe({
197
+ next: data => {
198
+ if (!this.api.hasUpgradeOptions(data)) {
199
+ this.error.set('No upgrade is available for the selected flight(s).');
200
+ return;
201
+ }
202
+ this.freshOptions.set(data);
203
+ this.main.goTo('upgrade');
204
+ },
205
+ error: () => this.error.set('Could not load the upgrade options for the selected flight(s).'),
206
+ });
207
+ }
208
+ /** Back from the options: to "select leg" when that step was shown, otherwise to the service list. */
209
+ back() {
210
+ this.main.goTo(this.legsStepSkipped() ? 'service' : 'upgrade-legs');
211
+ }
212
+ select(sectionId, key) {
213
+ if (this.unavailableKeys().has(key))
214
+ return;
215
+ this.error.set(null);
216
+ this.selected.update(s => ({ ...s, [sectionId]: key }));
217
+ }
218
+ /** Options -> confirm: prices the pick(s) with choose-flight (same body the web sends). */
219
+ continue() {
220
+ const ctx = this.main.ctx();
221
+ const picks = this.picks();
222
+ if (!ctx || !picks.length || !this.canContinue())
223
+ return;
224
+ this.submitting.set(true);
225
+ this.error.set(null);
226
+ this.api
227
+ .chooseFlight(ctx.bookingId, this.main.postBookingId(), this.chooseBody(picks))
228
+ .pipe(finalize(() => this.submitting.set(false)), takeUntilDestroyed(this.destroyRef))
229
+ .subscribe({
230
+ next: res => {
231
+ if (res?.itineraryAvailable === false) {
232
+ this.unavailableKeys.update(keys => new Set([...keys, ...picks.map(p => p.option.referenceKey)]));
233
+ this.selected.set({});
234
+ this.error.set('This option is no longer available. Please choose another one.');
235
+ return;
236
+ }
237
+ this.priceChanged.set(res?.priceChanged === true);
238
+ this.main.goTo('confirm');
239
+ },
240
+ error: () => this.error.set('Could not price the selected upgrade. Please try again.'),
241
+ });
242
+ }
243
+ /** Confirm step primary action: place the free upgrade, or generate the payment link. */
244
+ confirm() {
245
+ const action = this.action();
246
+ if (action === 'done' || this.submitting())
247
+ return;
248
+ const postBookingId = this.main.postBookingId();
249
+ this.submitting.set(true);
250
+ this.error.set(null);
251
+ const request$ = action === 'book'
252
+ ? this.api.bookNow(postBookingId)
253
+ : this.api.getPaymentLink(postBookingId, this.total(), this.currency());
254
+ request$
255
+ .pipe(finalize(() => this.submitting.set(false)), takeUntilDestroyed(this.destroyRef))
256
+ .subscribe({
257
+ next: res => {
258
+ // The dialog does not follow the result (no confirmation-status): after `book-now`, or once the link is
259
+ // sent, the agent follows the booking from the dashboard.
260
+ if (action === 'book')
261
+ this.booked.set(true);
262
+ else
263
+ this.paymentLink.set(res);
264
+ },
265
+ error: (err) => this.error.set(action === 'book'
266
+ ? 'Could not place the upgrade. Please try again.'
267
+ : err instanceof Error && err.message.startsWith('The cart ')
268
+ ? err.message
269
+ : 'Could not get the payment link. Please try again.'),
270
+ });
271
+ }
272
+ reset() {
273
+ this.selected.set({});
274
+ this.unavailableKeys.set(new Set());
275
+ this.legIds.set([]);
276
+ this.freshOptions.set(null);
277
+ this.legsStepSkipped.set(false);
278
+ this.submitting.set(false);
279
+ this.error.set(null);
280
+ this.priceChanged.set(false);
281
+ this.booked.set(false);
282
+ this.paymentLink.set(null);
283
+ }
284
+ /** Booking scope: one itinerary. Leg scope: each picked leg as onwardLeg / returnLeg (by the real leg direction). */
285
+ chooseBody(picks) {
286
+ const scope = this.options()?.fareOptionScope ?? 'booking';
287
+ if (scope !== 'leg')
288
+ return { fareOptionScope: 'booking', ItineraryId: picks[0].option.referenceKey };
289
+ // A partial fetch re-indexes the sections from 0, so resolve the direction from the legs the options were requested for.
290
+ const legs = this.optionLegs();
291
+ const toLeg = (p) => (p ? { legId: p.option.referenceKey, providerType: p.option.providerType } : undefined);
292
+ const isReturn = (p) => legs[Number(p.section.id)]?.direction === 'Return';
293
+ return {
294
+ fareOptionScope: 'leg',
295
+ onwardLeg: toLeg(picks.find(p => !isReturn(p))),
296
+ returnLeg: toLeg(picks.find(isReturn)),
297
+ };
298
+ }
299
+ static { this.ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "18.2.14", ngImport: i0, type: SbdReissueUpgradeStore, deps: [], target: i0.ɵɵFactoryTarget.Injectable }); }
300
+ static { this.ɵprov = i0.ɵɵngDeclareInjectable({ minVersion: "12.0.0", version: "18.2.14", ngImport: i0, type: SbdReissueUpgradeStore }); }
301
+ }
302
+ i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "18.2.14", ngImport: i0, type: SbdReissueUpgradeStore, decorators: [{
303
+ type: Injectable
304
+ }], ctorParameters: () => [] });
305
+ //# sourceMappingURL=data:application/json;base64,eyJ2ZXJzaW9uIjozLCJmaWxlIjoicmVpc3N1ZS11cGdyYWRlLnN0b3JlLmpzIiwic291cmNlUm9vdCI6IiIsInNvdXJjZXMiOlsiLi4vLi4vLi4vLi4vLi4vLi4vcHJvamVjdHMvc21hcnQtYm9va2luZy1kYXNoYm9hcmQvc3JjL2xpYi9jb21wb25lbnRzL3JlaXNzdWUtZGlhbG9nL3JlaXNzdWUtdXBncmFkZS5zdG9yZS50cyJdLCJuYW1lcyI6W10sIm1hcHBpbmdzIjoiQUFBQSxPQUFPLEVBQUUsVUFBVSxFQUFFLFVBQVUsRUFBRSxRQUFRLEVBQUUsTUFBTSxFQUFFLE1BQU0sRUFBRSxNQUFNLEVBQUUsU0FBUyxFQUFFLE1BQU0sZUFBZSxDQUFDO0FBQ3BHLE9BQU8sRUFBRSxrQkFBa0IsRUFBRSxNQUFNLDRCQUE0QixDQUFDO0FBQ2hFLE9BQU8sRUFBRSxRQUFRLEVBQUUsTUFBTSxnQkFBZ0IsQ0FBQztBQUUxQyxPQUFPLEVBQUUsaUJBQWlCLEVBQUUsTUFBTSxnQ0FBZ0MsQ0FBQztBQVFuRSxPQUFPLEVBQUUsV0FBVyxFQUFFLE1BQU0sNEJBQTRCLENBQUM7QUFDekQsT0FBTyxFQUFpQixlQUFlLEVBQUUsV0FBVyxFQUFFLE1BQU0saUJBQWlCLENBQUM7O0FBWTlFLE1BQU0sT0FBTyxHQUFHLENBQUMsQ0FBdUIsRUFBVSxFQUFFLENBQUMsQ0FBQyxDQUFDLFdBQVcsRUFBRSxtQkFBbUIsSUFBSSxDQUFDLENBQUMsZUFBZSxJQUFJLENBQUMsQ0FBQztBQUNsSCxNQUFNLE9BQU8sR0FBRyxDQUFDLENBQTRELEVBQVUsRUFBRSxDQUFDLEdBQUcsQ0FBQyxDQUFDLE1BQU0sTUFBTSxDQUFDLENBQUMsV0FBVyxFQUFFLENBQUM7QUFDM0gsTUFBTSxTQUFTLEdBQUcsQ0FBQyxDQUE2QixFQUFVLEVBQUU7SUFDMUQsSUFBSSxDQUFDLENBQUM7UUFBRSxPQUFPLEVBQUUsQ0FBQztJQUNsQixNQUFNLEtBQUssR0FBRyxDQUFDLENBQUMsQ0FBQyxLQUFLLEVBQUUsQ0FBQyxDQUFDLFNBQVMsRUFBRSxJQUFJ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LFNBQVMsRUFBRSxXQUFXLEVBQUUsS0FBSyxDQUFDLENBQUMsQ0FBQyxDQUFDLE1BQU0sQ0FBQyxZQUFZLEVBQUUsQ0FBQztRQUV0Ryx5SEFBeUg7UUFDekgsTUFBTSxJQUFJLEdBQUcsSUFBSSxDQUFDLFVBQVUsRUFBRSxDQUFDO1FBQy9CLE1BQU0sS0FBSyxHQUFHLENBQUMsQ0FBZSxFQUFFLEVBQUUsQ0FBQyxDQUFDLENBQUMsQ0FBQyxDQUFDLENBQUMsRUFBRSxLQUFLLEVBQUUsQ0FBQyxDQUFDLE1BQU0sQ0FBQyxZQUFZLEVBQUUsWUFBWSxFQUFFLENBQUMsQ0FBQyxNQUFNLENBQUMsWUFBWSxFQUFFLENBQUMsQ0FBQyxDQUFDLFNBQVMsQ0FBQyxDQUFDO1FBQzNILE1BQU0sUUFBUSxHQUFHLENBQUMsQ0FBYyxFQUFFLEVBQUUsQ0FBQyxJQUFJLENBQUMsTUFBTSxDQUFDLENBQUMsQ0FBQyxPQUFPLENBQUMsRUFBRSxDQUFDLENBQUMsRUFBRSxTQUFTLEtBQUssUUFBUSxDQUFDO1FBQ3hGLE9BQU87WUFDTCxlQUFlLEVBQUUsS0FBSztZQUN0QixTQUFTLEVBQUUsS0FBSyxDQUFDLEtBQUssQ0FBQyxJQUFJLENBQUMsQ0FBQyxDQUFDLEVBQUUsQ0FBQyxDQUFDLFFBQVEsQ0FBQyxDQUFDLENBQUMsQ0FBQyxDQUFDO1lBQy9DLFNBQVMsRUFBRSxLQUFLLENBQUMsS0FBSyxDQUFDLElBQUksQ0FBQyxRQUFRLENBQUMsQ0FBQztTQUN2QyxDQUFDO0lBQ0osQ0FBQzsrR0FqVVUsc0JBQXNCO21IQUF0QixzQkFBc0I7OzRGQUF0QixzQkFBc0I7a0JBRGxDLFVBQVUiLCJzb3VyY2VzQ29udGVudCI6WyJpbXBvcnQgeyBEZXN0cm95UmVmLCBJbmplY3RhYmxlLCBjb21wdXRlZCwgZWZmZWN0LCBpbmplY3QsIHNpZ25hbCwgdW50cmFja2VkIH0gZnJvbSAnQGFuZ3VsYXIvY29yZSc7XG5pbXBvcnQgeyB0YWtlVW50aWxEZXN0cm95ZWQgfSBmcm9tICdAYW5ndWxhci9jb3JlL3J4anMtaW50ZXJvcCc7XG5pbXBvcnQgeyBmaW5hbGl6ZSB9IGZyb20gJ3J4anMvb3BlcmF0b3JzJztcblxuaW1wb3J0IHsgU2JkUmVpc3N1ZVNlcnZpY2UgfSBmcm9tICcuLi8uLi9zZXJ2aWNlcy9yZWlzc3VlLnNlcnZpY2UnO1xuaW1wb3J0IHtcbiAgUmVpc3N1ZUNob29zZUZsaWdodFJlcXVlc3QsXG4gIFJlaXNzdWVQYXltZW50TGluayxcbiAgUmVpc3N1ZVVwZ3JhZGVFeGlzdGluZ0xlZyxcbiAgUmVpc3N1ZVVwZ3JhZGVPcHRpb24sXG4gIFJlaXNzdWVVcGdyYWRlT3B0aW9uc1Jlc3BvbnNlLFxufSBmcm9tICcuLi8uLi9tb2RlbHMvcmVpc3N1ZS50eXBlcyc7XG5pbXBvcnQgeyBmb3JtYXRNb25leSB9IGZyb20gJy4uLy4uL3V0aWxzL3JlaXNzdWUtZm9ybWF0JztcbmltcG9ydCB7IFJlaXNzdWVMZWdSb3csIFNiZFJlaXNzdWVTdG9yZSwgYnVpbGRMZWdSb3cgfSBmcm9tICcuL3JlaXNzdWUuc3RvcmUnO1xuXG4vKiogVmlldyBtb2RlbHMgZm9yIHRoZSBVcGdyYWRlIENsYXNzIHN0ZXBzLiAqL1xuZXhwb3J0IGludGVyZmFjZSBVcGdyYWRlT3B0aW9uUm93IHsga2V5OiBzdHJpbmc7IG5hbWU6IHN0cmluZzsgY29kZTogc3RyaW5nOyBleHRyYUxhYmVsOiBzdHJpbmc7IHNlbGVjdGVkOiBib29sZWFuOyB1bmF2YWlsYWJsZTogYm9vbGVhbiB9XG5leHBvcnQgaW50ZXJmYWNlIFVwZ3JhZGVTZWN0aW9uUm93IHsgaWQ6IHN0cmluZzsgdGl0bGU6IHN0cmluZzsgY3VycmVudDogc3RyaW5nOyBvcHRpb25zOiBVcGdyYWRlT3B0aW9uUm93W10gfVxuZXhwb3J0IGludGVyZmFjZSBVcGdyYWRlU3VtbWFyeVJvdyB7IHRpdGxlOiBzdHJpbmc7IGZyb206IHN0cmluZzsgdG86IHN0cmluZzsgZXh0cmFMYWJlbDogc3RyaW5nIH1cbi8qKiBXaGF0IHRoZSBwcmltYXJ5IGJ1dHRvbiBvZiB0aGUgY29uZmlybSBzdGVwIGRvZXMuICovXG5leHBvcnQgdHlwZSBVcGdyYWRlQWN0aW9uID0gJ2Jvb2snIHwgJ2xpbmsnIHwgJ2RvbmUnO1xuXG5pbnRlcmZhY2UgUmF3U2VjdGlvbiB7IGlkOiBzdHJpbmc7IHRpdGxlOiBzdHJpbmc7IGN1cnJlbnQ6IHN0cmluZzsgb3B0aW9uczogUmVpc3N1ZVVwZ3JhZGVPcHRpb25bXSB9XG5pbnRlcmZhY2UgVXBncmFkZVBpY2sgeyBzZWN0aW9uOiBSYXdTZWN0aW9uOyBvcHRpb246IFJlaXNzdWVVcGdyYWRlT3B0aW9uIH1cblxuY29uc3QgZXh0cmFPZiA9IChvOiBSZWlzc3VlVXBncmFkZU9wdGlvbik6IG51bWJlciA9PiBvLmZhcmVEZXRhaWxzPy50b3RhbEFkZGl0aW9uYWxGYXJlID8/IG8ucHJpY2VEaWZmZXJlbmNlID8/IDA7XG5jb25zdCByb3V0ZU9mID0gKGw6IFBpY2s8UmVpc3N1ZVVwZ3JhZGVFeGlzdGluZ0xlZywgJ29yaWdpbicgfCAnZGVzdGluYXRpb24nPik6IHN0cmluZyA9PiBgJHtsLm9yaWdpbn0g4oaSICR7bC5kZXN0aW5hdGlvbn1gO1xuY29uc3QgY3VycmVudE9mID0gKGw/OiBSZWlzc3VlVXBncmFkZUV4aXN0aW5nTGVnKTogc3RyaW5nID0+IHtcbiAgaWYgKCFsKSByZXR1cm4gJyc7XG4gIGNvbnN0IGNhYmluID0gW2wuY2xhc3MsIGwuZmFyZUJyYW5kPy5uYW1lXS5maWx0ZXIoQm9vbGVhbikuam9pbignIMK3ICcpO1xuICByZXR1cm4gY2FiaW4gPyBgQ3VycmVudDogJHtjYWJpbn1gIDogJyc7XG59O1xuXG4vKipcbiAqIFVwZ3JhZGUgQ2xhc3MgZmxvdzogcGljayB0aGUgbmV3IGNsYXNzIC0+IHByaWNlIGl0IChjaG9vc2UtZmxpZ2h0KSAtPiBjb25maXJtIChib29rLW5vdyB3aGVuIG5vdGhpbmcgdG8gcGF5LFxuICogb3RoZXJ3aXNlIGEgYmFja2VuZC1nZW5lcmF0ZWQgcGF5bWVudCBsaW5rKS4gUmVhZHMgdGhlIG9wdGlvbnMgdGhlIG1haW4gc3RvcmUgYWxyZWFkeSBsb2FkZWQuXG4gKi9cbkBJbmplY3RhYmxlKClcbmV4cG9ydCBjbGFzcyBTYmRSZWlzc3VlVXBncmFkZVN0b3JlIHtcbiAgcHJpdmF0ZSBtYWluID0gaW5qZWN0KFNiZFJlaXNzdWVTdG9yZSk7XG4gIHByaXZhdGUgYXBpID0gaW5qZWN0KFNiZFJlaXNzdWVTZXJ2aWNlKTtcbiAgcHJpdmF0ZSBkZXN0cm95UmVmID0gaW5qZWN0KERlc3Ryb3lSZWYpO1xuXG4gIHJlYWRvbmx5IHN1Ym1pdHRpbmcgPSBzaWduYWwoZmFsc2UpO1xuICByZWFkb25seSBlcnJvciA9IHNpZ25hbDxzdHJpbmcgfCBudWxsPihudWxsKTtcbiAgcmVhZG9ubHkgcHJpY2VDaGFuZ2VkID0gc2lnbmFsKGZhbHNlKTtcbiAgLyoqIGBib29rLW5vd2Agc3VjY2VlZGVkIChub3RoaW5nIHRvIHBheSk6IHRoZSByZWlzc3VlIGlzIGJlaW5nIHBsYWNlZCB3aXRoIHRoZSBzdXBwbGllci4gKi9cbiAgcmVhZG9ubHkgYm9va2VkID0gc2lnbmFsKGZhbHNlKTtcbiAgcmVhZG9ubHkgcGF5bWVudExpbmsgPSBzaWduYWw8UmVpc3N1ZVBheW1lbnRMaW5rIHwgbnVsbD4obnVsbCk7XG5cbiAgcHJpdmF0ZSBzZWxlY3RlZCA9IHNpZ25hbDxSZWFkb25seTxSZWNvcmQ8c3RyaW5nLCBzdHJpbmc+Pj4oe30pOyAvLyBzZWN0aW9uSWQgLT4gcmVmZXJlbmNlS2V5XG4gIHByaXZhdGUgdW5hdmFpbGFibGVLZXlzID0gc2lnbmFsPFJlYWRvbmx5U2V0PHN0cmluZz4+KG5ldyBTZXQoKSk7XG5cbiAgLyoqIExlZ3MgdGhlIGFnZW50IGNob3NlIHRvIHVwZ3JhZGUgKHRoZSBcInNlbGVjdCBsZWdcIiBzdGVwOyBhIG9uZS13YXkgcHJlc2VsZWN0cyBpdHMgb25seSBsZWcpLiAqL1xuICBwcml2YXRlIGxlZ0lkcyA9IHNpZ25hbDxyZWFkb25seSBzdHJpbmdbXT4oW10pO1xuICAvKiogT3B0aW9ucyBmZXRjaGVkIGZvciBhIHBhcnRpYWwgbGVnIHNlbGVjdGlvbjsgYG51bGxgID0gdGhlIG9wdGlvbnMgbG9hZGVkIHdoZW4gdGhlIGRpYWxvZyBvcGVuZWQgKGFsbCBsZWdzKSBhcHBseS4gKi9cbiAgcHJpdmF0ZSBmcmVzaE9wdGlvbnMgPSBzaWduYWw8UmVpc3N1ZVVwZ3JhZGVPcHRpb25zUmVzcG9uc2UgfCBudWxsPihudWxsKTtcbiAgcHJpdmF0ZSBsZWdzU3RlcFNraXBwZWQgPSBzaWduYWwoZmFsc2UpO1xuXG4gIGNvbnN0cnVjdG9yKCkge1xuICAgIC8vIEEgZnJlc2ggb3B0aW9ucyByZXNwb25zZSAobmV3IGRpYWxvZyB2aXNpdCAvIHJldHJ5KSBzdGFydHMgdGhlIGZsb3cgb3Zlci5cbiAgICBlZmZlY3QoXG4gICAgICAoKSA9PiB7XG4gICAgICAgIHRoaXMubWFpbi51cGdyYWRlT3B0aW9ucygpO1xuICAgICAgICB1bnRyYWNrZWQoKCkgPT4gdGhpcy5yZXNldCgpKTtcbiAgICAgIH0sXG4gICAgICB7IGFsbG93U2lnbmFsV3JpdGVzOiB0cnVlIH0sXG4gICAgKTtcbiAgfVxuXG4gIC8vIOKUgOKUgCBkZXJpdmVkIOKUgOKUgOKUgOKUgOKUgOKUgOKUgOKUgOKUgOKUgOKUgOKUgOKUgOKUgOKUgOKUgOKUgOKUgOKUgOKUgOKUgOKUgOKUgOKUgOKUgOKUgOKUgOKUgOKUgOKUgOKUgOKUgOKUgOKUgOKUgOKUgOKUgOKUgOKUgOKUgOKUgOKUgOKUgOKUgOKUgOKUgOKUgOKUgOKUgOKUgOKUgOKUgOKUgOKUgOKUgOKUgOKUgOKUgOKUgOKUgOKUgOKUgOKUgFxuICByZWFkb25seSBjdXJyZW5jeSA9IGNvbXB1dGVkKCgpID0+IHRoaXMubWFpbi5jdHgoKT8uY3VycmVuY3kgPz8gJycpO1xuXG4gIC8qKiBUaGUgb3B0aW9ucyB0byBzaG93OiBmb3IgYSBwYXJ0aWFsIGxlZyBzZWxlY3Rpb24gdGhlIGZyZXNoIHJlc3BvbnNlLCBvdGhlcndpc2UgdGhlIG9uZSBsb2FkZWQgd2l0aCB0aGUgZGlhbG9nLiAqL1xuICBwcml2YXRlIG9wdGlvbnMgPSBjb21wdXRlZCgoKSA9PiB0aGlzLmZyZXNoT3B0aW9ucygpID8/IHRoaXMubWFpbi51cGdyYWRlT3B0aW9ucygpKTtcblxuICAvLyDilIDilIAgbGVnIHNlbGVjdGlvbiDilIDilIDilIDilIDilIDilIDilIDilIDilIDilIDilIDilIDilIDilIDilIDilIDilIDilIDilIDilIDilIDilIDilIDilIDilIDilIDilIDilIDilIDilIDilIDilIDilIDilIDilIDilIDilIDilIDilIDilIDilIDilIDilIDilIDilIDilIDilIDilIDilIDilIDilIDilIDilIDilIDilIDilIDilIBcblxuICAvKiogQSBsZWcgY2FuIGJlIHVwZ3JhZGVkIG9ubHkgaWYgaXQgaXMgb25saW5lIEFORCBoYXMgdXBncmFkZSBvcHRpb25zIChwZXIgbGVnIGZvciBsZWcgc2NvcGU7IGJvb2tpbmcgc2NvcGUgYXBwbGllcyB0byBhbGwpLiAqL1xuICBwcml2YXRlIGxlZ1VwZ3JhZGFibGUobGVnSWQ6IHN0cmluZywgaW5kZXg6IG51bWJlcik6IGJvb2xlYW4ge1xuICAgIGlmICghdGhpcy5tYWluLmlzTGVnT25saW5lKGxlZ0lkKSkgcmV0dXJuIGZhbHNlO1xuICAgIGNvbnN0IGRhdGEgPSB0aGlzLm1haW4udXBncmFkZU9wdGlvbnMoKTtcbiAgICBpZiAoIWRhdGEpIHJldHVybiBmYWxzZTtcbiAgICBpZiAoZGF0YS5mYXJlT3B0aW9uU2NvcGUgPT09ICdsZWcnKSB7XG4gICAgICByZXR1cm4gKGRhdGEubGVncz8uZmluZChsID0+IGwubGVnSW5kZXggPT09IGluZGV4KT8ub3B0aW9ucz8ubGVuZ3RoID8/IDApID4gMDtcbiAgICB9XG4gICAgcmV0dXJuIChkYXRhLm9wdGlvbnM/Lmxlbmd0aCA/PyAwKSA+IDA7XG4gIH1cblxuICByZWFkb25seSBsZWdSb3dzID0gY29tcHV0ZWQ8UmVpc3N1ZUxlZ1Jvd1tdPigoKSA9PiB7XG4gICAgY29uc3QgY2hvc2VuID0gbmV3IFNldCh0aGlzLmxlZ0lkcygpKTtcbiAgICByZXR1cm4gdGhpcy5tYWluXG4gICAgICAubGVncygpXG4gICAgICAubWFwKChsZWcsIGkpID0+XG4gICAgICAgIGJ1aWxkTGVnUm93KGxlZywgdGhpcy5sZWdVcGdyYWRhYmxlKGxlZy5sZWdJZCwgaSksIGNob3Nlbi5oYXMobGVnLmxlZ0lkKSwgdGhpcy5tYWluLmlzTGVnT25saW5lKGxlZy5sZWdJZCkgPyAnbm8tb3B0aW9ucycgOiAnb2ZmbGluZScpLFxuICAgICAgKTtcbiAgfSk7XG4gIHJlYWRvbmx5IGFueUxlZ1VwZ3JhZGFibGUgPSBjb21wdXRlZCgoKSA9PiB0aGlzLmxlZ1Jvd3MoKS5zb21lKHIgPT4gci5hdmFpbGFibGUpKTtcbiAgcmVhZG9ubHkgY2FuQ29udGludWVGcm9tTGVncyA9IGNvbXB1dGVkKCgpID0+IHRoaXMubGVnSWRzKCkubGVuZ3RoID4gMCAmJiAhdGhpcy5zdWJtaXR0aW5nKCkpO1xuXG4gIC8qKiBMZWdzIHRoZSBvcHRpb25zIG9uIHNjcmVlbiB3ZXJlIHJlcXVlc3RlZCBmb3IgKGFsbCBvZiB0aGVtLCBvciBqdXN0IHRoZSBzZWxlY3RlZCBvbmVzIGFmdGVyIGEgcGFydGlhbCBmZXRjaCkuICovXG4gIHByaXZhdGUgb3B0aW9uTGVncyA9IGNvbXB1dGVkKCgpID0+IHtcbiAgICBjb25zdCBhbGwgPSB0aGlzLm1haW4ubGVncygpO1xuICAgIHJldHVybiB0aGlzLmZyZXNoT3B0aW9ucygpID8gYWxsLmZpbHRlcihsID0+IHRoaXMubGVnSWRzKCkuaW5jbHVkZXMobC5sZWdJZCkpIDogYWxsO1xuICB9KTtcblxuICBwcml2YXRlIHJhd1NlY3Rpb25zID0gY29tcHV0ZWQ8UmF3U2VjdGlvbltdPigoKSA9PiB7XG4gICAgY29uc3QgZGF0YSA9IHRoaXMub3B0aW9ucygpO1xuICAgIGlmICghZGF0YSkgcmV0dXJuIFtdO1xuXG4gICAgaWYgKGRhdGEuZmFyZU9wdGlvblNjb3BlID09PSAnbGVnJykge1xuICAgICAgcmV0dXJuIChkYXRhLmxlZ3MgPz8gW10pLm1hcChsZWcgPT4gKHtcbiAgICAgICAgaWQ6IFN0cmluZyhsZWcubGVnSW5kZXgpLFxuICAgICAgICB0aXRsZTogcm91dGVPZih7IG9yaWdpbjogbGVnLm9yaWdpbiA/PyBsZWcuZXhpc3RpbmdMZWcub3JpZ2luLCBkZXN0aW5hdGlvbjogbGVnLmRlc3RpbmF0aW9uID8/IGxlZy5leGlzdGluZ0xlZy5kZXN0aW5hdGlvbiB9KSxcbiAgICAgICAgY3VycmVudDogY3VycmVudE9mKGxlZy5leGlzdGluZ0xlZyksXG4gICAgICAgIG9wdGlvbnM6IGxlZy5vcHRpb25zID8/IFtdLFxuICAgICAgfSkpO1xuICAgIH1cbiAgICBjb25zdCBvcmlnaW5hbHMgPSBkYXRhLmV4aXN0aW5nTGVncyA/PyBkYXRhLm9yaWdpbmFsTGVncyA/PyBbXTtcbiAgICByZXR1cm4gW1xuICAgICAge1xuICAgICAgICBpZDogJ2Jvb2tpbmcnLFxuICAgICAgICB0aXRsZTogb3JpZ2luYWxzLm1hcChyb3V0ZU9mKS5qb2luKCcgwrcgJykgfHwgJ1dob2xlIGJvb2tpbmcnLFxuICAgICAgICBjdXJyZW50OiBjdXJyZW50T2Yob3JpZ2luYWxzWzBdKSxcbiAgICAgICAgb3B0aW9uczogZGF0YS5vcHRpb25zID8/IFtdLFxuICAgICAgfSxcbiAgICBdO1xuICB9KTtcblxuICByZWFkb25seSBzZWN0aW9ucyA9IGNvbXB1dGVkPFVwZ3JhZGVTZWN0aW9uUm93W10+KCgpID0+IHtcbiAgICBjb25zdCBzZWxlY3RlZCA9IHRoaXMuc2VsZWN0ZWQoKTtcbiAgICBjb25zdCB1bmF2YWlsYWJsZSA9IHRoaXMudW5hdmFpbGFibGVLZXlzKCk7XG4gICAgY29uc3QgY3VycmVuY3kgPSB0aGlzLmN1cnJlbmN5KCk7XG4gICAgcmV0dXJuIHRoaXMucmF3U2VjdGlvbnMoKS5tYXAocyA9PiAoe1xuICAgICAgaWQ6IHMuaWQsXG4gICAgICB0aXRsZTogcy50aXRsZSxcbiAgICAgIGN1cnJlbnQ6IHMuY3VycmVudCxcbiAgICAgIG9wdGlvbnM6IHMub3B0aW9ucy5tYXAobyA9PiB7XG4gICAgICAgIGNvbnN0IGV4dHJhID0gZXh0cmFPZihvKTtcbiAgICAgICAgcmV0dXJuIHtcbiAgICAgICAgICBrZXk6IG8ucmVmZXJlbmNlS2V5LFxuICAgICAgICAgIG5hbWU6IG8ubmFtZSxcbiAgICAgICAgICBjb2RlOiBvLmNvZGUsXG4gICAgICAgICAgZXh0cmFMYWJlbDogZXh0cmEgPiAwID8gYCske2Zvcm1hdE1vbmV5KGV4dHJhLCBjdXJyZW5jeSl9YCA6ICdObyBleHRyYSBjb3N0JyxcbiAgICAgICAgICBzZWxlY3RlZDogc2VsZWN0ZWRbcy5pZF0gPT09IG8ucmVmZXJlbmNlS2V5LFxuICAgICAgICAgIHVuYXZhaWxhYmxlOiB1bmF2YWlsYWJsZS5oYXMoby5yZWZlcmVuY2VLZXkpLFxuICAgICAgICB9O1xuICAgICAgfSksXG4gICAgfSkpO1xuICB9KTtcblxuICBwcml2YXRlIHBpY2tzID0gY29tcHV0ZWQ8VXBncmFkZVBpY2tbXT4oKCkgPT4ge1xuICAgIGNvbnN0IHNlbGVjdGVkID0gdGhpcy5zZWxlY3RlZCgpO1xuICAgIHJldHVybiB0aGlzLnJhd1NlY3Rpb25zKCkuZmxhdE1hcChzZWN0aW9uID0+IHtcbiAgICAgIGNvbnN0IG9wdGlvbiA9IHNlY3Rpb24ub3B0aW9ucy5maW5kKG8gPT4gby5yZWZlcmVuY2VLZXkgPT09IHNlbGVjdGVkW3NlY3Rpb24uaWRdKTtcbiAgICAgIHJldHVybiBvcHRpb24gPyBbeyBzZWN0aW9uLCBvcHRpb24gfV0gOiBbXTtcbiAgICB9KTtcbiAgfSk7XG5cbiAgcmVhZG9ubHkgY2FuQ29udGludWUgPSBjb21wdXRlZCgoKSA9PiB0aGlzLnBpY2tzKCkubGVuZ3RoID4gMCAmJiAhdGhpcy5zdWJtaXR0aW5nKCkpO1xuXG4gIC8qKlxuICAgKiBBbW91bnQgdG8gcGF5OiB0aGUgc3VtIG9mIHRoZSBwaWNrZWQgb3B0aW9ucycgYWRkaXRpb25hbCBmYXJlIChzYW1lIGFzIHRoZSB3ZWIncyBgZ2V0VG90YWxUb1BheWApLlxuICAgKiBjaG9vc2UtZmxpZ2h0J3Mgb3duIGBwcmljZWAgaXMgZGVsaWJlcmF0ZWx5IG5vdCB1c2VkIOKAlCBpdCBpcyBub3Qga25vd24gd2hldGhlciBpdCBpcyB0aGUgZGlmZmVyZW5jZSBvciB0aGUgZnVsbCBmYXJlLlxuICAgKi9cbiAgcmVhZG9ubHkgdG90YWwgPSBjb21wdXRlZCgoKSA9PiB0aGlzLnBpY2tzKCkucmVkdWNlKChzdW0sIHApID0+IHN1bSArIGV4dHJhT2YocC5vcHRpb24pLCAwKSk7XG4gIHJlYWRvbmx5IHRvdGFsTGFiZWwgPSBjb21wdXRlZCgoKSA9PiAodGhpcy50b3RhbCgpID4gMCA/IGZvcm1hdE1vbmV5KHRoaXMudG90YWwoKSwgdGhpcy5jdXJyZW5jeSgpKSA6ICdOb3RoaW5nIHRvIHBheScpKTtcblxuICByZWFkb25seSBzdW1tYXJ5ID0gY29tcHV0ZWQ8VXBncmFkZVN1bW1hcnlSb3dbXT4oKCkgPT5cbiAgICB0aGlzLnBpY2tzKCkubWFwKCh7IHNlY3Rpb24sIG9wdGlvbiB9KSA9PiAoe1xuICAgICAgdGl0bGU6IHNlY3Rpb24udGl0bGUsXG4gICAgICBmcm9tOiBzZWN0aW9uLmN1cnJlbnQucmVwbGFjZSgvXkN1cnJlbnQ6XFxzKi8sICcnKSxcbiAgICAgIHRvOiBvcHRpb24ubmFtZSxcbiAgICAgIGV4dHJhTGFiZWw6IGV4dHJhT2Yob3B0aW9uKSA+IDAgPyBgKyR7Zm9ybWF0TW9uZXkoZXh0cmFPZihvcHRpb24pLCB0aGlzLmN1cnJlbmN5KCkpfWAgOiAnTm8gZXh0cmEgY29zdCcsXG4gICAgfSkpLFxuICApO1xuXG4gIHJlYWRvbmx5IGFjdGlvbiA9IGNvbXB1dGVkPFVwZ3JhZGVBY3Rpb24+KCgpID0+IHtcbiAgICBpZiAodGhpcy5ib29rZWQoKSB8fCB0aGlzLnBheW1lbnRMaW5rKCkpIHJldHVybiAnZG9uZSc7XG4gICAgcmV0dXJuIHRoaXMudG90YWwoKSA+IDAgPyAnbGluaycgOiAnYm9vayc7XG4gIH0pO1xuXG4gIC8qKiBOb3RoaW5nIGNhbiBiZSBjaGFuZ2VkIGFueSBtb3JlIG9uY2UgdGhlIHVwZ3JhZGUgaXMgcGxhY2VkIG9yIGEgbGluayB3YXMgZ2VuZXJhdGVkLiAqL1xuICByZWFkb25seSBsb2NrZWQgPSBjb21wdXRlZCgoKSA9PiB0aGlzLmJvb2tlZCgpIHx8ICEhdGhpcy5wYXltZW50TGluaygpIHx8IHRoaXMuc3VibWl0dGluZygpKTtcblxuICAvLyDilIDilIAgYWN0aW9ucyDilIDilIDilIDilIDilIDilIDilIDilIDilIDilIDilIDilIDilIDilIDilIDilIDilIDilIDilIDilIDilIDilIDilIDilIDilIDilIDilIDilIDilIDilIDilIDilIDilIDilIDilIDilIDilIDilIDilIDilIDilIDilIDilIDilIDilIDilIDilIDilIDilIDilIDilIDilIDilIDilIDilIDilIDilIDilIDilIDilIDilIDilIDilIBcblxuICAvKipcbiAgICogU2VydmljZSBwaWNrZWQ6IGdvIHRvIFwic2VsZWN0IGxlZ1wiLCB1bmxlc3MgdGhlcmUgaXMgbm90aGluZyB0byBjaG9vc2UgKG9uZS13YXkgd2l0aCBpdHMgb25seSBsZWcgdXBncmFkYWJsZSksXG4gICAqIHdoaWNoIGdvZXMgc3RyYWlnaHQgdG8gdGhlIG9wdGlvbnMgbGlrZSB0aGUgd2ViLlxuICAgKi9cbiAgc3RhcnQoKTogdm9pZCB7XG4gICAgaWYgKHRoaXMubWFpbi5sb2FkaW5nKCkgfHwgdGhpcy5tYWluLmVycm9yKCkpIHJldHVybjtcbiAgICB0aGlzLm1haW4uc2VydmljZS5zZXQoJ3VwZ3JhZGVfY2xhc3MnKTtcbiAgICB0aGlzLmZyZXNoT3B0aW9ucy5zZXQobnVsbCk7XG4gICAgdGhpcy5zZWxlY3RlZC5zZXQoe30pO1xuICAgIHRoaXMuZXJyb3Iuc2V0KG51bGwpO1xuXG4gICAgY29uc3QgdXBncmFkYWJsZSA9IHRoaXMubGVnUm93cygpLmZpbHRlcihyID0+IHIuYXZhaWxhYmxlKTtcbiAgICBpZiAodGhpcy5sZWdSb3dzKCkubGVuZ3RoID09PSAxICYmIHVwZ3JhZGFibGUubGVuZ3RoID09PSAxKSB7XG4gICAgICB0aGlzLmxlZ0lkcy5zZXQoW3VwZ3JhZGFibGVbMF0ubGVnLmxlZ0lkXSk7XG4gICAgICB0aGlzLmxlZ3NTdGVwU2tpcHBlZC5zZXQodHJ1ZSk7XG4gICAgICB0aGlzLm1haW4uZ29UbygndXBncmFkZScpO1xuICAgICAgcmV0dXJuO1xuICAgIH1cbiAgICB0aGlzLmxlZ3NTdGVwU2tpcHBlZC5zZXQoZmFsc2UpO1xuICAgIC8vIFwiVXBncmFkZSBhcyBhIHdob2xlXCIgYm9va2luZ3M6IGV2ZXJ5IHVwZ3JhZGFibGUgbGVnIGlzIHByZXNlbGVjdGVkIGFuZCBjYW5ub3QgYmUgdW50aWNrZWQuXG4gICAgdGhpcy5sZWdJZHMuc2V0KHRoaXMubWFpbi5hbGxvd1NpbmdsZUxlZ1NlbGVjdGlvbigpID8gW10gOiB1cGdyYWRhYmxlLm1hcChyID0+IHIubGVnLmxlZ0lkKSk7XG4gICAgdGhpcy5tYWluLmdvVG8oJ3VwZ3JhZGUtbGVncycpO1xuICB9XG5cbiAgdG9nZ2xlTGVnKGxlZ0lkOiBzdHJpbmcpOiB2b2lkIHtcbiAgICBjb25zdCByb3cgPSB0aGlzLmxlZ1Jvd3MoKS5maW5kKHIgPT4gci5sZWcubGVnSWQgPT09IGxlZ0lkKTtcbiAgICBpZiAoIXJvdz8uYXZhaWxhYmxlIHx8ICF0aGlzLm1haW4uYWxsb3dTaW5nbGVMZWdTZWxlY3Rpb24oKSkgcmV0dXJuO1xuICAgIHRoaXMuZXJyb3Iuc2V0KG51bGwpO1xuICAgIHRoaXMubGVnSWRzLnVwZGF0ZShpZHMgPT4gKGlkcy5pbmNsdWRlcyhsZWdJZCkgPyBpZHMuZmlsdGVyKGkgPT4gaSAhPT0gbGVnSWQpIDogWy4uLmlkcywgbGVnSWRdKSk7XG4gIH1cblxuICAvKipcbiAgICogU2VsZWN0IGxlZyAtPiBvcHRpb25zLiBBbGwgbGVncyBzZWxlY3RlZDogcmV1c2UgdGhlIG9wdGlvbnMgbG9hZGVkIHdpdGggdGhlIGRpYWxvZy4gQSBzdWJzZXQ6IGZldGNoIHRoZSBvcHRpb25zXG4gICAqIGFnYWluIGZvciBqdXN0IHRob3NlIGxlZ3MgKHRoZSBlYXJsaWVyIHJlc3BvbnNlIGNvdmVycyB0aGUgd2hvbGUgYm9va2luZywgc28gaXQgd291bGQgcHJpY2UgdGhlIHdyb25nIGxlZ3MpLlxuICAgKi9cbiAgY29udGludWVGcm9tTGVncygpOiB2b2lkIHtcbiAgICBjb25zdCBjdHggPSB0aGlzLm1haW4uY3R4KCk7XG4gICAgY29uc3QgY2hvc2VuID0gdGhpcy5tYWluLmxlZ3MoKS5maWx0ZXIobCA9PiB0aGlzLmxlZ0lkcygpLmluY2x1ZGVzKGwubGVnSWQpKTtcbiAgICBpZiAoIWN0eCB8fCAhY2hvc2VuLmxlbmd0aCB8fCAhdGhpcy5jYW5Db250aW51ZUZyb21MZWdzKCkpIHJldHVybjtcblxuICAgIHRoaXMuc2VsZWN0ZWQuc2V0KHt9KTtcbiAgICB0aGlzLnVuYXZhaWxhYmxlS2V5cy5zZXQobmV3IFNldCgpKTtcbiAgICBpZiAoY2hvc2VuLmxlbmd0aCA9PT0gdGhpcy5tYWluLmxlZ3MoKS5sZW5ndGgpIHtcbiAgICAgIHRoaXMuZnJlc2hPcHRpb25zLnNldChudWxsKTtcbiAgICAgIHRoaXMubWFpbi5nb1RvKCd1cGdyYWRlJyk7XG4gICAgICByZXR1cm47XG4gICAgfVxuXG4gICAgdGhpcy5zdWJtaXR0aW5nLnNldCh0cnVlKTtcbiAgICB0aGlzLmVycm9yLnNldChudWxsKTtcbiAgICB0aGlzLmFwaVxuICAgICAgLmdldFVwZ3JhZGVDbGFzc09wdGlvbnMoY3R4LmJvb2tpbmdJZCwgdGhpcy5tYWluLnBvc3RCb29raW5nSWQoKSwgeyAuLi5jdHgsIGxlZ3M6IGNob3NlbiB9KVxuICAgICAgLnBpcGUoXG4gICAgICAgIGZpbmFsaXplKCgpID0+IHRoaXMuc3VibWl0dGluZy5zZXQoZmFsc2UpKSxcbiAgICAgICAgdGFrZVVudGlsRGVzdHJveWVkKHRoaXMuZGVzdHJveVJlZiksXG4gICAgICApXG4gICAgICAuc3Vic2NyaWJlKHtcbiAgICAgICAgbmV4dDogZGF0YSA9PiB7XG4gICAgICAgICAgaWYgKCF0aGlzLmFwaS5oYXNVcGdyYWRlT3B0aW9ucyhkYXRhKSkge1xuICAgICAgICAgICAgdGhpcy5lcnJvci5zZXQoJ05vIHVwZ3JhZGUgaXMgYXZhaWxhYmxlIGZvciB0aGUgc2VsZWN0ZWQgZmxpZ2h0KHMpLicpO1xuICAgICAgICAgICAgcmV0dXJuO1xuICAgICAgICAgIH1cbiAgICAgICAgICB0aGlzLmZyZXNoT3B0aW9ucy5zZXQoZGF0YSk7XG4gICAgICAgICAgdGhpcy5tYWluLmdvVG8oJ3VwZ3JhZGUnKTtcbiAgICAgICAgfSxcbiAgICAgICAgZXJyb3I6ICgpID0+IHRoaXMuZXJyb3Iuc2V0KCdDb3VsZCBub3QgbG9hZCB0aGUgdXBncmFkZSBvcHRpb25zIGZvciB0aGUgc2VsZWN0ZWQgZmxpZ2h0KHMpLicpLFxuICAgICAgfSk7XG4gIH1cblxuICAvKiogQmFjayBmcm9tIHRoZSBvcHRpb25zOiB0byBcInNlbGVjdCBsZWdcIiB3aGVuIHRoYXQgc3RlcCB3YXMgc2hvd24sIG90aGVyd2lzZSB0byB0aGUgc2VydmljZSBsaXN0LiAqL1xuICBiYWNrKCk6IHZvaWQge1xuICAgIHRoaXMubWFpbi5nb1RvKHRoaXMubGVnc1N0ZXBTa2lwcGVkKCkgPyAnc2VydmljZScgOiAndXBncmFkZS1sZWdzJyk7XG4gIH1cblxuICBzZWxlY3Qoc2VjdGlvbklkOiBzdHJpbmcsIGtleTogc3RyaW5nKTogdm9pZCB7XG4gICAgaWYgKHRoaXMudW5hdmFpbGFibGVLZXlzKCkuaGFzKGtleSkpIHJldHVybjtcbiAgICB0aGlzLmVycm9yLnNldChudWxsKTtcbiAgICB0aGlzLnNlbGVjdGVkLnVwZGF0ZShzID0+ICh7IC4uLnMsIFtzZWN0aW9uSWRdOiBrZXkgfSkpO1xuICB9XG5cbiAgLyoqIE9wdGlvbnMgLT4gY29uZmlybTogcHJpY2VzIHRoZSBwaWNrKHMpIHdpdGggY2hvb3NlLWZsaWdodCAoc2FtZSBib2R5IHRoZSB3ZWIgc2VuZHMpLiAqL1xuICBjb250aW51ZSgpOiB2b2lkIHtcbiAgICBjb25zdCBjdHggPSB0aGlzLm1haW4uY3R4KCk7XG4gICAgY29uc3QgcGlja3MgPSB0aGlzLnBpY2tzKCk7XG4gICAgaWYgKCFjdHggfHwgIXBpY2tzLmxlbmd0aCB8fCAhdGhpcy5jYW5Db250aW51ZSgpKSByZXR1cm47XG5cbiAgICB0aGlzLnN1Ym1pdHRpbmcuc2V0KHRydWUpO1xuICAgIHRoaXMuZXJyb3Iuc2V0KG51bGwpO1xuICAgIHRoaXMuYXBpXG4gICAgICAuY2hvb3NlRmxpZ2h0KGN0eC5ib29raW5nSWQsIHRoaXMubWFpbi5wb3N0Qm9va2luZ0lkKCksIHRoaXMuY2hvb3NlQm9keShwaWNrcykpXG4gICAgICAucGlwZShcbiAgICAgICAgZmluYWxpemUoKCkgPT4gdGhpcy5zdWJtaXR0aW5nLnNldChmYWxzZSkpLFxuICAgICAgICB0YWtlVW50aWxEZXN0cm95ZWQodGhpcy5kZXN0cm95UmVmKSxcbiAgICAgIClcbiAgICAgIC5zdWJzY3JpYmUoe1xuICAgICAgICBuZXh0OiByZXMgPT4ge1xuICAgICAgICAgIGlmIChyZXM/Lml0aW5lcmFyeUF2YWlsYWJsZSA9PT0gZmFsc2UpIHtcbiAgICAgICAgICAgIHRoaXMudW5hdmFpbGFibGVLZXlzLnVwZGF0ZShrZXlzID0+IG5ldyBTZXQoWy4uLmtleXMsIC4uLnBpY2tzLm1hcChwID0+IHAub3B0aW9uLnJlZmVyZW5jZUtleSldKSk7XG4gICAgICAgICAgICB0aGlzLnNlbGVjdGVkLnNldCh7fSk7XG4gICAgICAgICAgICB0aGlzLmVycm9yLnNldCgnVGhpcyBvcHRpb24gaXMgbm8gbG9uZ2VyIGF2YWlsYWJsZS4gUGxlYXNlIGNob29zZSBhbm90aGVyIG9uZS4nKTtcbiAgICAgICAgICAgIHJldHVybjtcbiAgICAgICAgICB9XG4gICAgICAgICAgdGhpcy5wcmljZUNoYW5nZWQuc2V0KHJlcz8ucHJpY2VDaGFuZ2VkID09PSB0cnVlKTtcbiAgICAgICAgICB0aGlzLm1haW4uZ29UbygnY29uZmlybScpO1xuICAgICAgICB9LFxuICAgICAgICBlcnJvcjogKCkgPT4gdGhpcy5lcnJvci5zZXQoJ0NvdWxkIG5vdCBwcmljZSB0aGUgc2VsZWN0ZWQgdXBncmFkZS4gUGxlYXNlIHRyeSBhZ2Fpbi4nKSxcbiAgICAgIH0pO1xuICB9XG5cbiAgLyoqIENvbmZpcm0gc3RlcCBwcmltYXJ5IGFjdGlvbjogcGxhY2UgdGhlIGZyZWUgdXBncmFkZSwgb3IgZ2VuZXJhdGUgdGhlIHBheW1lbnQgbGluay4gKi9cbiAgY29uZmlybSgpOiB2b2lkIHtcbiAgICBjb25zdCBhY3Rpb24gPSB0aGlzLmFjdGlvbigpO1xuICAgIGlmIChhY3Rpb24gPT09ICdkb25lJyB8fCB0aGlzLnN1Ym1pdHRpbmcoKSkgcmV0dXJuO1xuICAgIGNvbnN0IHBvc3RCb29raW5nSWQgPSB0aGlzLm1haW4ucG9zdEJvb2tpbmdJZCgpO1xuXG4gICAgdGhpcy5zdWJtaXR0aW5nLnNldCh0cnVlKTtcbiAgICB0aGlzLmVycm9yLnNldChudWxsKTtcbiAgICBjb25zdCByZXF1ZXN0JCA9XG4gICAgICBhY3Rpb24gPT09ICdib29rJ1xuICAgICAgICA/IHRoaXMuYXBpLmJvb2tOb3cocG9zdEJvb2tpbmdJZClcbiAgICAgICAgOiB0aGlzLmFwaS5nZXRQYXltZW50TGluayhwb3N0Qm9va2luZ0lkLCB0aGlzLnRvdGFsKCksIHRoaXMuY3VycmVuY3koKSk7XG5cbiAgICByZXF1ZXN0JFxuICAgICAgLnBpcGUoXG4gICAgICAgIGZpbmFsaXplKCgpID0+IHRoaXMuc3VibWl0dGluZy5zZXQoZmFsc2UpKSxcbiAgICAgICAgdGFrZVVudGlsRGVzdHJveWVkKHRoaXMuZGVzdHJveVJlZiksXG4gICAgICApXG4gICAgICAuc3Vic2NyaWJlKHtcbiAgICAgICAgbmV4dDogcmVzID0+IHtcbiAgICAgICAgICAvLyBUaGUgZGlhbG9nIGRvZXMgbm90IGZvbGxvdyB0aGUgcmVzdWx0IChubyBjb25maXJtYXRpb24tc3RhdHVzKTogYWZ0ZXIgYGJvb2stbm93YCwgb3Igb25jZSB0aGUgbGluayBpc1xuICAgICAgICAgIC8vIHNlbnQsIHRoZSBhZ2VudCBmb2xsb3dzIHRoZSBib29raW5nIGZyb20gdGhlIGRhc2hib2FyZC5cbiAgICAgICAgICBpZiAoYWN0aW9uID09PSAnYm9vaycpIHRoaXMuYm9va2VkLnNldCh0cnVlKTtcbiAgICAgICAgICBlbHNlIHRoaXMucGF5bWVudExpbmsuc2V0KHJlcyBhcyBSZWlzc3VlUGF5bWVudExpbmspO1xuICAgICAgICB9LFxuICAgICAgICBlcnJvcjogKGVycjogdW5rbm93bikgPT5cbiAgICAgICAgICB0aGlzLmVycm9yLnNldChcbiAgICAgICAgICAgIGFjdGlvbiA9PT0gJ2Jvb2snXG4gICAgICAgICAgICAgID8gJ0NvdWxkIG5vdCBwbGFjZSB0aGUgdXBncmFkZS4gUGxlYXNlIHRyeSBhZ2Fpbi4nXG4gICAgICAgICAgICAgIDogZXJyIGluc3RhbmNlb2YgRXJyb3IgJiYgZXJyLm1lc3NhZ2Uuc3RhcnRzV2l0aCgnVGhlIGNhcnQgJylcbiAgICAgICAgICAgICAgICA/IGVyci5tZXNzYWdlXG4gICAgICAgICAgICAgICAgOiAnQ291bGQgbm90IGdldCB0aGUgcGF5bWVudCBsaW5rLiBQbGVhc2UgdHJ5IGFnYWluLicsXG4gICAgICAgICAgKSxcbiAgICAgIH0pO1xuICB9XG5cbiAgcHJpdmF0ZSByZXNldCgpOiB2b2lkIHtcbiAgICB0aGlzLnNlbGVjdGVkLnNldCh7fSk7XG4gICAgdGhpcy51bmF2YWlsYWJsZUtleXMuc2V0KG5ldyBTZXQoKSk7XG4gICAgdGhpcy5sZWdJZHMuc2V0KFtdKTtcbiAgICB0aGlzLmZyZXNoT3B0aW9ucy5zZXQobnVsbCk7XG4gICAgdGhpcy5sZWdzU3RlcFNraXBwZWQuc2V0KGZhbHNlKTtcbiAgICB0aGlzLnN1Ym1pdHRpbmcuc2V0KGZhbHNlKTtcbiAgICB0aGlzLmVycm9yLnNldChudWxsKTtcbiAgICB0aGlzLnByaWNlQ2hhbmdlZC5zZXQoZmFsc2UpO1xuICAgIHRoaXMuYm9va2VkLnNldChmYWxzZSk7XG4gICAgdGhpcy5wYXltZW50TGluay5zZXQobnVsbCk7XG4gIH1cblxuICAvKiogQm9va2luZyBzY29wZTogb25lIGl0aW5lcmFyeS4gTGVnIHNjb3BlOiBlYWNoIHBpY2tlZCBsZWcgYXMgb253YXJkTGVnIC8gcmV0dXJuTGVnIChieSB0aGUgcmVhbCBsZWcgZGlyZWN0aW9uKS4gKi9cbiAgcHJpdmF0ZSBjaG9vc2VCb2R5KHBpY2tzOiBVcGdyYWRlUGlja1tdKTogUmVpc3N1ZUNob29zZUZsaWdodFJlcXVlc3Qge1xuICAgIGNvbnN0IHNjb3BlID0gdGhpcy5vcHRpb25zKCk/LmZhcmVPcHRpb25TY29wZSA/PyAnYm9va2luZyc7XG4gICAgaWYgKHNjb3BlICE9PSAnbGVnJykgcmV0dXJuIHsgZmFyZU9wdGlvblNjb3BlOiAnYm9va2luZycsIEl0aW5lcmFyeUlkOiBwaWNrc1swXS5vcHRpb24ucmVmZXJlbmNlS2V5IH07XG5cbiAgICAvLyBBIHBhcnRpYWwgZmV0Y2ggcmUtaW5kZXhlcyB0aGUgc2VjdGlvbnMgZnJvbSAwLCBzbyByZXNvbHZlIHRoZSBkaXJlY3Rpb24gZnJvbSB0aGUgbGVncyB0aGUgb3B0aW9ucyB3ZXJlIHJlcXVlc3RlZCBmb3IuXG4gICAgY29uc3QgbGVncyA9IHRoaXMub3B0aW9uTGVncygpO1xuICAgIGNvbnN0IHRvTGVnID0gKHA/OiBVcGdyYWRlUGljaykgPT4gKHAgPyB7IGxlZ0lkOiBwLm9wdGlvbi5yZWZlcmVuY2VLZXksIHByb3ZpZGVyVHlwZTogcC5vcHRpb24ucHJvdmlkZXJUeXBlIH0gOiB1bmRlZmluZWQpO1xuICAgIGNvbnN0IGlzUmV0dXJuID0gKHA6IFVwZ3JhZGVQaWNrKSA9PiBsZWdzW051bWJlcihwLnNlY3Rpb24uaWQpXT8uZGlyZWN0aW9uID09PSAnUmV0dXJuJztcbiAgICByZXR1cm4ge1xuICAgICAgZmFyZU9wdGlvblNjb3BlOiAnbGVnJyxcbiAgICAgIG9ud2FyZExlZzogdG9MZWcocGlja3MuZmluZChwID0+ICFpc1JldHVybihwKSkpLFxuICAgICAgcmV0dXJuTGVnOiB0b0xlZyhwaWNrcy5maW5kKGlzUmV0dXJuKSksXG4gICAgfTtcbiAgfVxufVxuIl19