valtech-components 2.0.498 → 2.0.501

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 (49) hide show
  1. package/esm2022/lib/components/atoms/button/button.component.mjs +87 -48
  2. package/esm2022/lib/components/molecules/action-header/action-header.component.mjs +1 -1
  3. package/esm2022/lib/components/molecules/ad-slot/ad-slot.component.mjs +249 -0
  4. package/esm2022/lib/components/molecules/button-group/button-group.component.mjs +1 -1
  5. package/esm2022/lib/components/molecules/card/card.component.mjs +2 -2
  6. package/esm2022/lib/components/molecules/file-input/file-input.component.mjs +1 -1
  7. package/esm2022/lib/components/molecules/raffle-status-card/raffle-status-card.component.mjs +2 -2
  8. package/esm2022/lib/components/organisms/article/article.component.mjs +2 -2
  9. package/esm2022/lib/components/organisms/menu/menu.component.mjs +1 -1
  10. package/esm2022/lib/components/templates/page-template/page-template.component.mjs +1 -1
  11. package/esm2022/lib/services/ads/ads-consent.service.mjs +152 -0
  12. package/esm2022/lib/services/ads/ads-loader.service.mjs +160 -0
  13. package/esm2022/lib/services/ads/ads.service.mjs +449 -0
  14. package/esm2022/lib/services/ads/config.mjs +118 -0
  15. package/esm2022/lib/services/ads/index.mjs +14 -0
  16. package/esm2022/lib/services/ads/types.mjs +23 -0
  17. package/esm2022/lib/services/auth/auth.service.mjs +103 -6
  18. package/esm2022/lib/services/auth/index.mjs +4 -1
  19. package/esm2022/lib/services/auth/oauth-callback.component.mjs +141 -0
  20. package/esm2022/lib/services/auth/oauth.service.mjs +250 -0
  21. package/esm2022/lib/services/auth/types.mjs +1 -1
  22. package/esm2022/lib/services/firebase/analytics-error-handler.mjs +141 -0
  23. package/esm2022/lib/services/firebase/analytics-router-tracker.mjs +99 -0
  24. package/esm2022/lib/services/firebase/analytics.service.mjs +597 -0
  25. package/esm2022/lib/services/firebase/config.mjs +21 -2
  26. package/esm2022/lib/services/firebase/index.mjs +6 -1
  27. package/esm2022/public-api.mjs +6 -1
  28. package/fesm2022/valtech-components.mjs +2739 -239
  29. package/fesm2022/valtech-components.mjs.map +1 -1
  30. package/lib/components/atoms/button/button.component.d.ts +30 -6
  31. package/lib/components/molecules/ad-slot/ad-slot.component.d.ts +78 -0
  32. package/lib/components/organisms/article/article.component.d.ts +3 -3
  33. package/lib/services/ads/ads-consent.service.d.ts +59 -0
  34. package/lib/services/ads/ads-loader.service.d.ts +46 -0
  35. package/lib/services/ads/ads.service.d.ts +123 -0
  36. package/lib/services/ads/config.d.ts +69 -0
  37. package/lib/services/ads/index.d.ts +10 -0
  38. package/lib/services/ads/types.d.ts +163 -0
  39. package/lib/services/auth/auth.service.d.ts +56 -3
  40. package/lib/services/auth/index.d.ts +2 -0
  41. package/lib/services/auth/oauth-callback.component.d.ts +34 -0
  42. package/lib/services/auth/oauth.service.d.ts +90 -0
  43. package/lib/services/auth/types.d.ts +69 -0
  44. package/lib/services/firebase/analytics-error-handler.d.ts +54 -0
  45. package/lib/services/firebase/analytics-router-tracker.d.ts +51 -0
  46. package/lib/services/firebase/analytics.service.d.ts +256 -0
  47. package/lib/services/firebase/index.d.ts +4 -0
  48. package/package.json +1 -1
  49. package/public-api.d.ts +2 -0
@@ -0,0 +1,449 @@
1
+ /**
2
+ * Ads Service
3
+ *
4
+ * Servicio principal para Google Ad Manager (GPT).
5
+ * Integra con el sistema de consent existente y respeta usuarios premium.
6
+ */
7
+ import { Inject, Injectable, PLATFORM_ID, signal, computed } from '@angular/core';
8
+ import { isPlatformBrowser } from '@angular/common';
9
+ import { NavigationEnd } from '@angular/router';
10
+ import { filter } from 'rxjs/operators';
11
+ import { VALTECH_ADS_CONFIG } from './config';
12
+ import { AD_SIZE_MAP, } from './types';
13
+ import * as i0 from "@angular/core";
14
+ import * as i1 from "@angular/router";
15
+ import * as i2 from "./ads-loader.service";
16
+ import * as i3 from "./ads-consent.service";
17
+ /**
18
+ * Servicio principal de Google Ad Manager.
19
+ *
20
+ * Maneja la creacion, destruccion y refresh de ad slots.
21
+ * Integra automaticamente con consent mode y detecta usuarios premium.
22
+ *
23
+ * @example
24
+ * ```typescript
25
+ * @Component({...})
26
+ * export class MyComponent {
27
+ * private ads = inject(AdsService);
28
+ *
29
+ * // Verificar si mostrar ads
30
+ * showAds = this.ads.isEnabled;
31
+ *
32
+ * // Verificar si usuario es premium
33
+ * isPremium = this.ads.isPremiumUser;
34
+ * }
35
+ * ```
36
+ */
37
+ export class AdsService {
38
+ constructor(injector, config, platformId, router, loaderService, consentService) {
39
+ this.injector = injector;
40
+ this.config = config;
41
+ this.platformId = platformId;
42
+ this.router = router;
43
+ this.loaderService = loaderService;
44
+ this.consentService = consentService;
45
+ // ===========================================================================
46
+ // ESTADO (Signals)
47
+ // ===========================================================================
48
+ this._isInitialized = signal(false);
49
+ this._isEnabled = signal(false);
50
+ this._isPremiumUser = signal(false);
51
+ this._isDebugMode = signal(false);
52
+ this._slots = signal(new Map());
53
+ this._slotStates = signal(new Map());
54
+ this._events = signal([]);
55
+ /** Indica si el servicio esta inicializado */
56
+ this.isInitialized = this._isInitialized.asReadonly();
57
+ /** Indica si los ads estan habilitados (consent + no premium) */
58
+ this.isEnabled = computed(() => {
59
+ return (this._isInitialized() &&
60
+ this._isEnabled() &&
61
+ !this._isPremiumUser() &&
62
+ this.consentService.canShowAds());
63
+ });
64
+ /** Indica si el usuario es premium (no ve ads) */
65
+ this.isPremiumUser = this._isPremiumUser.asReadonly();
66
+ /** Indica si esta en modo debug */
67
+ this.isDebugMode = this._isDebugMode.asReadonly();
68
+ /** Estado de consent para ads */
69
+ this.consentState = this.consentService.adsConsentState;
70
+ /** Eventos de ads (historial) */
71
+ this.events = this._events.asReadonly();
72
+ // ===========================================================================
73
+ // INTERNOS
74
+ // ===========================================================================
75
+ this.activeSlots = new Map();
76
+ this.routerSubscription = null;
77
+ this.refreshTimerId = null;
78
+ this._isDebugMode.set(config.debugMode ?? false);
79
+ }
80
+ // ===========================================================================
81
+ // INICIALIZACION
82
+ // ===========================================================================
83
+ /**
84
+ * Inicializa el servicio de ads.
85
+ * Llamado automaticamente por APP_INITIALIZER.
86
+ * NO carga el script GPT hasta que se necesite el primer ad.
87
+ */
88
+ async initialize() {
89
+ if (!isPlatformBrowser(this.platformId)) {
90
+ return;
91
+ }
92
+ // Verificar si usuario es premium
93
+ if (this.config.isPremiumUser) {
94
+ try {
95
+ this._isPremiumUser.set(this.config.isPremiumUser());
96
+ }
97
+ catch {
98
+ this._isPremiumUser.set(false);
99
+ }
100
+ }
101
+ // Si es premium, no inicializar ads
102
+ if (this._isPremiumUser()) {
103
+ if (this._isDebugMode()) {
104
+ console.log('[ValtechAds] Usuario premium detectado - ads deshabilitados');
105
+ }
106
+ this._isInitialized.set(true);
107
+ return;
108
+ }
109
+ // Verificar consent basico
110
+ if (!this.consentService.canShowAds() && !this.config.showNonPersonalizedAds) {
111
+ if (this._isDebugMode()) {
112
+ console.log('[ValtechAds] Sin consent para ads');
113
+ }
114
+ this._isInitialized.set(true);
115
+ return;
116
+ }
117
+ // Suscribirse a cambios de ruta para verificar exclusiones
118
+ this.setupRouteListener();
119
+ // Configurar auto-refresh si esta habilitado
120
+ if (this.config.autoRefreshInterval && this.config.autoRefreshInterval > 0) {
121
+ this.setupAutoRefresh();
122
+ }
123
+ this._isEnabled.set(true);
124
+ this._isInitialized.set(true);
125
+ if (this._isDebugMode()) {
126
+ console.log('[ValtechAds] Inicializado en modo debug', {
127
+ networkId: this.config.networkId,
128
+ lazyLoad: this.config.lazyLoad,
129
+ excludeRoutes: this.config.excludeRoutes,
130
+ });
131
+ }
132
+ }
133
+ /**
134
+ * Carga el script GPT de forma lazy.
135
+ * Llamado automaticamente cuando se renderiza el primer ad slot.
136
+ */
137
+ async ensureGPTLoaded() {
138
+ if (!this.isEnabled()) {
139
+ return null;
140
+ }
141
+ return this.loaderService.loadGPT();
142
+ }
143
+ // ===========================================================================
144
+ // GESTION DE SLOTS
145
+ // ===========================================================================
146
+ /**
147
+ * Define y muestra un ad slot.
148
+ * Llamado internamente por el componente AdSlot.
149
+ *
150
+ * @param config - Configuracion del slot
151
+ * @returns ID del slot o null si no se puede mostrar
152
+ */
153
+ async defineSlot(config) {
154
+ if (!this.isEnabled()) {
155
+ this.updateSlotState(config.slotId, 'hidden');
156
+ return null;
157
+ }
158
+ // Verificar si la ruta actual esta excluida
159
+ if (this.isRouteExcluded()) {
160
+ this.updateSlotState(config.slotId, 'hidden');
161
+ return null;
162
+ }
163
+ this.updateSlotState(config.slotId, 'loading');
164
+ const googletag = await this.ensureGPTLoaded();
165
+ if (!googletag) {
166
+ this.updateSlotState(config.slotId, 'error');
167
+ return null;
168
+ }
169
+ return new Promise((resolve) => {
170
+ googletag.cmd.push(() => {
171
+ try {
172
+ const adUnitPath = `${this.config.networkId}${config.adUnitPath}`;
173
+ const sizes = this.resolveSizes(config.size);
174
+ const slot = googletag.defineSlot(adUnitPath, sizes, config.slotId);
175
+ if (!slot) {
176
+ this.updateSlotState(config.slotId, 'error');
177
+ this.emitEvent({ type: 'error', slotId: config.slotId, error: new Error('No se pudo crear el slot') });
178
+ resolve(null);
179
+ return;
180
+ }
181
+ // Agregar al servicio pubads
182
+ slot.addService(googletag.pubads());
183
+ // Configurar size mapping responsivo
184
+ if (config.sizeMapping && config.sizeMapping.length > 0) {
185
+ const mapping = this.buildSizeMapping(googletag, config.sizeMapping);
186
+ slot.defineSizeMapping(mapping);
187
+ }
188
+ // Configurar targeting
189
+ this.applyTargeting(slot, config.targeting);
190
+ // Colapsar si esta vacio
191
+ if (config.collapseEmpty ?? this.config.defaultSlotConfig?.collapseEmpty) {
192
+ slot.setCollapseEmptyDiv(true, true);
193
+ }
194
+ // Guardar referencia
195
+ this.activeSlots.set(config.slotId, slot);
196
+ this._slots.update((slots) => new Map(slots).set(config.slotId, slot));
197
+ // Mostrar el ad
198
+ googletag.enableServices();
199
+ googletag.display(config.slotId);
200
+ this.updateSlotState(config.slotId, 'rendered');
201
+ this.emitEvent({ type: 'loaded', slotId: config.slotId, isEmpty: false });
202
+ if (this._isDebugMode()) {
203
+ console.log(`[ValtechAds] Slot definido: ${config.slotId}`, {
204
+ adUnitPath,
205
+ sizes: config.size,
206
+ });
207
+ }
208
+ resolve(config.slotId);
209
+ }
210
+ catch (error) {
211
+ console.error('[ValtechAds] Error definiendo slot:', error);
212
+ this.updateSlotState(config.slotId, 'error');
213
+ this.emitEvent({ type: 'error', slotId: config.slotId, error: error });
214
+ resolve(null);
215
+ }
216
+ });
217
+ });
218
+ }
219
+ /**
220
+ * Destruye un slot y libera recursos.
221
+ *
222
+ * @param slotId - ID del slot a destruir
223
+ */
224
+ destroySlot(slotId) {
225
+ const slot = this.activeSlots.get(slotId);
226
+ if (!slot)
227
+ return;
228
+ const googletag = window.googletag;
229
+ if (googletag) {
230
+ googletag.cmd.push(() => {
231
+ googletag.destroySlots([slot]);
232
+ });
233
+ }
234
+ this.activeSlots.delete(slotId);
235
+ this._slots.update((slots) => {
236
+ const newSlots = new Map(slots);
237
+ newSlots.delete(slotId);
238
+ return newSlots;
239
+ });
240
+ this._slotStates.update((states) => {
241
+ const newStates = new Map(states);
242
+ newStates.delete(slotId);
243
+ return newStates;
244
+ });
245
+ if (this._isDebugMode()) {
246
+ console.log(`[ValtechAds] Slot destruido: ${slotId}`);
247
+ }
248
+ }
249
+ /**
250
+ * Refresca un slot especifico o todos los slots activos.
251
+ *
252
+ * @param slotIds - IDs de slots a refrescar (undefined = todos)
253
+ */
254
+ refreshSlots(slotIds) {
255
+ if (!this.isEnabled())
256
+ return;
257
+ const googletag = window.googletag;
258
+ if (!googletag)
259
+ return;
260
+ googletag.cmd.push(() => {
261
+ if (slotIds && slotIds.length > 0) {
262
+ const slots = slotIds.map((id) => this.activeSlots.get(id)).filter((s) => !!s);
263
+ if (slots.length > 0) {
264
+ googletag.pubads().refresh(slots);
265
+ if (this._isDebugMode()) {
266
+ console.log(`[ValtechAds] Slots refrescados: ${slotIds.join(', ')}`);
267
+ }
268
+ }
269
+ }
270
+ else {
271
+ googletag.pubads().refresh();
272
+ if (this._isDebugMode()) {
273
+ console.log('[ValtechAds] Todos los slots refrescados');
274
+ }
275
+ }
276
+ });
277
+ }
278
+ /**
279
+ * Obtiene el estado de un slot.
280
+ *
281
+ * @param slotId - ID del slot
282
+ * @returns Estado actual del slot
283
+ */
284
+ getSlotState(slotId) {
285
+ return this._slotStates().get(slotId) ?? 'idle';
286
+ }
287
+ // ===========================================================================
288
+ // PREMIUM USER
289
+ // ===========================================================================
290
+ /**
291
+ * Actualiza el estado premium del usuario.
292
+ * Llamar cuando cambie el estado de suscripcion.
293
+ *
294
+ * @param isPremium - Nuevo estado premium
295
+ */
296
+ updatePremiumStatus(isPremium) {
297
+ const wasEnabled = this.isEnabled();
298
+ this._isPremiumUser.set(isPremium);
299
+ if (isPremium && wasEnabled) {
300
+ // Destruir todos los slots activos
301
+ this.destroyAllSlots();
302
+ if (this._isDebugMode()) {
303
+ console.log('[ValtechAds] Usuario ahora es premium - ads deshabilitados');
304
+ }
305
+ }
306
+ else if (!isPremium && !wasEnabled && this._isInitialized()) {
307
+ if (this._isDebugMode()) {
308
+ console.log('[ValtechAds] Usuario ya no es premium - ads habilitados');
309
+ }
310
+ }
311
+ }
312
+ /**
313
+ * Destruye todos los slots activos.
314
+ */
315
+ destroyAllSlots() {
316
+ const googletag = window.googletag;
317
+ if (googletag) {
318
+ googletag.cmd.push(() => {
319
+ googletag.destroySlots();
320
+ });
321
+ }
322
+ this.activeSlots.clear();
323
+ this._slots.set(new Map());
324
+ this._slotStates.set(new Map());
325
+ if (this._isDebugMode()) {
326
+ console.log('[ValtechAds] Todos los slots destruidos');
327
+ }
328
+ }
329
+ // ===========================================================================
330
+ // PRIVATE METHODS
331
+ // ===========================================================================
332
+ resolveSizes(size) {
333
+ if (typeof size === 'string') {
334
+ // Single preset size
335
+ const mapped = AD_SIZE_MAP[size];
336
+ return mapped === 'fluid' ? 'fluid' : [mapped];
337
+ }
338
+ if (Array.isArray(size)) {
339
+ if (typeof size[0] === 'string') {
340
+ // Array of preset sizes
341
+ return size.map((s) => {
342
+ const mapped = AD_SIZE_MAP[s];
343
+ return mapped === 'fluid' ? 'fluid' : mapped;
344
+ });
345
+ }
346
+ // Direct size array
347
+ return size;
348
+ }
349
+ return 'fluid';
350
+ }
351
+ buildSizeMapping(googletag, mapping) {
352
+ const builder = googletag.sizeMapping();
353
+ // Ordenar por viewport descendente
354
+ const sorted = [...mapping].sort((a, b) => b.viewportWidth - a.viewportWidth);
355
+ for (const m of sorted) {
356
+ builder.addSize([m.viewportWidth, 0], m.sizes);
357
+ }
358
+ return builder.build();
359
+ }
360
+ applyTargeting(slot, targeting) {
361
+ // Aplicar targeting global
362
+ if (this.config.globalTargeting) {
363
+ for (const [key, value] of Object.entries(this.config.globalTargeting)) {
364
+ slot.setTargeting(key, value);
365
+ }
366
+ }
367
+ // Aplicar targeting del slot
368
+ if (targeting) {
369
+ for (const [key, value] of Object.entries(targeting)) {
370
+ slot.setTargeting(key, value);
371
+ }
372
+ }
373
+ // Agregar targeting de debug si esta habilitado
374
+ if (this._isDebugMode()) {
375
+ slot.setTargeting('test', 'true');
376
+ }
377
+ }
378
+ updateSlotState(slotId, state) {
379
+ this._slotStates.update((states) => new Map(states).set(slotId, state));
380
+ }
381
+ emitEvent(event) {
382
+ const fullEvent = { ...event, timestamp: new Date() };
383
+ this._events.update((events) => [...events.slice(-99), fullEvent]);
384
+ // Callbacks de configuracion
385
+ if (event.type === 'loaded' || event.type === 'empty') {
386
+ this.config.onAdLoaded?.(event.slotId, event.isEmpty ?? false);
387
+ }
388
+ else if (event.type === 'error' && event.error) {
389
+ this.config.onAdError?.(event.slotId, event.error);
390
+ }
391
+ }
392
+ setupRouteListener() {
393
+ if (!this.config.excludeRoutes || this.config.excludeRoutes.length === 0) {
394
+ return;
395
+ }
396
+ this.routerSubscription = this.router.events
397
+ .pipe(filter((event) => event instanceof NavigationEnd))
398
+ .subscribe((event) => {
399
+ const shouldHide = this.isRouteExcluded(event.urlAfterRedirects);
400
+ if (shouldHide) {
401
+ this.destroyAllSlots();
402
+ }
403
+ });
404
+ }
405
+ setupAutoRefresh() {
406
+ const intervalMs = (this.config.autoRefreshInterval ?? 0) * 1000;
407
+ if (intervalMs <= 0)
408
+ return;
409
+ this.refreshTimerId = setInterval(() => {
410
+ if (this.isEnabled() && this.activeSlots.size > 0) {
411
+ this.refreshSlots();
412
+ }
413
+ }, intervalMs);
414
+ }
415
+ isRouteExcluded(url) {
416
+ if (!this.config.excludeRoutes || this.config.excludeRoutes.length === 0) {
417
+ return false;
418
+ }
419
+ const currentUrl = url ?? this.router.url;
420
+ return this.config.excludeRoutes.some((pattern) => {
421
+ const regex = new RegExp(pattern);
422
+ return regex.test(currentUrl);
423
+ });
424
+ }
425
+ // ===========================================================================
426
+ // LIFECYCLE
427
+ // ===========================================================================
428
+ ngOnDestroy() {
429
+ this.routerSubscription?.unsubscribe();
430
+ if (this.refreshTimerId) {
431
+ clearInterval(this.refreshTimerId);
432
+ }
433
+ this.destroyAllSlots();
434
+ this.consentService.destroy();
435
+ }
436
+ static { this.ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "18.2.14", ngImport: i0, type: AdsService, deps: [{ token: i0.Injector }, { token: VALTECH_ADS_CONFIG }, { token: PLATFORM_ID }, { token: i1.Router }, { token: i2.AdsLoaderService }, { token: i3.AdsConsentService }], target: i0.ɵɵFactoryTarget.Injectable }); }
437
+ static { this.ɵprov = i0.ɵɵngDeclareInjectable({ minVersion: "12.0.0", version: "18.2.14", ngImport: i0, type: AdsService, providedIn: 'root' }); }
438
+ }
439
+ i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "18.2.14", ngImport: i0, type: AdsService, decorators: [{
440
+ type: Injectable,
441
+ args: [{ providedIn: 'root' }]
442
+ }], ctorParameters: () => [{ type: i0.Injector }, { type: undefined, decorators: [{
443
+ type: Inject,
444
+ args: [VALTECH_ADS_CONFIG]
445
+ }] }, { type: Object, decorators: [{
446
+ type: Inject,
447
+ args: [PLATFORM_ID]
448
+ }] }, { type: i1.Router }, { type: i2.AdsLoaderService }, { type: i3.AdsConsentService }] });
449
+ //# sourceMappingURL=data:application/json;base64,eyJ2ZXJzaW9uIjozLCJmaWxlIjoiYWRzLnNlcnZpY2UuanMiLCJzb3VyY2VSb290IjoiIiwic291cmNlcyI6WyIuLi8uLi8uLi8uLi8uLi8uLi9zcmMvbGliL3NlcnZpY2VzL2Fkcy9hZHMuc2VydmljZS50cyJdLCJuYW1lcyI6W10sIm1hcHBpbmdzIjoiQUFBQTs7Ozs7R0FLRztBQUVILE9BQU8sRUFBRSxNQUFNLEVBQUUsVUFBVSxFQUFZLFdBQVcsRUFBRSxNQUFNLEVBQUUsUUFBUSxFQUFhLE1BQU0sZUFBZSxDQUFDO0FBQ3ZHLE9BQU8sRUFBRSxpQkFBaUIsRUFBRSxNQUFNLGlCQUFpQixDQUFDO0FBQ3BELE9BQU8sRUFBVSxhQUFhLEVBQUUsTUFBTSxpQkFBaUIsQ0FBQztBQUN4RCxPQUFPLEVBQUUsTUFBTSxFQUFFLE1BQU0sZ0JBQWdCLENBQUM7QUFHeEMsT0FBTyxFQUFFLGtCQUFrQixFQUFFLE1BQU0sVUFBVSxDQUFDO0FBRzlDLE9BQU8sRUFRTCxXQUFXLEdBRVosTUFBTSxTQUFTLENBQUM7Ozs7O0FBRWpCOzs7Ozs7Ozs7Ozs7Ozs7Ozs7O0dBbUJHO0FBRUgsTUFBTSxPQUFPLFVBQVU7SUE4Q3JCLFlBQ1UsUUFBa0IsRUFDVSxNQUF3QixFQUMvQixVQUFrQixFQUN2QyxNQUFjLEVBQ2QsYUFBK0IsRUFDL0IsY0FBaUM7UUFMakMsYUFBUSxHQUFSLFFBQVEsQ0FBVTtRQUNVLFdBQU0sR0FBTixNQUFNLENBQWtCO1FBQy9CLGVBQVUsR0FBVixVQUFVLENBQVE7UUFDdkMsV0FBTSxHQUFOLE1BQU0sQ0FBUTtRQUNkLGtCQUFhLEdBQWIsYUFBYSxDQUFrQjtRQUMvQixtQkFBYyxHQUFkLGNBQWMsQ0FBbUI7UUFuRDNDLDhFQUE4RTtRQUM5RSxtQkFBbUI7UUFDbkIsOEVBQThFO1FBRTdELG1CQUFjLEdBQUcsTUFBTSxDQUFVLEtBQUssQ0FBQyxDQUFDO1FBQ3hDLGVBQVUsR0FBRyxNQUFNLENBQVUsS0FBSyxDQUFDLENBQUM7UUFDcEMsbUJBQWMsR0FBRyxNQUFNLENBQVUsS0FBSyxDQUFD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QUFDLGFBQWEsQ0FBQyxJQUFJLENBQUMsQ0FBQyxPQUFPLEVBQUUsRUFBRTtZQUNoRCxNQUFNLEtBQUssR0FBRyxJQUFJLE1BQU0sQ0FBQyxPQUFPLENBQUMsQ0FBQztZQUNsQyxPQUFPLEtBQUssQ0FBQyxJQUFJLENBQUMsVUFBVSxDQUFDLENBQUM7UUFDaEMsQ0FBQyxDQUFDLENBQUM7SUFDTCxDQUFDO0lBRUQsOEVBQThFO0lBQzlFLFlBQVk7SUFDWiw4RUFBOEU7SUFFOUUsV0FBVztRQUNULElBQUksQ0FBQyxrQkFBa0IsRUFBRSxXQUFXLEVBQUUsQ0FBQztRQUV2QyxJQUFJLElBQUksQ0FBQyxjQUFjLEVBQUUsQ0FBQztZQUN4QixhQUFhLENBQUMsSUFBSSxDQUFDLGNBQWMsQ0FBQyxDQUFDO1FBQ3JDLENBQUM7UUFFRCxJQUFJLENBQUMsZUFBZSxFQUFFLENBQUM7UUFDdkIsSUFBSSxDQUFDLGNBQWMsQ0FBQyxPQUFPLEVBQUUsQ0FBQztJQUNoQyxDQUFDOytHQW5kVSxVQUFVLDBDQWdEWCxrQkFBa0IsYUFDbEIsV0FBVzttSEFqRFYsVUFBVSxjQURHLE1BQU07OzRGQUNuQixVQUFVO2tCQUR0QixVQUFVO21CQUFDLEVBQUUsVUFBVSxFQUFFLE1BQU0sRUFBRTs7MEJBaUQ3QixNQUFNOzJCQUFDLGtCQUFrQjs7MEJBQ3pCLE1BQU07MkJBQUMsV0FBVyIsInNvdXJjZXNDb250ZW50IjpbIi8qKlxuICogQWRzIFNlcnZpY2VcbiAqXG4gKiBTZXJ2aWNpbyBwcmluY2lwYWwgcGFyYSBHb29nbGUgQWQgTWFuYWdlciAoR1BUKS5cbiAqIEludGVncmEgY29uIGVsIHNpc3RlbWEgZGUgY29uc2VudCBleGlzdGVudGUgeSByZXNwZXRhIHVzdWFyaW9zIHByZW1pdW0uXG4gKi9cblxuaW1wb3J0IHsgSW5qZWN0LCBJbmplY3RhYmxlLCBJbmplY3RvciwgUExBVEZPUk1fSUQsIHNpZ25hbCwgY29tcHV0ZWQsIE9uRGVzdHJveSB9IGZyb20gJ0Bhbmd1bGFyL2NvcmUnO1xuaW1wb3J0IHsgaXNQbGF0Zm9ybUJyb3dzZXIgfSBmcm9tICdAYW5ndWxhci9jb21tb24nO1xuaW1wb3J0IHsgUm91dGVyLCBOYXZpZ2F0aW9uRW5kIH0gZnJvbSAnQGFuZ3VsYXIvcm91dGVyJztcbmltcG9ydCB7IGZpbHRlciB9IGZyb20gJ3J4anMvb3BlcmF0b3JzJztcbmltcG9ydCB7IFN1YnNjcmlwdGlvbiB9IGZyb20gJ3J4anMnO1xuXG5pbXBvcnQgeyBWQUxURUNIX0FEU19DT05GSUcgfSBmcm9tICcuL2NvbmZpZyc7XG5pbXBvcnQgeyBBZHNMb2FkZXJTZXJ2aWNlIH0gZnJvbSAnLi9hZHMtbG9hZGVyLnNlcnZpY2UnO1xuaW1wb3J0IHsgQWRzQ29uc2VudFNlcnZpY2UgfSBmcm9tICcuL2Fkcy1jb25zZW50LnNlcnZpY2UnO1xuaW1wb3J0IHtcbiAgVmFsdGVjaEFkc0NvbmZpZyxcbiAgQWRTbG90Q29uZmlnLFxuICBBZFNsb3RTdGF0ZSxcbiAgQWRFdmVudCxcbiAgR1BUU2xvdCxcbiAgR1BUTmFtZXNwYWNlLFxuICBTaXplTWFwcGluZyxcbiAgQURfU0laRV9NQVAsXG4gIEFkU2xvdFNpemUsXG59IGZyb20gJy4vdHlwZXMnO1xuXG4vKipcbiAqIFNlcnZpY2lvIHByaW5jaXBhbCBkZSBHb29nbGUgQWQgTWFuYWdlci5cbiAqXG4gKiBNYW5lamEgbGEgY3JlYWNpb24sIGRlc3RydWNjaW9uIHkgcmVmcmVzaCBkZSBhZCBzbG90cy5cbiAqIEludGVncmEgYXV0b21hdGljYW1lbnRlIGNvbiBjb25zZW50IG1vZGUgeSBkZXRlY3RhIHVzdWFyaW9zIHByZW1pdW0uXG4gKlxuICogQGV4YW1wbGVcbiAqIGBgYHR5cGVzY3JpcHRcbiAqIEBDb21wb25lbnQoey4uLn0pXG4gKiBleHBvcnQgY2xhc3MgTXlDb21wb25lbnQge1xuICogICBwcml2YXRlIGFkcyA9IGluamVjdChBZHNTZXJ2aWNlKTtcbiAqXG4gKiAgIC8vIFZlcmlmaWNhciBzaSBtb3N0cmFyIGFkc1xuICogICBzaG93QWRzID0gdGhpcy5hZHMuaXNFbmFibGVkO1xuICpcbiAqICAgLy8gVmVyaWZpY2FyIHNpIHVzdWFyaW8gZXMgcHJlbWl1bVxuICogICBpc1ByZW1pdW0gPSB0aGlzLmFkcy5pc1ByZW1pdW1Vc2VyO1xuICogfVxuICogYGBgXG4gKi9cbkBJbmplY3RhYmxlKHsgcHJvdmlkZWRJbjogJ3Jvb3QnIH0pXG5leHBvcnQgY2xhc3MgQWRzU2VydmljZSBpbXBsZW1lbnRzIE9uRGVzdHJveSB7XG4gIC8vID09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PVxuICAvLyBFU1RBRE8gKFNpZ25hbHMpXG4gIC8vID09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PVxuXG4gIHByaXZhdGUgcmVhZG9ubHkgX2lzSW5pdGlhbGl6ZWQgPSBzaWduYWw8Ym9vbGVhbj4oZmFsc2UpO1xuICBwcml2YXRlIHJlYWRvbmx5IF9pc0VuYWJsZWQgPSBzaWduYWw8Ym9vbGVhbj4oZmFsc2UpO1xuICBwcml2YXRlIHJlYWRvbmx5IF9pc1ByZW1pdW1Vc2VyID0gc2lnbmFsPGJvb2xlYW4+KGZhbHNlKTtcbiAgcHJpdmF0ZSByZWFkb25seSBfaXNEZWJ1Z01vZGUgPSBzaWduYWw8Ym9vbGVhbj4oZmFsc2UpO1xuICBwcml2YXRlIHJlYWRvbmx5IF9zbG90cyA9IHNpZ25hbDxNYXA8c3RyaW5nLCBHUFRTbG90Pj4obmV3IE1hcCgpKTtcbiAgcHJpdmF0ZSByZWFkb25seSBfc2xvdFN0YXRlcyA9IHNpZ25hbDxNYXA8c3RyaW5nLCBBZFNsb3RTdGF0ZT4+KG5ldyBNYXAoKSk7XG4gIHByaXZhdGUgcmVhZG9ubHkgX2V2ZW50cyA9IHNpZ25hbDxBZEV2ZW50W10+KFtdKTtcblxuICAvKiogSW5kaWNhIHNpIGVsIHNlcnZpY2lvIGVzdGEgaW5pY2lhbGl6YWRvICovXG4gIHJlYWRvbmx5IGlzSW5pdGlhbGl6ZWQgPSB0aGlzLl9pc0luaXRpYWxpemVkLmFzUmVhZG9ubHkoKTtcblxuICAvKiogSW5kaWNhIHNpIGxvcyBhZHMgZXN0YW4gaGFiaWxpdGFkb3MgKGNvbnNlbnQgKyBubyBwcmVtaXVtKSAqL1xuICByZWFkb25seSBpc0VuYWJsZWQgPSBjb21wdXRlZCgoKSA9PiB7XG4gICAgcmV0dXJuIChcbiAgICAgIHRoaXMuX2lzSW5pdGlhbGl6ZWQoKSAmJlxuICAgICAgdGhpcy5faXNFbmFibGVkKCkgJiZcbiAgICAgICF0aGlzLl9pc1ByZW1pdW1Vc2VyKCkgJiZcbiAgICAgIHRoaXMuY29uc2VudFNlcnZpY2UuY2FuU2hvd0FkcygpXG4gICAgKTtcbiAgfSk7XG5cbiAgLyoqIEluZGljYSBzaSBlbCB1c3VhcmlvIGVzIHByZW1pdW0gKG5vIHZlIGFkcykgKi9cbiAgcmVhZG9ubHkgaXNQcmVtaXVtVXNlciA9IHRoaXMuX2lzUHJlbWl1bVVzZXIuYXNSZWFkb25seSgpO1xuXG4gIC8qKiBJbmRpY2Egc2kgZXN0YSBlbiBtb2RvIGRlYnVnICovXG4gIHJlYWRvbmx5IGlzRGVidWdNb2RlID0gdGhpcy5faXNEZWJ1Z01vZGUuYXNSZWFkb25seSgpO1xuXG4gIC8qKiBFc3RhZG8gZGUgY29uc2VudCBwYXJhIGFkcyAqL1xuICByZWFkb25seSBjb25zZW50U3RhdGUgPSB0aGlzLmNvbnNlbnRTZXJ2aWNlLmFkc0NvbnNlbnRTdGF0ZTtcblxuICAvKiogRXZlbnRvcyBkZSBhZHMgKGhpc3RvcmlhbCkgKi9cbiAgcmVhZG9ubHkgZXZlbnRzID0gdGhpcy5fZXZlbnRzLmFzUmVhZG9ubHkoKTtcblxuICAvLyA9PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT1cbiAgLy8gSU5URVJOT1NcbiAgLy8gPT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09XG5cbiAgcHJpdmF0ZSBhY3RpdmVTbG90czogTWFwPHN0cmluZywgR1BUU2xvdD4gPSBuZXcgTWFwKCk7XG4gIHByaXZhdGUgcm91dGVyU3Vic2NyaXB0aW9uOiBTdWJzY3JpcHRpb24gfCBudWxsID0gbnVsbDtcbiAgcHJpdmF0ZSByZWZyZXNoVGltZXJJZDogUmV0dXJuVHlwZTx0eXBlb2Ygc2V0SW50ZXJ2YWw+IHwgbnVsbCA9IG51bGw7XG5cbiAgY29uc3RydWN0b3IoXG4gICAgcHJpdmF0ZSBpbmplY3RvcjogSW5qZWN0b3IsXG4gICAgQEluamVjdChWQUxURUNIX0FEU19DT05GSUcpIHByaXZhdGUgY29uZmlnOiBWYWx0ZWNoQWRzQ29uZmlnLFxuICAgIEBJbmplY3QoUExBVEZPUk1fSUQpIHByaXZhdGUgcGxhdGZvcm1JZDogT2JqZWN0LFxuICAgIHByaXZhdGUgcm91dGVyOiBSb3V0ZXIsXG4gICAgcHJpdmF0ZSBsb2FkZXJTZXJ2aWNlOiBBZHNMb2FkZXJTZXJ2aWNlLFxuICAgIHByaXZhdGUgY29uc2VudFNlcnZpY2U6IEFkc0NvbnNlbnRTZXJ2aWNlXG4gICkge1xuICAgIHRoaXMuX2lzRGVidWdNb2RlLnNldChjb25maWcuZGVidWdNb2RlID8/IGZhbHNlKTtcbiAgfVxuXG4gIC8vID09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PVxuICAvLyBJTklDSUFMSVpBQ0lPTlxuICAvLyA9PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT1cblxuICAvKipcbiAgICogSW5pY2lhbGl6YSBlbCBzZXJ2aWNpbyBkZSBhZHMuXG4gICAqIExsYW1hZG8gYXV0b21hdGljYW1lbnRlIHBvciBBUFBfSU5JVElBTElaRVIuXG4gICAqIE5PIGNhcmdhIGVsIHNjcmlwdCBHUFQgaGFzdGEgcXVlIHNlIG5lY2VzaXRlIGVsIHByaW1lciBhZC5cbiAgICovXG4gIGFzeW5jIGluaXRpYWxpemUoKTogUHJvbWlzZTx2b2lkPiB7XG4gICAgaWYgKCFpc1BsYXRmb3JtQnJvd3Nlcih0aGlzLnBsYXRmb3JtSWQpKSB7XG4gICAgICByZXR1cm47XG4gICAgfVxuXG4gICAgLy8gVmVyaWZpY2FyIHNpIHVzdWFyaW8gZXMgcHJlbWl1bVxuICAgIGlmICh0aGlzLmNvbmZpZy5pc1ByZW1pdW1Vc2VyKSB7XG4gICAgICB0cnkge1xuICAgICAgICB0aGlzLl9pc1ByZW1pdW1Vc2VyLnNldCh0aGlzLmNvbmZpZy5pc1ByZW1pdW1Vc2VyKCkpO1xuICAgICAgfSBjYXRjaCB7XG4gICAgICAgIHRoaXMuX2lzUHJlbWl1bVVzZXIuc2V0KGZhbHNlKTtcbiAgICAgIH1cbiAgICB9XG5cbiAgICAvLyBTaSBlcyBwcmVtaXVtLCBubyBpbmljaWFsaXphciBhZHNcbiAgICBpZiAodGhpcy5faXNQcmVtaXVtVXNlcigpKSB7XG4gICAgICBpZiAodGhpcy5faXNEZWJ1Z01vZGUoKSkge1xuICAgICAgICBjb25zb2xlLmxvZygnW1ZhbHRlY2hBZHNdIFVzdWFyaW8gcHJlbWl1bSBkZXRlY3RhZG8gLSBhZHMgZGVzaGFiaWxpdGFkb3MnKTtcbiAgICAgIH1cbiAgICAgIHRoaXMuX2lzSW5pdGlhbGl6ZWQuc2V0KHRydWUpO1xuICAgICAgcmV0dXJuO1xuICAgIH1cblxuICAgIC8vIFZlcmlmaWNhciBjb25zZW50IGJhc2ljb1xuICAgIGlmICghdGhpcy5jb25zZW50U2VydmljZS5jYW5TaG93QWRzKCkgJiYgIXRoaXMuY29uZmlnLnNob3dOb25QZXJzb25hbGl6ZWRBZHMpIHtcbiAgICAgIGlmICh0aGlzLl9pc0RlYnVnTW9kZSgpKSB7XG4gICAgICAgIGNvbnNvbGUubG9nKCdbVmFsdGVjaEFkc10gU2luIGNvbnNlbnQgcGFyYSBhZHMnKTtcbiAgICAgIH1cbiAgICAgIHRoaXMuX2lzSW5pdGlhbGl6ZWQuc2V0KHRydWUpO1xuICAgICAgcmV0dXJuO1xuICAgIH1cblxuICAgIC8vIFN1c2NyaWJpcnNlIGEgY2FtYmlvcyBkZSBydXRhIHBhcmEgdmVyaWZpY2FyIGV4Y2x1c2lvbmVzXG4gICAgdGhpcy5zZXR1cFJvdXRlTGlzdGVuZXIoKTtcblxuICAgIC8vIENvbmZpZ3VyYXIgYXV0by1yZWZyZXNoIHNpIGVzdGEgaGFiaWxpdGFkb1xuICAgIGlmICh0aGlzLmNvbmZpZy5hdXRvUmVmcmVzaEludGVydmFsICYmIHRoaXMuY29uZmlnLmF1dG9SZWZyZXNoSW50ZXJ2YWwgPiAwKSB7XG4gICAgICB0aGlzLnNldHVwQXV0b1JlZnJlc2goKTtcbiAgICB9XG5cbiAgICB0aGlzLl9pc0VuYWJsZWQuc2V0KHRydWUpO1xuICAgIHRoaXMuX2lzSW5pdGlhbGl6ZWQuc2V0KHRydWUpO1xuXG4gICAgaWYgKHRoaXMuX2lzRGVidWdNb2RlKCkpIHtcbiAgICAgIGNvbnNvbGUubG9nKCdbVmFsdGVjaEFkc10gSW5pY2lhbGl6YWRvIGVuIG1vZG8gZGVidWcnLCB7XG4gICAgICAgIG5ldHdvcmtJZDogdGhpcy5jb25maWcubmV0d29ya0lkLFxuICAgICAgICBsYXp5TG9hZDogdGhpcy5jb25maWcubGF6eUxvYWQsXG4gICAgICAgIGV4Y2x1ZGVSb3V0ZXM6IHRoaXMuY29uZmlnLmV4Y2x1ZGVSb3V0ZXMsXG4gICAgICB9KTtcbiAgICB9XG4gIH1cblxuICAvKipcbiAgICogQ2FyZ2EgZWwgc2NyaXB0IEdQVCBkZSBmb3JtYSBsYXp5LlxuICAgKiBMbGFtYWRvIGF1dG9tYXRpY2FtZW50ZSBjdWFuZG8gc2UgcmVuZGVyaXphIGVsIHByaW1lciBhZCBzbG90LlxuICAgKi9cbiAgYXN5bmMgZW5zdXJlR1BUTG9hZGVkKCk6IFByb21pc2U8R1BUTmFtZXNwYWNlIHwgbnVsbD4ge1xuICAgIGlmICghdGhpcy5pc0VuYWJsZWQoKSkge1xuICAgICAgcmV0dXJuIG51bGw7XG4gICAgfVxuXG4gICAgcmV0dXJuIHRoaXMubG9hZGVyU2VydmljZS5sb2FkR1BUKCk7XG4gIH1cblxuICAvLyA9PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT1cbiAgLy8gR0VTVElPTiBERSBTTE9UU1xuICAvLyA9PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT1cblxuICAvKipcbiAgICogRGVmaW5lIHkgbXVlc3RyYSB1biBhZCBzbG90LlxuICAgKiBMbGFtYWRvIGludGVybmFtZW50ZSBwb3IgZWwgY29tcG9uZW50ZSBBZFNsb3QuXG4gICAqXG4gICAqIEBwYXJhbSBjb25maWcgLSBDb25maWd1cmFjaW9uIGRlbCBzbG90XG4gICAqIEByZXR1cm5zIElEIGRlbCBzbG90IG8gbnVsbCBzaSBubyBzZSBwdWVkZSBtb3N0cmFyXG4gICAqL1xuICBhc3luYyBkZWZpbmVTbG90KGNvbmZpZzogQWRTbG90Q29uZmlnKTogUHJvbWlzZTxzdHJpbmcgfCBudWxsPiB7XG4gICAgaWYgKCF0aGlzLmlzRW5hYmxlZCgpKSB7XG4gICAgICB0aGlzLnVwZGF0ZVNsb3RTdGF0ZShjb25maWcuc2xvdElkLCAnaGlkZGVuJyk7XG4gICAgICByZXR1cm4gbnVsbDtcbiAgICB9XG5cbiAgICAvLyBWZXJpZmljYXIgc2kgbGEgcnV0YSBhY3R1YWwgZXN0YSBleGNsdWlkYVxuICAgIGlmICh0aGlzLmlzUm91dGVFeGNsdWRlZCgpKSB7XG4gICAgICB0aGlzLnVwZGF0ZVNsb3RTdGF0ZShjb25maWcuc2xvdElkLCAnaGlkZGVuJyk7XG4gICAgICByZXR1cm4gbnVsbDtcbiAgICB9XG5cbiAgICB0aGlzLnVwZGF0ZVNsb3RTdGF0ZShjb25maWcuc2xvdElkLCAnbG9hZGluZycpO1xuXG4gICAgY29uc3QgZ29vZ2xldGFnID0gYXdhaXQgdGhpcy5lbnN1cmVHUFRMb2FkZWQoKTtcbiAgICBpZiAoIWdvb2dsZXRhZykge1xuICAgICAgdGhpcy51cGRhdGVTbG90U3RhdGUoY29uZmlnLnNsb3RJZCwgJ2Vycm9yJyk7XG4gICAgICByZXR1cm4gbnVsbDtcbiAgICB9XG5cbiAgICByZXR1cm4gbmV3IFByb21pc2UoKHJlc29sdmUpID0+IHtcbiAgICAgIGdvb2dsZXRhZy5jbWQucHVzaCgoKSA9PiB7XG4gICAgICAgIHRyeSB7XG4gICAgICAgICAgY29uc3QgYWRVbml0UGF0aCA9IGAke3RoaXMuY29uZmlnLm5ldHdvcmtJZH0ke2NvbmZpZy5hZFVuaXRQYXRofWA7XG4gICAgICAgICAgY29uc3Qgc2l6ZXMgPSB0aGlzLnJlc29sdmVTaXplcyhjb25maWcuc2l6ZSk7XG5cbiAgICAgICAgICBjb25zdCBzbG90ID0gZ29vZ2xldGFnLmRlZmluZVNsb3QoYWRVbml0UGF0aCwgc2l6ZXMsIGNvbmZpZy5zbG90SWQpO1xuICAgICAgICAgIGlmICghc2xvdCkge1xuICAgICAgICAgICAgdGhpcy51cGRhdGVTbG90U3RhdGUoY29uZmlnLnNsb3RJZCwgJ2Vycm9yJyk7XG4gICAgICAgICAgICB0aGlzLmVtaXRFdmVudCh7IHR5cGU6ICdlcnJvcicsIHNsb3RJZDogY29uZmlnLnNsb3RJZCwgZXJyb3I6IG5ldyBFcnJvcignTm8gc2UgcHVkbyBjcmVhciBlbCBzbG90JykgfSk7XG4gICAgICAgICAgICByZXNvbHZlKG51bGwpO1xuICAgICAgICAgICAgcmV0dXJuO1xuICAgICAgICAgIH1cblxuICAgICAgICAgIC8vIEFncmVnYXIgYWwgc2VydmljaW8gcHViYWRzXG4gICAgICAgICAgc2xvdC5hZGRTZXJ2aWNlKGdvb2dsZXRhZy5wdWJhZHMoKSk7XG5cbiAgICAgICAgICAvLyBDb25maWd1cmFyIHNpemUgbWFwcGluZyByZXNwb25zaXZvXG4gICAgICAgICAgaWYgKGNvbmZpZy5zaXplTWFwcGluZyAmJiBjb25maWcuc2l6ZU1hcHBpbmcubGVuZ3RoID4gMCkge1xuICAgICAgICAgICAgY29uc3QgbWFwcGluZyA9IHRoaXMuYnVpbGRTaXplTWFwcGluZyhnb29nbGV0YWcsIGNvbmZpZy5zaXplTWFwcGluZyk7XG4gICAgICAgICAgICBzbG90LmRlZmluZVNpemVNYXBwaW5nKG1hcHBpbmcpO1xuICAgICAgICAgIH1cblxuICAgICAgICAgIC8vIENvbmZpZ3VyYXIgdGFyZ2V0aW5nXG4gICAgICAgICAgdGhpcy5hcHBseVRhcmdldGluZyhzbG90LCBjb25maWcudGFyZ2V0aW5nKTtcblxuICAgICAgICAgIC8vIENvbGFwc2FyIHNpIGVzdGEgdmFjaW9cbiAgICAgICAgICBpZiAoY29uZmlnLmNvbGxhcHNlRW1wdHkgPz8gdGhpcy5jb25maWcuZGVmYXVsdFNsb3RDb25maWc/LmNvbGxhcHNlRW1wdHkpIHtcbiAgICAgICAgICAgIHNsb3Quc2V0Q29sbGFwc2VFbXB0eURpdih0cnVlLCB0cnVlKTtcbiAgICAgICAgICB9XG5cbiAgICAgICAgICAvLyBHdWFyZGFyIHJlZmVyZW5jaWFcbiAgICAgICAgICB0aGlzLmFjdGl2ZVNsb3RzLnNldChjb25maWcuc2xvdElkLCBzbG90KTtcbiAgICAgICAgICB0aGlzLl9zbG90cy51cGRhdGUoKHNsb3RzKSA9PiBuZXcgTWFwKHNsb3RzKS5zZXQoY29uZmlnLnNsb3RJZCwgc2xvdCkpO1xuXG4gICAgICAgICAgLy8gTW9zdHJhciBlbCBhZFxuICAgICAgICAgIGdvb2dsZXRhZy5lbmFibGVTZXJ2aWNlcygpO1xuICAgICAgICAgIGdvb2dsZXRhZy5kaXNwbGF5KGNvbmZpZy5zbG90SWQpO1xuXG4gICAgICAgICAgdGhpcy51cGRhdGVTbG90U3RhdGUoY29uZmlnLnNsb3RJZCwgJ3JlbmRlcmVkJyk7XG4gICAgICAgICAgdGhpcy5lbWl0RXZlbnQoeyB0eXBlOiAnbG9hZGVkJywgc2xvdElkOiBjb25maWcuc2xvdElkLCBpc0VtcHR5OiBmYWxzZSB9KTtcblxuICAgICAgICAgIGlmICh0aGlzLl9pc0RlYnVnTW9kZSgpKSB7XG4gICAgICAgICAgICBjb25zb2xlLmxvZyhgW1ZhbHRlY2hBZHNdIFNsb3QgZGVmaW5pZG86ICR7Y29uZmlnLnNsb3RJZH1gLCB7XG4gICAgICAgICAgICAgIGFkVW5pdFBhdGgsXG4gICAgICAgICAgICAgIHNpemVzOiBjb25maWcuc2l6ZSxcbiAgICAgICAgICAgIH0pO1xuICAgICAgICAgIH1cblxuICAgICAgICAgIHJlc29sdmUoY29uZmlnLnNsb3RJZCk7XG4gICAgICAgIH0gY2F0Y2ggKGVycm9yKSB7XG4gICAgICAgICAgY29uc29sZS5lcnJvcignW1ZhbHRlY2hBZHNdIEVycm9yIGRlZmluaWVuZG8gc2xvdDonLCBlcnJvcik7XG4gICAgICAgICAgdGhpcy51cGRhdGVTbG90U3RhdGUoY29uZmlnLnNsb3RJZCwgJ2Vycm9yJyk7XG4gICAgICAgICAgdGhpcy5lbWl0RXZlbnQoeyB0eXBlOiAnZXJyb3InLCBzbG90SWQ6IGNvbmZpZy5zbG90SWQsIGVycm9yOiBlcnJvciBhcyBFcnJvciB9KTtcbiAgICAgICAgICByZXNvbHZlKG51bGwpO1xuICAgICAgICB9XG4gICAgICB9KTtcbiAgICB9KTtcbiAgfVxuXG4gIC8qKlxuICAgKiBEZXN0cnV5ZSB1biBzbG90IHkgbGliZXJhIHJlY3Vyc29zLlxuICAgKlxuICAgKiBAcGFyYW0gc2xvdElkIC0gSUQgZGVsIHNsb3QgYSBkZXN0cnVpclxuICAgKi9cbiAgZGVzdHJveVNsb3Qoc2xvdElkOiBzdHJpbmcpOiB2b2lkIHtcbiAgICBjb25zdCBzbG90ID0gdGhpcy5hY3RpdmVTbG90cy5nZXQoc2xvdElkKTtcbiAgICBpZiAoIXNsb3QpIHJldHVybjtcblxuICAgIGNvbnN0IGdvb2dsZXRhZyA9IHdpbmRvdy5nb29nbGV0YWc7XG4gICAgaWYgKGdvb2dsZXRhZykge1xuICAgICAgZ29vZ2xldGFnLmNtZC5wdXNoKCgpID0+IHtcbiAgICAgICAgZ29vZ2xldGFnLmRlc3Ryb3lTbG90cyhbc2xvdF0pO1xuICAgICAgfSk7XG4gICAgfVxuXG4gICAgdGhpcy5hY3RpdmVTbG90cy5kZWxldGUoc2xvdElkKTtcbiAgICB0aGlzLl9zbG90cy51cGRhdGUoKHNsb3RzKSA9PiB7XG4gICAgICBjb25zdCBuZXdTbG90cyA9IG5ldyBNYXAoc2xvdHMpO1xuICAgICAgbmV3U2xvdHMuZGVsZXRlKHNsb3RJZCk7XG4gICAgICByZXR1cm4gbmV3U2xvdHM7XG4gICAgfSk7XG4gICAgdGhpcy5fc2xvdFN0YXRlcy51cGRhdGUoKHN0YXRlcykgPT4ge1xuICAgICAgY29uc3QgbmV3U3RhdGVzID0gbmV3IE1hcChzdGF0ZXMpO1xuICAgICAgbmV3U3RhdGVzLmRlbGV0ZShzbG90SWQpO1xuICAgICAgcmV0dXJuIG5ld1N0YXRlcztcbiAgICB9KTtcblxuICAgIGlmICh0aGlzLl9pc0RlYnVnTW9kZSgpKSB7XG4gICAgICBjb25zb2xlLmxvZyhgW1ZhbHRlY2hBZHNdIFNsb3QgZGVzdHJ1aWRvOiAke3Nsb3RJZH1gKTtcbiAgICB9XG4gIH1cblxuICAvKipcbiAgICogUmVmcmVzY2EgdW4gc2xvdCBlc3BlY2lmaWNvIG8gdG9kb3MgbG9zIHNsb3RzIGFjdGl2b3MuXG4gICAqXG4gICAqIEBwYXJhbSBzbG90SWRzIC0gSURzIGRlIHNsb3RzIGEgcmVmcmVzY2FyICh1bmRlZmluZWQgPSB0b2RvcylcbiAgICovXG4gIHJlZnJlc2hTbG90cyhzbG90SWRzPzogc3RyaW5nW10pOiB2b2lkIHtcbiAgICBpZiAoIXRoaXMuaXNFbmFibGVkKCkpIHJldHVybjtcblxuICAgIGNvbnN0IGdvb2dsZXRhZyA9IHdpbmRvdy5nb29nbGV0YWc7XG4gICAgaWYgKCFnb29nbGV0YWcpIHJldHVybjtcblxuICAgIGdvb2dsZXRhZy5jbWQucHVzaCgoKSA9PiB7XG4gICAgICBpZiAoc2xvdElkcyAmJiBzbG90SWRzLmxlbmd0aCA+IDApIHtcbiAgICAgICAgY29uc3Qgc2xvdHMgPSBzbG90SWRzLm1hcCgoaWQpID0+IHRoaXMuYWN0aXZlU2xvdHMuZ2V0KGlkKSkuZmlsdGVyKChzKTogcyBpcyBHUFRTbG90ID0+ICEhcyk7XG4gICAgICAgIGlmIChzbG90cy5sZW5ndGggPiAwKSB7XG4gICAgICAgICAgZ29vZ2xldGFnLnB1YmFkcygpLnJlZnJlc2goc2xvdHMpO1xuICAgICAgICAgIGlmICh0aGlzLl9pc0RlYnVnTW9kZSgpKSB7XG4gICAgICAgICAgICBjb25zb2xlLmxvZyhgW1ZhbHRlY2hBZHNdIFNsb3RzIHJlZnJlc2NhZG9zOiAke3Nsb3RJZHMuam9pbignLCAnKX1gKTtcbiAgICAgICAgICB9XG4gICAgICAgIH1cbiAgICAgIH0gZWxzZSB7XG4gICAgICAgIGdvb2dsZXRhZy5wdWJhZHMoKS5yZWZyZXNoKCk7XG4gICAgICAgIGlmICh0aGlzLl9pc0RlYnVnTW9kZSgpKSB7XG4gICAgICAgICAgY29uc29sZS5sb2coJ1tWYWx0ZWNoQWRzXSBUb2RvcyBsb3Mgc2xvdHMgcmVmcmVzY2Fkb3MnKTtcbiAgICAgICAgfVxuICAgICAgfVxuICAgIH0pO1xuICB9XG5cbiAgLyoqXG4gICAqIE9idGllbmUgZWwgZXN0YWRvIGRlIHVuIHNsb3QuXG4gICAqXG4gICAqIEBwYXJhbSBzbG90SWQgLSBJRCBkZWwgc2xvdFxuICAgKiBAcmV0dXJucyBFc3RhZG8gYWN0dWFsIGRlbCBzbG90XG4gICAqL1xuICBnZXRTbG90U3RhdGUoc2xvdElkOiBzdHJpbmcpOiBBZFNsb3RTdGF0ZSB7XG4gICAgcmV0dXJuIHRoaXMuX3Nsb3RTdGF0ZXMoKS5nZXQoc2xvdElkKSA/PyAnaWRsZSc7XG4gIH1cblxuICAvLyA9PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT1cbiAgLy8gUFJFTUlVTSBVU0VSXG4gIC8vID09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PVxuXG4gIC8qKlxuICAgKiBBY3R1YWxpemEgZWwgZXN0YWRvIHByZW1pdW0gZGVsIHVzdWFyaW8uXG4gICAqIExsYW1hciBjdWFuZG8gY2FtYmllIGVsIGVzdGFkbyBkZSBzdXNjcmlwY2lvbi5cbiAgICpcbiAgICogQHBhcmFtIGlzUHJlbWl1bSAtIE51ZXZvIGVzdGFkbyBwcmVtaXVtXG4gICAqL1xuICB1cGRhdGVQcmVtaXVtU3RhdHVzKGlzUHJlbWl1bTogYm9vbGVhbik6IHZvaWQge1xuICAgIGNvbnN0IHdhc0VuYWJsZWQgPSB0aGlzLmlzRW5hYmxlZCgpO1xuICAgIHRoaXMuX2lzUHJlbWl1bVVzZXIuc2V0KGlzUHJlbWl1bSk7XG5cbiAgICBpZiAoaXNQcmVtaXVtICYmIHdhc0VuYWJsZWQpIHtcbiAgICAgIC8vIERlc3RydWlyIHRvZG9zIGxvcyBzbG90cyBhY3Rpdm9zXG4gICAgICB0aGlzLmRlc3Ryb3lBbGxTbG90cygpO1xuICAgICAgaWYgKHRoaXMuX2lzRGVidWdNb2RlKCkpIHtcbiAgICAgICAgY29uc29sZS5sb2coJ1tWYWx0ZWNoQWRzXSBVc3VhcmlvIGFob3JhIGVzIHByZW1pdW0gLSBhZHMgZGVzaGFiaWxpdGFkb3MnKTtcbiAgICAgIH1cbiAgICB9IGVsc2UgaWYgKCFpc1ByZW1pdW0gJiYgIXdhc0VuYWJsZWQgJiYgdGhpcy5faXNJbml0aWFsaXplZCgpKSB7XG4gICAgICBpZiAodGhpcy5faXNEZWJ1Z01vZGUoKSkge1xuICAgICAgICBjb25zb2xlLmxvZygnW1ZhbHRlY2hBZHNdIFVzdWFyaW8geWEgbm8gZXMgcHJlbWl1bSAtIGFkcyBoYWJpbGl0YWRvcycpO1xuICAgICAgfVxuICAgIH1cbiAgfVxuXG4gIC8qKlxuICAgKiBEZXN0cnV5ZSB0b2RvcyBsb3Mgc2xvdHMgYWN0aXZvcy5cbiAgICovXG4gIGRlc3Ryb3lBbGxTbG90cygpOiB2b2lkIHtcbiAgICBjb25zdCBnb29nbGV0YWcgPSB3aW5kb3cuZ29vZ2xldGFnO1xuICAgIGlmIChnb29nbGV0YWcpIHtcbiAgICAgIGdvb2dsZXRhZy5jbWQucHVzaCgoKSA9PiB7XG4gICAgICAgIGdvb2dsZXRhZy5kZXN0cm95U2xvdHMoKTtcbiAgICAgIH0pO1xuICAgIH1cbiAgICB0aGlzLmFjdGl2ZVNsb3RzLmNsZWFyKCk7XG4gICAgdGhpcy5fc2xvdHMuc2V0KG5ldyBNYXAoKSk7XG4gICAgdGhpcy5fc2xvdFN0YXRlcy5zZXQobmV3IE1hcCgpKTtcblxuICAgIGlmICh0aGlzLl9pc0RlYnVnTW9kZSgpKSB7XG4gICAgICBjb25zb2xlLmxvZygnW1ZhbHRlY2hBZHNdIFRvZG9zIGxvcyBzbG90cyBkZXN0cnVpZG9zJyk7XG4gICAgfVxuICB9XG5cbiAgLy8gPT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09XG4gIC8vIFBSSVZBVEUgTUVUSE9EU1xuICAvLyA9PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT1cblxuICBwcml2YXRlIHJlc29sdmVTaXplcyhzaXplOiBBZFNsb3RDb25maWdbJ3NpemUnXSk6IHVua25vd24ge1xuICAgIGlmICh0eXBlb2Ygc2l6ZSA9PT0gJ3N0cmluZycpIHtcbiAgICAgIC8vIFNpbmdsZSBwcmVzZXQgc2l6ZVxuICAgICAgY29uc3QgbWFwcGVkID0gQURfU0laRV9NQVBbc2l6ZSBhcyBBZFNsb3RTaXplXTtcbiAgICAgIHJldHVybiBtYXBwZWQgPT09ICdmbHVpZCcgPyAnZmx1aWQnIDogW21hcHBlZF07XG4gICAgfVxuXG4gICAgaWYgKEFycmF5LmlzQXJyYXkoc2l6ZSkpIHtcbiAgICAgIGlmICh0eXBlb2Ygc2l6ZVswXSA9PT0gJ3N0cmluZycpIHtcbiAgICAgICAgLy8gQXJyYXkgb2YgcHJlc2V0IHNpemVzXG4gICAgICAgIHJldHVybiAoc2l6ZSBhcyBBZFNsb3RTaXplW10pLm1hcCgocykgPT4ge1xuICAgICAgICAgIGNvbnN0IG1hcHBlZCA9IEFEX1NJWkVfTUFQW3NdO1xuICAgICAgICAgIHJldHVybiBtYXBwZWQgPT09ICdmbHVpZCcgPyAnZmx1aWQnIDogbWFwcGVkO1xuICAgICAgICB9KTtcbiAgICAgIH1cbiAgICAgIC8vIERpcmVjdCBzaXplIGFycmF5XG4gICAgICByZXR1cm4gc2l6ZTtcbiAgICB9XG5cbiAgICByZXR1cm4gJ2ZsdWlkJztcbiAgfVxuXG4gIHByaXZhdGUgYnVpbGRTaXplTWFwcGluZyhnb29nbGV0YWc6IEdQVE5hbWVzcGFjZSwgbWFwcGluZzogU2l6ZU1hcHBpbmdbXSk6IHVua25vd24ge1xuICAgIGNvbnN0IGJ1aWxkZXIgPSBnb29nbGV0YWcuc2l6ZU1hcHBpbmcoKTtcblxuICAgIC8vIE9yZGVuYXIgcG9yIHZpZXdwb3J0IGRlc2NlbmRlbnRlXG4gICAgY29uc3Qgc29ydGVkID0gWy4uLm1hcHBpbmddLnNvcnQoKGEsIGIpID0+IGIudmlld3BvcnRXaWR0aCAtIGEudmlld3BvcnRXaWR0aCk7XG5cbiAgICBmb3IgKGNvbnN0IG0gb2Ygc29ydGVkKSB7XG4gICAgICBidWlsZGVyLmFkZFNpemUoW20udmlld3BvcnRXaWR0aCwgMF0sIG0uc2l6ZXMpO1xuICAgIH1cblxuICAgIHJldHVybiBidWlsZGVyLmJ1aWxkKCk7XG4gIH1cblxuICBwcml2YXRlIGFwcGx5VGFyZ2V0aW5nKHNsb3Q6IEdQVFNsb3QsIHRhcmdldGluZz86IFJlY29yZDxzdHJpbmcsIHN0cmluZyB8IHN0cmluZ1tdPik6IHZvaWQge1xuICAgIC8vIEFwbGljYXIgdGFyZ2V0aW5nIGdsb2JhbFxuICAgIGlmICh0aGlzLmNvbmZpZy5nbG9iYWxUYXJnZXRpbmcpIHtcbiAgICAgIGZvciAoY29uc3QgW2tleSwgdmFsdWVdIG9mIE9iamVjdC5lbnRyaWVzKHRoaXMuY29uZmlnLmdsb2JhbFRhcmdldGluZykpIHtcbiAgICAgICAgc2xvdC5zZXRUYXJnZXRpbmcoa2V5LCB2YWx1ZSk7XG4gICAgICB9XG4gICAgfVxuXG4gICAgLy8gQXBsaWNhciB0YXJnZXRpbmcgZGVsIHNsb3RcbiAgICBpZiAodGFyZ2V0aW5nKSB7XG4gICAgICBmb3IgKGNvbnN0IFtrZXksIHZhbHVlXSBvZiBPYmplY3QuZW50cmllcyh0YXJnZXRpbmcpKSB7XG4gICAgICAgIHNsb3Quc2V0VGFyZ2V0aW5nKGtleSwgdmFsdWUpO1xuICAgICAgfVxuICAgIH1cblxuICAgIC8vIEFncmVnYXIgdGFyZ2V0aW5nIGRlIGRlYnVnIHNpIGVzdGEgaGFiaWxpdGFkb1xuICAgIGlmICh0aGlzLl9pc0RlYnVnTW9kZSgpKSB7XG4gICAgICBzbG90LnNldFRhcmdldGluZygndGVzdCcsICd0cnVlJyk7XG4gICAgfVxuICB9XG5cbiAgcHJpdmF0ZSB1cGRhdGVTbG90U3RhdGUoc2xvdElkOiBzdHJpbmcsIHN0YXRlOiBBZFNsb3RTdGF0ZSk6IHZvaWQge1xuICAgIHRoaXMuX3Nsb3RTdGF0ZXMudXBkYXRlKChzdGF0ZXMpID0+IG5ldyBNYXAoc3RhdGVzKS5zZXQoc2xvdElkLCBzdGF0ZSkpO1xuICB9XG5cbiAgcHJpdmF0ZSBlbWl0RXZlbnQoZXZlbnQ6IE9taXQ8QWRFdmVudCwgJ3RpbWVzdGFtcCc+KTogdm9pZCB7XG4gICAgY29uc3QgZnVsbEV2ZW50OiBBZEV2ZW50ID0geyAuLi5ldmVudCwgdGltZXN0YW1wOiBuZXcgRGF0ZSgpIH07XG4gICAgdGhpcy5fZXZlbnRzLnVwZGF0ZSgoZXZlbnRzKSA9PiBbLi4uZXZlbnRzLnNsaWNlKC05OSksIGZ1bGxFdmVudF0pO1xuXG4gICAgLy8gQ2FsbGJhY2tzIGRlIGNvbmZpZ3VyYWNpb25cbiAgICBpZiAoZXZlbnQudHlwZSA9PT0gJ2xvYWRlZCcgfHwgZXZlbnQudHlwZSA9PT0gJ2VtcHR5Jykge1xuICAgICAgdGhpcy5jb25maWcub25BZExvYWRlZD8uKGV2ZW50LnNsb3RJZCwgZXZlbnQuaXNFbXB0eSA/PyBmYWxzZSk7XG4gICAgfSBlbHNlIGlmIChldmVudC50eXBlID09PSAnZXJyb3InICYmIGV2ZW50LmVycm9yKSB7XG4gICAgICB0aGlzLmNvbmZpZy5vbkFkRXJyb3I/LihldmVudC5zbG90SWQsIGV2ZW50LmVycm9yKTtcbiAgICB9XG4gIH1cblxuICBwcml2YXRlIHNldHVwUm91dGVMaXN0ZW5lcigpOiB2b2lkIHtcbiAgICBpZiAoIXRoaXMuY29uZmlnLmV4Y2x1ZGVSb3V0ZXMgfHwgdGhpcy5jb25maWcuZXhjbHVkZVJvdXRlcy5sZW5ndGggPT09IDApIHtcbiAgICAgIHJldHVybjtcbiAgICB9XG5cbiAgICB0aGlzLnJvdXRlclN1YnNjcmlwdGlvbiA9IHRoaXMucm91dGVyLmV2ZW50c1xuICAgICAgLnBpcGUoZmlsdGVyKChldmVudCk6IGV2ZW50IGlzIE5hdmlnYXRpb25FbmQgPT4gZXZlbnQgaW5zdGFuY2VvZiBOYXZpZ2F0aW9uRW5kKSlcbiAgICAgIC5zdWJzY3JpYmUoKGV2ZW50OiBOYXZpZ2F0aW9uRW5kKSA9PiB7XG4gICAgICAgIGNvbnN0IHNob3VsZEhpZGUgPSB0aGlzLmlzUm91dGVFeGNsdWRlZChldmVudC51cmxBZnRlclJlZGlyZWN0cyk7XG5cbiAgICAgICAgaWYgKHNob3VsZEhpZGUpIHtcbiAgICAgICAgICB0aGlzLmRlc3Ryb3lBbGxTbG90cygpO1xuICAgICAgICB9XG4gICAgICB9KTtcbiAgfVxuXG4gIHByaXZhdGUgc2V0dXBBdXRvUmVmcmVzaCgpOiB2b2lkIHtcbiAgICBjb25zdCBpbnRlcnZhbE1zID0gKHRoaXMuY29uZmlnLmF1dG9SZWZyZXNoSW50ZXJ2YWwgPz8gMCkgKiAxMDAwO1xuICAgIGlmIChpbnRlcnZhbE1zIDw9IDApIHJldHVybjtcblxuICAgIHRoaXMucmVmcmVzaFRpbWVySWQgPSBzZXRJbnRlcnZhbCgoKSA9PiB7XG4gICAgICBpZiAodGhpcy5pc0VuYWJsZWQoKSAmJiB0aGlzLmFjdGl2ZVNsb3RzLnNpemUgPiAwKSB7XG4gICAgICAgIHRoaXMucmVmcmVzaFNsb3RzKCk7XG4gICAgICB9XG4gICAgfSwgaW50ZXJ2YWxNcyk7XG4gIH1cblxuICBwcml2YXRlIGlzUm91dGVFeGNsdWRlZCh1cmw/OiBzdHJpbmcpOiBib29sZWFuIHtcbiAgICBpZiAoIXRoaXMuY29uZmlnLmV4Y2x1ZGVSb3V0ZXMgfHwgdGhpcy5jb25maWcuZXhjbHVkZVJvdXRlcy5sZW5ndGggPT09IDApIHtcbiAgICAgIHJldHVybiBmYWxzZTtcbiAgICB9XG5cbiAgICBjb25zdCBjdXJyZW50VXJsID0gdXJsID8/IHRoaXMucm91dGVyLnVybDtcbiAgICByZXR1cm4gdGhpcy5jb25maWcuZXhjbHVkZVJvdXRlcy5zb21lKChwYXR0ZXJuKSA9PiB7XG4gICAgICBjb25zdCByZWdleCA9IG5ldyBSZWdFeHAocGF0dGVybik7XG4gICAgICByZXR1cm4gcmVnZXgudGVzdChjdXJyZW50VXJsKTtcbiAgICB9KTtcbiAgfVxuXG4gIC8vID09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PVxuICAvLyBMSUZFQ1lDTEVcbiAgLy8gPT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09XG5cbiAgbmdPbkRlc3Ryb3koKTogdm9pZCB7XG4gICAgdGhpcy5yb3V0ZXJTdWJzY3JpcHRpb24/LnVuc3Vic2NyaWJlKCk7XG5cbiAgICBpZiAodGhpcy5yZWZyZXNoVGltZXJJZCkge1xuICAgICAgY2xlYXJJbnRlcnZhbCh0aGlzLnJlZnJlc2hUaW1lcklkKTtcbiAgICB9XG5cbiAgICB0aGlzLmRlc3Ryb3lBbGxTbG90cygpO1xuICAgIHRoaXMuY29uc2VudFNlcnZpY2UuZGVzdHJveSgpO1xuICB9XG59XG4iXX0=
@@ -0,0 +1,118 @@
1
+ /**
2
+ * Ads Configuration
3
+ *
4
+ * Configuracion e inicializacion de Google Ad Manager para Angular.
5
+ * Usa provideValtechAds() en el bootstrap de tu aplicacion.
6
+ */
7
+ import { InjectionToken, makeEnvironmentProviders, APP_INITIALIZER, } from '@angular/core';
8
+ import { AdsService } from './ads.service';
9
+ /**
10
+ * Token de inyeccion para la configuracion de Ads.
11
+ * Usado internamente por los servicios de ads.
12
+ */
13
+ export const VALTECH_ADS_CONFIG = new InjectionToken('ValtechAdsConfig');
14
+ /**
15
+ * Configuracion por defecto de lazy loading.
16
+ */
17
+ export const DEFAULT_LAZY_LOAD_CONFIG = {
18
+ rootMargin: '200px',
19
+ threshold: 0,
20
+ fetchMarginPercent: 200,
21
+ renderMarginPercent: 100,
22
+ };
23
+ /**
24
+ * Configuracion por defecto del servicio de ads.
25
+ */
26
+ export const DEFAULT_ADS_CONFIG = {
27
+ debugMode: false,
28
+ lazyLoad: true,
29
+ lazyLoadConfig: DEFAULT_LAZY_LOAD_CONFIG,
30
+ enablePersonalization: true,
31
+ showNonPersonalizedAds: true,
32
+ autoRefreshInterval: 0, // Deshabilitado por defecto
33
+ defaultSlotConfig: {
34
+ collapseEmpty: true,
35
+ showSkeleton: true,
36
+ minHeight: '90px',
37
+ },
38
+ };
39
+ /**
40
+ * Factory para inicializar AdsService.
41
+ * Se ejecuta durante el bootstrap de la aplicacion.
42
+ */
43
+ function initializeAds(adsService) {
44
+ return () => adsService.initialize();
45
+ }
46
+ /**
47
+ * Provee el servicio de Ads a la aplicacion Angular.
48
+ *
49
+ * @param config - Configuracion de Google Ad Manager
50
+ * @returns EnvironmentProviders para usar en bootstrapApplication
51
+ *
52
+ * @example
53
+ * ```typescript
54
+ * // main.ts
55
+ * import { bootstrapApplication } from '@angular/platform-browser';
56
+ * import { provideValtechAds, provideValtechFirebase } from 'valtech-components';
57
+ * import { environment } from './environments/environment';
58
+ *
59
+ * bootstrapApplication(AppComponent, {
60
+ * providers: [
61
+ * // Firebase primero (para consent mode)
62
+ * provideValtechFirebase({
63
+ * firebase: environment.firebase,
64
+ * enableAnalytics: true,
65
+ * }),
66
+ *
67
+ * // Luego Ads
68
+ * provideValtechAds({
69
+ * networkId: '/12345678',
70
+ * debugMode: !environment.production,
71
+ * isPremiumUser: () => inject(AuthService).hasRole('premium'),
72
+ * }),
73
+ * ],
74
+ * });
75
+ * ```
76
+ *
77
+ * @example Con targeting global y rutas excluidas
78
+ * ```typescript
79
+ * provideValtechAds({
80
+ * networkId: '/12345678',
81
+ * globalTargeting: {
82
+ * site: 'myvaltech',
83
+ * section: 'app',
84
+ * },
85
+ * excludeRoutes: [
86
+ * '^/checkout',
87
+ * '^/payment',
88
+ * '^/premium',
89
+ * ],
90
+ * })
91
+ * ```
92
+ */
93
+ export function provideValtechAds(config) {
94
+ // Merge config con defaults
95
+ const mergedConfig = {
96
+ ...DEFAULT_ADS_CONFIG,
97
+ ...config,
98
+ lazyLoadConfig: {
99
+ ...DEFAULT_LAZY_LOAD_CONFIG,
100
+ ...config.lazyLoadConfig,
101
+ },
102
+ defaultSlotConfig: {
103
+ ...DEFAULT_ADS_CONFIG.defaultSlotConfig,
104
+ ...config.defaultSlotConfig,
105
+ },
106
+ };
107
+ return makeEnvironmentProviders([
108
+ { provide: VALTECH_ADS_CONFIG, useValue: mergedConfig },
109
+ // Inicializar AdsService al arrancar (pero NO cargar script GPT aun)
110
+ {
111
+ provide: APP_INITIALIZER,
112
+ useFactory: initializeAds,
113
+ deps: [AdsService],
114
+ multi: true,
115
+ },
116
+ ]);
117
+ }
118
+ //# sourceMappingURL=data:application/json;base64,eyJ2ZXJzaW9uIjozLCJmaWxlIjoiY29uZmlnLmpzIiwic291cmNlUm9vdCI6IiIsInNvdXJjZXMiOlsiLi4vLi4vLi4vLi4vLi4vLi4vc3JjL2xpYi9zZXJ2aWNlcy9hZHMvY29uZmlnLnRzIl0sIm5hbWVzIjpbXSwibWFwcGluZ3MiOiJBQUFBOzs7OztHQUtHO0FBRUgsT0FBTyxFQUVMLGNBQWMsRUFDZCx3QkFBd0IsRUFDeEIsZUFBZSxHQUNoQixNQUFNLGVBQWUsQ0FBQztBQUV2QixPQUFPLEVBQUUsVUFBVSxFQUFFLE1BQU0sZUFBZSxDQUFDO0FBRTNDOzs7R0FHRztBQUNILE1BQU0sQ0FBQyxNQUFNLGtCQUFrQixHQUFHLElBQUksY0FBYyxDQUFtQixrQkFBa0IsQ0FBQyxDQUFDO0FBRTNGOztHQUVHO0FBQ0gsTUFBTSxDQUFDLE1BQU0sd0JBQXdCLEdBQW1CO0lBQ3RELFVBQVUsRUFBRSxPQUFPO0lBQ25CLFNBQVMsRUFBRSxDQUFDO0lBQ1osa0JBQWtCLEVBQUUsR0FBRztJQUN2QixtQkFBbUIsRUFBRSxHQUFHO0NBQ3pCLENBQUM7QUFFRjs7R0FFRztBQUNILE1BQU0sQ0FBQyxNQUFNLGtCQUFrQixHQUE4QjtJQUMzRCxTQUFTLEVBQUUsS0FBSztJQUNoQixRQUFRLEVBQUUsSUFBSTtJQUNkLGNBQWMsRUFBRSx3QkFBd0I7SUFDeEMscUJBQXFCLEVBQUUsSUFBSTtJQUMzQixzQkFBc0IsRUFBRSxJQUFJO0lBQzVCLG1CQUFtQixFQUFFLENBQUMsRUFBRSw0QkFBNEI7SUFDcEQsaUJBQWlCLEVBQUU7UUFDakIsYUFBYSxFQUFFLElBQUk7UUFDbkIsWUFBWSxFQUFFLElBQUk7UUFDbEIsU0FBUyxFQUFFLE1BQU07S0FDbEI7Q0FDRixDQUFDO0FBRUY7OztHQUdHO0FBQ0gsU0FBUyxhQUFhLENBQUMsVUFBc0I7SUFDM0MsT0FBTyxHQUFHLEVBQUUsQ0FBQyxVQUFVLENBQUMsVUFBVSxFQUFFLENBQUM7QUFDdkMsQ0FBQztBQUVEOzs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7O0dBOENHO0FBQ0gsTUFBTSxVQUFVLGlCQUFpQixDQUFDLE1BQXdCO0lBQ3hELDRCQUE0QjtJQUM1QixNQUFNLFlBQVksR0FBcUI7UUFDckMsR0FBRyxrQkFBa0I7UUFDckIsR0FBRyxNQUFNO1FBQ1QsY0FBYyxFQUFFO1lBQ2QsR0FBRyx3QkFBd0I7WUFDM0IsR0FBRyxNQUFNLENBQUMsY0FBYztTQUN6QjtRQUNELGlCQUFpQixFQUFFO1lBQ2pCLEdBQUcsa0JBQWtCLENBQUMsaUJBQWlCO1lBQ3ZDLEdBQUcsTUFBTSxDQUFDLGlCQUFpQjtTQUM1QjtLQUNGLENBQUM7SUFFRixPQUFPLHdCQUF3QixDQUFDO1FBQzlCLEVBQUUsT0FBTyxFQUFFLGtCQUFrQixFQUFFLFFBQVEsRUFBRSxZQUFZLEVBQUU7UUFDdkQscUVBQXFFO1FBQ3JFO1lBQ0UsT0FBTyxFQUFFLGVBQWU7WUFDeEIsVUFBVSxFQUFFLGFBQWE7WUFDekIsSUFBSSxFQUFFLENBQUMsVUFBVSxDQUFDO1lBQ2xCLEtBQUssRUFBRSxJQUFJO1NBQ1o7S0FDRixDQUFDLENBQUM7QUFDTCxDQUFDIiwic291cmNlc0NvbnRlbnQiOlsiLyoqXG4gKiBBZHMgQ29uZmlndXJhdGlvblxuICpcbiAqIENvbmZpZ3VyYWNpb24gZSBpbmljaWFsaXphY2lvbiBkZSBHb29nbGUgQWQgTWFuYWdlciBwYXJhIEFuZ3VsYXIuXG4gKiBVc2EgcHJvdmlkZVZhbHRlY2hBZHMoKSBlbiBlbCBib290c3RyYXAgZGUgdHUgYXBsaWNhY2lvbi5cbiAqL1xuXG5pbXBvcnQge1xuICBFbnZpcm9ubWVudFByb3ZpZGVycyxcbiAgSW5qZWN0aW9uVG9rZW4sXG4gIG1ha2VFbnZpcm9ubWVudFByb3ZpZGVycyxcbiAgQVBQX0lOSVRJQUxJWkVSLFxufSBmcm9tICdAYW5ndWxhci9jb3JlJztcbmltcG9ydCB7IFZhbHRlY2hBZHNDb25maWcsIExhenlMb2FkQ29uZmlnIH0gZnJvbSAnLi90eXBlcyc7XG5pbXBvcnQgeyBBZHNTZXJ2aWNlIH0gZnJvbSAnLi9hZHMuc2VydmljZSc7XG5cbi8qKlxuICogVG9rZW4gZGUgaW55ZWNjaW9uIHBhcmEgbGEgY29uZmlndXJhY2lvbiBkZSBBZHMuXG4gKiBVc2FkbyBpbnRlcm5hbWVudGUgcG9yIGxvcyBzZXJ2aWNpb3MgZGUgYWRzLlxuICovXG5leHBvcnQgY29uc3QgVkFMVEVDSF9BRFNfQ09ORklHID0gbmV3IEluamVjdGlvblRva2VuPFZhbHRlY2hBZHNDb25maWc+KCdWYWx0ZWNoQWRzQ29uZmlnJyk7XG5cbi8qKlxuICogQ29uZmlndXJhY2lvbiBwb3IgZGVmZWN0byBkZSBsYXp5IGxvYWRpbmcuXG4gKi9cbmV4cG9ydCBjb25zdCBERUZBVUxUX0xBWllfTE9BRF9DT05GSUc6IExhenlMb2FkQ29uZmlnID0ge1xuICByb290TWFyZ2luOiAnMjAwcHgnLFxuICB0aHJlc2hvbGQ6IDAsXG4gIGZldGNoTWFyZ2luUGVyY2VudDogMjAwLFxuICByZW5kZXJNYXJnaW5QZXJjZW50OiAxMDAsXG59O1xuXG4vKipcbiAqIENvbmZpZ3VyYWNpb24gcG9yIGRlZmVjdG8gZGVsIHNlcnZpY2lvIGRlIGFkcy5cbiAqL1xuZXhwb3J0IGNvbnN0IERFRkFVTFRfQURTX0NPTkZJRzogUGFydGlhbDxWYWx0ZWNoQWRzQ29uZmlnPiA9IHtcbiAgZGVidWdNb2RlOiBmYWxzZSxcbiAgbGF6eUxvYWQ6IHRydWUsXG4gIGxhenlMb2FkQ29uZmlnOiBERUZBVUxUX0xBWllfTE9BRF9DT05GSUcsXG4gIGVuYWJsZVBlcnNvbmFsaXphdGlvbjogdHJ1ZSxcbiAgc2hvd05vblBlcnNvbmFsaXplZEFkczogdHJ1ZSxcbiAgYXV0b1JlZnJlc2hJbnRlcnZhbDogMCwgLy8gRGVzaGFiaWxpdGFkbyBwb3IgZGVmZWN0b1xuICBkZWZhdWx0U2xvdENvbmZpZzoge1xuICAgIGNvbGxhcHNlRW1wdHk6IHRydWUsXG4gICAgc2hvd1NrZWxldG9uOiB0cnVlLFxuICAgIG1pbkhlaWdodDogJzkwcHgnLFxuICB9LFxufTtcblxuLyoqXG4gKiBGYWN0b3J5IHBhcmEgaW5pY2lhbGl6YXIgQWRzU2VydmljZS5cbiAqIFNlIGVqZWN1dGEgZHVyYW50ZSBlbCBib290c3RyYXAgZGUgbGEgYXBsaWNhY2lvbi5cbiAqL1xuZnVuY3Rpb24gaW5pdGlhbGl6ZUFkcyhhZHNTZXJ2aWNlOiBBZHNTZXJ2aWNlKTogKCkgPT4gUHJvbWlzZTx2b2lkPiB7XG4gIHJldHVybiAoKSA9PiBhZHNTZXJ2aWNlLmluaXRpYWxpemUoKTtcbn1cblxuLyoqXG4gKiBQcm92ZWUgZWwgc2VydmljaW8gZGUgQWRzIGEgbGEgYXBsaWNhY2lvbiBBbmd1bGFyLlxuICpcbiAqIEBwYXJhbSBjb25maWcgLSBDb25maWd1cmFjaW9uIGRlIEdvb2dsZSBBZCBNYW5hZ2VyXG4gKiBAcmV0dXJucyBFbnZpcm9ubWVudFByb3ZpZGVycyBwYXJhIHVzYXIgZW4gYm9vdHN0cmFwQXBwbGljYXRpb25cbiAqXG4gKiBAZXhhbXBsZVxuICogYGBgdHlwZXNjcmlwdFxuICogLy8gbWFpbi50c1xuICogaW1wb3J0IHsgYm9vdHN0cmFwQXBwbGljYXRpb24gfSBmcm9tICdAYW5ndWxhci9wbGF0Zm9ybS1icm93c2VyJztcbiAqIGltcG9ydCB7IHByb3ZpZGVWYWx0ZWNoQWRzLCBwcm92aWRlVmFsdGVjaEZpcmViYXNlIH0gZnJvbSAndmFsdGVjaC1jb21wb25lbnRzJztcbiAqIGltcG9ydCB7IGVudmlyb25tZW50IH0gZnJvbSAnLi9lbnZpcm9ubWVudHMvZW52aXJvbm1lbnQnO1xuICpcbiAqIGJvb3RzdHJhcEFwcGxpY2F0aW9uKEFwcENvbXBvbmVudCwge1xuICogICBwcm92aWRlcnM6IFtcbiAqICAgICAvLyBGaXJlYmFzZSBwcmltZXJvIChwYXJhIGNvbnNlbnQgbW9kZSlcbiAqICAgICBwcm92aWRlVmFsdGVjaEZpcmViYXNlKHtcbiAqICAgICAgIGZpcmViYXNlOiBlbnZpcm9ubWVudC5maXJlYmFzZSxcbiAqICAgICAgIGVuYWJsZUFuYWx5dGljczogdHJ1ZSxcbiAqICAgICB9KSxcbiAqXG4gKiAgICAgLy8gTHVlZ28gQWRzXG4gKiAgICAgcHJvdmlkZVZhbHRlY2hBZHMoe1xuICogICAgICAgbmV0d29ya0lkOiAnLzEyMzQ1Njc4JyxcbiAqICAgICAgIGRlYnVnTW9kZTogIWVudmlyb25tZW50LnByb2R1Y3Rpb24sXG4gKiAgICAgICBpc1ByZW1pdW1Vc2VyOiAoKSA9PiBpbmplY3QoQXV0aFNlcnZpY2UpLmhhc1JvbGUoJ3ByZW1pdW0nKSxcbiAqICAgICB9KSxcbiAqICAgXSxcbiAqIH0pO1xuICogYGBgXG4gKlxuICogQGV4YW1wbGUgQ29uIHRhcmdldGluZyBnbG9iYWwgeSBydXRhcyBleGNsdWlkYXNcbiAqIGBgYHR5cGVzY3JpcHRcbiAqIHByb3ZpZGVWYWx0ZWNoQWRzKHtcbiAqICAgbmV0d29ya0lkOiAnLzEyMzQ1Njc4JyxcbiAqICAgZ2xvYmFsVGFyZ2V0aW5nOiB7XG4gKiAgICAgc2l0ZTogJ215dmFsdGVjaCcsXG4gKiAgICAgc2VjdGlvbjogJ2FwcCcsXG4gKiAgIH0sXG4gKiAgIGV4Y2x1ZGVSb3V0ZXM6IFtcbiAqICAgICAnXi9jaGVja291dCcsXG4gKiAgICAgJ14vcGF5bWVudCcsXG4gKiAgICAgJ14vcHJlbWl1bScsXG4gKiAgIF0sXG4gKiB9KVxuICogYGBgXG4gKi9cbmV4cG9ydCBmdW5jdGlvbiBwcm92aWRlVmFsdGVjaEFkcyhjb25maWc6IFZhbHRlY2hBZHNDb25maWcpOiBFbnZpcm9ubWVudFByb3ZpZGVycyB7XG4gIC8vIE1lcmdlIGNvbmZpZyBjb24gZGVmYXVsdHNcbiAgY29uc3QgbWVyZ2VkQ29uZmlnOiBWYWx0ZWNoQWRzQ29uZmlnID0ge1xuICAgIC4uLkRFRkFVTFRfQURTX0NPTkZJRyxcbiAgICAuLi5jb25maWcsXG4gICAgbGF6eUxvYWRDb25maWc6IHtcbiAgICAgIC4uLkRFRkFVTFRfTEFaWV9MT0FEX0NPTkZJRyxcbiAgICAgIC4uLmNvbmZpZy5sYXp5TG9hZENvbmZpZyxcbiAgICB9LFxuICAgIGRlZmF1bHRTbG90Q29uZmlnOiB7XG4gICAgICAuLi5ERUZBVUxUX0FEU19DT05GSUcuZGVmYXVsdFNsb3RDb25maWcsXG4gICAgICAuLi5jb25maWcuZGVmYXVsdFNsb3RDb25maWcsXG4gICAgfSxcbiAgfTtcblxuICByZXR1cm4gbWFrZUVudmlyb25tZW50UHJvdmlkZXJzKFtcbiAgICB7IHByb3ZpZGU6IFZBTFRFQ0hfQURTX0NPTkZJRywgdXNlVmFsdWU6IG1lcmdlZENvbmZpZyB9LFxuICAgIC8vIEluaWNpYWxpemFyIEFkc1NlcnZpY2UgYWwgYXJyYW5jYXIgKHBlcm8gTk8gY2FyZ2FyIHNjcmlwdCBHUFQgYXVuKVxuICAgIHtcbiAgICAgIHByb3ZpZGU6IEFQUF9JTklUSUFMSVpFUixcbiAgICAgIHVzZUZhY3Rvcnk6IGluaXRpYWxpemVBZHMsXG4gICAgICBkZXBzOiBbQWRzU2VydmljZV0sXG4gICAgICBtdWx0aTogdHJ1ZSxcbiAgICB9LFxuICBdKTtcbn1cbiJdfQ==