valtech-components 2.0.452 → 2.0.454

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 (48) hide show
  1. package/esm2022/lib/components/molecules/pin-input/pin-input.component.mjs +10 -2
  2. package/esm2022/lib/services/auth/auth-state.service.mjs +173 -0
  3. package/esm2022/lib/services/auth/auth.service.mjs +454 -0
  4. package/esm2022/lib/services/auth/config.mjs +76 -0
  5. package/esm2022/lib/services/auth/guards.mjs +194 -0
  6. package/esm2022/lib/services/auth/index.mjs +70 -0
  7. package/esm2022/lib/services/auth/interceptor.mjs +98 -0
  8. package/esm2022/lib/services/auth/storage.service.mjs +141 -0
  9. package/esm2022/lib/services/auth/sync.service.mjs +149 -0
  10. package/esm2022/lib/services/auth/token.service.mjs +113 -0
  11. package/esm2022/lib/services/auth/types.mjs +29 -0
  12. package/esm2022/lib/services/firebase/config.mjs +108 -0
  13. package/esm2022/lib/services/firebase/firebase.service.mjs +288 -0
  14. package/esm2022/lib/services/firebase/firestore-collection.mjs +254 -0
  15. package/esm2022/lib/services/firebase/firestore.service.mjs +509 -0
  16. package/esm2022/lib/services/firebase/index.mjs +49 -0
  17. package/esm2022/lib/services/firebase/messaging.service.mjs +512 -0
  18. package/esm2022/lib/services/firebase/shared-config.mjs +138 -0
  19. package/esm2022/lib/services/firebase/storage.service.mjs +422 -0
  20. package/esm2022/lib/services/firebase/types.mjs +8 -0
  21. package/esm2022/lib/services/firebase/utils/path-builder.mjs +195 -0
  22. package/esm2022/lib/services/firebase/utils/query-builder.mjs +302 -0
  23. package/esm2022/public-api.mjs +3 -5
  24. package/fesm2022/valtech-components.mjs +4204 -5
  25. package/fesm2022/valtech-components.mjs.map +1 -1
  26. package/lib/services/auth/auth-state.service.d.ts +85 -0
  27. package/lib/services/auth/auth.service.d.ts +146 -0
  28. package/lib/services/auth/config.d.ts +38 -0
  29. package/lib/services/auth/guards.d.ts +123 -0
  30. package/lib/services/auth/index.d.ts +63 -0
  31. package/lib/services/auth/interceptor.d.ts +22 -0
  32. package/lib/services/auth/storage.service.d.ts +48 -0
  33. package/lib/services/auth/sync.service.d.ts +49 -0
  34. package/lib/services/auth/token.service.d.ts +51 -0
  35. package/lib/services/auth/types.d.ts +315 -0
  36. package/lib/services/firebase/config.d.ts +49 -0
  37. package/lib/services/firebase/firebase.service.d.ts +140 -0
  38. package/lib/services/firebase/firestore-collection.d.ts +175 -0
  39. package/lib/services/firebase/firestore.service.d.ts +304 -0
  40. package/lib/services/firebase/index.d.ts +39 -0
  41. package/lib/services/firebase/messaging.service.d.ts +263 -0
  42. package/lib/services/firebase/shared-config.d.ts +126 -0
  43. package/lib/services/firebase/storage.service.d.ts +206 -0
  44. package/lib/services/firebase/types.d.ts +281 -0
  45. package/lib/services/firebase/utils/path-builder.d.ts +132 -0
  46. package/lib/services/firebase/utils/query-builder.d.ts +210 -0
  47. package/package.json +1 -1
  48. package/public-api.d.ts +2 -0
@@ -0,0 +1,512 @@
1
+ /**
2
+ * Messaging Service (FCM)
3
+ *
4
+ * Servicio para Firebase Cloud Messaging (Push Notifications).
5
+ * Permite solicitar permisos, obtener tokens, escuchar mensajes y manejar
6
+ * navegación (deep linking) cuando el usuario toca una notificación.
7
+ */
8
+ import { Inject, Injectable, Optional, PLATFORM_ID } from '@angular/core';
9
+ import { isPlatformBrowser } from '@angular/common';
10
+ import { getToken, deleteToken, onMessage } from '@angular/fire/messaging';
11
+ import { Subject, BehaviorSubject } from 'rxjs';
12
+ import { VALTECH_FIREBASE_CONFIG } from './config';
13
+ import * as i0 from "@angular/core";
14
+ import * as i1 from "@angular/fire/messaging";
15
+ /**
16
+ * Servicio para Firebase Cloud Messaging (FCM).
17
+ *
18
+ * Permite recibir notificaciones push en la aplicación web.
19
+ * Requiere VAPID key configurada en ValtechFirebaseConfig.
20
+ *
21
+ * @example
22
+ * ```typescript
23
+ * @Component({...})
24
+ * export class NotificationComponent {
25
+ * private messaging = inject(MessagingService);
26
+ *
27
+ * token = signal<string | null>(null);
28
+ *
29
+ * async enableNotifications() {
30
+ * // Solicitar permiso y obtener token
31
+ * const token = await this.messaging.requestPermission();
32
+ *
33
+ * if (token) {
34
+ * this.token.set(token);
35
+ * // Enviar token a tu backend para almacenarlo
36
+ * await this.backend.registerDeviceToken(token);
37
+ * }
38
+ * }
39
+ *
40
+ * // Escuchar mensajes en foreground
41
+ * messages$ = this.messaging.onMessage();
42
+ * }
43
+ * ```
44
+ */
45
+ export class MessagingService {
46
+ constructor(messaging, config, platformId, ngZone) {
47
+ this.messaging = messaging;
48
+ this.config = config;
49
+ this.platformId = platformId;
50
+ this.ngZone = ngZone;
51
+ this.messageSubject = new Subject();
52
+ this.notificationClickSubject = new Subject();
53
+ this.stateSubject = new BehaviorSubject({
54
+ token: null,
55
+ permission: 'default',
56
+ isSupported: false,
57
+ });
58
+ this.initializeMessaging();
59
+ }
60
+ // ===========================================================================
61
+ // INICIALIZACIÓN
62
+ // ===========================================================================
63
+ /**
64
+ * Inicializa el servicio de messaging
65
+ */
66
+ async initializeMessaging() {
67
+ if (!isPlatformBrowser(this.platformId)) {
68
+ return;
69
+ }
70
+ const supported = await this.checkSupport();
71
+ const permission = this.getPermissionState();
72
+ this.stateSubject.next({
73
+ ...this.stateSubject.value,
74
+ isSupported: supported,
75
+ permission,
76
+ });
77
+ // Si ya tiene permiso, configurar listeners
78
+ if (supported && permission === 'granted') {
79
+ this.setupMessageListener();
80
+ }
81
+ // Escuchar mensajes del Service Worker (clicks en notificaciones background)
82
+ this.setupServiceWorkerListener();
83
+ }
84
+ /**
85
+ * Configura listener para mensajes del Service Worker.
86
+ * Recibe eventos cuando el usuario hace click en una notificación background.
87
+ */
88
+ setupServiceWorkerListener() {
89
+ if (!isPlatformBrowser(this.platformId) || !('serviceWorker' in navigator)) {
90
+ return;
91
+ }
92
+ navigator.serviceWorker.addEventListener('message', (event) => {
93
+ // Verificar que es un mensaje de notificación click
94
+ if (event.data?.type === 'NOTIFICATION_CLICK') {
95
+ this.ngZone.run(() => {
96
+ const notification = event.data.notification;
97
+ const action = this.extractActionFromData(notification.data);
98
+ this.notificationClickSubject.next({
99
+ notification,
100
+ action,
101
+ timestamp: new Date(),
102
+ });
103
+ });
104
+ }
105
+ });
106
+ }
107
+ /**
108
+ * Verifica si FCM está soportado en el navegador actual
109
+ */
110
+ async checkSupport() {
111
+ if (!isPlatformBrowser(this.platformId)) {
112
+ return false;
113
+ }
114
+ // Verificar APIs necesarias
115
+ if (!('Notification' in window)) {
116
+ return false;
117
+ }
118
+ if (!('serviceWorker' in navigator)) {
119
+ return false;
120
+ }
121
+ // Verificar que messaging esté disponible
122
+ if (!this.messaging) {
123
+ return false;
124
+ }
125
+ return true;
126
+ }
127
+ // ===========================================================================
128
+ // PERMISOS Y TOKEN
129
+ // ===========================================================================
130
+ /**
131
+ * Solicita permiso de notificaciones y obtiene el token FCM.
132
+ *
133
+ * @returns Token FCM si se otorgó permiso, null si se denegó
134
+ *
135
+ * @example
136
+ * ```typescript
137
+ * const token = await messaging.requestPermission();
138
+ * if (token) {
139
+ * console.log('Token FCM:', token);
140
+ * // Enviar a backend
141
+ * } else {
142
+ * console.log('Permiso denegado o no soportado');
143
+ * }
144
+ * ```
145
+ */
146
+ async requestPermission() {
147
+ if (!await this.isSupported()) {
148
+ console.warn('FCM no está soportado en este navegador');
149
+ return null;
150
+ }
151
+ try {
152
+ // Solicitar permiso de notificaciones
153
+ const permission = await Notification.requestPermission();
154
+ this.stateSubject.next({
155
+ ...this.stateSubject.value,
156
+ permission: permission,
157
+ });
158
+ if (permission !== 'granted') {
159
+ console.warn('Permiso de notificaciones denegado');
160
+ return null;
161
+ }
162
+ // Obtener token FCM
163
+ const token = await this.getToken();
164
+ if (token) {
165
+ // Configurar listener de mensajes
166
+ this.setupMessageListener();
167
+ }
168
+ return token;
169
+ }
170
+ catch (error) {
171
+ console.error('Error solicitando permiso de notificaciones:', error);
172
+ return null;
173
+ }
174
+ }
175
+ /**
176
+ * Obtiene el token FCM actual (sin solicitar permiso).
177
+ *
178
+ * @returns Token FCM si está disponible, null si no
179
+ *
180
+ * @example
181
+ * ```typescript
182
+ * const token = await messaging.getToken();
183
+ * ```
184
+ */
185
+ async getToken() {
186
+ if (!this.messaging) {
187
+ return null;
188
+ }
189
+ const vapidKey = this.config.messagingVapidKey;
190
+ if (!vapidKey) {
191
+ console.warn('VAPID key no configurada. FCM no funcionará.');
192
+ return null;
193
+ }
194
+ try {
195
+ const token = await getToken(this.messaging, { vapidKey });
196
+ this.stateSubject.next({
197
+ ...this.stateSubject.value,
198
+ token,
199
+ });
200
+ return token;
201
+ }
202
+ catch (error) {
203
+ console.error('Error obteniendo token FCM:', error);
204
+ return null;
205
+ }
206
+ }
207
+ /**
208
+ * Elimina el token FCM actual (unsubscribe de notificaciones).
209
+ *
210
+ * @example
211
+ * ```typescript
212
+ * await messaging.deleteToken();
213
+ * console.log('Token eliminado, no recibirá más notificaciones');
214
+ * ```
215
+ */
216
+ async deleteToken() {
217
+ if (!this.messaging) {
218
+ return;
219
+ }
220
+ try {
221
+ await deleteToken(this.messaging);
222
+ this.stateSubject.next({
223
+ ...this.stateSubject.value,
224
+ token: null,
225
+ });
226
+ // Limpiar listener de mensajes
227
+ if (this.unsubscribeOnMessage) {
228
+ this.unsubscribeOnMessage();
229
+ this.unsubscribeOnMessage = undefined;
230
+ }
231
+ }
232
+ catch (error) {
233
+ console.error('Error eliminando token FCM:', error);
234
+ throw new Error('No se pudo eliminar el token de notificaciones');
235
+ }
236
+ }
237
+ // ===========================================================================
238
+ // MENSAJES
239
+ // ===========================================================================
240
+ /**
241
+ * Observable de mensajes recibidos en foreground.
242
+ *
243
+ * IMPORTANTE: Los mensajes en background son manejados por el Service Worker.
244
+ *
245
+ * @returns Observable que emite cuando llega un mensaje en foreground
246
+ *
247
+ * @example
248
+ * ```typescript
249
+ * messaging.onMessage().subscribe(payload => {
250
+ * console.log('Mensaje recibido:', payload);
251
+ * // Mostrar notificación custom o actualizar UI
252
+ * });
253
+ * ```
254
+ */
255
+ onMessage() {
256
+ return this.messageSubject.asObservable();
257
+ }
258
+ /**
259
+ * Configura el listener de mensajes en foreground
260
+ */
261
+ setupMessageListener() {
262
+ if (!this.messaging || this.unsubscribeOnMessage) {
263
+ return;
264
+ }
265
+ this.unsubscribeOnMessage = onMessage(this.messaging, (payload) => {
266
+ const notification = {
267
+ title: payload.notification?.title,
268
+ body: payload.notification?.body,
269
+ image: payload.notification?.image,
270
+ data: payload.data,
271
+ messageId: payload.messageId,
272
+ };
273
+ this.messageSubject.next(notification);
274
+ });
275
+ }
276
+ // ===========================================================================
277
+ // ESTADO Y UTILIDADES
278
+ // ===========================================================================
279
+ /**
280
+ * Obtiene el estado actual del permiso de notificaciones.
281
+ *
282
+ * @returns 'granted' | 'denied' | 'default'
283
+ *
284
+ * @example
285
+ * ```typescript
286
+ * const permission = messaging.getPermissionState();
287
+ * if (permission === 'granted') {
288
+ * // Ya tiene permiso
289
+ * } else if (permission === 'default') {
290
+ * // Puede solicitar permiso
291
+ * } else {
292
+ * // Denegado, debe habilitar manualmente
293
+ * }
294
+ * ```
295
+ */
296
+ getPermissionState() {
297
+ if (!isPlatformBrowser(this.platformId)) {
298
+ return 'default';
299
+ }
300
+ if (!('Notification' in window)) {
301
+ return 'denied';
302
+ }
303
+ return Notification.permission;
304
+ }
305
+ /**
306
+ * Verifica si FCM está soportado en el navegador actual.
307
+ *
308
+ * @returns true si FCM está soportado
309
+ *
310
+ * @example
311
+ * ```typescript
312
+ * if (await messaging.isSupported()) {
313
+ * // Puede usar notificaciones push
314
+ * } else {
315
+ * // Navegador no soporta o no tiene Service Worker
316
+ * }
317
+ * ```
318
+ */
319
+ async isSupported() {
320
+ return this.checkSupport();
321
+ }
322
+ /**
323
+ * Obtiene el token actual sin hacer request.
324
+ *
325
+ * @returns Token almacenado o null
326
+ */
327
+ get currentToken() {
328
+ return this.stateSubject.value.token;
329
+ }
330
+ /**
331
+ * Observable del estado completo del servicio de messaging.
332
+ */
333
+ get state$() {
334
+ return this.stateSubject.asObservable();
335
+ }
336
+ /**
337
+ * Verifica si el usuario ya otorgó permiso de notificaciones.
338
+ */
339
+ get hasPermission() {
340
+ return this.stateSubject.value.permission === 'granted';
341
+ }
342
+ // ===========================================================================
343
+ // DEEP LINKING / NAVEGACIÓN
344
+ // ===========================================================================
345
+ /**
346
+ * Observable de clicks en notificaciones.
347
+ *
348
+ * Emite cuando el usuario hace click en una notificación (foreground o background).
349
+ * Usa este observable para navegar a la página correspondiente.
350
+ *
351
+ * @returns Observable que emite NotificationClickEvent
352
+ *
353
+ * @example
354
+ * ```typescript
355
+ * @Component({...})
356
+ * export class AppComponent {
357
+ * private messaging = inject(MessagingService);
358
+ * private router = inject(Router);
359
+ *
360
+ * constructor() {
361
+ * this.messaging.onNotificationClick().subscribe(event => {
362
+ * if (event.action.route) {
363
+ * this.router.navigate([event.action.route], {
364
+ * queryParams: event.action.queryParams
365
+ * });
366
+ * }
367
+ * });
368
+ * }
369
+ * }
370
+ * ```
371
+ */
372
+ onNotificationClick() {
373
+ return this.notificationClickSubject.asObservable();
374
+ }
375
+ /**
376
+ * Extrae la acción de navegación de los datos de una notificación.
377
+ *
378
+ * Busca campos específicos en el payload de datos:
379
+ * - `route`: Ruta interna de la app (ej: '/orders/123')
380
+ * - `url`: URL externa (ej: 'https://example.com')
381
+ * - `action_type`: Tipo de acción personalizada
382
+ * - Campos con prefijo `action_`: Datos adicionales
383
+ *
384
+ * @param data - Datos del payload de la notificación
385
+ * @returns Acción de navegación extraída
386
+ *
387
+ * @example
388
+ * ```typescript
389
+ * // Payload desde el backend:
390
+ * // { route: '/orders/123', action_type: 'view_order', action_orderId: '123' }
391
+ *
392
+ * const action = messaging.extractActionFromData(notification.data);
393
+ * // { route: '/orders/123', actionType: 'view_order', actionData: { orderId: '123' } }
394
+ * ```
395
+ */
396
+ extractActionFromData(data) {
397
+ if (!data) {
398
+ return {};
399
+ }
400
+ const action = {};
401
+ // Ruta interna
402
+ if (data['route']) {
403
+ action.route = data['route'];
404
+ }
405
+ // URL externa
406
+ if (data['url']) {
407
+ action.url = data['url'];
408
+ }
409
+ // Tipo de acción
410
+ if (data['action_type']) {
411
+ action.actionType = data['action_type'];
412
+ }
413
+ // Query params (puede venir como JSON string)
414
+ if (data['query_params']) {
415
+ try {
416
+ action.queryParams = JSON.parse(data['query_params']);
417
+ }
418
+ catch {
419
+ // Si no es JSON válido, intentar parsear como key=value
420
+ action.queryParams = this.parseQueryString(data['query_params']);
421
+ }
422
+ }
423
+ // Datos adicionales con prefijo action_
424
+ const actionData = {};
425
+ for (const [key, value] of Object.entries(data)) {
426
+ if (key.startsWith('action_') && key !== 'action_type') {
427
+ const cleanKey = key.replace('action_', '');
428
+ // Intentar parsear JSON si es posible
429
+ try {
430
+ actionData[cleanKey] = JSON.parse(value);
431
+ }
432
+ catch {
433
+ actionData[cleanKey] = value;
434
+ }
435
+ }
436
+ }
437
+ if (Object.keys(actionData).length > 0) {
438
+ action.actionData = actionData;
439
+ }
440
+ return action;
441
+ }
442
+ /**
443
+ * Emite manualmente un evento de click en notificación.
444
+ *
445
+ * Útil para manejar clicks en notificaciones foreground donde
446
+ * la app decide mostrar un banner custom.
447
+ *
448
+ * @param notification - Payload de la notificación
449
+ *
450
+ * @example
451
+ * ```typescript
452
+ * messaging.onMessage().subscribe(notification => {
453
+ * // Mostrar banner custom
454
+ * this.showBanner(notification, () => {
455
+ * // Usuario hizo click en el banner
456
+ * messaging.handleNotificationClick(notification);
457
+ * });
458
+ * });
459
+ * ```
460
+ */
461
+ handleNotificationClick(notification) {
462
+ const action = this.extractActionFromData(notification.data);
463
+ this.notificationClickSubject.next({
464
+ notification,
465
+ action,
466
+ timestamp: new Date(),
467
+ });
468
+ }
469
+ /**
470
+ * Verifica si una notificación tiene acción de navegación.
471
+ *
472
+ * @param data - Datos del payload
473
+ * @returns true si tiene route o url
474
+ */
475
+ hasNavigationAction(data) {
476
+ if (!data)
477
+ return false;
478
+ return !!(data['route'] || data['url']);
479
+ }
480
+ /**
481
+ * Parsea un query string en un objeto.
482
+ */
483
+ parseQueryString(queryString) {
484
+ const params = {};
485
+ if (!queryString)
486
+ return params;
487
+ // Remover ? inicial si existe
488
+ const cleanQuery = queryString.startsWith('?') ? queryString.slice(1) : queryString;
489
+ for (const pair of cleanQuery.split('&')) {
490
+ const [key, value] = pair.split('=');
491
+ if (key) {
492
+ params[decodeURIComponent(key)] = decodeURIComponent(value || '');
493
+ }
494
+ }
495
+ return params;
496
+ }
497
+ static { this.ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "18.2.14", ngImport: i0, type: MessagingService, deps: [{ token: i1.Messaging, optional: true }, { token: VALTECH_FIREBASE_CONFIG }, { token: PLATFORM_ID }, { token: i0.NgZone }], target: i0.ɵɵFactoryTarget.Injectable }); }
498
+ static { this.ɵprov = i0.ɵɵngDeclareInjectable({ minVersion: "12.0.0", version: "18.2.14", ngImport: i0, type: MessagingService, providedIn: 'root' }); }
499
+ }
500
+ i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "18.2.14", ngImport: i0, type: MessagingService, decorators: [{
501
+ type: Injectable,
502
+ args: [{ providedIn: 'root' }]
503
+ }], ctorParameters: () => [{ type: i1.Messaging, decorators: [{
504
+ type: Optional
505
+ }] }, { type: undefined, decorators: [{
506
+ type: Inject,
507
+ args: [VALTECH_FIREBASE_CONFIG]
508
+ }] }, { type: Object, decorators: [{
509
+ type: Inject,
510
+ args: [PLATFORM_ID]
511
+ }] }, { type: i0.NgZone }] });
512
+ //# sourceMappingURL=data:application/json;base64,eyJ2ZXJzaW9uIjozLCJmaWxlIjoibWVzc2FnaW5nLnNlcnZpY2UuanMiLCJzb3VyY2VSb290IjoiIiwic291cmNlcyI6WyIuLi8uLi8uLi8uLi8uLi8uLi9zcmMvbGliL3NlcnZpY2VzL2ZpcmViYXNlL21lc3NhZ2luZy5zZXJ2aWNlLnRzIl0sIm5hbWVzIjpbXSwibWFwcGluZ3MiOiJBQUFBOzs7Ozs7R0FNRztBQUVILE9BQU8sRUFBRSxNQUFNLEVBQUUsVUFBVSxFQUFVLFFBQVEsRUFBRSxXQUFXLEVBQUUsTUFBTSxlQUFlLENBQUM7QUFDbEYsT0FBTyxFQUFFLGlCQUFpQixFQUFFLE1BQU0saUJBQWlCLENBQUM7QUFDcEQsT0FBTyxFQUFhLFFBQVEsRUFBRSxXQUFXLEVBQUUsU0FBUyxFQUFFLE1BQU0seUJBQXlCLENBQUM7QUFDdEYsT0FBTyxFQUFjLE9BQU8sRUFBRSxlQUFlLEVBQUUsTUFBTSxNQUFNLENBQUM7QUFFNUQsT0FBTyxFQUFFLHVCQUF1QixFQUFFLE1BQU0sVUFBVSxDQUFDOzs7QUFrQm5EOzs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7OztHQTZCRztBQUVILE1BQU0sT0FBTyxnQkFBZ0I7SUFXM0IsWUFDc0IsU0FBMkIsRUFDTixNQUE2QixFQUN6QyxVQUFrQixFQUN2QyxNQUFjO1FBSEYsY0FBUyxHQUFULFNBQVMsQ0FBa0I7UUFDTixXQUFNLEdBQU4sTUFBTSxDQUF1QjtRQUN6QyxlQUFVLEdBQVYsVUFBVSxDQUFRO1FBQ3ZDLFdBQU0sR0FBTixNQUFNLENBQVE7UUFkaEIsbUJBQWMsR0FBRyxJQUFJLE9BQU8sRUFBdUIsQ0FBQztRQUNwRCw2QkFBd0IsR0FBRyxJQUFJLE9BQU8sRUFBMEIsQ0FBQztRQUNqRSxpQkFBWSxHQUFHLElBQUksZUFBZSxDQUFpQjtZQUN6RCxLQUFLLEVBQUUsSUFBSTtZQUNYLFVBQVUsRUFBRSxTQUFTO1lBQ3JCLFdBQVcsRUFBRSxLQUFLO1NBQ25CLENBQUMsQ0FBQztRQVVELElBQUksQ0FBQyxtQkFBbUIsRUFBRSxDQUFDO0lBQzdCLENBQUM7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QUMsQ0FBQztZQUNwRSxDQUFDO1FBQ0gsQ0FBQztRQUVELE9BQU8sTUFBTSxDQUFDO0lBQ2hCLENBQUM7K0dBL2ZVLGdCQUFnQiwyREFhakIsdUJBQXVCLGFBQ3ZCLFdBQVc7bUhBZFYsZ0JBQWdCLGNBREgsTUFBTTs7NEZBQ25CLGdCQUFnQjtrQkFENUIsVUFBVTttQkFBQyxFQUFFLFVBQVUsRUFBRSxNQUFNLEVBQUU7OzBCQWE3QixRQUFROzswQkFDUixNQUFNOzJCQUFDLHVCQUF1Qjs7MEJBQzlCLE1BQU07MkJBQUMsV0FBVyIsInNvdXJjZXNDb250ZW50IjpbIi8qKlxuICogTWVzc2FnaW5nIFNlcnZpY2UgKEZDTSlcbiAqXG4gKiBTZXJ2aWNpbyBwYXJhIEZpcmViYXNlIENsb3VkIE1lc3NhZ2luZyAoUHVzaCBOb3RpZmljYXRpb25zKS5cbiAqIFBlcm1pdGUgc29saWNpdGFyIHBlcm1pc29zLCBvYnRlbmVyIHRva2VucywgZXNjdWNoYXIgbWVuc2FqZXMgeSBtYW5lamFyXG4gKiBuYXZlZ2FjacOzbiAoZGVlcCBsaW5raW5nKSBjdWFuZG8gZWwgdXN1YXJpbyB0b2NhIHVuYSBub3RpZmljYWNpw7NuLlxuICovXG5cbmltcG9ydCB7IEluamVjdCwgSW5qZWN0YWJsZSwgTmdab25lLCBPcHRpb25hbCwgUExBVEZPUk1fSUQgfSBmcm9tICdAYW5ndWxhci9jb3JlJztcbmltcG9ydCB7IGlzUGxhdGZvcm1Ccm93c2VyIH0gZnJvbSAnQGFuZ3VsYXIvY29tbW9uJztcbmltcG9ydCB7IE1lc3NhZ2luZywgZ2V0VG9rZW4sIGRlbGV0ZVRva2VuLCBvbk1lc3NhZ2UgfSBmcm9tICdAYW5ndWxhci9maXJlL21lc3NhZ2luZyc7XG5pbXBvcnQgeyBPYnNlcnZhYmxlLCBTdWJqZWN0LCBCZWhhdmlvclN1YmplY3QgfSBmcm9tICdyeGpzJztcblxuaW1wb3J0IHsgVkFMVEVDSF9GSVJFQkFTRV9DT05GSUcgfSBmcm9tICcuL2NvbmZpZyc7XG5pbXBvcnQge1xuICBOb3RpZmljYXRpb25BY3Rpb24sXG4gIE5vdGlmaWNhdGlvbkNsaWNrRXZlbnQsXG4gIE5vdGlmaWNhdGlvblBheWxvYWQsXG4gIE5vdGlmaWNhdGlvblBlcm1pc3Npb24sXG4gIFZhbHRlY2hGaXJlYmFzZUNvbmZpZyxcbn0gZnJvbSAnLi90eXBlcyc7XG5cbi8qKlxuICogRXN0YWRvIGludGVybm8gZGVsIHNlcnZpY2lvIGRlIG1lc3NhZ2luZ1xuICovXG5pbnRlcmZhY2UgTWVzc2FnaW5nU3RhdGUge1xuICB0b2tlbjogc3RyaW5nIHwgbnVsbDtcbiAgcGVybWlzc2lvbjogTm90aWZpY2F0aW9uUGVybWlzc2lvbjtcbiAgaXNTdXBwb3J0ZWQ6IGJvb2xlYW47XG59XG5cbi8qKlxuICogU2VydmljaW8gcGFyYSBGaXJlYmFzZSBDbG91ZCBNZXNzYWdpbmcgKEZDTSkuXG4gKlxuICogUGVybWl0ZSByZWNpYmlyIG5vdGlmaWNhY2lvbmVzIHB1c2ggZW4gbGEgYXBsaWNhY2nDs24gd2ViLlxuICogUmVxdWllcmUgVkFQSUQga2V5IGNvbmZpZ3VyYWRhIGVuIFZhbHRlY2hGaXJlYmFzZUNvbmZpZy5cbiAqXG4gKiBAZXhhbXBsZVxuICogYGBgdHlwZXNjcmlwdFxuICogQENvbXBvbmVudCh7Li4ufSlcbiAqIGV4cG9ydCBjbGFzcyBOb3RpZmljYXRpb25Db21wb25lbnQge1xuICogICBwcml2YXRlIG1lc3NhZ2luZyA9IGluamVjdChNZXNzYWdpbmdTZXJ2aWNlKTtcbiAqXG4gKiAgIHRva2VuID0gc2lnbmFsPHN0cmluZyB8IG51bGw+KG51bGwpO1xuICpcbiAqICAgYXN5bmMgZW5hYmxlTm90aWZpY2F0aW9ucygpIHtcbiAqICAgICAvLyBTb2xpY2l0YXIgcGVybWlzbyB5IG9idGVuZXIgdG9rZW5cbiAqICAgICBjb25zdCB0b2tlbiA9IGF3YWl0IHRoaXMubWVzc2FnaW5nLnJlcXVlc3RQZXJtaXNzaW9uKCk7XG4gKlxuICogICAgIGlmICh0b2tlbikge1xuICogICAgICAgdGhpcy50b2tlbi5zZXQodG9rZW4pO1xuICogICAgICAgLy8gRW52aWFyIHRva2VuIGEgdHUgYmFja2VuZCBwYXJhIGFsbWFjZW5hcmxvXG4gKiAgICAgICBhd2FpdCB0aGlzLmJhY2tlbmQucmVnaXN0ZXJEZXZpY2VUb2tlbih0b2tlbik7XG4gKiAgICAgfVxuICogICB9XG4gKlxuICogICAvLyBFc2N1Y2hhciBtZW5zYWplcyBlbiBmb3JlZ3JvdW5kXG4gKiAgIG1lc3NhZ2VzJCA9IHRoaXMubWVzc2FnaW5nLm9uTWVzc2FnZSgpO1xuICogfVxuICogYGBgXG4gKi9cbkBJbmplY3RhYmxlKHsgcHJvdmlkZWRJbjogJ3Jvb3QnIH0pXG5leHBvcnQgY2xhc3MgTWVzc2FnaW5nU2VydmljZSB7XG4gIHByaXZhdGUgbWVzc2FnZVN1YmplY3QgPSBuZXcgU3ViamVjdDxOb3RpZmljYXRpb25QYXlsb2FkPigpO1xuICBwcml2YXRlIG5vdGlmaWNhdGlvbkNsaWNrU3ViamVjdCA9IG5ldyBTdWJqZWN0PE5vdGlmaWNhdGlvbkNsaWNrRXZlbnQ+KCk7XG4gIHByaXZhdGUgc3RhdGVTdWJqZWN0ID0gbmV3IEJlaGF2aW9yU3ViamVjdDxNZXNzYWdpbmdTdGF0ZT4oe1xuICAgIHRva2VuOiBudWxsLFxuICAgIHBlcm1pc3Npb246ICdkZWZhdWx0JyxcbiAgICBpc1N1cHBvcnRlZDogZmFsc2UsXG4gIH0pO1xuXG4gIHByaXZhdGUgdW5zdWJzY3JpYmVPbk1lc3NhZ2U/OiAoKSA9PiB2b2lkO1xuXG4gIGNvbnN0cnVjdG9yKFxuICAgIEBPcHRpb25hbCgpIHByaXZhdGUgbWVzc2FnaW5nOiBNZXNzYWdpbmcgfCBudWxsLFxuICAgIEBJbmplY3QoVkFMVEVDSF9GSVJFQkFTRV9DT05GSUcpIHByaXZhdGUgY29uZmlnOiBWYWx0ZWNoRmlyZWJhc2VDb25maWcsXG4gICAgQEluamVjdChQTEFURk9STV9JRCkgcHJpdmF0ZSBwbGF0Zm9ybUlkOiBPYmplY3QsXG4gICAgcHJpdmF0ZSBuZ1pvbmU6IE5nWm9uZVxuICApIHtcbiAgICB0aGlzLmluaXRpYWxpemVNZXNzYWdpbmcoKTtcbiAgfVxuXG4gIC8vID09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PVxuICAvLyBJTklDSUFMSVpBQ0nDk05cbiAgLy8gPT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09XG5cbiAgLyoqXG4gICAqIEluaWNpYWxpemEgZWwgc2VydmljaW8gZGUgbWVzc2FnaW5nXG4gICAqL1xuICBwcml2YXRlIGFzeW5jIGluaXRpYWxpemVNZXNzYWdpbmcoKTogUHJvbWlzZTx2b2lkPiB7XG4gICAgaWYgKCFpc1BsYXRmb3JtQnJvd3Nlcih0aGlzLnBsYXRmb3JtSWQpKSB7XG4gICAgICByZXR1cm47XG4gICAgfVxuXG4gICAgY29uc3Qgc3VwcG9ydGVkID0gYXdhaXQgdGhpcy5jaGVja1N1cHBvcnQoKTtcbiAgICBjb25zdCBwZXJtaXNzaW9uID0gdGhpcy5nZXRQZXJtaXNzaW9uU3RhdGUoKTtcblxuICAgIHRoaXMuc3RhdGVTdWJqZWN0Lm5leHQoe1xuICAgICAgLi4udGhpcy5zdGF0ZVN1YmplY3QudmFsdWUsXG4gICAgICBpc1N1cHBvcnRlZDogc3VwcG9ydGVkLFxuICAgICAgcGVybWlzc2lvbixcbiAgICB9KTtcblxuICAgIC8vIFNpIHlhIHRpZW5lIHBlcm1pc28sIGNvbmZpZ3VyYXIgbGlzdGVuZXJzXG4gICAgaWYgKHN1cHBvcnRlZCAmJiBwZXJtaXNzaW9uID09PSAnZ3JhbnRlZCcpIHtcbiAgICAgIHRoaXMuc2V0dXBNZXNzYWdlTGlzdGVuZXIoKTtcbiAgICB9XG5cbiAgICAvLyBFc2N1Y2hhciBtZW5zYWplcyBkZWwgU2VydmljZSBXb3JrZXIgKGNsaWNrcyBlbiBub3RpZmljYWNpb25lcyBiYWNrZ3JvdW5kKVxuICAgIHRoaXMuc2V0dXBTZXJ2aWNlV29ya2VyTGlzdGVuZXIoKTtcbiAgfVxuXG4gIC8qKlxuICAgKiBDb25maWd1cmEgbGlzdGVuZXIgcGFyYSBtZW5zYWplcyBkZWwgU2VydmljZSBXb3JrZXIuXG4gICAqIFJlY2liZSBldmVudG9zIGN1YW5kbyBlbCB1c3VhcmlvIGhhY2UgY2xpY2sgZW4gdW5hIG5vdGlmaWNhY2nDs24gYmFja2dyb3VuZC5cbiAgICovXG4gIHByaXZhdGUgc2V0dXBTZXJ2aWNlV29ya2VyTGlzdGVuZXIoKTogdm9pZCB7XG4gICAgaWYgKCFpc1BsYXRmb3JtQnJvd3Nlcih0aGlzLnBsYXRmb3JtSWQpIHx8ICEoJ3NlcnZpY2VXb3JrZXInIGluIG5hdmlnYXRvcikpIHtcbiAgICAgIHJldHVybjtcbiAgICB9XG5cbiAgICBuYXZpZ2F0b3Iuc2VydmljZVdvcmtlci5hZGRFdmVudExpc3RlbmVyKCdtZXNzYWdlJywgKGV2ZW50KSA9PiB7XG4gICAgICAvLyBWZXJpZmljYXIgcXVlIGVzIHVuIG1lbnNhamUgZGUgbm90aWZpY2FjacOzbiBjbGlja1xuICAgICAgaWYgKGV2ZW50LmRhdGE/LnR5cGUgPT09ICdOT1RJRklDQVRJT05fQ0xJQ0snKSB7XG4gICAgICAgIHRoaXMubmdab25lLnJ1bigoKSA9PiB7XG4gICAgICAgICAgY29uc3Qgbm90aWZpY2F0aW9uID0gZXZlbnQuZGF0YS5ub3RpZmljYXRpb24gYXMgTm90aWZpY2F0aW9uUGF5bG9hZDtcbiAgICAgICAgICBjb25zdCBhY3Rpb24gPSB0aGlzLmV4dHJhY3RBY3Rpb25Gcm9tRGF0YShub3RpZmljYXRpb24uZGF0YSk7XG5cbiAgICAgICAgICB0aGlzLm5vdGlmaWNhdGlvbkNsaWNrU3ViamVjdC5uZXh0KHtcbiAgICAgICAgICAgIG5vdGlmaWNhdGlvbixcbiAgICAgICAgICAgIGFjdGlvbixcbiAgICAgICAgICAgIHRpbWVzdGFtcDogbmV3IERhdGUoKSxcbiAgICAgICAgICB9KTtcbiAgICAgICAgfSk7XG4gICAgICB9XG4gICAgfSk7XG4gIH1cblxuICAvKipcbiAgICogVmVyaWZpY2Egc2kgRkNNIGVzdMOhIHNvcG9ydGFkbyBlbiBlbCBuYXZlZ2Fkb3IgYWN0dWFsXG4gICAqL1xuICBwcml2YXRlIGFzeW5jIGNoZWNrU3VwcG9ydCgpOiBQcm9taXNlPGJvb2xlYW4+IHtcbiAgICBpZiAoIWlzUGxhdGZvcm1Ccm93c2VyKHRoaXMucGxhdGZvcm1JZCkpIHtcbiAgICAgIHJldHVybiBmYWxzZTtcbiAgICB9XG5cbiAgICAvLyBWZXJpZmljYXIgQVBJcyBuZWNlc2FyaWFzXG4gICAgaWYgKCEoJ05vdGlmaWNhdGlvbicgaW4gd2luZG93KSkge1xuICAgICAgcmV0dXJuIGZhbHNlO1xuICAgIH1cblxuICAgIGlmICghKCdzZXJ2aWNlV29ya2VyJyBpbiBuYXZpZ2F0b3IpKSB7XG4gICAgICByZXR1cm4gZmFsc2U7XG4gICAgfVxuXG4gICAgLy8gVmVyaWZpY2FyIHF1ZSBtZXNzYWdpbmcgZXN0w6kgZGlzcG9uaWJsZVxuICAgIGlmICghdGhpcy5tZXNzYWdpbmcpIHtcbiAgICAgIHJldHVybiBmYWxzZTtcbiAgICB9XG5cbiAgICByZXR1cm4gdHJ1ZTtcbiAgfVxuXG4gIC8vID09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PVxuICAvLyBQRVJNSVNPUyBZIFRPS0VOXG4gIC8vID09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PVxuXG4gIC8qKlxuICAgKiBTb2xpY2l0YSBwZXJtaXNvIGRlIG5vdGlmaWNhY2lvbmVzIHkgb2J0aWVuZSBlbCB0b2tlbiBGQ00uXG4gICAqXG4gICAqIEByZXR1cm5zIFRva2VuIEZDTSBzaSBzZSBvdG9yZ8OzIHBlcm1pc28sIG51bGwgc2kgc2UgZGVuZWfDs1xuICAgKlxuICAgKiBAZXhhbXBsZVxuICAgKiBgYGB0eXBlc2NyaXB0XG4gICAqIGNvbnN0IHRva2VuID0gYXdhaXQgbWVzc2FnaW5nLnJlcXVlc3RQZXJtaXNzaW9uKCk7XG4gICAqIGlmICh0b2tlbikge1xuICAgKiAgIGNvbnNvbGUubG9nKCdUb2tlbiBGQ006JywgdG9rZW4pO1xuICAgKiAgIC8vIEVudmlhciBhIGJhY2tlbmRcbiAgICogfSBlbHNlIHtcbiAgICogICBjb25zb2xlLmxvZygnUGVybWlzbyBkZW5lZ2FkbyBvIG5vIHNvcG9ydGFkbycpO1xuICAgKiB9XG4gICAqIGBgYFxuICAgKi9cbiAgYXN5bmMgcmVxdWVzdFBlcm1pc3Npb24oKTogUHJvbWlzZTxzdHJpbmcgfCBudWxsPiB7XG4gICAgaWYgKCFhd2FpdCB0aGlzLmlzU3VwcG9ydGVkKCkpIHtcbiAgICAgIGNvbnNvbGUud2FybignRkNNIG5vIGVzdMOhIHNvcG9ydGFkbyBlbiBlc3RlIG5hdmVnYWRvcicpO1xuICAgICAgcmV0dXJuIG51bGw7XG4gICAgfVxuXG4gICAgdHJ5IHtcbiAgICAgIC8vIFNvbGljaXRhciBwZXJtaXNvIGRlIG5vdGlmaWNhY2lvbmVzXG4gICAgICBjb25zdCBwZXJtaXNzaW9uID0gYXdhaXQgTm90aWZpY2F0aW9uLnJlcXVlc3RQZXJtaXNzaW9uKCk7XG5cbiAgICAgIHRoaXMuc3RhdGVTdWJqZWN0Lm5leHQoe1xuICAgICAgICAuLi50aGlzLnN0YXRlU3ViamVjdC52YWx1ZSxcbiAgICAgICAgcGVybWlzc2lvbjogcGVybWlzc2lvbiBhcyBOb3RpZmljYXRpb25QZXJtaXNzaW9uLFxuICAgICAgfSk7XG5cbiAgICAgIGlmIChwZXJtaXNzaW9uICE9PSAnZ3JhbnRlZCcpIHtcbiAgICAgICAgY29uc29sZS53YXJuKCdQZXJtaXNvIGRlIG5vdGlmaWNhY2lvbmVzIGRlbmVnYWRvJyk7XG4gICAgICAgIHJldHVybiBudWxsO1xuICAgICAgfVxuXG4gICAgICAvLyBPYnRlbmVyIHRva2VuIEZDTVxuICAgICAgY29uc3QgdG9rZW4gPSBhd2FpdCB0aGlzLmdldFRva2VuKCk7XG5cbiAgICAgIGlmICh0b2tlbikge1xuICAgICAgICAvLyBDb25maWd1cmFyIGxpc3RlbmVyIGRlIG1lbnNhamVzXG4gICAgICAgIHRoaXMuc2V0dXBNZXNzYWdlTGlzdGVuZXIoKTtcbiAgICAgIH1cblxuICAgICAgcmV0dXJuIHRva2VuO1xuICAgIH0gY2F0Y2ggKGVycm9yKSB7XG4gICAgICBjb25zb2xlLmVycm9yKCdFcnJvciBzb2xpY2l0YW5kbyBwZXJtaXNvIGRlIG5vdGlmaWNhY2lvbmVzOicsIGVycm9yKTtcbiAgICAgIHJldHVybiBudWxsO1xuICAgIH1cbiAgfVxuXG4gIC8qKlxuICAgKiBPYnRpZW5lIGVsIHRva2VuIEZDTSBhY3R1YWwgKHNpbiBzb2xpY2l0YXIgcGVybWlzbykuXG4gICAqXG4gICAqIEByZXR1cm5zIFRva2VuIEZDTSBzaSBlc3TDoSBkaXNwb25pYmxlLCBudWxsIHNpIG5vXG4gICAqXG4gICAqIEBleGFtcGxlXG4gICAqIGBgYHR5cGVzY3JpcHRcbiAgICogY29uc3QgdG9rZW4gPSBhd2FpdCBtZXNzYWdpbmcuZ2V0VG9rZW4oKTtcbiAgICogYGBgXG4gICAqL1xuICBhc3luYyBnZXRUb2tlbigpOiBQcm9taXNlPHN0cmluZyB8IG51bGw+IHtcbiAgICBpZiAoIXRoaXMubWVzc2FnaW5nKSB7XG4gICAgICByZXR1cm4gbnVsbDtcbiAgICB9XG5cbiAgICBjb25zdCB2YXBpZEtleSA9IHRoaXMuY29uZmlnLm1lc3NhZ2luZ1ZhcGlkS2V5O1xuICAgIGlmICghdmFwaWRLZXkpIHtcbiAgICAgIGNvbnNvbGUud2FybignVkFQSUQga2V5IG5vIGNvbmZpZ3VyYWRhLiBGQ00gbm8gZnVuY2lvbmFyw6EuJyk7XG4gICAgICByZXR1cm4gbnVsbDtcbiAgICB9XG5cbiAgICB0cnkge1xuICAgICAgY29uc3QgdG9rZW4gPSBhd2FpdCBnZXRUb2tlbih0aGlzLm1lc3NhZ2luZywgeyB2YXBpZEtleSB9KTtcblxuICAgICAgdGhpcy5zdGF0ZVN1YmplY3QubmV4dCh7XG4gICAgICAgIC4uLnRoaXMuc3RhdGVTdWJqZWN0LnZhbHVlLFxuICAgICAgICB0b2tlbixcbiAgICAgIH0pO1xuXG4gICAgICByZXR1cm4gdG9rZW47XG4gICAgfSBjYXRjaCAoZXJyb3IpIHtcbiAgICAgIGNvbnNvbGUuZXJyb3IoJ0Vycm9yIG9idGVuaWVuZG8gdG9rZW4gRkNNOicsIGVycm9yKTtcbiAgICAgIHJldHVybiBudWxsO1xuICAgIH1cbiAgfVxuXG4gIC8qKlxuICAgKiBFbGltaW5hIGVsIHRva2VuIEZDTSBhY3R1YWwgKHVuc3Vic2NyaWJlIGRlIG5vdGlmaWNhY2lvbmVzKS5cbiAgICpcbiAgICogQGV4YW1wbGVcbiAgICogYGBgdHlwZXNjcmlwdFxuICAgKiBhd2FpdCBtZXNzYWdpbmcuZGVsZXRlVG9rZW4oKTtcbiAgICogY29uc29sZS5sb2coJ1Rva2VuIGVsaW1pbmFkbywgbm8gcmVjaWJpcsOhIG3DoXMgbm90aWZpY2FjaW9uZXMnKTtcbiAgICogYGBgXG4gICAqL1xuICBhc3luYyBkZWxldGVUb2tlbigpOiBQcm9taXNlPHZvaWQ+IHtcbiAgICBpZiAoIXRoaXMubWVzc2FnaW5nKSB7XG4gICAgICByZXR1cm47XG4gICAgfVxuXG4gICAgdHJ5IHtcbiAgICAgIGF3YWl0IGRlbGV0ZVRva2VuKHRoaXMubWVzc2FnaW5nKTtcblxuICAgICAgdGhpcy5zdGF0ZVN1YmplY3QubmV4dCh7XG4gICAgICAgIC4uLnRoaXMuc3RhdGVTdWJqZWN0LnZhbHVlLFxuICAgICAgICB0b2tlbjogbnVsbCxcbiAgICAgIH0pO1xuXG4gICAgICAvLyBMaW1waWFyIGxpc3RlbmVyIGRlIG1lbnNhamVzXG4gICAgICBpZiAodGhpcy51bnN1YnNjcmliZU9uTWVzc2FnZSkge1xuICAgICAgICB0aGlzLnVuc3Vic2NyaWJlT25NZXNzYWdlKCk7XG4gICAgICAgIHRoaXMudW5zdWJzY3JpYmVPbk1lc3NhZ2UgPSB1bmRlZmluZWQ7XG4gICAgICB9XG4gICAgfSBjYXRjaCAoZXJyb3IpIHtcbiAgICAgIGNvbnNvbGUuZXJyb3IoJ0Vycm9yIGVsaW1pbmFuZG8gdG9rZW4gRkNNOicsIGVycm9yKTtcbiAgICAgIHRocm93IG5ldyBFcnJvcignTm8gc2UgcHVkbyBlbGltaW5hciBlbCB0b2tlbiBkZSBub3RpZmljYWNpb25lcycpO1xuICAgIH1cbiAgfVxuXG4gIC8vID09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PVxuICAvLyBNRU5TQUpFU1xuICAvLyA9PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT1cblxuICAvKipcbiAgICogT2JzZXJ2YWJsZSBkZSBtZW5zYWplcyByZWNpYmlkb3MgZW4gZm9yZWdyb3VuZC5cbiAgICpcbiAgICogSU1QT1JUQU5URTogTG9zIG1lbnNhamVzIGVuIGJhY2tncm91bmQgc29uIG1hbmVqYWRvcyBwb3IgZWwgU2VydmljZSBXb3JrZXIuXG4gICAqXG4gICAqIEByZXR1cm5zIE9ic2VydmFibGUgcXVlIGVtaXRlIGN1YW5kbyBsbGVnYSB1biBtZW5zYWplIGVuIGZvcmVncm91bmRcbiAgICpcbiAgICogQGV4YW1wbGVcbiAgICogYGBgdHlwZXNjcmlwdFxuICAgKiBtZXNzYWdpbmcub25NZXNzYWdlKCkuc3Vic2NyaWJlKHBheWxvYWQgPT4ge1xuICAgKiAgIGNvbnNvbGUubG9nKCdNZW5zYWplIHJlY2liaWRvOicsIHBheWxvYWQpO1xuICAgKiAgIC8vIE1vc3RyYXIgbm90aWZpY2FjacOzbiBjdXN0b20gbyBhY3R1YWxpemFyIFVJXG4gICAqIH0pO1xuICAgKiBgYGBcbiAgICovXG4gIG9uTWVzc2FnZSgpOiBPYnNlcnZhYmxlPE5vdGlmaWNhdGlvblBheWxvYWQ+IHtcbiAgICByZXR1cm4gdGhpcy5tZXNzYWdlU3ViamVjdC5hc09ic2VydmFibGUoKTtcbiAgfVxuXG4gIC8qKlxuICAgKiBDb25maWd1cmEgZWwgbGlzdGVuZXIgZGUgbWVuc2FqZXMgZW4gZm9yZWdyb3VuZFxuICAgKi9cbiAgcHJpdmF0ZSBzZXR1cE1lc3NhZ2VMaXN0ZW5lcigpOiB2b2lkIHtcbiAgICBpZiAoIXRoaXMubWVzc2FnaW5nIHx8IHRoaXMudW5zdWJzY3JpYmVPbk1lc3NhZ2UpIHtcbiAgICAgIHJldHVybjtcbiAgICB9XG5cbiAgICB0aGlzLnVuc3Vic2NyaWJlT25NZXNzYWdlID0gb25NZXNzYWdlKHRoaXMubWVzc2FnaW5nLCAocGF5bG9hZCkgPT4ge1xuICAgICAgY29uc3Qgbm90aWZpY2F0aW9uOiBOb3RpZmljYXRpb25QYXlsb2FkID0ge1xuICAgICAgICB0aXRsZTogcGF5bG9hZC5ub3RpZmljYXRpb24/LnRpdGxlLFxuICAgICAgICBib2R5OiBwYXlsb2FkLm5vdGlmaWNhdGlvbj8uYm9keSxcbiAgICAgICAgaW1hZ2U6IHBheWxvYWQubm90aWZpY2F0aW9uPy5pbWFnZSxcbiAgICAgICAgZGF0YTogcGF5bG9hZC5kYXRhIGFzIFJlY29yZDxzdHJpbmcsIHN0cmluZz4sXG4gICAgICAgIG1lc3NhZ2VJZDogcGF5bG9hZC5tZXNzYWdlSWQsXG4gICAgICB9O1xuXG4gICAgICB0aGlzLm1lc3NhZ2VTdWJqZWN0Lm5leHQobm90aWZpY2F0aW9uKTtcbiAgICB9KTtcbiAgfVxuXG4gIC8vID09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PVxuICAvLyBFU1RBRE8gWSBVVElMSURBREVTXG4gIC8vID09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PVxuXG4gIC8qKlxuICAgKiBPYnRpZW5lIGVsIGVzdGFkbyBhY3R1YWwgZGVsIHBlcm1pc28gZGUgbm90aWZpY2FjaW9uZXMuXG4gICAqXG4gICAqIEByZXR1cm5zICdncmFudGVkJyB8ICdkZW5pZWQnIHwgJ2RlZmF1bHQnXG4gICAqXG4gICAqIEBleGFtcGxlXG4gICAqIGBgYHR5cGVzY3JpcHRcbiAgICogY29uc3QgcGVybWlzc2lvbiA9IG1lc3NhZ2luZy5nZXRQZXJtaXNzaW9uU3RhdGUoKTtcbiAgICogaWYgKHBlcm1pc3Npb24gPT09ICdncmFudGVkJykge1xuICAgKiAgIC8vIFlhIHRpZW5lIHBlcm1pc29cbiAgICogfSBlbHNlIGlmIChwZXJtaXNzaW9uID09PSAnZGVmYXVsdCcpIHtcbiAgICogICAvLyBQdWVkZSBzb2xpY2l0YXIgcGVybWlzb1xuICAgKiB9IGVsc2Uge1xuICAgKiAgIC8vIERlbmVnYWRvLCBkZWJlIGhhYmlsaXRhciBtYW51YWxtZW50ZVxuICAgKiB9XG4gICAqIGBgYFxuICAgKi9cbiAgZ2V0UGVybWlzc2lvblN0YXRlKCk6IE5vdGlmaWNhdGlvblBlcm1pc3Npb24ge1xuICAgIGlmICghaXNQbGF0Zm9ybUJyb3dzZXIodGhpcy5wbGF0Zm9ybUlkKSkge1xuICAgICAgcmV0dXJuICdkZWZhdWx0JztcbiAgICB9XG5cbiAgICBpZiAoISgnTm90aWZpY2F0aW9uJyBpbiB3aW5kb3cpKSB7XG4gICAgICByZXR1cm4gJ2RlbmllZCc7XG4gICAgfVxuXG4gICAgcmV0dXJuIE5vdGlmaWNhdGlvbi5wZXJtaXNzaW9uIGFzIE5vdGlmaWNhdGlvblBlcm1pc3Npb247XG4gIH1cblxuICAvKipcbiAgICogVmVyaWZpY2Egc2kgRkNNIGVzdMOhIHNvcG9ydGFkbyBlbiBlbCBuYXZlZ2Fkb3IgYWN0dWFsLlxuICAgKlxuICAgKiBAcmV0dXJucyB0cnVlIHNpIEZDTSBlc3TDoSBzb3BvcnRhZG9cbiAgICpcbiAgICogQGV4YW1wbGVcbiAgICogYGBgdHlwZXNjcmlwdFxuICAgKiBpZiAoYXdhaXQgbWVzc2FnaW5nLmlzU3VwcG9ydGVkKCkpIHtcbiAgICogICAvLyBQdWVkZSB1c2FyIG5vdGlmaWNhY2lvbmVzIHB1c2hcbiAgICogfSBlbHNlIHtcbiAgICogICAvLyBOYXZlZ2Fkb3Igbm8gc29wb3J0YSBvIG5vIHRpZW5lIFNlcnZpY2UgV29ya2VyXG4gICAqIH1cbiAgICogYGBgXG4gICAqL1xuICBhc3luYyBpc1N1cHBvcnRlZCgpOiBQcm9taXNlPGJvb2xlYW4+IHtcbiAgICByZXR1cm4gdGhpcy5jaGVja1N1cHBvcnQoKTtcbiAgfVxuXG4gIC8qKlxuICAgKiBPYnRpZW5lIGVsIHRva2VuIGFjdHVhbCBzaW4gaGFjZXIgcmVxdWVzdC5cbiAgICpcbiAgICogQHJldHVybnMgVG9rZW4gYWxtYWNlbmFkbyBvIG51bGxcbiAgICovXG4gIGdldCBjdXJyZW50VG9rZW4oKTogc3RyaW5nIHwgbnVsbCB7XG4gICAgcmV0dXJuIHRoaXMuc3RhdGVTdWJqZWN0LnZhbHVlLnRva2VuO1xuICB9XG5cbiAgLyoqXG4gICAqIE9ic2VydmFibGUgZGVsIGVzdGFkbyBjb21wbGV0byBkZWwgc2VydmljaW8gZGUgbWVzc2FnaW5nLlxuICAgKi9cbiAgZ2V0IHN0YXRlJCgpOiBPYnNlcnZhYmxlPE1lc3NhZ2luZ1N0YXRlPiB7XG4gICAgcmV0dXJuIHRoaXMuc3RhdGVTdWJqZWN0LmFzT2JzZXJ2YWJsZSgpO1xuICB9XG5cbiAgLyoqXG4gICAqIFZlcmlmaWNhIHNpIGVsIHVzdWFyaW8geWEgb3RvcmfDsyBwZXJtaXNvIGRlIG5vdGlmaWNhY2lvbmVzLlxuICAgKi9cbiAgZ2V0IGhhc1Blcm1pc3Npb24oKTogYm9vbGVhbiB7XG4gICAgcmV0dXJuIHRoaXMuc3RhdGVTdWJqZWN0LnZhbHVlLnBlcm1pc3Npb24gPT09ICdncmFudGVkJztcbiAgfVxuXG4gIC8vID09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PVxuICAvLyBERUVQIExJTktJTkcgLyBOQVZFR0FDScOTTlxuICAvLyA9PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT1cblxuICAvKipcbiAgICogT2JzZXJ2YWJsZSBkZSBjbGlja3MgZW4gbm90aWZpY2FjaW9uZXMuXG4gICAqXG4gICAqIEVtaXRlIGN1YW5kbyBlbCB1c3VhcmlvIGhhY2UgY2xpY2sgZW4gdW5hIG5vdGlmaWNhY2nDs24gKGZvcmVncm91bmQgbyBiYWNrZ3JvdW5kKS5cbiAgICogVXNhIGVzdGUgb2JzZXJ2YWJsZSBwYXJhIG5hdmVnYXIgYSBsYSBww6FnaW5hIGNvcnJlc3BvbmRpZW50ZS5cbiAgICpcbiAgICogQHJldHVybnMgT2JzZXJ2YWJsZSBxdWUgZW1pdGUgTm90aWZpY2F0aW9uQ2xpY2tFdmVudFxuICAgKlxuICAgKiBAZXhhbXBsZVxuICAgKiBgYGB0eXBlc2NyaXB0XG4gICAqIEBDb21wb25lbnQoey4uLn0pXG4gICAqIGV4cG9ydCBjbGFzcyBBcHBDb21wb25lbnQge1xuICAgKiAgIHByaXZhdGUgbWVzc2FnaW5nID0gaW5qZWN0KE1lc3NhZ2luZ1NlcnZpY2UpO1xuICAgKiAgIHByaXZhdGUgcm91dGVyID0gaW5qZWN0KFJvdXRlcik7XG4gICAqXG4gICAqICAgY29uc3RydWN0b3IoKSB7XG4gICAqICAgICB0aGlzLm1lc3NhZ2luZy5vbk5vdGlmaWNhdGlvbkNsaWNrKCkuc3Vic2NyaWJlKGV2ZW50ID0+IHtcbiAgICogICAgICAgaWYgKGV2ZW50LmFjdGlvbi5yb3V0ZSkge1xuICAgKiAgICAgICAgIHRoaXMucm91dGVyLm5hdmlnYXRlKFtldmVudC5hY3Rpb24ucm91dGVdLCB7XG4gICAqICAgICAgICAgICBxdWVyeVBhcmFtczogZXZlbnQuYWN0aW9uLnF1ZXJ5UGFyYW1zXG4gICAqICAgICAgICAgfSk7XG4gICAqICAgICAgIH1cbiAgICogICAgIH0pO1xuICAgKiAgIH1cbiAgICogfVxuICAgKiBgYGBcbiAgICovXG4gIG9uTm90aWZpY2F0aW9uQ2xpY2soKTogT2JzZXJ2YWJsZTxOb3RpZmljYXRpb25DbGlja0V2ZW50PiB7XG4gICAgcmV0dXJuIHRoaXMubm90aWZpY2F0aW9uQ2xpY2tTdWJqZWN0LmFzT2JzZXJ2YWJsZSgpO1xuICB9XG5cbiAgLyoqXG4gICAqIEV4dHJhZSBsYSBhY2Npw7NuIGRlIG5hdmVnYWNpw7NuIGRlIGxvcyBkYXRvcyBkZSB1bmEgbm90aWZpY2FjacOzbi5cbiAgICpcbiAgICogQnVzY2EgY2FtcG9zIGVzcGVjw61maWNvcyBlbiBlbCBwYXlsb2FkIGRlIGRhdG9zOlxuICAgKiAtIGByb3V0ZWA6IFJ1dGEgaW50ZXJuYSBkZSBsYSBhcHAgKGVqOiAnL29yZGVycy8xMjMnKVxuICAgKiAtIGB1cmxgOiBVUkwgZXh0ZXJuYSAoZWo6ICdodHRwczovL2V4YW1wbGUuY29tJylcbiAgICogLSBgYWN0aW9uX3R5cGVgOiBUaXBvIGRlIGFjY2nDs24gcGVyc29uYWxpemFkYVxuICAgKiAtIENhbXBvcyBjb24gcHJlZmlqbyBgYWN0aW9uX2A6IERhdG9zIGFkaWNpb25hbGVzXG4gICAqXG4gICAqIEBwYXJhbSBkYXRhIC0gRGF0b3MgZGVsIHBheWxvYWQgZGUgbGEgbm90aWZpY2FjacOzblxuICAgKiBAcmV0dXJucyBBY2Npw7NuIGRlIG5hdmVnYWNpw7NuIGV4dHJhw61kYVxuICAgKlxuICAgKiBAZXhhbXBsZVxuICAgKiBgYGB0eXBlc2NyaXB0XG4gICAqIC8vIFBheWxvYWQgZGVzZGUgZWwgYmFja2VuZDpcbiAgICogLy8geyByb3V0ZTogJy9vcmRlcnMvMTIzJywgYWN0aW9uX3R5cGU6ICd2aWV3X29yZGVyJywgYWN0aW9uX29yZGVySWQ6ICcxMjMnIH1cbiAgICpcbiAgICogY29uc3QgYWN0aW9uID0gbWVzc2FnaW5nLmV4dHJhY3RBY3Rpb25Gcm9tRGF0YShub3RpZmljYXRpb24uZGF0YSk7XG4gICAqIC8vIHsgcm91dGU6ICcvb3JkZXJzLzEyMycsIGFjdGlvblR5cGU6ICd2aWV3X29yZGVyJywgYWN0aW9uRGF0YTogeyBvcmRlcklkOiAnMTIzJyB9IH1cbiAgICogYGBgXG4gICAqL1xuICBleHRyYWN0QWN0aW9uRnJvbURhdGEoZGF0YT86IFJlY29yZDxzdHJpbmcsIHN0cmluZz4pOiBOb3RpZmljYXRpb25BY3Rpb24ge1xuICAgIGlmICghZGF0YSkge1xuICAgICAgcmV0dXJuIHt9O1xuICAgIH1cblxuICAgIGNvbnN0IGFjdGlvbjogTm90aWZpY2F0aW9uQWN0aW9uID0ge307XG5cbiAgICAvLyBSdXRhIGludGVybmFcbiAgICBpZiAoZGF0YVsncm91dGUnXSkge1xuICAgICAgYWN0aW9uLnJvdXRlID0gZGF0YVsncm91dGUnXTtcbiAgICB9XG5cbiAgICAvLyBVUkwgZXh0ZXJuYVxuICAgIGlmIChkYXRhWyd1cmwnXSkge1xuICAgICAgYWN0aW9uLnVybCA9IGRhdGFbJ3VybCddO1xuICAgIH1cblxuICAgIC8vIFRpcG8gZGUgYWNjacOzblxuICAgIGlmIChkYXRhWydhY3Rpb25fdHlwZSddKSB7XG4gICAgICBhY3Rpb24uYWN0aW9uVHlwZSA9IGRhdGFbJ2FjdGlvbl90eXBlJ107XG4gICAgfVxuXG4gICAgLy8gUXVlcnkgcGFyYW1zIChwdWVkZSB2ZW5pciBjb21vIEpTT04gc3RyaW5nKVxuICAgIGlmIChkYXRhWydxdWVyeV9wYXJhbXMnXSkge1xuICAgICAgdHJ5IHtcbiAgICAgICAgYWN0aW9uLnF1ZXJ5UGFyYW1zID0gSlNPTi5wYXJzZShkYXRhWydxdWVyeV9wYXJhbXMnXSk7XG4gICAgICB9IGNhdGNoIHtcbiAgICAgICAgLy8gU2kgbm8gZXMgSlNPTiB2w6FsaWRvLCBpbnRlbnRhciBwYXJzZWFyIGNvbW8ga2V5PXZhbHVlXG4gICAgICAgIGFjdGlvbi5xdWVyeVBhcmFtcyA9IHRoaXMucGFyc2VRdWVyeVN0cmluZyhkYXRhWydxdWVyeV9wYXJhbXMnXSk7XG4gICAgICB9XG4gICAgfVxuXG4gICAgLy8gRGF0b3MgYWRpY2lvbmFsZXMgY29uIHByZWZpam8gYWN0aW9uX1xuICAgIGNvbnN0IGFjdGlvbkRhdGE6IFJlY29yZDxzdHJpbmcsIHVua25vd24+ID0ge307XG4gICAgZm9yIChjb25zdCBba2V5LCB2YWx1ZV0gb2YgT2JqZWN0LmVudHJpZXMoZGF0YSkpIHtcbiAgICAgIGlmIChrZXkuc3RhcnRzV2l0aCgnYWN0aW9uXycpICYmIGtleSAhPT0gJ2FjdGlvbl90eXBlJykge1xuICAgICAgICBjb25zdCBjbGVhbktleSA9IGtleS5yZXBsYWNlKCdhY3Rpb25fJywgJycpO1xuICAgICAgICAvLyBJbnRlbnRhciBwYXJzZWFyIEpTT04gc2kgZXMgcG9zaWJsZVxuICAgICAgICB0cnkge1xuICAgICAgICAgIGFjdGlvbkRhdGFbY2xlYW5LZXldID0gSlNPTi5wYXJzZSh2YWx1ZSk7XG4gICAgICAgIH0gY2F0Y2gge1xuICAgICAgICAgIGFjdGlvbkRhdGFbY2xlYW5LZXldID0gdmFsdWU7XG4gICAgICAgIH1cbiAgICAgIH1cbiAgICB9XG5cbiAgICBpZiAoT2JqZWN0LmtleXMoYWN0aW9uRGF0YSkubGVuZ3RoID4gMCkge1xuICAgICAgYWN0aW9uLmFjdGlvbkRhdGEgPSBhY3Rpb25EYXRhO1xuICAgIH1cblxuICAgIHJldHVybiBhY3Rpb247XG4gIH1cblxuICAvKipcbiAgICogRW1pdGUgbWFudWFsbWVudGUgdW4gZXZlbnRvIGRlIGNsaWNrIGVuIG5vdGlmaWNhY2nDs24uXG4gICAqXG4gICAqIMOadGlsIHBhcmEgbWFuZWphciBjbGlja3MgZW4gbm90aWZpY2FjaW9uZXMgZm9yZWdyb3VuZCBkb25kZVxuICAgKiBsYSBhcHAgZGVjaWRlIG1vc3RyYXIgdW4gYmFubmVyIGN1c3RvbS5cbiAgICpcbiAgICogQHBhcmFtIG5vdGlmaWNhdGlvbiAtIFBheWxvYWQgZGUgbGEgbm90aWZpY2FjacOzblxuICAgKlxuICAgKiBAZXhhbXBsZVxuICAgKiBgYGB0eXBlc2NyaXB0XG4gICAqIG1lc3NhZ2luZy5vbk1lc3NhZ2UoKS5zdWJzY3JpYmUobm90aWZpY2F0aW9uID0+IHtcbiAgICogICAvLyBNb3N0cmFyIGJhbm5lciBjdXN0b21cbiAgICogICB0aGlzLnNob3dCYW5uZXIobm90aWZpY2F0aW9uLCAoKSA9PiB7XG4gICAqICAgICAvLyBVc3VhcmlvIGhpem8gY2xpY2sgZW4gZWwgYmFubmVyXG4gICAqICAgICBtZXNzYWdpbmcuaGFuZGxlTm90aWZpY2F0aW9uQ2xpY2sobm90aWZpY2F0aW9uKTtcbiAgICogICB9KTtcbiAgICogfSk7XG4gICAqIGBgYFxuICAgKi9cbiAgaGFuZGxlTm90aWZpY2F0aW9uQ2xpY2sobm90aWZpY2F0aW9uOiBOb3RpZmljYXRpb25QYXlsb2FkKTogdm9pZCB7XG4gICAgY29uc3QgYWN0aW9uID0gdGhpcy5leHRyYWN0QWN0aW9uRnJvbURhdGEobm90aWZpY2F0aW9uLmRhdGEpO1xuXG4gICAgdGhpcy5ub3RpZmljYXRpb25DbGlja1N1YmplY3QubmV4dCh7XG4gICAgICBub3RpZmljYXRpb24sXG4gICAgICBhY3Rpb24sXG4gICAgICB0aW1lc3RhbXA6IG5ldyBEYXRlKCksXG4gICAgfSk7XG4gIH1cblxuICAvKipcbiAgICogVmVyaWZpY2Egc2kgdW5hIG5vdGlmaWNhY2nDs24gdGllbmUgYWNjacOzbiBkZSBuYXZlZ2FjacOzbi5cbiAgICpcbiAgICogQHBhcmFtIGRhdGEgLSBEYXRvcyBkZWwgcGF5bG9hZFxuICAgKiBAcmV0dXJucyB0cnVlIHNpIHRpZW5lIHJvdXRlIG8gdXJsXG4gICAqL1xuICBoYXNOYXZpZ2F0aW9uQWN0aW9uKGRhdGE/OiBSZWNvcmQ8c3RyaW5nLCBzdHJpbmc+KTogYm9vbGVhbiB7XG4gICAgaWYgKCFkYXRhKSByZXR1cm4gZmFsc2U7XG4gICAgcmV0dXJuICEhKGRhdGFbJ3JvdXRlJ10gfHwgZGF0YVsndXJsJ10pO1xuICB9XG5cbiAgLyoqXG4gICAqIFBhcnNlYSB1biBxdWVyeSBzdHJpbmcgZW4gdW4gb2JqZXRvLlxuICAgKi9cbiAgcHJpdmF0ZSBwYXJzZVF1ZXJ5U3RyaW5nKHF1ZXJ5U3RyaW5nOiBzdHJpbmcpOiBSZWNvcmQ8c3RyaW5nLCBzdHJpbmc+IHtcbiAgICBjb25zdCBwYXJhbXM6IFJlY29yZDxzdHJpbmcsIHN0cmluZz4gPSB7fTtcblxuICAgIGlmICghcXVlcnlTdHJpbmcpIHJldHVybiBwYXJhbXM7XG5cbiAgICAvLyBSZW1vdmVyID8gaW5pY2lhbCBzaSBleGlzdGVcbiAgICBjb25zdCBjbGVhblF1ZXJ5ID0gcXVlcnlTdHJpbmcuc3RhcnRzV2l0aCgnPycpID8gcXVlcnlTdHJpbmcuc2xpY2UoMSkgOiBxdWVyeVN0cmluZztcblxuICAgIGZvciAoY29uc3QgcGFpciBvZiBjbGVhblF1ZXJ5LnNwbGl0KCcmJykpIHtcbiAgICAgIGNvbnN0IFtrZXksIHZhbHVlXSA9IHBhaXIuc3BsaXQoJz0nKTtcbiAgICAgIGlmIChrZXkpIHtcbiAgICAgICAgcGFyYW1zW2RlY29kZVVSSUNvbXBvbmVudChrZXkpXSA9IGRlY29kZVVSSUNvbXBvbmVudCh2YWx1ZSB8fCAnJyk7XG4gICAgICB9XG4gICAgfVxuXG4gICAgcmV0dXJuIHBhcmFtcztcbiAgfVxufVxuIl19