valtech-components 2.0.408 → 2.0.410

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 (109) hide show
  1. package/esm2022/lib/components/atoms/horizontal-scroll/horizontal-scroll.component.mjs +82 -0
  2. package/esm2022/lib/components/atoms/horizontal-scroll/types.mjs +2 -0
  3. package/esm2022/lib/components/atoms/rights-footer/rights-footer.component.mjs +82 -0
  4. package/esm2022/lib/components/atoms/rights-footer/types.mjs +2 -0
  5. package/esm2022/lib/components/molecules/check-input/check-input.component.mjs +55 -11
  6. package/esm2022/lib/components/molecules/email-input/email-input.component.mjs +13 -4
  7. package/esm2022/lib/components/molecules/expandable-text/expandable-text.component.mjs +27 -23
  8. package/esm2022/lib/components/molecules/footer-links/footer-links.component.mjs +277 -0
  9. package/esm2022/lib/components/molecules/footer-links/types.mjs +2 -0
  10. package/esm2022/lib/components/molecules/links-accordion/links-accordion.component.mjs +157 -0
  11. package/esm2022/lib/components/molecules/links-accordion/types.mjs +2 -0
  12. package/esm2022/lib/components/molecules/password-input/password-input.component.mjs +12 -2
  13. package/esm2022/lib/components/molecules/prompter/prompter.component.mjs +21 -9
  14. package/esm2022/lib/components/molecules/prompter/types.mjs +1 -1
  15. package/esm2022/lib/components/molecules/radio-input/radio-input.component.mjs +13 -4
  16. package/esm2022/lib/components/molecules/recap-card/recap-card.component.mjs +78 -0
  17. package/esm2022/lib/components/molecules/recap-card/types.mjs +2 -0
  18. package/esm2022/lib/components/molecules/select-input/select-input.component.mjs +31 -14
  19. package/esm2022/lib/components/molecules/swipe-carousel/swipe-carousel.component.mjs +206 -0
  20. package/esm2022/lib/components/molecules/swipe-carousel/types.mjs +2 -0
  21. package/esm2022/lib/components/molecules/testimonial-card/testimonial-card.component.mjs +138 -0
  22. package/esm2022/lib/components/molecules/testimonial-card/types.mjs +2 -0
  23. package/esm2022/lib/components/molecules/text-input/text-input.component.mjs +14 -4
  24. package/esm2022/lib/components/organisms/cards-carousel/cards-carousel.component.mjs +61 -0
  25. package/esm2022/lib/components/organisms/cards-carousel/types.mjs +2 -0
  26. package/esm2022/lib/components/organisms/company-footer/company-footer.component.mjs +72 -0
  27. package/esm2022/lib/components/organisms/company-footer/types.mjs +2 -0
  28. package/esm2022/lib/components/organisms/data-table/data-table.component.mjs +175 -3
  29. package/esm2022/lib/components/organisms/data-table/types.mjs +1 -1
  30. package/esm2022/lib/components/organisms/form/form.component.mjs +2 -2
  31. package/esm2022/lib/components/organisms/fun-header/fun-header.component.mjs +225 -0
  32. package/esm2022/lib/components/organisms/fun-header/types.mjs +2 -0
  33. package/esm2022/lib/components/organisms/menu/menu.component.mjs +197 -0
  34. package/esm2022/lib/components/organisms/menu/types.mjs +2 -0
  35. package/esm2022/lib/components/organisms/testimonial-carousel/testimonial-carousel.component.mjs +72 -0
  36. package/esm2022/lib/components/organisms/testimonial-carousel/types.mjs +2 -0
  37. package/esm2022/lib/components/templates/page-content/page-content.component.mjs +156 -0
  38. package/esm2022/lib/components/templates/page-content/types.mjs +2 -0
  39. package/esm2022/lib/components/templates/page-template/page-template.component.mjs +181 -0
  40. package/esm2022/lib/components/templates/page-template/types.mjs +2 -0
  41. package/esm2022/lib/components/templates/page-wrapper/page-wrapper.component.mjs +195 -0
  42. package/esm2022/lib/components/templates/page-wrapper/types.mjs +2 -0
  43. package/esm2022/lib/components/types.mjs +1 -1
  44. package/esm2022/lib/services/firebase/config.mjs +103 -0
  45. package/esm2022/lib/services/firebase/firebase.service.mjs +285 -0
  46. package/esm2022/lib/services/firebase/firestore-collection.mjs +266 -0
  47. package/esm2022/lib/services/firebase/firestore.service.mjs +508 -0
  48. package/esm2022/lib/services/firebase/index.mjs +46 -0
  49. package/esm2022/lib/services/firebase/messaging.service.mjs +503 -0
  50. package/esm2022/lib/services/firebase/storage.service.mjs +421 -0
  51. package/esm2022/lib/services/firebase/types.mjs +8 -0
  52. package/esm2022/lib/services/firebase/utils/path-builder.mjs +195 -0
  53. package/esm2022/lib/services/firebase/utils/query-builder.mjs +302 -0
  54. package/esm2022/public-api.mjs +33 -1
  55. package/fesm2022/valtech-components.mjs +5821 -868
  56. package/fesm2022/valtech-components.mjs.map +1 -1
  57. package/lib/components/atoms/horizontal-scroll/horizontal-scroll.component.d.ts +41 -0
  58. package/lib/components/atoms/horizontal-scroll/types.d.ts +13 -0
  59. package/lib/components/atoms/rights-footer/rights-footer.component.d.ts +39 -0
  60. package/lib/components/atoms/rights-footer/types.d.ts +13 -0
  61. package/lib/components/molecules/check-input/check-input.component.d.ts +17 -2
  62. package/lib/components/molecules/email-input/email-input.component.d.ts +1 -2
  63. package/lib/components/molecules/footer-links/footer-links.component.d.ts +47 -0
  64. package/lib/components/molecules/footer-links/types.d.ts +37 -0
  65. package/lib/components/molecules/links-accordion/links-accordion.component.d.ts +48 -0
  66. package/lib/components/molecules/links-accordion/types.d.ts +33 -0
  67. package/lib/components/molecules/password-input/password-input.component.d.ts +1 -1
  68. package/lib/components/molecules/prompter/prompter.component.d.ts +8 -1
  69. package/lib/components/molecules/prompter/types.d.ts +7 -1
  70. package/lib/components/molecules/radio-input/radio-input.component.d.ts +1 -2
  71. package/lib/components/molecules/recap-card/recap-card.component.d.ts +36 -0
  72. package/lib/components/molecules/recap-card/types.d.ts +30 -0
  73. package/lib/components/molecules/select-input/select-input.component.d.ts +6 -1
  74. package/lib/components/molecules/swipe-carousel/swipe-carousel.component.d.ts +66 -0
  75. package/lib/components/molecules/swipe-carousel/types.d.ts +35 -0
  76. package/lib/components/molecules/testimonial-card/testimonial-card.component.d.ts +41 -0
  77. package/lib/components/molecules/testimonial-card/types.d.ts +25 -0
  78. package/lib/components/molecules/text-input/text-input.component.d.ts +13 -4
  79. package/lib/components/organisms/cards-carousel/cards-carousel.component.d.ts +30 -0
  80. package/lib/components/organisms/cards-carousel/types.d.ts +11 -0
  81. package/lib/components/organisms/company-footer/company-footer.component.d.ts +32 -0
  82. package/lib/components/organisms/company-footer/types.d.ts +15 -0
  83. package/lib/components/organisms/data-table/data-table.component.d.ts +1 -1
  84. package/lib/components/organisms/data-table/types.d.ts +6 -0
  85. package/lib/components/organisms/fun-header/fun-header.component.d.ts +72 -0
  86. package/lib/components/organisms/fun-header/types.d.ts +28 -0
  87. package/lib/components/organisms/menu/menu.component.d.ts +39 -0
  88. package/lib/components/organisms/menu/types.d.ts +23 -0
  89. package/lib/components/organisms/testimonial-carousel/testimonial-carousel.component.d.ts +33 -0
  90. package/lib/components/organisms/testimonial-carousel/types.d.ts +8 -0
  91. package/lib/components/templates/page-content/page-content.component.d.ts +55 -0
  92. package/lib/components/templates/page-content/types.d.ts +14 -0
  93. package/lib/components/templates/page-template/page-template.component.d.ts +49 -0
  94. package/lib/components/templates/page-template/types.d.ts +17 -0
  95. package/lib/components/templates/page-wrapper/page-wrapper.component.d.ts +61 -0
  96. package/lib/components/templates/page-wrapper/types.d.ts +19 -0
  97. package/lib/components/types.d.ts +14 -0
  98. package/lib/services/firebase/config.d.ts +49 -0
  99. package/lib/services/firebase/firebase.service.d.ts +140 -0
  100. package/lib/services/firebase/firestore-collection.d.ts +195 -0
  101. package/lib/services/firebase/firestore.service.d.ts +303 -0
  102. package/lib/services/firebase/index.d.ts +38 -0
  103. package/lib/services/firebase/messaging.service.d.ts +254 -0
  104. package/lib/services/firebase/storage.service.d.ts +204 -0
  105. package/lib/services/firebase/types.d.ts +279 -0
  106. package/lib/services/firebase/utils/path-builder.d.ts +132 -0
  107. package/lib/services/firebase/utils/query-builder.d.ts +210 -0
  108. package/package.json +3 -1
  109. package/public-api.d.ts +31 -0
@@ -0,0 +1,285 @@
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
@@ -0,0 +1,266 @@
1
+ /**
2
+ * Firestore Collection
3
+ *
4
+ * Clase base abstracta para crear servicios de colección tipados.
5
+ * Extiende esta clase para tener un servicio dedicado por entidad.
6
+ */
7
+ import { inject } from '@angular/core';
8
+ import { FirestoreService } from './firestore.service';
9
+ /**
10
+ * Clase base para servicios de colección tipados.
11
+ *
12
+ * Extiende esta clase para crear un servicio dedicado para cada entidad,
13
+ * con métodos personalizados y tipado fuerte.
14
+ *
15
+ * @example
16
+ * ```typescript
17
+ * // Definir el modelo
18
+ * interface User extends FirestoreDocument {
19
+ * name: string;
20
+ * email: string;
21
+ * role: 'admin' | 'user';
22
+ * active: boolean;
23
+ * }
24
+ *
25
+ * // Crear el servicio
26
+ * @Injectable({ providedIn: 'root' })
27
+ * export class UsersCollection extends FirestoreCollection<User> {
28
+ * constructor() {
29
+ * super('users');
30
+ * }
31
+ *
32
+ * // Métodos personalizados
33
+ * async getActiveUsers(): Promise<User[]> {
34
+ * return this.query({
35
+ * where: [{ field: 'active', operator: '==', value: true }]
36
+ * });
37
+ * }
38
+ *
39
+ * async getAdmins(): Promise<User[]> {
40
+ * return this.query({
41
+ * where: [{ field: 'role', operator: '==', value: 'admin' }]
42
+ * });
43
+ * }
44
+ *
45
+ * watchOnlineUsers(): Observable<User[]> {
46
+ * return this.watchQuery({
47
+ * where: [{ field: 'status', operator: '==', value: 'online' }]
48
+ * });
49
+ * }
50
+ * }
51
+ *
52
+ * // Usar en componentes
53
+ * @Component({...})
54
+ * export class UsersComponent {
55
+ * private users = inject(UsersCollection);
56
+ *
57
+ * admins$ = this.users.getAdmins();
58
+ * onlineUsers$ = this.users.watchOnlineUsers();
59
+ *
60
+ * async createUser(data: Omit<User, 'id'>) {
61
+ * const user = await this.users.create(data);
62
+ * }
63
+ * }
64
+ * ```
65
+ */
66
+ export class FirestoreCollection {
67
+ /**
68
+ * @param collectionPath - Ruta de la colección en Firestore
69
+ * @param options - Opciones de configuración
70
+ */
71
+ constructor(collectionPath, options = {}) {
72
+ this.firestore = inject(FirestoreService);
73
+ this.collectionPath = collectionPath;
74
+ this.options = {
75
+ softDelete: false,
76
+ timestamps: true,
77
+ ...options,
78
+ };
79
+ }
80
+ // ===========================================================================
81
+ // LECTURAS ONE-TIME
82
+ // ===========================================================================
83
+ /**
84
+ * Obtiene un documento por ID.
85
+ */
86
+ async getById(id) {
87
+ return this.firestore.getDoc(this.collectionPath, id);
88
+ }
89
+ /**
90
+ * Obtiene todos los documentos de la colección.
91
+ */
92
+ async getAll(options) {
93
+ const queryOptions = this.applyDefaultFilters(options);
94
+ return this.firestore.getDocs(this.collectionPath, queryOptions);
95
+ }
96
+ /**
97
+ * Ejecuta una query personalizada.
98
+ */
99
+ async query(options) {
100
+ const queryOptions = this.applyDefaultFilters(options);
101
+ return this.firestore.getDocs(this.collectionPath, queryOptions);
102
+ }
103
+ /**
104
+ * Obtiene documentos con paginación.
105
+ */
106
+ async paginate(options) {
107
+ const queryOptions = this.applyDefaultFilters(options);
108
+ return this.firestore.getPaginated(this.collectionPath, queryOptions);
109
+ }
110
+ /**
111
+ * Obtiene el primer documento que coincida con la query.
112
+ */
113
+ async getFirst(options) {
114
+ const queryOptions = this.applyDefaultFilters({
115
+ ...options,
116
+ limit: 1,
117
+ });
118
+ const results = await this.firestore.getDocs(this.collectionPath, queryOptions);
119
+ return results[0] ?? null;
120
+ }
121
+ /**
122
+ * Cuenta los documentos que coinciden con la query.
123
+ * Nota: Esto carga todos los documentos, usar con cuidado en colecciones grandes.
124
+ */
125
+ async count(options) {
126
+ const queryOptions = this.applyDefaultFilters(options);
127
+ const results = await this.firestore.getDocs(this.collectionPath, queryOptions);
128
+ return results.length;
129
+ }
130
+ /**
131
+ * Verifica si un documento existe.
132
+ */
133
+ async exists(id) {
134
+ return this.firestore.exists(this.collectionPath, id);
135
+ }
136
+ // ===========================================================================
137
+ // SUBSCRIPCIONES REAL-TIME
138
+ // ===========================================================================
139
+ /**
140
+ * Suscribe a cambios de un documento.
141
+ */
142
+ watch(id) {
143
+ return this.firestore.docChanges(this.collectionPath, id);
144
+ }
145
+ /**
146
+ * Suscribe a cambios de la colección.
147
+ */
148
+ watchAll(options) {
149
+ const queryOptions = this.applyDefaultFilters(options);
150
+ return this.firestore.collectionChanges(this.collectionPath, queryOptions);
151
+ }
152
+ /**
153
+ * Suscribe a una query personalizada.
154
+ */
155
+ watchQuery(options) {
156
+ const queryOptions = this.applyDefaultFilters(options);
157
+ return this.firestore.collectionChanges(this.collectionPath, queryOptions);
158
+ }
159
+ // ===========================================================================
160
+ // ESCRITURA
161
+ // ===========================================================================
162
+ /**
163
+ * Crea un nuevo documento con ID auto-generado.
164
+ */
165
+ async create(data) {
166
+ return this.firestore.addDoc(this.collectionPath, data);
167
+ }
168
+ /**
169
+ * Crea un documento con ID específico.
170
+ */
171
+ async createWithId(id, data) {
172
+ return this.firestore.setDoc(this.collectionPath, id, data);
173
+ }
174
+ /**
175
+ * Actualiza campos de un documento.
176
+ */
177
+ async update(id, data) {
178
+ return this.firestore.updateDoc(this.collectionPath, id, data);
179
+ }
180
+ /**
181
+ * Elimina un documento.
182
+ * Si softDelete está habilitado, marca como eliminado en lugar de borrar.
183
+ */
184
+ async delete(id) {
185
+ if (this.options.softDelete) {
186
+ return this.firestore.updateDoc(this.collectionPath, id, {
187
+ deletedAt: new Date(),
188
+ });
189
+ }
190
+ return this.firestore.deleteDoc(this.collectionPath, id);
191
+ }
192
+ /**
193
+ * Restaura un documento soft-deleted.
194
+ */
195
+ async restore(id) {
196
+ if (!this.options.softDelete) {
197
+ throw new Error('Soft delete no está habilitado para esta colección');
198
+ }
199
+ return this.firestore.updateDoc(this.collectionPath, id, {
200
+ deletedAt: null,
201
+ });
202
+ }
203
+ // ===========================================================================
204
+ // SUB-COLECCIONES
205
+ // ===========================================================================
206
+ /**
207
+ * Obtiene una referencia a una sub-colección.
208
+ *
209
+ * @example
210
+ * ```typescript
211
+ * // En UsersCollection
212
+ * getUserDocuments(userId: string) {
213
+ * return this.subcollection<Document>(userId, 'documents');
214
+ * }
215
+ *
216
+ * // Uso
217
+ * const docs = await users.getUserDocuments('user123').getAll();
218
+ * ```
219
+ */
220
+ subcollection(parentId, subcollectionName) {
221
+ const subPath = `${this.collectionPath}/${parentId}/${subcollectionName}`;
222
+ return {
223
+ getById: (id) => this.firestore.getDoc(subPath, id),
224
+ getAll: (options) => this.firestore.getDocs(subPath, options),
225
+ watch: (id) => this.firestore.docChanges(subPath, id),
226
+ watchAll: (options) => this.firestore.collectionChanges(subPath, options),
227
+ create: (data) => this.firestore.addDoc(subPath, data),
228
+ update: (id, data) => this.firestore.updateDoc(subPath, id, data),
229
+ delete: (id) => this.firestore.deleteDoc(subPath, id),
230
+ };
231
+ }
232
+ // ===========================================================================
233
+ // MÉTODOS PROTEGIDOS (para override en subclases)
234
+ // ===========================================================================
235
+ /**
236
+ * Aplica filtros por defecto a las queries.
237
+ * Override este método para agregar filtros globales (ej: excluir soft-deleted).
238
+ */
239
+ applyDefaultFilters(options) {
240
+ if (!this.options.softDelete) {
241
+ return options ?? {};
242
+ }
243
+ // Excluir documentos soft-deleted por defecto
244
+ const whereClause = { field: 'deletedAt', operator: '==', value: null };
245
+ return {
246
+ ...options,
247
+ where: [...(options?.where ?? []), whereClause],
248
+ };
249
+ }
250
+ // ===========================================================================
251
+ // UTILIDADES
252
+ // ===========================================================================
253
+ /**
254
+ * Genera un nuevo ID sin crear el documento.
255
+ */
256
+ generateId() {
257
+ return this.firestore.generateId(this.collectionPath);
258
+ }
259
+ /**
260
+ * Obtiene la ruta de la colección.
261
+ */
262
+ getPath() {
263
+ return this.collectionPath;
264
+ }
265
+ }
266
+ //# sourceMappingURL=data:application/json;base64,eyJ2ZXJzaW9uIjozLCJmaWxlIjoiZmlyZXN0b3JlLWNvbGxlY3Rpb24uanMiLCJzb3VyY2VSb290IjoiIiwic291cmNlcyI6WyIuLi8uLi8uLi8uLi8uLi8uLi9zcmMvbGliL3NlcnZpY2VzL2ZpcmViYXNlL2ZpcmVzdG9yZS1jb2xsZWN0aW9uLnRzIl0sIm5hbWVzIjpbXSwibWFwcGluZ3MiOiJBQUFBOzs7OztHQUtHO0FBRUgsT0FBTyxFQUFFLE1BQU0sRUFBRSxNQUFNLGVBQWUsQ0FBQztBQUd2QyxPQUFPLEVBQUUsZ0JBQWdCLEVBQUUsTUFBTSxxQkFBcUIsQ0FBQztBQWlDdkQ7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7O0dBd0RHO0FBQ0gsTUFBTSxPQUFnQixtQkFBbUI7SUFLdkM7OztPQUdHO0lBQ0gsWUFBWSxjQUFzQixFQUFFLFVBQTZCLEVBQUU7UUFDakUsSUFBSSxDQUFDLFNBQVMsR0FBRyxNQUFNLENBQUMsZ0JBQWdCLENBQUMsQ0FBQztRQUMxQyxJQUFJLENBQUMsY0FBYyxHQUFHLGNBQWMsQ0FBQztRQUNyQyxJQUFJLENBQUMsT0FBTyxHQUFHO1lBQ2IsVUFBVSxFQUFFLEtBQUs7WUFDakIsVUFBVSxFQUFFLElBQUk7WUFDaEIsR0FBRyxPQUFPO1NBQ1gsQ0FBQztJQUNKLENBQUM7SUFFRCw4RUFBOEU7SUFDOUUsb0JBQW9CO0lBQ3BCLDhFQUE4RTtJQUU5RTs7T0FFRztJQUNILEtBQUssQ0FBQyxPQUFPLENBQUMsRUFBVTtRQUN0QixPQUFPLElBQUksQ0FBQyxTQUFTLENBQUMsTUFBTSxDQUFJLElBQUksQ0FBQyxjQUFjLEVBQUUsRUFBRSxDQUFDLENBQUM7SUFDM0QsQ0FBQztJQUVEOztPQUVHO0lBQ0gsS0FBSyxDQUFDLE1BQU0sQ0FBQyxPQUFzQjtRQUNqQyxNQUFNLFlBQVksR0FBRyxJQUFJLENBQUMsbUJBQW1CLENBQUMsT0FBTyxDQUFDLENBQUM7UUFDdkQsT0FBTyxJQUFJLENBQUMsU0FBUyxDQUFDLE9BQU8sQ0FB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QUM3QixPQUFPLE9BQU8sSUFBSSxFQUFFLENBQUM7UUFDdkIsQ0FBQztRQUVELDhDQUE4QztRQUM5QyxNQUFNLFdBQVcsR0FBRyxFQUFFLEtBQUssRUFBRSxXQUFXLEVBQUUsUUFBUSxFQUFFLElBQWEsRUFBRSxLQUFLLEVBQUUsSUFBSSxFQUFFLENBQUM7UUFFakYsT0FBTztZQUNMLEdBQUcsT0FBTztZQUNWLEtBQUssRUFBRSxDQUFDLEdBQUcsQ0FBQyxPQUFPLEVBQUUsS0FBSyxJQUFJLEVBQUUsQ0FBQyxFQUFFLFdBQVcsQ0FBQztTQUNoRCxDQUFDO0lBQ0osQ0FBQztJQUVELDhFQUE4RTtJQUM5RSxhQUFhO0lBQ2IsOEVBQThFO0lBRTlFOztPQUVHO0lBQ0gsVUFBVTtRQUNSLE9BQU8sSUFBSSxDQUFDLFNBQVMsQ0FBQyxVQUFVLENBQUMsSUFBSSxDQUFDLGNBQWMsQ0FBQyxDQUFDO0lBQ3hELENBQUM7SUFFRDs7T0FFRztJQUNILE9BQU87UUFDTCxPQUFPLElBQUksQ0FBQyxjQUFjLENBQUM7SUFDN0IsQ0FBQztDQUNGIiwic291cmNlc0NvbnRlbnQiOlsiLyoqXG4gKiBGaXJlc3RvcmUgQ29sbGVjdGlvblxuICpcbiAqIENsYXNlIGJhc2UgYWJzdHJhY3RhIHBhcmEgY3JlYXIgc2VydmljaW9zIGRlIGNvbGVjY2nDs24gdGlwYWRvcy5cbiAqIEV4dGllbmRlIGVzdGEgY2xhc2UgcGFyYSB0ZW5lciB1biBzZXJ2aWNpbyBkZWRpY2FkbyBwb3IgZW50aWRhZC5cbiAqL1xuXG5pbXBvcnQgeyBpbmplY3QgfSBmcm9tICdAYW5ndWxhci9jb3JlJztcbmltcG9ydCB7IE9ic2VydmFibGUgfSBmcm9tICdyeGpzJztcblxuaW1wb3J0IHsgRmlyZXN0b3JlU2VydmljZSB9IGZyb20gJy4vZmlyZXN0b3JlLnNlcnZpY2UnO1xuaW1wb3J0IHsgRmlyZXN0b3JlRG9jdW1lbnQsIFBhZ2luYXRlZFJlc3VsdCwgUXVlcnlPcHRpb25zIH0gZnJvbSAnLi90eXBlcyc7XG5cbi8qKlxuICogT3BjaW9uZXMgZGUgY29uZmlndXJhY2nDs24gcGFyYSB1bmEgY29sZWNjacOzbi5cbiAqL1xuZXhwb3J0IGludGVyZmFjZSBDb2xsZWN0aW9uT3B0aW9ucyB7XG4gIC8qKlxuICAgKiBTaSB0cnVlLCB1c2Egc29mdCBkZWxldGUgKG1hcmNhIGRlbGV0ZWRBdCBlbiBsdWdhciBkZSBlbGltaW5hcikuXG4gICAqIERlZmF1bHQ6IGZhbHNlXG4gICAqL1xuICBzb2Z0RGVsZXRlPzogYm9vbGVhbjtcblxuICAvKipcbiAgICogU2kgdHJ1ZSwgbWFuZWphIGF1dG9tw6F0aWNhbWVudGUgY3JlYXRlZEF0L3VwZGF0ZWRBdC5cbiAgICogRGVmYXVsdDogdHJ1ZVxuICAgKi9cbiAgdGltZXN0YW1wcz86IGJvb2xlYW47XG59XG5cbi8qKlxuICogUmVmZXJlbmNpYSBhIHVuYSBzdWItY29sZWNjacOzbiB0aXBhZGEuXG4gKi9cbmV4cG9ydCBpbnRlcmZhY2UgU3ViQ29sbGVjdGlvblJlZjxUIGV4dGVuZHMgRmlyZXN0b3JlRG9jdW1lbnQ+IHtcbiAgZ2V0QnlJZChpZDogc3RyaW5nKTogUHJvbWlzZTxUIHwgbnVsbD47XG4gIGdldEFsbChvcHRpb25zPzogUXVlcnlPcHRpb25zKTogUHJvbWlzZTxUW10+O1xuICB3YXRjaChpZDogc3RyaW5nKTogT2JzZXJ2YWJsZTxUIHwgbnVsbD47XG4gIHdhdGNoQWxsKG9wdGlvbnM/OiBRdWVyeU9wdGlvbnMpOiBPYnNlcnZhYmxlPFRbXT47XG4gIGNyZWF0ZShkYXRhOiBPbWl0PFQsICdpZCcgfCAnY3JlYXRlZEF0JyB8ICd1cGRhdGVkQXQnPik6IFByb21pc2U8VD47XG4gIHVwZGF0ZShpZDogc3RyaW5nLCBkYXRhOiBQYXJ0aWFsPFQ+KTogUHJvbWlzZTx2b2lkPjtcbiAgZGVsZXRlKGlkOiBzdHJpbmcpOiBQcm9taXNlPHZvaWQ+O1xufVxuXG4vKipcbiAqIENsYXNlIGJhc2UgcGFyYSBzZXJ2aWNpb3MgZGUgY29sZWNjacOzbiB0aXBhZG9zLlxuICpcbiAqIEV4dGllbmRlIGVzdGEgY2xhc2UgcGFyYSBjcmVhciB1biBzZXJ2aWNpbyBkZWRpY2FkbyBwYXJhIGNhZGEgZW50aWRhZCxcbiAqIGNvbiBtw6l0b2RvcyBwZXJzb25hbGl6YWRvcyB5IHRpcGFkbyBmdWVydGUuXG4gKlxuICogQGV4YW1wbGVcbiAqIGBgYHR5cGVzY3JpcHRcbiAqIC8vIERlZmluaXIgZWwgbW9kZWxvXG4gKiBpbnRlcmZhY2UgVXNlciBleHRlbmRzIEZpcmVzdG9yZURvY3VtZW50IHtcbiAqICAgbmFtZTogc3RyaW5nO1xuICogICBlbWFpbDogc3RyaW5nO1xuICogICByb2xlOiAnYWRtaW4nIHwgJ3VzZXInO1xuICogICBhY3RpdmU6IGJvb2xlYW47XG4gKiB9XG4gKlxuICogLy8gQ3JlYXIgZWwgc2VydmljaW9cbiAqIEBJbmplY3RhYmxlKHsgcHJvdmlkZWRJbjogJ3Jvb3QnIH0pXG4gKiBleHBvcnQgY2xhc3MgVXNlcnNDb2xsZWN0aW9uIGV4dGVuZHMgRmlyZXN0b3JlQ29sbGVjdGlvbjxVc2VyPiB7XG4gKiAgIGNvbnN0cnVjdG9yKCkge1xuICogICAgIHN1cGVyKCd1c2VycycpO1xuICogICB9XG4gKlxuICogICAvLyBNw6l0b2RvcyBwZXJzb25hbGl6YWRvc1xuICogICBhc3luYyBnZXRBY3RpdmVVc2VycygpOiBQcm9taXNlPFVzZXJbXT4ge1xuICogICAgIHJldHVybiB0aGlzLnF1ZXJ5KHtcbiAqICAgICAgIHdoZXJlOiBbeyBmaWVsZDogJ2FjdGl2ZScsIG9wZXJhdG9yOiAnPT0nLCB2YWx1ZTogdHJ1ZSB9XVxuICogICAgIH0pO1xuICogICB9XG4gKlxuICogICBhc3luYyBnZXRBZG1pbnMoKTogUHJvbWlzZTxVc2VyW10+IHtcbiAqICAgICByZXR1cm4gdGhpcy5xdWVyeSh7XG4gKiAgICAgICB3aGVyZTogW3sgZmllbGQ6ICdyb2xlJywgb3BlcmF0b3I6ICc9PScsIHZhbHVlOiAnYWRtaW4nIH1dXG4gKiAgICAgfSk7XG4gKiAgIH1cbiAqXG4gKiAgIHdhdGNoT25saW5lVXNlcnMoKTogT2JzZXJ2YWJsZTxVc2VyW10+IHtcbiAqICAgICByZXR1cm4gdGhpcy53YXRjaFF1ZXJ5KHtcbiAqICAgICAgIHdoZXJlOiBbeyBmaWVsZDogJ3N0YXR1cycsIG9wZXJhdG9yOiAnPT0nLCB2YWx1ZTogJ29ubGluZScgfV1cbiAqICAgICB9KTtcbiAqICAgfVxuICogfVxuICpcbiAqIC8vIFVzYXIgZW4gY29tcG9uZW50ZXNcbiAqIEBDb21wb25lbnQoey4uLn0pXG4gKiBleHBvcnQgY2xhc3MgVXNlcnNDb21wb25lbnQge1xuICogICBwcml2YXRlIHVzZXJzID0gaW5qZWN0KFVzZXJzQ29sbGVjdGlvbik7XG4gKlxuICogICBhZG1pbnMkID0gdGhpcy51c2Vycy5nZXRBZG1pbnMoKTtcbiAqICAgb25saW5lVXNlcnMkID0gdGhpcy51c2Vycy53YXRjaE9ubGluZVVzZXJzKCk7XG4gKlxuICogICBhc3luYyBjcmVhdGVVc2VyKGRhdGE6IE9taXQ8VXNlciwgJ2lkJz4pIHtcbiAqICAgICBjb25zdCB1c2VyID0gYXdhaXQgdGhpcy51c2Vycy5jcmVhdGUoZGF0YSk7XG4gKiAgIH1cbiAqIH1cbiAqIGBgYFxuICovXG5leHBvcnQgYWJzdHJhY3QgY2xhc3MgRmlyZXN0b3JlQ29sbGVjdGlvbjxUIGV4dGVuZHMgRmlyZXN0b3JlRG9jdW1lbnQ+IHtcbiAgcHJvdGVjdGVkIGZpcmVzdG9yZTogRmlyZXN0b3JlU2VydmljZTtcbiAgcHJvdGVjdGVkIHJlYWRvbmx5IGNvbGxlY3Rpb25QYXRoOiBzdHJpbmc7XG4gIHByb3RlY3RlZCByZWFkb25seSBvcHRpb25zOiBDb2xsZWN0aW9uT3B0aW9ucztcblxuICAvKipcbiAgICogQHBhcmFtIGNvbGxlY3Rpb25QYXRoIC0gUnV0YSBkZSBsYSBjb2xlY2Npw7NuIGVuIEZpcmVzdG9yZVxuICAgKiBAcGFyYW0gb3B0aW9ucyAtIE9wY2lvbmVzIGRlIGNvbmZpZ3VyYWNpw7NuXG4gICAqL1xuICBjb25zdHJ1Y3Rvcihjb2xsZWN0aW9uUGF0aDogc3RyaW5nLCBvcHRpb25zOiBDb2xsZWN0aW9uT3B0aW9ucyA9IHt9KSB7XG4gICAgdGhpcy5maXJlc3RvcmUgPSBpbmplY3QoRmlyZXN0b3JlU2VydmljZSk7XG4gICAgdGhpcy5jb2xsZWN0aW9uUGF0aCA9IGNvbGxlY3Rpb25QYXRoO1xuICAgIHRoaXMub3B0aW9ucyA9IHtcbiAgICAgIHNvZnREZWxldGU6IGZhbHNlLFxuICAgICAgdGltZXN0YW1wczogdHJ1ZSxcbiAgICAgIC4uLm9wdGlvbnMsXG4gICAgfTtcbiAgfVxuXG4gIC8vID09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PVxuICAvLyBMRUNUVVJBUyBPTkUtVElNRVxuICAvLyA9PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT1cblxuICAvKipcbiAgICogT2J0aWVuZSB1biBkb2N1bWVudG8gcG9yIElELlxuICAgKi9cbiAgYXN5bmMgZ2V0QnlJZChpZDogc3RyaW5nKTogUHJvbWlzZTxUIHwgbnVsbD4ge1xuICAgIHJldHVybiB0aGlzLmZpcmVzdG9yZS5nZXREb2M8VD4odGhpcy5jb2xsZWN0aW9uUGF0aCwgaWQpO1xuICB9XG5cbiAgLyoqXG4gICAqIE9idGllbmUgdG9kb3MgbG9zIGRvY3VtZW50b3MgZGUgbGEgY29sZWNjacOzbi5cbiAgICovXG4gIGFzeW5jIGdldEFsbChvcHRpb25zPzogUXVlcnlPcHRpb25zKTogUHJvbWlzZTxUW10+IHtcbiAgICBjb25zdCBxdWVyeU9wdGlvbnMgPSB0aGlzLmFwcGx5RGVmYXVsdEZpbHRlcnMob3B0aW9ucyk7XG4gICAgcmV0dXJuIHRoaXMuZmlyZXN0b3JlLmdldERvY3M8VD4odGhpcy5jb2xsZWN0aW9uUGF0aCwgcXVlcnlPcHRpb25zKTtcbiAgfVxuXG4gIC8qKlxuICAgKiBFamVjdXRhIHVuYSBxdWVyeSBwZXJzb25hbGl6YWRhLlxuICAgKi9cbiAgYXN5bmMgcXVlcnkob3B0aW9uczogUXVlcnlPcHRpb25zKTogUHJvbWlzZTxUW10+IHtcbiAgICBjb25zdCBxdWVyeU9wdGlvbnMgPSB0aGlzLmFwcGx5RGVmYXVsdEZpbHRlcnMob3B0aW9ucyk7XG4gICAgcmV0dXJuIHRoaXMuZmlyZXN0b3JlLmdldERvY3M8VD4odGhpcy5jb2xsZWN0aW9uUGF0aCwgcXVlcnlPcHRpb25zKTtcbiAgfVxuXG4gIC8qKlxuICAgKiBPYnRpZW5lIGRvY3VtZW50b3MgY29uIHBhZ2luYWNpw7NuLlxuICAgKi9cbiAgYXN5bmMgcGFnaW5hdGUob3B0aW9uczogUXVlcnlPcHRpb25zICYgeyBsaW1pdDogbnVtYmVyIH0pOiBQcm9taXNlPFBhZ2luYXRlZFJlc3VsdDxUPj4ge1xuICAgIGNvbnN0IHF1ZXJ5T3B0aW9ucyA9IHRoaXMuYXBwbHlEZWZhdWx0RmlsdGVycyhvcHRpb25zKSBhcyBRdWVyeU9wdGlvbnMgJiB7IGxpbWl0OiBudW1iZXIgfTtcbiAgICByZXR1cm4gdGhpcy5maXJlc3RvcmUuZ2V0UGFnaW5hdGVkPFQ+KHRoaXMuY29sbGVjdGlvblBhdGgsIHF1ZXJ5T3B0aW9ucyk7XG4gIH1cblxuICAvKipcbiAgICogT2J0aWVuZSBlbCBwcmltZXIgZG9jdW1lbnRvIHF1ZSBjb2luY2lkYSBjb24gbGEgcXVlcnkuXG4gICAqL1xuICBhc3luYyBnZXRGaXJzdChvcHRpb25zPzogUXVlcnlPcHRpb25zKTogUHJvbWlzZTxUIHwgbnVsbD4ge1xuICAgIGNvbnN0IHF1ZXJ5T3B0aW9ucyA9IHRoaXMuYXBwbHlEZWZhdWx0RmlsdGVycyh7XG4gICAgICAuLi5vcHRpb25zLFxuICAgICAgbGltaXQ6IDEsXG4gICAgfSk7XG4gICAgY29uc3QgcmVzdWx0cyA9IGF3YWl0IHRoaXMuZmlyZXN0b3JlLmdldERvY3M8VD4odGhpcy5jb2xsZWN0aW9uUGF0aCwgcXVlcnlPcHRpb25zKTtcbiAgICByZXR1cm4gcmVzdWx0c1swXSA/PyBudWxsO1xuICB9XG5cbiAgLyoqXG4gICAqIEN1ZW50YSBsb3MgZG9jdW1lbnRvcyBxdWUgY29pbmNpZGVuIGNvbiBsYSBxdWVyeS5cbiAgICogTm90YTogRXN0byBjYXJnYSB0b2RvcyBsb3MgZG9jdW1lbnRvcywgdXNhciBjb24gY3VpZGFkbyBlbiBjb2xlY2Npb25lcyBncmFuZGVzLlxuICAgKi9cbiAgYXN5bmMgY291bnQob3B0aW9ucz86IFF1ZXJ5T3B0aW9ucyk6IFByb21pc2U8bnVtYmVyPiB7XG4gICAgY29uc3QgcXVlcnlPcHRpb25zID0gdGhpcy5hcHBseURlZmF1bHRGaWx0ZXJzKG9wdGlvbnMpO1xuICAgIGNvbnN0IHJlc3VsdHMgPSBhd2FpdCB0aGlzLmZpcmVzdG9yZS5nZXREb2NzPFQ+KHRoaXMuY29sbGVjdGlvblBhdGgsIHF1ZXJ5T3B0aW9ucyk7XG4gICAgcmV0dXJuIHJlc3VsdHMubGVuZ3RoO1xuICB9XG5cbiAgLyoqXG4gICAqIFZlcmlmaWNhIHNpIHVuIGRvY3VtZW50byBleGlzdGUuXG4gICAqL1xuICBhc3luYyBleGlzdHMoaWQ6IHN0cmluZyk6IFByb21pc2U8Ym9vbGVhbj4ge1xuICAgIHJldHVybiB0aGlzLmZpcmVzdG9yZS5leGlzdHModGhpcy5jb2xsZWN0aW9uUGF0aCwgaWQpO1xuICB9XG5cbiAgLy8gPT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09XG4gIC8vIFNVQlNDUklQQ0lPTkVTIFJFQUwtVElNRVxuICAvLyA9PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT1cblxuICAvKipcbiAgICogU3VzY3JpYmUgYSBjYW1iaW9zIGRlIHVuIGRvY3VtZW50by5cbiAgICovXG4gIHdhdGNoKGlkOiBzdHJpbmcpOiBPYnNlcnZhYmxlPFQgfCBudWxsPiB7XG4gICAgcmV0dXJuIHRoaXMuZmlyZXN0b3JlLmRvY0NoYW5nZXM8VD4odGhpcy5jb2xsZWN0aW9uUGF0aCwgaWQpO1xuICB9XG5cbiAgLyoqXG4gICAqIFN1c2NyaWJlIGEgY2FtYmlvcyBkZSBsYSBjb2xlY2Npw7NuLlxuICAgKi9cbiAgd2F0Y2hBbGwob3B0aW9ucz86IFF1ZXJ5T3B0aW9ucyk6IE9ic2VydmFibGU8VFtdPiB7XG4gICAgY29uc3QgcXVlcnlPcHRpb25zID0gdGhpcy5hcHBseURlZmF1bHRGaWx0ZXJzKG9wdGlvbnMpO1xuICAgIHJldHVybiB0aGlzLmZpcmVzdG9yZS5jb2xsZWN0aW9uQ2hhbmdlczxUPih0aGlzLmNvbGxlY3Rpb25QYXRoLCBxdWVyeU9wdGlvbnMpO1xuICB9XG5cbiAgLyoqXG4gICAqIFN1c2NyaWJlIGEgdW5hIHF1ZXJ5IHBlcnNvbmFsaXphZGEuXG4gICAqL1xuICB3YXRjaFF1ZXJ5KG9wdGlvbnM6IFF1ZXJ5T3B0aW9ucyk6IE9ic2VydmFibGU8VFtdPiB7XG4gICAgY29uc3QgcXVlcnlPcHRpb25zID0gdGhpcy5hcHBseURlZmF1bHRGaWx0ZXJzKG9wdGlvbnMpO1xuICAgIHJldHVybiB0aGlzLmZpcmVzdG9yZS5jb2xsZWN0aW9uQ2hhbmdlczxUPih0aGlzLmNvbGxlY3Rpb25QYXRoLCBxdWVyeU9wdGlvbnMpO1xuICB9XG5cbiAgLy8gPT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09XG4gIC8vIEVTQ1JJVFVSQVxuICAvLyA9PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT1cblxuICAvKipcbiAgICogQ3JlYSB1biBudWV2byBkb2N1bWVudG8gY29uIElEIGF1dG8tZ2VuZXJhZG8uXG4gICAqL1xuICBhc3luYyBjcmVhdGUoZGF0YTogT21pdDxULCAnaWQnIHwgJ2NyZWF0ZWRBdCcgfCAndXBkYXRlZEF0Jz4pOiBQcm9taXNlPFQ+IHtcbiAgICByZXR1cm4gdGhpcy5maXJlc3RvcmUuYWRkRG9jPFQ+KHRoaXMuY29sbGVjdGlvblBhdGgsIGRhdGEpO1xuICB9XG5cbiAgLyoqXG4gICAqIENyZWEgdW4gZG9jdW1lbnRvIGNvbiBJRCBlc3BlY8OtZmljby5cbiAgICovXG4gIGFzeW5jIGNyZWF0ZVdpdGhJZChpZDogc3RyaW5nLCBkYXRhOiBPbWl0PFQsICdpZCc+KTogUHJvbWlzZTx2b2lkPiB7XG4gICAgcmV0dXJuIHRoaXMuZmlyZXN0b3JlLnNldERvYzxUPih0aGlzLmNvbGxlY3Rpb25QYXRoLCBpZCwgZGF0YSk7XG4gIH1cblxuICAvKipcbiAgICogQWN0dWFsaXphIGNhbXBvcyBkZSB1biBkb2N1bWVudG8uXG4gICAqL1xuICBhc3luYyB1cGRhdGUoaWQ6IHN0cmluZywgZGF0YTogUGFydGlhbDxPbWl0PFQsICdpZCcgfCAnY3JlYXRlZEF0Jz4+KTogUHJvbWlzZTx2b2lkPiB7XG4gICAgcmV0dXJuIHRoaXMuZmlyZXN0b3JlLnVwZGF0ZURvYzxUPih0aGlzLmNvbGxlY3Rpb25QYXRoLCBpZCwgZGF0YSk7XG4gIH1cblxuICAvKipcbiAgICogRWxpbWluYSB1biBkb2N1bWVudG8uXG4gICAqIFNpIHNvZnREZWxldGUgZXN0w6EgaGFiaWxpdGFkbywgbWFyY2EgY29tbyBlbGltaW5hZG8gZW4gbHVnYXIgZGUgYm9ycmFyLlxuICAgKi9cbiAgYXN5bmMgZGVsZXRlKGlkOiBzdHJpbmcpOiBQcm9taXNlPHZvaWQ+IHtcbiAgICBpZiAodGhpcy5vcHRpb25zLnNvZnREZWxldGUpIHtcbiAgICAgIHJldHVybiB0aGlzLmZpcmVzdG9yZS51cGRhdGVEb2M8VD4odGhpcy5jb2xsZWN0aW9uUGF0aCwgaWQsIHtcbiAgICAgICAgZGVsZXRlZEF0OiBuZXcgRGF0ZSgpLFxuICAgICAgfSBhcyB1bmtub3duIGFzIFBhcnRpYWw8VD4pO1xuICAgIH1cbiAgICByZXR1cm4gdGhpcy5maXJlc3RvcmUuZGVsZXRlRG9jKHRoaXMuY29sbGVjdGlvblBhdGgsIGlkKTtcbiAgfVxuXG4gIC8qKlxuICAgKiBSZXN0YXVyYSB1biBkb2N1bWVudG8gc29mdC1kZWxldGVkLlxuICAgKi9cbiAgYXN5bmMgcmVzdG9yZShpZDogc3RyaW5nKTogUHJvbWlzZTx2b2lkPiB7XG4gICAgaWYgKCF0aGlzLm9wdGlvbnMuc29mdERlbGV0ZSkge1xuICAgICAgdGhyb3cgbmV3IEVycm9yKCdTb2Z0IGRlbGV0ZSBubyBlc3TDoSBoYWJpbGl0YWRvIHBhcmEgZXN0YSBjb2xlY2Npw7NuJyk7XG4gICAgfVxuICAgIHJldHVybiB0aGlzLmZpcmVzdG9yZS51cGRhdGVEb2M8VD4odGhpcy5jb2xsZWN0aW9uUGF0aCwgaWQsIHtcbiAgICAgIGRlbGV0ZWRBdDogbnVsbCxcbiAgICB9IGFzIHVua25vd24gYXMgUGFydGlhbDxUPik7XG4gIH1cblxuICAvLyA9PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT1cbiAgLy8gU1VCLUNPTEVDQ0lPTkVTXG4gIC8vID09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PVxuXG4gIC8qKlxuICAgKiBPYnRpZW5lIHVuYSByZWZlcmVuY2lhIGEgdW5hIHN1Yi1jb2xlY2Npw7NuLlxuICAgKlxuICAgKiBAZXhhbXBsZVxuICAgKiBgYGB0eXBlc2NyaXB0XG4gICAqIC8vIEVuIFVzZXJzQ29sbGVjdGlvblxuICAgKiBnZXRVc2VyRG9jdW1lbnRzKHVzZXJJZDogc3RyaW5nKSB7XG4gICAqICAgcmV0dXJuIHRoaXMuc3ViY29sbGVjdGlvbjxEb2N1bWVudD4odXNlcklkLCAnZG9jdW1lbnRzJyk7XG4gICAqIH1cbiAgICpcbiAgICogLy8gVXNvXG4gICAqIGNvbnN0IGRvY3MgPSBhd2FpdCB1c2Vycy5nZXRVc2VyRG9jdW1lbnRzKCd1c2VyMTIzJykuZ2V0QWxsKCk7XG4gICAqIGBgYFxuICAgKi9cbiAgc3ViY29sbGVjdGlvbjxTIGV4dGVuZHMgRmlyZXN0b3JlRG9jdW1lbnQ+KFxuICAgIHBhcmVudElkOiBzdHJpbmcsXG4gICAgc3ViY29sbGVjdGlvbk5hbWU6IHN0cmluZ1xuICApOiBTdWJDb2xsZWN0aW9uUmVmPFM+IHtcbiAgICBjb25zdCBzdWJQYXRoID0gYCR7dGhpcy5jb2xsZWN0aW9uUGF0aH0vJHtwYXJlbnRJZH0vJHtzdWJjb2xsZWN0aW9uTmFtZX1gO1xuXG4gICAgcmV0dXJuIHtcbiAgICAgIGdldEJ5SWQ6IChpZDogc3RyaW5nKSA9PiB0aGlzLmZpcmVzdG9yZS5nZXREb2M8Uz4oc3ViUGF0aCwgaWQpLFxuICAgICAgZ2V0QWxsOiAob3B0aW9ucz86IFF1ZXJ5T3B0aW9ucykgPT4gdGhpcy5maXJlc3RvcmUuZ2V0RG9jczxTPihzdWJQYXRoLCBvcHRpb25zKSxcbiAgICAgIHdhdGNoOiAoaWQ6IHN0cmluZykgPT4gdGhpcy5maXJlc3RvcmUuZG9jQ2hhbmdlczxTPihzdWJQYXRoLCBpZCksXG4gICAgICB3YXRjaEFsbDogKG9wdGlvbnM/OiBRdWVyeU9wdGlvbnMpID0+IHRoaXMuZmlyZXN0b3JlLmNvbGxlY3Rpb25DaGFuZ2VzPFM+KHN1YlBhdGgsIG9wdGlvbnMpLFxuICAgICAgY3JlYXRlOiAoZGF0YTogT21pdDxTLCAnaWQnIHwgJ2NyZWF0ZWRBdCcgfCAndXBkYXRlZEF0Jz4pID0+XG4gICAgICAgIHRoaXMuZmlyZXN0b3JlLmFkZERvYzxTPihzdWJQYXRoLCBkYXRhKSxcbiAgICAgIHVwZGF0ZTogKGlkOiBzdHJpbmcsIGRhdGE6IFBhcnRpYWw8Uz4pID0+IHRoaXMuZmlyZXN0b3JlLnVwZGF0ZURvYzxTPihzdWJQYXRoLCBpZCwgZGF0YSksXG4gICAgICBkZWxldGU6IChpZDogc3RyaW5nKSA9PiB0aGlzLmZpcmVzdG9yZS5kZWxldGVEb2Moc3ViUGF0aCwgaWQpLFxuICAgIH07XG4gIH1cblxuICAvLyA9PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT1cbiAgLy8gTcOJVE9ET1MgUFJPVEVHSURPUyAocGFyYSBvdmVycmlkZSBlbiBzdWJjbGFzZXMpXG4gIC8vID09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PVxuXG4gIC8qKlxuICAgKiBBcGxpY2EgZmlsdHJvcyBwb3IgZGVmZWN0byBhIGxhcyBxdWVyaWVzLlxuICAgKiBPdmVycmlkZSBlc3RlIG3DqXRvZG8gcGFyYSBhZ3JlZ2FyIGZpbHRyb3MgZ2xvYmFsZXMgKGVqOiBleGNsdWlyIHNvZnQtZGVsZXRlZCkuXG4gICAqL1xuICBwcm90ZWN0ZWQgYXBwbHlEZWZhdWx0RmlsdGVycyhvcHRpb25zPzogUXVlcnlPcHRpb25zKTogUXVlcnlPcHRpb25zIHtcbiAgICBpZiAoIXRoaXMub3B0aW9ucy5zb2Z0RGVsZXRlKSB7XG4gICAgICByZXR1cm4gb3B0aW9ucyA/PyB7fTtcbiAgICB9XG5cbiAgICAvLyBFeGNsdWlyIGRvY3VtZW50b3Mgc29mdC1kZWxldGVkIHBvciBkZWZlY3RvXG4gICAgY29uc3Qgd2hlcmVDbGF1c2UgPSB7IGZpZWxkOiAnZGVsZXRlZEF0Jywgb3BlcmF0b3I6ICc9PScgYXMgY29uc3QsIHZhbHVlOiBudWxsIH07XG5cbiAgICByZXR1cm4ge1xuICAgICAgLi4ub3B0aW9ucyxcbiAgICAgIHdoZXJlOiBbLi4uKG9wdGlvbnM/LndoZXJlID8/IFtdKSwgd2hlcmVDbGF1c2VdLFxuICAgIH07XG4gIH1cblxuICAvLyA9PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT1cbiAgLy8gVVRJTElEQURFU1xuICAvLyA9PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT1cblxuICAvKipcbiAgICogR2VuZXJhIHVuIG51ZXZvIElEIHNpbiBjcmVhciBlbCBkb2N1bWVudG8uXG4gICAqL1xuICBnZW5lcmF0ZUlkKCk6IHN0cmluZyB7XG4gICAgcmV0dXJuIHRoaXMuZmlyZXN0b3JlLmdlbmVyYXRlSWQodGhpcy5jb2xsZWN0aW9uUGF0aCk7XG4gIH1cblxuICAvKipcbiAgICogT2J0aWVuZSBsYSBydXRhIGRlIGxhIGNvbGVjY2nDs24uXG4gICAqL1xuICBnZXRQYXRoKCk6IHN0cmluZyB7XG4gICAgcmV0dXJuIHRoaXMuY29sbGVjdGlvblBhdGg7XG4gIH1cbn1cbiJdfQ==