valtech-components 2.0.417 → 2.0.418

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.
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "valtech-components",
3
- "version": "2.0.417",
3
+ "version": "2.0.418",
4
4
  "private": false,
5
5
  "repository": {
6
6
  "type": "git",
package/public-api.d.ts CHANGED
@@ -212,7 +212,6 @@ export * from './lib/services/qr-generator/qr-generator.service';
212
212
  export * from './lib/services/qr-generator/types';
213
213
  export * from './lib/services/modal/modal.service';
214
214
  export * from './lib/services/modal/types';
215
- export * from './lib/services/firebase';
216
215
  export * from './lib/components/types';
217
216
  export * from './lib/shared/pipes/process-links.pipe';
218
217
  export * from './lib/shared/utils/content';
@@ -1,108 +0,0 @@
1
- /**
2
- * Firebase Configuration
3
- *
4
- * Configuración e inicialización de Firebase para aplicaciones Angular.
5
- * Usa provideValtechFirebase() en el bootstrap de tu aplicación.
6
- */
7
- import { InjectionToken, makeEnvironmentProviders } from '@angular/core';
8
- import { initializeApp, provideFirebaseApp } from '@angular/fire/app';
9
- import { connectAuthEmulator, getAuth, provideAuth } from '@angular/fire/auth';
10
- import { connectFirestoreEmulator, enableIndexedDbPersistence, getFirestore, provideFirestore, } from '@angular/fire/firestore';
11
- import { getMessaging, provideMessaging } from '@angular/fire/messaging';
12
- import { connectStorageEmulator, getStorage, provideStorage } from '@angular/fire/storage';
13
- /**
14
- * Token de inyección para la configuración de Firebase.
15
- * Usado internamente por los servicios de Firebase.
16
- */
17
- export const VALTECH_FIREBASE_CONFIG = new InjectionToken('ValtechFirebaseConfig');
18
- /**
19
- * Provee Firebase a la aplicación Angular.
20
- *
21
- * @param config - Configuración de Firebase
22
- * @returns EnvironmentProviders para usar en bootstrapApplication
23
- *
24
- * @example
25
- * ```typescript
26
- * // main.ts
27
- * import { bootstrapApplication } from '@angular/platform-browser';
28
- * import { provideValtechFirebase } from 'valtech-components';
29
- * import { environment } from './environments/environment';
30
- *
31
- * bootstrapApplication(AppComponent, {
32
- * providers: [
33
- * provideValtechFirebase({
34
- * firebase: environment.firebase,
35
- * persistence: true,
36
- * emulator: environment.useEmulators ? {
37
- * firestore: { host: 'localhost', port: 8080 },
38
- * auth: { host: 'localhost', port: 9099 },
39
- * storage: { host: 'localhost', port: 9199 },
40
- * } : undefined,
41
- * }),
42
- * ],
43
- * });
44
- * ```
45
- */
46
- export function provideValtechFirebase(config) {
47
- // Construir array de providers base
48
- const providers = [
49
- // Guardar configuración para uso en servicios
50
- { provide: VALTECH_FIREBASE_CONFIG, useValue: config },
51
- // Inicializar Firebase App
52
- provideFirebaseApp(() => initializeApp(config.firebase)),
53
- // Firestore con soporte para emuladores y persistencia
54
- provideFirestore(() => {
55
- const firestore = getFirestore();
56
- // Conectar a emulador si está configurado
57
- if (config.emulator?.firestore) {
58
- connectFirestoreEmulator(firestore, config.emulator.firestore.host, config.emulator.firestore.port);
59
- }
60
- // Habilitar persistencia offline si está configurada
61
- if (config.persistence) {
62
- enableIndexedDbPersistence(firestore).catch((err) => {
63
- if (err.code === 'failed-precondition') {
64
- console.warn('[ValtechFirebase] Persistencia no disponible: múltiples pestañas abiertas');
65
- }
66
- else if (err.code === 'unimplemented') {
67
- console.warn('[ValtechFirebase] Persistencia no soportada en este navegador');
68
- }
69
- });
70
- }
71
- return firestore;
72
- }),
73
- // Auth con soporte para emulador
74
- provideAuth(() => {
75
- const auth = getAuth();
76
- // Conectar a emulador si está configurado
77
- if (config.emulator?.auth) {
78
- connectAuthEmulator(auth, `http://${config.emulator.auth.host}:${config.emulator.auth.port}`, { disableWarnings: true });
79
- }
80
- return auth;
81
- }),
82
- // Storage con soporte para emulador
83
- provideStorage(() => {
84
- const storage = getStorage();
85
- // Conectar a emulador si está configurado
86
- if (config.emulator?.storage) {
87
- connectStorageEmulator(storage, config.emulator.storage.host, config.emulator.storage.port);
88
- }
89
- return storage;
90
- }),
91
- ];
92
- // Messaging (FCM) - solo si está explícitamente habilitado
93
- // Requiere Service Worker configurado, puede congelar la app si no está disponible
94
- if (config.enableMessaging) {
95
- providers.push(provideMessaging(() => getMessaging()));
96
- }
97
- return makeEnvironmentProviders(providers);
98
- }
99
- /**
100
- * Verifica si los emuladores están configurados.
101
- *
102
- * @param config - Configuración de Firebase
103
- * @returns true si hay al menos un emulador configurado
104
- */
105
- export function hasEmulators(config) {
106
- return !!(config.emulator?.firestore || config.emulator?.auth || config.emulator?.storage);
107
- }
108
- //# sourceMappingURL=data:application/json;base64,eyJ2ZXJzaW9uIjozLCJmaWxlIjoiY29uZmlnLmpzIiwic291cmNlUm9vdCI6IiIsInNvdXJjZXMiOlsiLi4vLi4vLi4vLi4vLi4vLi4vc3JjL2xpYi9zZXJ2aWNlcy9maXJlYmFzZS9jb25maWcudHMiXSwibmFtZXMiOltdLCJtYXBwaW5ncyI6IkFBQUE7Ozs7O0dBS0c7QUFFSCxPQUFPLEVBQXdCLGNBQWMsRUFBRSx3QkFBd0IsRUFBRSxNQUFNLGVBQWUsQ0FBQztBQUMvRixPQUFPLEVBQUUsYUFBYSxFQUFFLGtCQUFrQixFQUFFLE1BQU0sbUJBQW1CLENBQUM7QUFDdEUsT0FBTyxFQUFFLG1CQUFtQixFQUFFLE9BQU8sRUFBRSxXQUFXLEVBQUUsTUFBTSxvQkFBb0IsQ0FBQztBQUMvRSxPQUFPLEVBQ0wsd0JBQXdCLEVBQ3hCLDBCQUEwQixFQUMxQixZQUFZLEVBQ1osZ0JBQWdCLEdBQ2pCLE1BQU0seUJBQXlCLENBQUM7QUFDakMsT0FBTyxFQUFFLFlBQVksRUFBRSxnQkFBZ0IsRUFBRSxNQUFNLHlCQUF5QixDQUFDO0FBQ3pFLE9BQU8sRUFBRSxzQkFBc0IsRUFBRSxVQUFVLEVBQUUsY0FBYyxFQUFFLE1BQU0sdUJBQXVCLENBQUM7QUFJM0Y7OztHQUdHO0FBQ0gsTUFBTSxDQUFDLE1BQU0sdUJBQXVCLEdBQUcsSUFBSSxjQUFjLENBQ3ZELHVCQUF1QixDQUN4QixDQUFDO0FBRUY7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7OztHQTJCRztBQUNILE1BQU0sVUFBVSxzQkFBc0IsQ0FBQyxNQUE2QjtJQUNsRSxvQ0FBb0M7SUFDcEMsTUFBTSxTQUFTLEdBQVU7UUFDdkIsOENBQThDO1FBQzlDLEVBQUUsT0FBTyxFQUFFLHVCQUF1QixFQUFFLFFBQVEsRUFBRSxNQUFNLEVBQUU7UUFFdEQsMkJBQTJCO1FBQzNCLGtCQUFrQixDQUFDLEdBQUcsRUFBRSxDQUFDLGFBQWEsQ0FBQyxNQUFNLENBQUMsUUFBUSxDQUFDLENBQUM7UUFFeEQsdURBQXVEO1FBQ3ZELGdCQUFnQixDQUFDLEdBQUcsRUFBRTtZQUNwQixNQUFNLFNBQVMsR0FBRyxZQUFZLEVBQUUsQ0FBQztZQUVqQywwQ0FBMEM7WUFDMUMsSUFBSSxNQUFNLENBQUMsUUFBUSxFQUFFLFNBQVMsRUFBRSxDQUFDO2dCQUMvQix3QkFBd0IsQ0FDdEIsU0FBUyxFQUNULE1BQU0sQ0FBQyxRQUFRLENBQUMsU0FBUyxDQUFDLElBQUksRUFDOUIsTUFBTSxDQUFDLFFBQVEsQ0FBQyxTQUFTLENBQUMsSUFBSSxDQUMvQixDQUFDO1lBQ0osQ0FBQztZQUVELHFEQUFxRDtZQUNyRCxJQUFJLE1BQU0sQ0FBQyxXQUFXLEVBQUUsQ0FBQztnQkFDdkIsMEJBQTBCLENBQUMsU0FBUyxDQUFDLENBQUMsS0FBSyxDQUFDLENBQUMsR0FBRyxFQUFFLEVBQUU7b0JBQ2xELElBQUksR0FBRyxDQUFDLElBQUksS0FBSyxxQkFBcUIsRUFBRSxDQUFDO3dCQUN2QyxPQUFPLENBQUMsSUFBSSxDQUNWLDJFQUEyRSxDQUM1RSxDQUFDO29CQUNKLENBQUM7eUJBQU0sSUFBSSxHQUFHLENBQUMsSUFBSSxLQUFLLGVBQWUsRUFBRSxDQUFDO3dCQUN4QyxPQUFPLENBQUMsSUFBSSxDQUFDLCtEQUErRCxDQUFDLENBQUM7b0JBQ2hGLENBQUM7Z0JBQ0gsQ0FBQyxDQUFDLENBQUM7WUFDTCxDQUFDO1lBRUQsT0FBTyxTQUFTLENBQUM7UUFDbkIsQ0FBQyxDQUFDO1FBRUYsaUNBQWlDO1FBQ2pDLFdBQVcsQ0FBQyxHQUFHLEVBQUU7WUFDZixNQUFNLElBQUksR0FBRyxPQUFPLEVBQUUsQ0FBQztZQUV2QiwwQ0FBMEM7WUFDMUMsSUFBSSxNQUFNLENBQUMsUUFBUSxFQUFFLElBQUksRUFBRSxDQUFDO2dCQUMxQixtQkFBbUIsQ0FDakIsSUFBSSxFQUNKLFVBQVUsTUFBTSxDQUFDLFFBQVEsQ0FBQyxJQUFJLENBQUMsSUFBSSxJQUFJLE1BQU0sQ0FBQyxRQUFRLENBQUMsSUFBSSxDQUFDLElBQUksRUFBRSxFQUNsRSxFQUFFLGVBQWUsRUFBRSxJQUFJLEVBQUUsQ0FDMUIsQ0FBQztZQUNKLENBQUM7WUFFRCxPQUFPLElBQUksQ0FBQztRQUNkLENBQUMsQ0FBQztRQUVGLG9DQUFvQztRQUNwQyxjQUFjLENBQUMsR0FBRyxFQUFFO1lBQ2xCLE1BQU0sT0FBTyxHQUFHLFVBQVUsRUFBRSxDQUFDO1lBRTdCLDBDQUEwQztZQUMxQyxJQUFJLE1BQU0sQ0FBQyxRQUFRLEVBQUUsT0FBTyxFQUFFLENBQUM7Z0JBQzdCLHNCQUFzQixDQUNwQixPQUFPLEVBQ1AsTUFBTSxDQUFDLFFBQVEsQ0FBQyxPQUFPLENBQUMsSUFBSSxFQUM1QixNQUFNLENBQUMsUUFBUSxDQUFDLE9BQU8sQ0FBQyxJQUFJLENBQzdCLENBQUM7WUFDSixDQUFDO1lBRUQsT0FBTyxPQUFPLENBQUM7UUFDakIsQ0FBQyxDQUFDO0tBQ0gsQ0FBQztJQUVGLDJEQUEyRDtJQUMzRCxtRkFBbUY7SUFDbkYsSUFBSSxNQUFNLENBQUMsZUFBZSxFQUFFLENBQUM7UUFDM0IsU0FBUyxDQUFDLElBQUksQ0FBQyxnQkFBZ0IsQ0FBQyxHQUFHLEVBQUUsQ0FBQyxZQUFZLEVBQUUsQ0FBQyxDQUFDLENBQUM7SUFDekQsQ0FBQztJQUVELE9BQU8sd0JBQXdCLENBQUMsU0FBUyxDQUFDLENBQUM7QUFDN0MsQ0FBQztBQUVEOzs7OztHQUtHO0FBQ0gsTUFBTSxVQUFVLFlBQVksQ0FBQyxNQUE2QjtJQUN4RCxPQUFPLENBQUMsQ0FBQyxDQUFDLE1BQU0sQ0FBQyxRQUFRLEVBQUUsU0FBUyxJQUFJLE1BQU0sQ0FBQyxRQUFRLEVBQUUsSUFBSSxJQUFJLE1BQU0sQ0FBQyxRQUFRLEVBQUUsT0FBTyxDQUFDLENBQUM7QUFDN0YsQ0FBQyIsInNvdXJjZXNDb250ZW50IjpbIi8qKlxuICogRmlyZWJhc2UgQ29uZmlndXJhdGlvblxuICpcbiAqIENvbmZpZ3VyYWNpw7NuIGUgaW5pY2lhbGl6YWNpw7NuIGRlIEZpcmViYXNlIHBhcmEgYXBsaWNhY2lvbmVzIEFuZ3VsYXIuXG4gKiBVc2EgcHJvdmlkZVZhbHRlY2hGaXJlYmFzZSgpIGVuIGVsIGJvb3RzdHJhcCBkZSB0dSBhcGxpY2FjacOzbi5cbiAqL1xuXG5pbXBvcnQgeyBFbnZpcm9ubWVudFByb3ZpZGVycywgSW5qZWN0aW9uVG9rZW4sIG1ha2VFbnZpcm9ubWVudFByb3ZpZGVycyB9IGZyb20gJ0Bhbmd1bGFyL2NvcmUnO1xuaW1wb3J0IHsgaW5pdGlhbGl6ZUFwcCwgcHJvdmlkZUZpcmViYXNlQXBwIH0gZnJvbSAnQGFuZ3VsYXIvZmlyZS9hcHAnO1xuaW1wb3J0IHsgY29ubmVjdEF1dGhFbXVsYXRvciwgZ2V0QXV0aCwgcHJvdmlkZUF1dGggfSBmcm9tICdAYW5ndWxhci9maXJlL2F1dGgnO1xuaW1wb3J0IHtcbiAgY29ubmVjdEZpcmVzdG9yZUVtdWxhdG9yLFxuICBlbmFibGVJbmRleGVkRGJQZXJzaXN0ZW5jZSxcbiAgZ2V0RmlyZXN0b3JlLFxuICBwcm92aWRlRmlyZXN0b3JlLFxufSBmcm9tICdAYW5ndWxhci9maXJlL2ZpcmVzdG9yZSc7XG5pbXBvcnQgeyBnZXRNZXNzYWdpbmcsIHByb3ZpZGVNZXNzYWdpbmcgfSBmcm9tICdAYW5ndWxhci9maXJlL21lc3NhZ2luZyc7XG5pbXBvcnQgeyBjb25uZWN0U3RvcmFnZUVtdWxhdG9yLCBnZXRTdG9yYWdlLCBwcm92aWRlU3RvcmFnZSB9IGZyb20gJ0Bhbmd1bGFyL2ZpcmUvc3RvcmFnZSc7XG5cbmltcG9ydCB7IFZhbHRlY2hGaXJlYmFzZUNvbmZpZyB9IGZyb20gJy4vdHlwZXMnO1xuXG4vKipcbiAqIFRva2VuIGRlIGlueWVjY2nDs24gcGFyYSBsYSBjb25maWd1cmFjacOzbiBkZSBGaXJlYmFzZS5cbiAqIFVzYWRvIGludGVybmFtZW50ZSBwb3IgbG9zIHNlcnZpY2lvcyBkZSBGaXJlYmFzZS5cbiAqL1xuZXhwb3J0IGNvbnN0IFZBTFRFQ0hfRklSRUJBU0VfQ09ORklHID0gbmV3IEluamVjdGlvblRva2VuPFZhbHRlY2hGaXJlYmFzZUNvbmZpZz4oXG4gICdWYWx0ZWNoRmlyZWJhc2VDb25maWcnXG4pO1xuXG4vKipcbiAqIFByb3ZlZSBGaXJlYmFzZSBhIGxhIGFwbGljYWNpw7NuIEFuZ3VsYXIuXG4gKlxuICogQHBhcmFtIGNvbmZpZyAtIENvbmZpZ3VyYWNpw7NuIGRlIEZpcmViYXNlXG4gKiBAcmV0dXJucyBFbnZpcm9ubWVudFByb3ZpZGVycyBwYXJhIHVzYXIgZW4gYm9vdHN0cmFwQXBwbGljYXRpb25cbiAqXG4gKiBAZXhhbXBsZVxuICogYGBgdHlwZXNjcmlwdFxuICogLy8gbWFpbi50c1xuICogaW1wb3J0IHsgYm9vdHN0cmFwQXBwbGljYXRpb24gfSBmcm9tICdAYW5ndWxhci9wbGF0Zm9ybS1icm93c2VyJztcbiAqIGltcG9ydCB7IHByb3ZpZGVWYWx0ZWNoRmlyZWJhc2UgfSBmcm9tICd2YWx0ZWNoLWNvbXBvbmVudHMnO1xuICogaW1wb3J0IHsgZW52aXJvbm1lbnQgfSBmcm9tICcuL2Vudmlyb25tZW50cy9lbnZpcm9ubWVudCc7XG4gKlxuICogYm9vdHN0cmFwQXBwbGljYXRpb24oQXBwQ29tcG9uZW50LCB7XG4gKiAgIHByb3ZpZGVyczogW1xuICogICAgIHByb3ZpZGVWYWx0ZWNoRmlyZWJhc2Uoe1xuICogICAgICAgZmlyZWJhc2U6IGVudmlyb25tZW50LmZpcmViYXNlLFxuICogICAgICAgcGVyc2lzdGVuY2U6IHRydWUsXG4gKiAgICAgICBlbXVsYXRvcjogZW52aXJvbm1lbnQudXNlRW11bGF0b3JzID8ge1xuICogICAgICAgICBmaXJlc3RvcmU6IHsgaG9zdDogJ2xvY2FsaG9zdCcsIHBvcnQ6IDgwODAgfSxcbiAqICAgICAgICAgYXV0aDogeyBob3N0OiAnbG9jYWxob3N0JywgcG9ydDogOTA5OSB9LFxuICogICAgICAgICBzdG9yYWdlOiB7IGhvc3Q6ICdsb2NhbGhvc3QnLCBwb3J0OiA5MTk5IH0sXG4gKiAgICAgICB9IDogdW5kZWZpbmVkLFxuICogICAgIH0pLFxuICogICBdLFxuICogfSk7XG4gKiBgYGBcbiAqL1xuZXhwb3J0IGZ1bmN0aW9uIHByb3ZpZGVWYWx0ZWNoRmlyZWJhc2UoY29uZmlnOiBWYWx0ZWNoRmlyZWJhc2VDb25maWcpOiBFbnZpcm9ubWVudFByb3ZpZGVycyB7XG4gIC8vIENvbnN0cnVpciBhcnJheSBkZSBwcm92aWRlcnMgYmFzZVxuICBjb25zdCBwcm92aWRlcnM6IGFueVtdID0gW1xuICAgIC8vIEd1YXJkYXIgY29uZmlndXJhY2nDs24gcGFyYSB1c28gZW4gc2VydmljaW9zXG4gICAgeyBwcm92aWRlOiBWQUxURUNIX0ZJUkVCQVNFX0NPTkZJRywgdXNlVmFsdWU6IGNvbmZpZyB9LFxuXG4gICAgLy8gSW5pY2lhbGl6YXIgRmlyZWJhc2UgQXBwXG4gICAgcHJvdmlkZUZpcmViYXNlQXBwKCgpID0+IGluaXRpYWxpemVBcHAoY29uZmlnLmZpcmViYXNlKSksXG5cbiAgICAvLyBGaXJlc3RvcmUgY29uIHNvcG9ydGUgcGFyYSBlbXVsYWRvcmVzIHkgcGVyc2lzdGVuY2lhXG4gICAgcHJvdmlkZUZpcmVzdG9yZSgoKSA9PiB7XG4gICAgICBjb25zdCBmaXJlc3RvcmUgPSBnZXRGaXJlc3RvcmUoKTtcblxuICAgICAgLy8gQ29uZWN0YXIgYSBlbXVsYWRvciBzaSBlc3TDoSBjb25maWd1cmFkb1xuICAgICAgaWYgKGNvbmZpZy5lbXVsYXRvcj8uZmlyZXN0b3JlKSB7XG4gICAgICAgIGNvbm5lY3RGaXJlc3RvcmVFbXVsYXRvcihcbiAgICAgICAgICBmaXJlc3RvcmUsXG4gICAgICAgICAgY29uZmlnLmVtdWxhdG9yLmZpcmVzdG9yZS5ob3N0LFxuICAgICAgICAgIGNvbmZpZy5lbXVsYXRvci5maXJlc3RvcmUucG9ydFxuICAgICAgICApO1xuICAgICAgfVxuXG4gICAgICAvLyBIYWJpbGl0YXIgcGVyc2lzdGVuY2lhIG9mZmxpbmUgc2kgZXN0w6EgY29uZmlndXJhZGFcbiAgICAgIGlmIChjb25maWcucGVyc2lzdGVuY2UpIHtcbiAgICAgICAgZW5hYmxlSW5kZXhlZERiUGVyc2lzdGVuY2UoZmlyZXN0b3JlKS5jYXRjaCgoZXJyKSA9PiB7XG4gICAgICAgICAgaWYgKGVyci5jb2RlID09PSAnZmFpbGVkLXByZWNvbmRpdGlvbicpIHtcbiAgICAgICAgICAgIGNvbnNvbGUud2FybihcbiAgICAgICAgICAgICAgJ1tWYWx0ZWNoRmlyZWJhc2VdIFBlcnNpc3RlbmNpYSBubyBkaXNwb25pYmxlOiBtw7psdGlwbGVzIHBlc3Rhw7FhcyBhYmllcnRhcydcbiAgICAgICAgICAgICk7XG4gICAgICAgICAgfSBlbHNlIGlmIChlcnIuY29kZSA9PT0gJ3VuaW1wbGVtZW50ZWQnKSB7XG4gICAgICAgICAgICBjb25zb2xlLndhcm4oJ1tWYWx0ZWNoRmlyZWJhc2VdIFBlcnNpc3RlbmNpYSBubyBzb3BvcnRhZGEgZW4gZXN0ZSBuYXZlZ2Fkb3InKTtcbiAgICAgICAgICB9XG4gICAgICAgIH0pO1xuICAgICAgfVxuXG4gICAgICByZXR1cm4gZmlyZXN0b3JlO1xuICAgIH0pLFxuXG4gICAgLy8gQXV0aCBjb24gc29wb3J0ZSBwYXJhIGVtdWxhZG9yXG4gICAgcHJvdmlkZUF1dGgoKCkgPT4ge1xuICAgICAgY29uc3QgYXV0aCA9IGdldEF1dGgoKTtcblxuICAgICAgLy8gQ29uZWN0YXIgYSBlbXVsYWRvciBzaSBlc3TDoSBjb25maWd1cmFkb1xuICAgICAgaWYgKGNvbmZpZy5lbXVsYXRvcj8uYXV0aCkge1xuICAgICAgICBjb25uZWN0QXV0aEVtdWxhdG9yKFxuICAgICAgICAgIGF1dGgsXG4gICAgICAgICAgYGh0dHA6Ly8ke2NvbmZpZy5lbXVsYXRvci5hdXRoLmhvc3R9OiR7Y29uZmlnLmVtdWxhdG9yLmF1dGgucG9ydH1gLFxuICAgICAgICAgIHsgZGlzYWJsZVdhcm5pbmdzOiB0cnVlIH1cbiAgICAgICAgKTtcbiAgICAgIH1cblxuICAgICAgcmV0dXJuIGF1dGg7XG4gICAgfSksXG5cbiAgICAvLyBTdG9yYWdlIGNvbiBzb3BvcnRlIHBhcmEgZW11bGFkb3JcbiAgICBwcm92aWRlU3RvcmFnZSgoKSA9PiB7XG4gICAgICBjb25zdCBzdG9yYWdlID0gZ2V0U3RvcmFnZSgpO1xuXG4gICAgICAvLyBDb25lY3RhciBhIGVtdWxhZG9yIHNpIGVzdMOhIGNvbmZpZ3VyYWRvXG4gICAgICBpZiAoY29uZmlnLmVtdWxhdG9yPy5zdG9yYWdlKSB7XG4gICAgICAgIGNvbm5lY3RTdG9yYWdlRW11bGF0b3IoXG4gICAgICAgICAgc3RvcmFnZSxcbiAgICAgICAgICBjb25maWcuZW11bGF0b3Iuc3RvcmFnZS5ob3N0LFxuICAgICAgICAgIGNvbmZpZy5lbXVsYXRvci5zdG9yYWdlLnBvcnRcbiAgICAgICAgKTtcbiAgICAgIH1cblxuICAgICAgcmV0dXJuIHN0b3JhZ2U7XG4gICAgfSksXG4gIF07XG5cbiAgLy8gTWVzc2FnaW5nIChGQ00pIC0gc29sbyBzaSBlc3TDoSBleHBsw61jaXRhbWVudGUgaGFiaWxpdGFkb1xuICAvLyBSZXF1aWVyZSBTZXJ2aWNlIFdvcmtlciBjb25maWd1cmFkbywgcHVlZGUgY29uZ2VsYXIgbGEgYXBwIHNpIG5vIGVzdMOhIGRpc3BvbmlibGVcbiAgaWYgKGNvbmZpZy5lbmFibGVNZXNzYWdpbmcpIHtcbiAgICBwcm92aWRlcnMucHVzaChwcm92aWRlTWVzc2FnaW5nKCgpID0+IGdldE1lc3NhZ2luZygpKSk7XG4gIH1cblxuICByZXR1cm4gbWFrZUVudmlyb25tZW50UHJvdmlkZXJzKHByb3ZpZGVycyk7XG59XG5cbi8qKlxuICogVmVyaWZpY2Egc2kgbG9zIGVtdWxhZG9yZXMgZXN0w6FuIGNvbmZpZ3VyYWRvcy5cbiAqXG4gKiBAcGFyYW0gY29uZmlnIC0gQ29uZmlndXJhY2nDs24gZGUgRmlyZWJhc2VcbiAqIEByZXR1cm5zIHRydWUgc2kgaGF5IGFsIG1lbm9zIHVuIGVtdWxhZG9yIGNvbmZpZ3VyYWRvXG4gKi9cbmV4cG9ydCBmdW5jdGlvbiBoYXNFbXVsYXRvcnMoY29uZmlnOiBWYWx0ZWNoRmlyZWJhc2VDb25maWcpOiBib29sZWFuIHtcbiAgcmV0dXJuICEhKGNvbmZpZy5lbXVsYXRvcj8uZmlyZXN0b3JlIHx8IGNvbmZpZy5lbXVsYXRvcj8uYXV0aCB8fCBjb25maWcuZW11bGF0b3I/LnN0b3JhZ2UpO1xufVxuIl19
@@ -1,285 +0,0 @@
1
- /**
2
- * Firebase Service
3
- *
4
- * Servicio principal para la autenticación con Firebase usando Custom Tokens.
5
- * Permite que usuarios autenticados con tu backend (Cognito, etc.) accedan
6
- * a servicios de Firebase (Firestore, Storage, FCM) de manera segura.
7
- */
8
- import { inject, Injectable } from '@angular/core';
9
- import { Auth, authState, signInWithCustomToken, signOut } from '@angular/fire/auth';
10
- import { BehaviorSubject, distinctUntilChanged, map } from 'rxjs';
11
- import { VALTECH_FIREBASE_CONFIG } from './config';
12
- import * as i0 from "@angular/core";
13
- /**
14
- * Servicio de autenticación de Firebase.
15
- *
16
- * Este servicio NO maneja el login de usuarios directamente.
17
- * En su lugar, trabaja con Custom Tokens generados por tu backend.
18
- *
19
- * @example
20
- * ```typescript
21
- * // Después de autenticarte con tu backend (ej: Cognito)
22
- * @Component({...})
23
- * export class LoginComponent {
24
- * private authService = inject(AuthService); // Tu servicio de auth
25
- * private firebase = inject(FirebaseService); // Este servicio
26
- *
27
- * async login(email: string, password: string) {
28
- * // 1. Autenticar con tu backend
29
- * const response = await this.authService.login(email, password);
30
- *
31
- * // 2. El backend devuelve un Firebase Custom Token
32
- * if (response.firebaseToken) {
33
- * await this.firebase.signInWithCustomToken(response.firebaseToken);
34
- * }
35
- *
36
- * // Ahora el usuario puede acceder a Firestore, Storage, etc.
37
- * }
38
- *
39
- * async logout() {
40
- * await this.authService.logout();
41
- * await this.firebase.signOut();
42
- * }
43
- * }
44
- * ```
45
- */
46
- export class FirebaseService {
47
- constructor() {
48
- this.auth = inject(Auth);
49
- this.config = inject(VALTECH_FIREBASE_CONFIG);
50
- /** Estado interno de la sesión */
51
- this.sessionState = new BehaviorSubject({
52
- user: null,
53
- isAuthenticated: false,
54
- isLoading: true,
55
- error: null,
56
- });
57
- /** Estado actual de la sesión como Observable */
58
- this.state$ = this.sessionState.asObservable();
59
- /** Usuario actual de Firebase como Observable */
60
- this.user$ = authState(this.auth).pipe(map((user) => (user ? this.mapUser(user) : null)), distinctUntilChanged((a, b) => a?.uid === b?.uid));
61
- /** Indica si el usuario está autenticado en Firebase */
62
- this.isAuthenticated$ = this.user$.pipe(map((user) => !!user), distinctUntilChanged());
63
- // Escuchar cambios en el estado de autenticación
64
- authState(this.auth).subscribe({
65
- next: (user) => {
66
- this.sessionState.next({
67
- user: user ? this.mapUser(user) : null,
68
- isAuthenticated: !!user,
69
- isLoading: false,
70
- error: null,
71
- });
72
- },
73
- error: (error) => {
74
- this.sessionState.next({
75
- user: null,
76
- isAuthenticated: false,
77
- isLoading: false,
78
- error,
79
- });
80
- },
81
- });
82
- }
83
- // ===========================================================================
84
- // AUTENTICACIÓN
85
- // ===========================================================================
86
- /**
87
- * Autentica al usuario con un Custom Token generado por el backend.
88
- *
89
- * @param token - Firebase Custom Token generado por tu backend
90
- * @returns UserCredential con la información del usuario
91
- * @throws Error si el token es inválido o expiró
92
- *
93
- * @example
94
- * ```typescript
95
- * // Después de login exitoso con tu backend
96
- * const { firebaseToken } = await backendAuth.login(email, password);
97
- * await firebaseService.signInWithCustomToken(firebaseToken);
98
- * ```
99
- */
100
- async signInWithCustomToken(token) {
101
- try {
102
- const credential = await signInWithCustomToken(this.auth, token);
103
- return credential;
104
- }
105
- catch (error) {
106
- const message = this.getErrorMessage(error);
107
- throw new Error(message);
108
- }
109
- }
110
- /**
111
- * Cierra la sesión de Firebase.
112
- * Llamar junto con el logout de tu sistema de autenticación principal.
113
- *
114
- * @example
115
- * ```typescript
116
- * async logout() {
117
- * await this.backendAuth.logout(); // Tu auth
118
- * await this.firebase.signOut(); // Firebase
119
- * }
120
- * ```
121
- */
122
- async signOut() {
123
- try {
124
- await signOut(this.auth);
125
- }
126
- catch (error) {
127
- const message = this.getErrorMessage(error);
128
- throw new Error(message);
129
- }
130
- }
131
- // ===========================================================================
132
- // GETTERS SÍNCRONOS
133
- // ===========================================================================
134
- /**
135
- * Obtiene el usuario actual de Firebase (síncrono).
136
- * Retorna null si no hay usuario autenticado.
137
- */
138
- get currentUser() {
139
- const user = this.auth.currentUser;
140
- return user ? this.mapUser(user) : null;
141
- }
142
- /**
143
- * Obtiene el UID del usuario actual.
144
- * Retorna null si no hay usuario autenticado.
145
- */
146
- get uid() {
147
- return this.auth.currentUser?.uid ?? null;
148
- }
149
- /**
150
- * Indica si hay un usuario autenticado actualmente.
151
- */
152
- get isAuthenticated() {
153
- return !!this.auth.currentUser;
154
- }
155
- // ===========================================================================
156
- // TOKENS
157
- // ===========================================================================
158
- /**
159
- * Obtiene el ID Token de Firebase para el usuario actual.
160
- * Útil para validar el usuario en tu backend.
161
- *
162
- * @param forceRefresh - Si true, fuerza la renovación del token
163
- * @returns ID Token o null si no hay usuario
164
- */
165
- async getIdToken(forceRefresh = false) {
166
- const user = this.auth.currentUser;
167
- if (!user)
168
- return null;
169
- try {
170
- return await user.getIdToken(forceRefresh);
171
- }
172
- catch {
173
- return null;
174
- }
175
- }
176
- /**
177
- * Obtiene los claims personalizados del token del usuario.
178
- * Los claims son establecidos por tu backend al crear el Custom Token.
179
- *
180
- * @returns Objeto con los claims o vacío si no hay usuario
181
- */
182
- async getClaims() {
183
- const user = this.auth.currentUser;
184
- if (!user)
185
- return {};
186
- try {
187
- const result = await user.getIdTokenResult();
188
- return result.claims;
189
- }
190
- catch {
191
- return {};
192
- }
193
- }
194
- /**
195
- * Verifica si el usuario tiene un rol específico.
196
- * El rol debe estar definido en los claims del Custom Token.
197
- *
198
- * @param role - Nombre del rol a verificar
199
- * @returns true si el usuario tiene el rol
200
- */
201
- async hasRole(role) {
202
- const claims = await this.getClaims();
203
- return claims['role'] === role || (Array.isArray(claims['roles']) && claims['roles'].includes(role));
204
- }
205
- // ===========================================================================
206
- // UTILIDADES
207
- // ===========================================================================
208
- /**
209
- * Espera a que el estado de autenticación esté determinado.
210
- * Útil en guards o al inicializar la app.
211
- *
212
- * @returns Usuario actual o null
213
- */
214
- waitForAuth() {
215
- return new Promise((resolve) => {
216
- const subscription = this.state$.subscribe((state) => {
217
- if (!state.isLoading) {
218
- subscription.unsubscribe();
219
- resolve(state.user);
220
- }
221
- });
222
- });
223
- }
224
- /**
225
- * Obtiene la configuración actual de Firebase.
226
- */
227
- getConfig() {
228
- return this.config;
229
- }
230
- /**
231
- * Indica si los emuladores están habilitados.
232
- */
233
- isUsingEmulators() {
234
- return !!(this.config.emulator?.firestore || this.config.emulator?.auth || this.config.emulator?.storage);
235
- }
236
- // ===========================================================================
237
- // MÉTODOS PRIVADOS
238
- // ===========================================================================
239
- /**
240
- * Mapea un User de Firebase a nuestra interface FirebaseUser
241
- */
242
- mapUser(user) {
243
- return {
244
- uid: user.uid,
245
- email: user.email,
246
- displayName: user.displayName,
247
- photoURL: user.photoURL,
248
- emailVerified: user.emailVerified,
249
- isAnonymous: user.isAnonymous,
250
- providerId: user.providerId,
251
- };
252
- }
253
- /**
254
- * Convierte errores de Firebase a mensajes en español
255
- */
256
- getErrorMessage(error) {
257
- if (error instanceof Error) {
258
- const code = error.code;
259
- switch (code) {
260
- case 'auth/invalid-custom-token':
261
- return 'Token de autenticación inválido';
262
- case 'auth/custom-token-mismatch':
263
- return 'El token no corresponde a este proyecto';
264
- case 'auth/network-request-failed':
265
- return 'Error de conexión. Verifica tu conexión a internet';
266
- case 'auth/too-many-requests':
267
- return 'Demasiados intentos. Intenta de nuevo más tarde';
268
- case 'auth/user-disabled':
269
- return 'Esta cuenta ha sido deshabilitada';
270
- case 'auth/user-not-found':
271
- return 'Usuario no encontrado';
272
- default:
273
- return error.message || 'Error de autenticación desconocido';
274
- }
275
- }
276
- return 'Error de autenticación desconocido';
277
- }
278
- static { this.ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "18.2.14", ngImport: i0, type: FirebaseService, deps: [], target: i0.ɵɵFactoryTarget.Injectable }); }
279
- static { this.ɵprov = i0.ɵɵngDeclareInjectable({ minVersion: "12.0.0", version: "18.2.14", ngImport: i0, type: FirebaseService, providedIn: 'root' }); }
280
- }
281
- i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "18.2.14", ngImport: i0, type: FirebaseService, decorators: [{
282
- type: Injectable,
283
- args: [{ providedIn: 'root' }]
284
- }], ctorParameters: () => [] });
285
- //# sourceMappingURL=data:application/json;base64,eyJ2ZXJzaW9uIjozLCJmaWxlIjoiZmlyZWJhc2Uuc2VydmljZS5qcyIsInNvdXJjZVJvb3QiOiIiLCJzb3VyY2VzIjpbIi4uLy4uLy4uLy4uLy4uLy4uL3NyYy9saWIvc2VydmljZXMvZmlyZWJhc2UvZmlyZWJhc2Uuc2VydmljZS50cyJdLCJuYW1lcyI6W10sIm1hcHBpbmdzIjoiQUFBQTs7Ozs7O0dBTUc7QUFFSCxPQUFPLEVBQUUsTUFBTSxFQUFFLFVBQVUsRUFBRSxNQUFNLGVBQWUsQ0FBQztBQUNuRCxPQUFPLEVBQUUsSUFBSSxFQUFFLFNBQVMsRUFBRSxxQkFBcUIsRUFBRSxPQUFPLEVBQXdCLE1BQU0sb0JBQW9CLENBQUM7QUFDM0csT0FBTyxFQUFFLGVBQWUsRUFBRSxvQkFBb0IsRUFBRSxHQUFHLEVBQWMsTUFBTSxNQUFNLENBQUM7QUFFOUUsT0FBTyxFQUFFLHVCQUF1QixFQUFFLE1BQU0sVUFBVSxDQUFDOztBQUduRDs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7R0FnQ0c7QUFFSCxNQUFNLE9BQU8sZUFBZTtJQTJCMUI7UUExQlEsU0FBSSxHQUFHLE1BQU0sQ0FBQyxJQUFJLENBQUMsQ0FBQztRQUNwQixXQUFNLEdBQUcsTUFBTSxDQUFDLHVCQUF1QixDQUFDLENBQUM7UUFFakQsa0NBQWtDO1FBQzFCLGlCQUFZLEdBQUcsSUFBSSxlQUFlLENBQWU7WUFDdkQsSUFBSSxFQUFFLElBQUk7WUFDVixlQUFlLEVBQUUsS0FBSztZQUN0QixTQUFTLEVBQUUsSUFBSTtZQUNmLEtBQUssRUFBRSxJQUFJO1NBQ1osQ0FBQyxDQUFDO1FBRUgsaURBQWlEO1FBQ3hDLFdBQU0sR0FBNkIsSUFBSSxDQUFDLFlBQVksQ0FBQyxZQUFZLEVBQUUsQ0FBQztRQUU3RSxpREFBaUQ7UUFDeEMsVUFBSyxHQUFvQyxTQUFTLENBQUMsSUFBSSxDQUFDLElBQUksQ0FBQyxDQUFDLElBQUksQ0FDekUsR0FBRyxDQUFDLENBQUMsSUFBSSxFQUFFLEVBQUUsQ0FBQyxDQUFDLElBQUksQ0FBQyxDQUFDLENBQUMsSUFBSSxDQUFDLE9BQU8sQ0FBQyxJQUFJLENBQUMsQ0FBQyxDQUFDLENBQUMsSUFBSSxDQUFDLENBQUMsRUFDakQsb0JBQW9CLENBQUMsQ0FBQyxDQUFDLEVBQUUsQ0FBQyxFQUFFLEVBQUUsQ0FBQyxDQUFDLEVBQUUsR0FBRyxLQUFLLENBQUMsRUFBRSxHQUFHLENBQUMsQ0FDbEQsQ0FBQztRQUVGLHdEQUF3RDtRQUMvQyxxQkFBZ0IsR0FBd0IsSUFBSSxDQUFDLEtBQUssQ0FBQyxJQUFJLENBQzlELEdBQUcsQ0FBQyxDQUFDLElBQUksRUFBRSxFQUFFLENBQUMsQ0FBQyxDQUFDLElBQUksQ0FBQyxFQUNyQixvQkFBb0IsRUFBRSxDQUN2QixDQUFDO1FBR0EsaURBQWlEO1FBQ2pELFNBQVMsQ0FBQyxJQUFJLENBQUMsSUFBSSxDQUFDLENBQUMsU0FBUyxDQUFDO1lBQzdCLElBQUksRUFBRSxDQUFDLElBQUksRUFBRSxFQUFFO2dCQUNiLElBQUksQ0FBQyxZQUFZLENBQUMsSUFBSSxDQUFDO29CQUNyQixJQUFJLEVBQUUsSUFBSSxDQUFDLENBQUMsQ0FBQyxJQUFJLENBQUMsT0FBTyxDQUFDLElBQUksQ0FBQyxDQUFDLENBQUMsQ0FBQyxJQUFJO29CQUN0QyxlQUFlLEVBQUUsQ0FBQyxDQUFDLElBQUk7b0JBQ3ZCLFNBQVMsRUFBRSxLQUFLO29CQUNoQixLQUFLLEVBQUUsSUFBSTtpQkFDWixDQUFDLENBQUM7WUFDTCxDQUFDO1lBQ0QsS0FBSyxFQUFFLENBQUMsS0FBSyxFQUFFLEVBQUU7Z0JBQ2YsSUFBSSxDQUFDLFlBQVksQ0FBQyxJQUFJLENBQUM7b0JBQ3JCLElBQUksRUFBRSxJQUFJO29CQUNWLGVBQWUsRUFBRSxLQUFLO29CQUN0QixTQUFTLEVBQUUsS0FBSztvQkFDaEIsS0FBSztpQkFDTixDQUFDLENBQUM7WUFDTCxDQUFDO1NBQ0YsQ0FBQyxDQUFDO0lBQ0wsQ0FBQztJQUVELDhFQUE4RTtJQUM5RSxnQkFBZ0I7SUFDaEIsOEVBQThFO0lBRTlFOzs7Ozs7Ozs7Ozs7O09BYUc7SUFDSCxLQUFLLENBQUMscUJBQXFCLENBQUMsS0FBYTtRQUN2QyxJQUFJLENBQUM7WUFDSCxNQUFNLFVBQVUsR0FBRyxNQUFNLHFCQUFxQixDQUFDLElBQUksQ0FBQyxJQUFJLEVBQUUsS0FBSyxDQUFDLENBQUM7WUFDakUsT0FBTyxVQUFVLENBQUM7UUFDcEIsQ0FBQztRQUFDLE9BQU8sS0FBSyxFQUFFLENBQUM7WUFDZixNQUFNLE9BQU8sR0FBRyxJQUFJLENBQUMsZUFBZSxDQUFDLEtBQUssQ0FBQyxDQUFDO1lBQzVDLE1BQU0sSUFBSSxLQUFLLENBQUMsT0FBTyxDQUFDLENBQUM7UUFDM0IsQ0FBQztJQUNILENBQUM7SUFFRDs7Ozs7Ozs7Ozs7T0FXRztJQUNILEtBQUssQ0FBQyxPQUFPO1FBQ1gsSUFBSSxDQUFDO1lBQ0gsTUFBTSxPQUFPLENBQUMsSUFBSSxDQUFDLElBQUksQ0FBQyxDQUFDO1FBQzNCLENBQUM7UUFBQyxPQUFPLEtBQUssRUFBRSxDQUFDO1lBQ2YsTUFBTSxPQUFPLEdBQUcsSUFBSSxDQUFDLGVBQWUsQ0FBQyxLQUFLLENBQUMsQ0FBQztZQUM1QyxNQUFNLElBQUksS0FBSyxDQUFDLE9BQU8sQ0FBQyxDQUFDO1FBQzNCLENBQUM7SUFDSCxDQUFDO0lBRUQsOEVBQThFO0lBQzlFLG9CQUFvQjtJQUNwQiw4RUFBOEU7SUFFOUU7OztPQUdHO0lBQ0gsSUFBSSxXQUFXO1FBQ2IsTUFBTSxJQUFJLEdBQUcsSUFBSSxDQUFDLElBQUksQ0FBQyxXQUFXLENBQUM7UUFDbkMsT0FBTyxJQUFJLENBQUMsQ0FBQyxDQUFDLElBQUksQ0FBQyxPQUFPLENBQUMsSUFBSSxDQUFDLENBQUMsQ0FBQyxDQUFDLElBQUksQ0FBQztJQUMxQyxDQUFDO0lBRUQ7OztPQUdHO0lBQ0gsSUFBSSxHQUFHO1FBQ0wsT0FBTyxJQUFJLENBQUMsSUFBSSxDQUFDLFdBQVcsRUFBRSxHQUFHLElBQUksSUFBSSxDQUFDO0lBQzVDLENBQUM7SUFFRDs7T0FFRztJQUNILElBQUksZUFBZTtRQUNqQixPQUFPLENBQUMsQ0FBQyxJQUFJLENBQUMsSUFBSSxDQUFDLFdBQVcsQ0FBQztJQUNqQyxDQUFDO0lBRUQsOEVBQThFO0lBQzlFLFNBQVM7SUFDVCw4RUFBOEU7SUFFOUU7Ozs7OztPQU1HO0lBQ0gsS0FBSyxDQUFDLFVBQVUsQ0FBQyxZQUFZLEdBQUcsS0FBSztRQUNuQyxNQUFNLElBQUksR0FBRyxJQUFJLENBQUMsSUFBSSxDQUFDLFdBQVcsQ0FBQztRQUNuQyxJQUFJLENBQUMsSUFBSTtZQUFFLE9BQU8sSUFBSSxDQUFDO1FBRXZCLElBQUksQ0FBQztZQUNILE9BQU8sTUFBTSxJQUFJLENBQUMsVUFBVSxDQUFDLFlBQVksQ0FBQyxDQUFDO1FBQzdDLENBQUM7UUFBQyxNQUFNLENBQUM7WUFDUCxPQUFPLElBQUksQ0FBQztRQUNkLENBQUM7SUFDSCxDQUFDO0lBRUQ7Ozs7O09BS0c7SUFDSCxLQUFLLENBQUMsU0FBUztRQUNiLE1BQU0sSUFBSSxHQUFHLElBQUksQ0FBQyxJQUFJLENBQUMsV0FBVyxDQUFDO1FBQ25DLElBQUksQ0FBQyxJQUFJO1lBQUUsT0FBTyxFQUFFLENBQUM7UUFFckIsSUFBSSxDQUFDO1lBQ0gsTUFBTSxNQUFNLEdBQUcsTUFBTSxJQUFJLENBQUMsZ0JBQWdCLEVBQUUsQ0FBQztZQUM3QyxPQUFPLE1BQU0sQ0FBQyxNQUFNLENBQUM7UUFDdkIsQ0FBQztRQUFDLE1BQU0sQ0FBQztZQUNQLE9BQU8sRUFBRSxDQUFDO1FBQ1osQ0FBQztJQUNILENBQUM7SUFFRDs7Ozs7O09BTUc7SUFDSCxLQUFLLENBQUMsT0FBTyxDQUFDLElBQVk7UUFDeEIsTUFBTSxNQUFNLEdBQUcsTUFBTSxJQUFJLENBQUMsU0FBUyxFQUFFLENBQUM7UUFDdEMsT0FBTyxNQUFNLENBQUMsTUFBTSxDQUFDLEtBQUssSUFBSSxJQUFJLENBQUMsS0FBSyxDQUFDLE9BQU8sQ0FBQyxNQUFNLENBQUMsT0FBTyxDQUFDLENBQUMsSUFBSSxNQUFNLENBQUMsT0FBTyxDQUFDLENBQUMsUUFBUSxDQUFDLElBQUksQ0FBQyxDQUFDLENBQUM7SUFDdkcsQ0FBQztJQUVELDhFQUE4RTtJQUM5RSxhQUFhO0lBQ2IsOEVBQThFO0lBRTlFOzs7OztPQUtHO0lBQ0gsV0FBVztRQUNULE9BQU8sSUFBSSxPQUFPLENBQUMsQ0FBQyxPQUFPLEVBQUUsRUFBRTtZQUM3QixNQUFNLFlBQVksR0FBRyxJQUFJLENBQUMsTUFBTSxDQUFDLFNBQVMsQ0FBQyxDQUFDLEtBQUssRUFBRSxFQUFFO2dCQUNuRCxJQUFJLENBQUMsS0FBSyxDQUFDLFNBQVMsRUFBRSxDQUFDO29CQUNyQixZQUFZLENBQUMsV0FBVyxFQUFFLENBQUM7b0JBQzNCLE9BQU8sQ0FBQyxLQUFLLENBQUMsSUFBSSxDQUFDLENBQUM7Z0JBQ3RCLENBQUM7WUFDSCxDQUFDLENBQUMsQ0FBQztRQUNMLENBQUMsQ0FBQyxDQUFDO0lBQ0wsQ0FBQztJQUVEOztPQUVHO0lBQ0gsU0FBUztRQUNQLE9BQU8sSUFBSSxDQUFDLE1BQU0sQ0FBQztJQUNyQixDQUFDO0lBRUQ7O09BRUc7SUFDSCxnQkFBZ0I7UUFDZCxPQUFPLENBQUMsQ0FBQyxDQUFDLElBQUksQ0FBQyxNQUFNLENBQUMsUUFBUSxFQUFFLFNBQVMsSUFBSSxJQUFJLENBQUMsTUFBTSxDQUFDLFFBQVEsRUFBRSxJQUFJLElBQUksSUFBSSxDQUFDLE1BQU0sQ0FBQyxRQUFRLEVBQUUsT0FBTyxDQUFDLENBQUM7SUFDNUcsQ0FBQztJQUVELDhFQUE4RTtJQUM5RSxtQkFBbUI7SUFDbkIsOEVBQThFO0lBRTlFOztPQUVHO0lBQ0ssT0FBTyxDQUFDLElBQVU7UUFDeEIsT0FBTztZQUNMLEdBQUcsRUFBRSxJQUFJLENBQUMsR0FBRztZQUNiLEtBQUssRUFBRSxJQUFJLENBQUMsS0FBSztZQUNqQixXQUFXLEVBQUUsSUFBSSxDQUFDLFdBQVc7WUFDN0IsUUFBUSxFQUFFLElBQUksQ0FBQyxRQUFRO1lBQ3ZCLGFBQWEsRUFBRSxJQUFJLENBQUMsYUFBYTtZQUNqQyxXQUFXLEVBQUUsSUFBSSxDQUFDLFdBQVc7WUFDN0IsVUFBVSxFQUFFLElBQUksQ0FBQyxVQUFVO1NBQzVCLENBQUM7SUFDSixDQUFDO0lBRUQ7O09BRUc7SUFDSyxlQUFlLENBQUMsS0FBYztRQUNwQyxJQUFJLEtBQUssWUFBWSxLQUFLLEVBQUUsQ0FBQztZQUMzQixNQUFNLElBQUksR0FBSSxLQUEyQixDQUFDLElBQUksQ0FBQztZQUUvQyxRQUFRLElBQUksRUFBRSxDQUFDO2dCQUNiLEtBQUssMkJBQTJCO29CQUM5QixPQUFPLGlDQUFpQyxDQUFDO2dCQUMzQyxLQUFLLDRCQUE0QjtvQkFDL0IsT0FBTyx5Q0FBeUMsQ0FBQztnQkFDbkQsS0FBSyw2QkFBNkI7b0JBQ2hDLE9BQU8sb0RBQW9ELENBQUM7Z0JBQzlELEtBQUssd0JBQXdCO29CQUMzQixPQUFPLGlEQUFpRCxDQUFDO2dCQUMzRCxLQUFLLG9CQUFvQjtvQkFDdkIsT0FBTyxtQ0FBbUMsQ0FBQztnQkFDN0MsS0FBSyxxQkFBcUI7b0JBQ3hCLE9BQU8sdUJBQXVCLENBQUM7Z0JBQ2pDO29CQUNFLE9BQU8sS0FBSyxDQUFDLE9BQU8sSUFBSSxvQ0FBb0MsQ0FBQztZQUNqRSxDQUFDO1FBQ0gsQ0FBQztRQUVELE9BQU8sb0NBQW9DLENBQUM7SUFDOUMsQ0FBQzsrR0FsUVUsZUFBZTttSEFBZixlQUFlLGNBREYsTUFBTTs7NEZBQ25CLGVBQWU7a0JBRDNCLFVBQVU7bUJBQUMsRUFBRSxVQUFVLEVBQUUsTUFBTSxFQUFFIiwic291cmNlc0NvbnRlbnQiOlsiLyoqXG4gKiBGaXJlYmFzZSBTZXJ2aWNlXG4gKlxuICogU2VydmljaW8gcHJpbmNpcGFsIHBhcmEgbGEgYXV0ZW50aWNhY2nDs24gY29uIEZpcmViYXNlIHVzYW5kbyBDdXN0b20gVG9rZW5zLlxuICogUGVybWl0ZSBxdWUgdXN1YXJpb3MgYXV0ZW50aWNhZG9zIGNvbiB0dSBiYWNrZW5kIChDb2duaXRvLCBldGMuKSBhY2NlZGFuXG4gKiBhIHNlcnZpY2lvcyBkZSBGaXJlYmFzZSAoRmlyZXN0b3JlLCBTdG9yYWdlLCBGQ00pIGRlIG1hbmVyYSBzZWd1cmEuXG4gKi9cblxuaW1wb3J0IHsgaW5qZWN0LCBJbmplY3RhYmxlIH0gZnJvbSAnQGFuZ3VsYXIvY29yZSc7XG5pbXBvcnQgeyBBdXRoLCBhdXRoU3RhdGUsIHNpZ25JbldpdGhDdXN0b21Ub2tlbiwgc2lnbk91dCwgVXNlciwgVXNlckNyZWRlbnRpYWwgfSBmcm9tICdAYW5ndWxhci9maXJlL2F1dGgnO1xuaW1wb3J0IHsgQmVoYXZpb3JTdWJqZWN0LCBkaXN0aW5jdFVudGlsQ2hhbmdlZCwgbWFwLCBPYnNlcnZhYmxlIH0gZnJvbSAncnhqcyc7XG5cbmltcG9ydCB7IFZBTFRFQ0hfRklSRUJBU0VfQ09ORklHIH0gZnJvbSAnLi9jb25maWcnO1xuaW1wb3J0IHsgRmlyZWJhc2VVc2VyLCBTZXNzaW9uU3RhdGUsIFZhbHRlY2hGaXJlYmFzZUNvbmZpZyB9IGZyb20gJy4vdHlwZXMnO1xuXG4vKipcbiAqIFNlcnZpY2lvIGRlIGF1dGVudGljYWNpw7NuIGRlIEZpcmViYXNlLlxuICpcbiAqIEVzdGUgc2VydmljaW8gTk8gbWFuZWphIGVsIGxvZ2luIGRlIHVzdWFyaW9zIGRpcmVjdGFtZW50ZS5cbiAqIEVuIHN1IGx1Z2FyLCB0cmFiYWphIGNvbiBDdXN0b20gVG9rZW5zIGdlbmVyYWRvcyBwb3IgdHUgYmFja2VuZC5cbiAqXG4gKiBAZXhhbXBsZVxuICogYGBgdHlwZXNjcmlwdFxuICogLy8gRGVzcHXDqXMgZGUgYXV0ZW50aWNhcnRlIGNvbiB0dSBiYWNrZW5kIChlajogQ29nbml0bylcbiAqIEBDb21wb25lbnQoey4uLn0pXG4gKiBleHBvcnQgY2xhc3MgTG9naW5Db21wb25lbnQge1xuICogICBwcml2YXRlIGF1dGhTZXJ2aWNlID0gaW5qZWN0KEF1dGhTZXJ2aWNlKTsgICAgIC8vIFR1IHNlcnZpY2lvIGRlIGF1dGhcbiAqICAgcHJpdmF0ZSBmaXJlYmFzZSA9IGluamVjdChGaXJlYmFzZVNlcnZpY2UpOyAgICAvLyBFc3RlIHNlcnZpY2lvXG4gKlxuICogICBhc3luYyBsb2dpbihlbWFpbDogc3RyaW5nLCBwYXNzd29yZDogc3RyaW5nKSB7XG4gKiAgICAgLy8gMS4gQXV0ZW50aWNhciBjb24gdHUgYmFja2VuZFxuICogICAgIGNvbnN0IHJlc3BvbnNlID0gYXdhaXQgdGhpcy5hdXRoU2VydmljZS5sb2dpbihlbWFpbCwgcGFzc3dvcmQpO1xuICpcbiAqICAgICAvLyAyLiBFbCBiYWNrZW5kIGRldnVlbHZlIHVuIEZpcmViYXNlIEN1c3RvbSBUb2tlblxuICogICAgIGlmIChyZXNwb25zZS5maXJlYmFzZVRva2VuKSB7XG4gKiAgICAgICBhd2FpdCB0aGlzLmZpcmViYXNlLnNpZ25JbldpdGhDdXN0b21Ub2tlbihyZXNwb25zZS5maXJlYmFzZVRva2VuKTtcbiAqICAgICB9XG4gKlxuICogICAgIC8vIEFob3JhIGVsIHVzdWFyaW8gcHVlZGUgYWNjZWRlciBhIEZpcmVzdG9yZSwgU3RvcmFnZSwgZXRjLlxuICogICB9XG4gKlxuICogICBhc3luYyBsb2dvdXQoKSB7XG4gKiAgICAgYXdhaXQgdGhpcy5hdXRoU2VydmljZS5sb2dvdXQoKTtcbiAqICAgICBhd2FpdCB0aGlzLmZpcmViYXNlLnNpZ25PdXQoKTtcbiAqICAgfVxuICogfVxuICogYGBgXG4gKi9cbkBJbmplY3RhYmxlKHsgcHJvdmlkZWRJbjogJ3Jvb3QnIH0pXG5leHBvcnQgY2xhc3MgRmlyZWJhc2VTZXJ2aWNlIHtcbiAgcHJpdmF0ZSBhdXRoID0gaW5qZWN0KEF1dGgpO1xuICBwcml2YXRlIGNvbmZpZyA9IGluamVjdChWQUxURUNIX0ZJUkVCQVNFX0NPTkZJRyk7XG5cbiAgLyoqIEVzdGFkbyBpbnRlcm5vIGRlIGxhIHNlc2nDs24gKi9cbiAgcHJpdmF0ZSBzZXNzaW9uU3RhdGUgPSBuZXcgQmVoYXZpb3JTdWJqZWN0PFNlc3Npb25TdGF0ZT4oe1xuICAgIHVzZXI6IG51bGwsXG4gICAgaXNBdXRoZW50aWNhdGVkOiBmYWxzZSxcbiAgICBpc0xvYWRpbmc6IHRydWUsXG4gICAgZXJyb3I6IG51bGwsXG4gIH0pO1xuXG4gIC8qKiBFc3RhZG8gYWN0dWFsIGRlIGxhIHNlc2nDs24gY29tbyBPYnNlcnZhYmxlICovXG4gIHJlYWRvbmx5IHN0YXRlJDogT2JzZXJ2YWJsZTxTZXNzaW9uU3RhdGU+ID0gdGhpcy5zZXNzaW9uU3RhdGUuYXNPYnNlcnZhYmxlKCk7XG5cbiAgLyoqIFVzdWFyaW8gYWN0dWFsIGRlIEZpcmViYXNlIGNvbW8gT2JzZXJ2YWJsZSAqL1xuICByZWFkb25seSB1c2VyJDogT2JzZXJ2YWJsZTxGaXJlYmFzZVVzZXIgfCBudWxsPiA9IGF1dGhTdGF0ZSh0aGlzLmF1dGgpLnBpcGUoXG4gICAgbWFwKCh1c2VyKSA9PiAodXNlciA/IHRoaXMubWFwVXNlcih1c2VyKSA6IG51bGwpKSxcbiAgICBkaXN0aW5jdFVudGlsQ2hhbmdlZCgoYSwgYikgPT4gYT8udWlkID09PSBiPy51aWQpXG4gICk7XG5cbiAgLyoqIEluZGljYSBzaSBlbCB1c3VhcmlvIGVzdMOhIGF1dGVudGljYWRvIGVuIEZpcmViYXNlICovXG4gIHJlYWRvbmx5IGlzQXV0aGVudGljYXRlZCQ6IE9ic2VydmFibGU8Ym9vbGVhbj4gPSB0aGlzLnVzZXIkLnBpcGUoXG4gICAgbWFwKCh1c2VyKSA9PiAhIXVzZXIpLFxuICAgIGRpc3RpbmN0VW50aWxDaGFuZ2VkKClcbiAgKTtcblxuICBjb25zdHJ1Y3RvcigpIHtcbiAgICAvLyBFc2N1Y2hhciBjYW1iaW9zIGVuIGVsIGVzdGFkbyBkZSBhdXRlbnRpY2FjacOzblxuICAgIGF1dGhTdGF0ZSh0aGlzLmF1dGgpLnN1YnNjcmliZSh7XG4gICAgICBuZXh0OiAodXNlcikgPT4ge1xuICAgICAgICB0aGlzLnNlc3Npb25TdGF0ZS5uZXh0KHtcbiAgICAgICAgICB1c2VyOiB1c2VyID8gdGhpcy5tYXBVc2VyKHVzZXIpIDogbnVsbCxcbiAgICAgICAgICBpc0F1dGhlbnRpY2F0ZWQ6ICEhdXNlcixcbiAgICAgICAgICBpc0xvYWRpbmc6IGZhbHNlLFxuICAgICAgICAgIGVycm9yOiBudWxsLFxuICAgICAgICB9KTtcbiAgICAgIH0sXG4gICAgICBlcnJvcjogKGVycm9yKSA9PiB7XG4gICAgICAgIHRoaXMuc2Vzc2lvblN0YXRlLm5leHQoe1xuICAgICAgICAgIHVzZXI6IG51bGwsXG4gICAgICAgICAgaXNBdXRoZW50aWNhdGVkOiBmYWxzZSxcbiAgICAgICAgICBpc0xvYWRpbmc6IGZhbHNlLFxuICAgICAgICAgIGVycm9yLFxuICAgICAgICB9KTtcbiAgICAgIH0sXG4gICAgfSk7XG4gIH1cblxuICAvLyA9PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT1cbiAgLy8gQVVURU5USUNBQ0nDk05cbiAgLy8gPT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09XG5cbiAgLyoqXG4gICAqIEF1dGVudGljYSBhbCB1c3VhcmlvIGNvbiB1biBDdXN0b20gVG9rZW4gZ2VuZXJhZG8gcG9yIGVsIGJhY2tlbmQuXG4gICAqXG4gICAqIEBwYXJhbSB0b2tlbiAtIEZpcmViYXNlIEN1c3RvbSBUb2tlbiBnZW5lcmFkbyBwb3IgdHUgYmFja2VuZFxuICAgKiBAcmV0dXJucyBVc2VyQ3JlZGVudGlhbCBjb24gbGEgaW5mb3JtYWNpw7NuIGRlbCB1c3VhcmlvXG4gICAqIEB0aHJvd3MgRXJyb3Igc2kgZWwgdG9rZW4gZXMgaW52w6FsaWRvIG8gZXhwaXLDs1xuICAgKlxuICAgKiBAZXhhbXBsZVxuICAgKiBgYGB0eXBlc2NyaXB0XG4gICAqIC8vIERlc3B1w6lzIGRlIGxvZ2luIGV4aXRvc28gY29uIHR1IGJhY2tlbmRcbiAgICogY29uc3QgeyBmaXJlYmFzZVRva2VuIH0gPSBhd2FpdCBiYWNrZW5kQXV0aC5sb2dpbihlbWFpbCwgcGFzc3dvcmQpO1xuICAgKiBhd2FpdCBmaXJlYmFzZVNlcnZpY2Uuc2lnbkluV2l0aEN1c3RvbVRva2VuKGZpcmViYXNlVG9rZW4pO1xuICAgKiBgYGBcbiAgICovXG4gIGFzeW5jIHNpZ25JbldpdGhDdXN0b21Ub2tlbih0b2tlbjogc3RyaW5nKTogUHJvbWlzZTxVc2VyQ3JlZGVudGlhbD4ge1xuICAgIHRyeSB7XG4gICAgICBjb25zdCBjcmVkZW50aWFsID0gYXdhaXQgc2lnbkluV2l0aEN1c3RvbVRva2VuKHRoaXMuYXV0aCwgdG9rZW4pO1xuICAgICAgcmV0dXJuIGNyZWRlbnRpYWw7XG4gICAgfSBjYXRjaCAoZXJyb3IpIHtcbiAgICAgIGNvbnN0IG1lc3NhZ2UgPSB0aGlzLmdldEVycm9yTWVzc2FnZShlcnJvcik7XG4gICAgICB0aHJvdyBuZXcgRXJyb3IobWVzc2FnZSk7XG4gICAgfVxuICB9XG5cbiAgLyoqXG4gICAqIENpZXJyYSBsYSBzZXNpw7NuIGRlIEZpcmViYXNlLlxuICAgKiBMbGFtYXIganVudG8gY29uIGVsIGxvZ291dCBkZSB0dSBzaXN0ZW1hIGRlIGF1dGVudGljYWNpw7NuIHByaW5jaXBhbC5cbiAgICpcbiAgICogQGV4YW1wbGVcbiAgICogYGBgdHlwZXNjcmlwdFxuICAgKiBhc3luYyBsb2dvdXQoKSB7XG4gICAqICAgYXdhaXQgdGhpcy5iYWNrZW5kQXV0aC5sb2dvdXQoKTsgICAgLy8gVHUgYXV0aFxuICAgKiAgIGF3YWl0IHRoaXMuZmlyZWJhc2Uuc2lnbk91dCgpOyAgICAgICAvLyBGaXJlYmFzZVxuICAgKiB9XG4gICAqIGBgYFxuICAgKi9cbiAgYXN5bmMgc2lnbk91dCgpOiBQcm9taXNlPHZvaWQ+IHtcbiAgICB0cnkge1xuICAgICAgYXdhaXQgc2lnbk91dCh0aGlzLmF1dGgpO1xuICAgIH0gY2F0Y2ggKGVycm9yKSB7XG4gICAgICBjb25zdCBtZXNzYWdlID0gdGhpcy5nZXRFcnJvck1lc3NhZ2UoZXJyb3IpO1xuICAgICAgdGhyb3cgbmV3IEVycm9yKG1lc3NhZ2UpO1xuICAgIH1cbiAgfVxuXG4gIC8vID09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PVxuICAvLyBHRVRURVJTIFPDjU5DUk9OT1NcbiAgLy8gPT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09XG5cbiAgLyoqXG4gICAqIE9idGllbmUgZWwgdXN1YXJpbyBhY3R1YWwgZGUgRmlyZWJhc2UgKHPDrW5jcm9ubykuXG4gICAqIFJldG9ybmEgbnVsbCBzaSBubyBoYXkgdXN1YXJpbyBhdXRlbnRpY2Fkby5cbiAgICovXG4gIGdldCBjdXJyZW50VXNlcigpOiBGaXJlYmFzZVVzZXIgfCBudWxsIHtcbiAgICBjb25zdCB1c2VyID0gdGhpcy5hdXRoLmN1cnJlbnRVc2VyO1xuICAgIHJldHVybiB1c2VyID8gdGhpcy5tYXBVc2VyKHVzZXIpIDogbnVsbDtcbiAgfVxuXG4gIC8qKlxuICAgKiBPYnRpZW5lIGVsIFVJRCBkZWwgdXN1YXJpbyBhY3R1YWwuXG4gICAqIFJldG9ybmEgbnVsbCBzaSBubyBoYXkgdXN1YXJpbyBhdXRlbnRpY2Fkby5cbiAgICovXG4gIGdldCB1aWQoKTogc3RyaW5nIHwgbnVsbCB7XG4gICAgcmV0dXJuIHRoaXMuYXV0aC5jdXJyZW50VXNlcj8udWlkID8/IG51bGw7XG4gIH1cblxuICAvKipcbiAgICogSW5kaWNhIHNpIGhheSB1biB1c3VhcmlvIGF1dGVudGljYWRvIGFjdHVhbG1lbnRlLlxuICAgKi9cbiAgZ2V0IGlzQXV0aGVudGljYXRlZCgpOiBib29sZWFuIHtcbiAgICByZXR1cm4gISF0aGlzLmF1dGguY3VycmVudFVzZXI7XG4gIH1cblxuICAvLyA9PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT1cbiAgLy8gVE9LRU5TXG4gIC8vID09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PVxuXG4gIC8qKlxuICAgKiBPYnRpZW5lIGVsIElEIFRva2VuIGRlIEZpcmViYXNlIHBhcmEgZWwgdXN1YXJpbyBhY3R1YWwuXG4gICAqIMOadGlsIHBhcmEgdmFsaWRhciBlbCB1c3VhcmlvIGVuIHR1IGJhY2tlbmQuXG4gICAqXG4gICAqIEBwYXJhbSBmb3JjZVJlZnJlc2ggLSBTaSB0cnVlLCBmdWVyemEgbGEgcmVub3ZhY2nDs24gZGVsIHRva2VuXG4gICAqIEByZXR1cm5zIElEIFRva2VuIG8gbnVsbCBzaSBubyBoYXkgdXN1YXJpb1xuICAgKi9cbiAgYXN5bmMgZ2V0SWRUb2tlbihmb3JjZVJlZnJlc2ggPSBmYWxzZSk6IFByb21pc2U8c3RyaW5nIHwgbnVsbD4ge1xuICAgIGNvbnN0IHVzZXIgPSB0aGlzLmF1dGguY3VycmVudFVzZXI7XG4gICAgaWYgKCF1c2VyKSByZXR1cm4gbnVsbDtcblxuICAgIHRyeSB7XG4gICAgICByZXR1cm4gYXdhaXQgdXNlci5nZXRJZFRva2VuKGZvcmNlUmVmcmVzaCk7XG4gICAgfSBjYXRjaCB7XG4gICAgICByZXR1cm4gbnVsbDtcbiAgICB9XG4gIH1cblxuICAvKipcbiAgICogT2J0aWVuZSBsb3MgY2xhaW1zIHBlcnNvbmFsaXphZG9zIGRlbCB0b2tlbiBkZWwgdXN1YXJpby5cbiAgICogTG9zIGNsYWltcyBzb24gZXN0YWJsZWNpZG9zIHBvciB0dSBiYWNrZW5kIGFsIGNyZWFyIGVsIEN1c3RvbSBUb2tlbi5cbiAgICpcbiAgICogQHJldHVybnMgT2JqZXRvIGNvbiBsb3MgY2xhaW1zIG8gdmFjw61vIHNpIG5vIGhheSB1c3VhcmlvXG4gICAqL1xuICBhc3luYyBnZXRDbGFpbXMoKTogUHJvbWlzZTxSZWNvcmQ8c3RyaW5nLCB1bmtub3duPj4ge1xuICAgIGNvbnN0IHVzZXIgPSB0aGlzLmF1dGguY3VycmVudFVzZXI7XG4gICAgaWYgKCF1c2VyKSByZXR1cm4ge307XG5cbiAgICB0cnkge1xuICAgICAgY29uc3QgcmVzdWx0ID0gYXdhaXQgdXNlci5nZXRJZFRva2VuUmVzdWx0KCk7XG4gICAgICByZXR1cm4gcmVzdWx0LmNsYWltcztcbiAgICB9IGNhdGNoIHtcbiAgICAgIHJldHVybiB7fTtcbiAgICB9XG4gIH1cblxuICAvKipcbiAgICogVmVyaWZpY2Egc2kgZWwgdXN1YXJpbyB0aWVuZSB1biByb2wgZXNwZWPDrWZpY28uXG4gICAqIEVsIHJvbCBkZWJlIGVzdGFyIGRlZmluaWRvIGVuIGxvcyBjbGFpbXMgZGVsIEN1c3RvbSBUb2tlbi5cbiAgICpcbiAgICogQHBhcmFtIHJvbGUgLSBOb21icmUgZGVsIHJvbCBhIHZlcmlmaWNhclxuICAgKiBAcmV0dXJucyB0cnVlIHNpIGVsIHVzdWFyaW8gdGllbmUgZWwgcm9sXG4gICAqL1xuICBhc3luYyBoYXNSb2xlKHJvbGU6IHN0cmluZyk6IFByb21pc2U8Ym9vbGVhbj4ge1xuICAgIGNvbnN0IGNsYWltcyA9IGF3YWl0IHRoaXMuZ2V0Q2xhaW1zKCk7XG4gICAgcmV0dXJuIGNsYWltc1sncm9sZSddID09PSByb2xlIHx8IChBcnJheS5pc0FycmF5KGNsYWltc1sncm9sZXMnXSkgJiYgY2xhaW1zWydyb2xlcyddLmluY2x1ZGVzKHJvbGUpKTtcbiAgfVxuXG4gIC8vID09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PVxuICAvLyBVVElMSURBREVTXG4gIC8vID09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PVxuXG4gIC8qKlxuICAgKiBFc3BlcmEgYSBxdWUgZWwgZXN0YWRvIGRlIGF1dGVudGljYWNpw7NuIGVzdMOpIGRldGVybWluYWRvLlxuICAgKiDDmnRpbCBlbiBndWFyZHMgbyBhbCBpbmljaWFsaXphciBsYSBhcHAuXG4gICAqXG4gICAqIEByZXR1cm5zIFVzdWFyaW8gYWN0dWFsIG8gbnVsbFxuICAgKi9cbiAgd2FpdEZvckF1dGgoKTogUHJvbWlzZTxGaXJlYmFzZVVzZXIgfCBudWxsPiB7XG4gICAgcmV0dXJuIG5ldyBQcm9taXNlKChyZXNvbHZlKSA9PiB7XG4gICAgICBjb25zdCBzdWJzY3JpcHRpb24gPSB0aGlzLnN0YXRlJC5zdWJzY3JpYmUoKHN0YXRlKSA9PiB7XG4gICAgICAgIGlmICghc3RhdGUuaXNMb2FkaW5nKSB7XG4gICAgICAgICAgc3Vic2NyaXB0aW9uLnVuc3Vic2NyaWJlKCk7XG4gICAgICAgICAgcmVzb2x2ZShzdGF0ZS51c2VyKTtcbiAgICAgICAgfVxuICAgICAgfSk7XG4gICAgfSk7XG4gIH1cblxuICAvKipcbiAgICogT2J0aWVuZSBsYSBjb25maWd1cmFjacOzbiBhY3R1YWwgZGUgRmlyZWJhc2UuXG4gICAqL1xuICBnZXRDb25maWcoKTogVmFsdGVjaEZpcmViYXNlQ29uZmlnIHtcbiAgICByZXR1cm4gdGhpcy5jb25maWc7XG4gIH1cblxuICAvKipcbiAgICogSW5kaWNhIHNpIGxvcyBlbXVsYWRvcmVzIGVzdMOhbiBoYWJpbGl0YWRvcy5cbiAgICovXG4gIGlzVXNpbmdFbXVsYXRvcnMoKTogYm9vbGVhbiB7XG4gICAgcmV0dXJuICEhKHRoaXMuY29uZmlnLmVtdWxhdG9yPy5maXJlc3RvcmUgfHwgdGhpcy5jb25maWcuZW11bGF0b3I/LmF1dGggfHwgdGhpcy5jb25maWcuZW11bGF0b3I/LnN0b3JhZ2UpO1xuICB9XG5cbiAgLy8gPT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09XG4gIC8vIE3DiVRPRE9TIFBSSVZBRE9TXG4gIC8vID09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PVxuXG4gIC8qKlxuICAgKiBNYXBlYSB1biBVc2VyIGRlIEZpcmViYXNlIGEgbnVlc3RyYSBpbnRlcmZhY2UgRmlyZWJhc2VVc2VyXG4gICAqL1xuICBwcml2YXRlIG1hcFVzZXIodXNlcjogVXNlcik6IEZpcmViYXNlVXNlciB7XG4gICAgcmV0dXJuIHtcbiAgICAgIHVpZDogdXNlci51aWQsXG4gICAgICBlbWFpbDogdXNlci5lbWFpbCxcbiAgICAgIGRpc3BsYXlOYW1lOiB1c2VyLmRpc3BsYXlOYW1lLFxuICAgICAgcGhvdG9VUkw6IHVzZXIucGhvdG9VUkwsXG4gICAgICBlbWFpbFZlcmlmaWVkOiB1c2VyLmVtYWlsVmVyaWZpZWQsXG4gICAgICBpc0Fub255bW91czogdXNlci5pc0Fub255bW91cyxcbiAgICAgIHByb3ZpZGVySWQ6IHVzZXIucHJvdmlkZXJJZCxcbiAgICB9O1xuICB9XG5cbiAgLyoqXG4gICAqIENvbnZpZXJ0ZSBlcnJvcmVzIGRlIEZpcmViYXNlIGEgbWVuc2FqZXMgZW4gZXNwYcOxb2xcbiAgICovXG4gIHByaXZhdGUgZ2V0RXJyb3JNZXNzYWdlKGVycm9yOiB1bmtub3duKTogc3RyaW5nIHtcbiAgICBpZiAoZXJyb3IgaW5zdGFuY2VvZiBFcnJvcikge1xuICAgICAgY29uc3QgY29kZSA9IChlcnJvciBhcyB7IGNvZGU/OiBzdHJpbmcgfSkuY29kZTtcblxuICAgICAgc3dpdGNoIChjb2RlKSB7XG4gICAgICAgIGNhc2UgJ2F1dGgvaW52YWxpZC1jdXN0b20tdG9rZW4nOlxuICAgICAgICAgIHJldHVybiAnVG9rZW4gZGUgYXV0ZW50aWNhY2nDs24gaW52w6FsaWRvJztcbiAgICAgICAgY2FzZSAnYXV0aC9jdXN0b20tdG9rZW4tbWlzbWF0Y2gnOlxuICAgICAgICAgIHJldHVybiAnRWwgdG9rZW4gbm8gY29ycmVzcG9uZGUgYSBlc3RlIHByb3llY3RvJztcbiAgICAgICAgY2FzZSAnYXV0aC9uZXR3b3JrLXJlcXVlc3QtZmFpbGVkJzpcbiAgICAgICAgICByZXR1cm4gJ0Vycm9yIGRlIGNvbmV4acOzbi4gVmVyaWZpY2EgdHUgY29uZXhpw7NuIGEgaW50ZXJuZXQnO1xuICAgICAgICBjYXNlICdhdXRoL3Rvby1tYW55LXJlcXVlc3RzJzpcbiAgICAgICAgICByZXR1cm4gJ0RlbWFzaWFkb3MgaW50ZW50b3MuIEludGVudGEgZGUgbnVldm8gbcOhcyB0YXJkZSc7XG4gICAgICAgIGNhc2UgJ2F1dGgvdXNlci1kaXNhYmxlZCc6XG4gICAgICAgICAgcmV0dXJuICdFc3RhIGN1ZW50YSBoYSBzaWRvIGRlc2hhYmlsaXRhZGEnO1xuICAgICAgICBjYXNlICdhdXRoL3VzZXItbm90LWZvdW5kJzpcbiAgICAgICAgICByZXR1cm4gJ1VzdWFyaW8gbm8gZW5jb250cmFkbyc7XG4gICAgICAgIGRlZmF1bHQ6XG4gICAgICAgICAgcmV0dXJuIGVycm9yLm1lc3NhZ2UgfHwgJ0Vycm9yIGRlIGF1dGVudGljYWNpw7NuIGRlc2Nvbm9jaWRvJztcbiAgICAgIH1cbiAgICB9XG5cbiAgICByZXR1cm4gJ0Vycm9yIGRlIGF1dGVudGljYWNpw7NuIGRlc2Nvbm9jaWRvJztcbiAgfVxufVxuIl19