valtech-components 2.0.417 → 2.0.419
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/esm2022/public-api.mjs +4 -2
- package/fesm2022/valtech-components.mjs +4 -2607
- package/fesm2022/valtech-components.mjs.map +1 -1
- package/package.json +1 -3
- package/public-api.d.ts +0 -1
- package/esm2022/lib/services/firebase/config.mjs +0 -108
- package/esm2022/lib/services/firebase/firebase.service.mjs +0 -285
- package/esm2022/lib/services/firebase/firestore-collection.mjs +0 -266
- package/esm2022/lib/services/firebase/firestore.service.mjs +0 -508
- package/esm2022/lib/services/firebase/index.mjs +0 -46
- package/esm2022/lib/services/firebase/messaging.service.mjs +0 -503
- package/esm2022/lib/services/firebase/storage.service.mjs +0 -421
- package/esm2022/lib/services/firebase/types.mjs +0 -8
- package/esm2022/lib/services/firebase/utils/path-builder.mjs +0 -195
- package/esm2022/lib/services/firebase/utils/query-builder.mjs +0 -302
- package/lib/services/firebase/config.d.ts +0 -49
- package/lib/services/firebase/firebase.service.d.ts +0 -140
- package/lib/services/firebase/firestore-collection.d.ts +0 -195
- package/lib/services/firebase/firestore.service.d.ts +0 -303
- package/lib/services/firebase/index.d.ts +0 -38
- package/lib/services/firebase/messaging.service.d.ts +0 -254
- package/lib/services/firebase/storage.service.d.ts +0 -204
- package/lib/services/firebase/types.d.ts +0 -281
- package/lib/services/firebase/utils/path-builder.d.ts +0 -132
- package/lib/services/firebase/utils/query-builder.d.ts +0 -210
|
@@ -1,508 +0,0 @@
|
|
|
1
|
-
/**
|
|
2
|
-
* Firestore Service
|
|
3
|
-
*
|
|
4
|
-
* Servicio genérico para operaciones CRUD en Firestore.
|
|
5
|
-
* Soporta lecturas one-time, subscripciones real-time, paginación y queries complejas.
|
|
6
|
-
*/
|
|
7
|
-
import { inject, Injectable } from '@angular/core';
|
|
8
|
-
import { addDoc, collection, collectionData, deleteDoc, doc, docData, Firestore, getDoc, getDocs, limit, orderBy, query, serverTimestamp, setDoc, startAfter, startAt, endBefore, endAt, Timestamp, updateDoc, where, writeBatch, increment, arrayUnion, arrayRemove, } from '@angular/fire/firestore';
|
|
9
|
-
import { map } from 'rxjs';
|
|
10
|
-
import { buildPath } from './utils/path-builder';
|
|
11
|
-
import * as i0 from "@angular/core";
|
|
12
|
-
/**
|
|
13
|
-
* Servicio para operaciones CRUD en Firestore.
|
|
14
|
-
*
|
|
15
|
-
* @example
|
|
16
|
-
* ```typescript
|
|
17
|
-
* interface User extends FirestoreDocument {
|
|
18
|
-
* name: string;
|
|
19
|
-
* email: string;
|
|
20
|
-
* role: 'admin' | 'user';
|
|
21
|
-
* }
|
|
22
|
-
*
|
|
23
|
-
* @Component({...})
|
|
24
|
-
* export class UsersComponent {
|
|
25
|
-
* private firestore = inject(FirestoreService);
|
|
26
|
-
*
|
|
27
|
-
* // Lectura one-time
|
|
28
|
-
* async loadUser(id: string) {
|
|
29
|
-
* const user = await this.firestore.getDoc<User>('users', id);
|
|
30
|
-
* }
|
|
31
|
-
*
|
|
32
|
-
* // Subscripción real-time
|
|
33
|
-
* users$ = this.firestore.collectionChanges<User>('users', {
|
|
34
|
-
* where: [{ field: 'role', operator: '==', value: 'admin' }],
|
|
35
|
-
* orderBy: [{ field: 'name', direction: 'asc' }]
|
|
36
|
-
* });
|
|
37
|
-
*
|
|
38
|
-
* // Crear documento
|
|
39
|
-
* async createUser(data: Omit<User, 'id'>) {
|
|
40
|
-
* const user = await this.firestore.addDoc<User>('users', data);
|
|
41
|
-
* }
|
|
42
|
-
* }
|
|
43
|
-
* ```
|
|
44
|
-
*/
|
|
45
|
-
export class FirestoreService {
|
|
46
|
-
constructor() {
|
|
47
|
-
this.firestore = inject(Firestore);
|
|
48
|
-
}
|
|
49
|
-
// ===========================================================================
|
|
50
|
-
// LECTURAS ONE-TIME (Promise)
|
|
51
|
-
// ===========================================================================
|
|
52
|
-
/**
|
|
53
|
-
* Obtiene un documento por ID (lectura única).
|
|
54
|
-
*
|
|
55
|
-
* @param collectionPath - Ruta de la colección
|
|
56
|
-
* @param docId - ID del documento
|
|
57
|
-
* @returns Documento o null si no existe
|
|
58
|
-
*
|
|
59
|
-
* @example
|
|
60
|
-
* ```typescript
|
|
61
|
-
* const user = await firestoreService.getDoc<User>('users', 'abc123');
|
|
62
|
-
* if (user) {
|
|
63
|
-
* console.log(user.name);
|
|
64
|
-
* }
|
|
65
|
-
* ```
|
|
66
|
-
*/
|
|
67
|
-
async getDoc(collectionPath, docId) {
|
|
68
|
-
const docRef = doc(this.firestore, collectionPath, docId);
|
|
69
|
-
const snapshot = await getDoc(docRef);
|
|
70
|
-
if (!snapshot.exists()) {
|
|
71
|
-
return null;
|
|
72
|
-
}
|
|
73
|
-
return this.mapDocument(snapshot);
|
|
74
|
-
}
|
|
75
|
-
/**
|
|
76
|
-
* Obtiene múltiples documentos con opciones de query.
|
|
77
|
-
*
|
|
78
|
-
* @param collectionPath - Ruta de la colección
|
|
79
|
-
* @param options - Opciones de query (where, orderBy, limit)
|
|
80
|
-
* @returns Array de documentos
|
|
81
|
-
*
|
|
82
|
-
* @example
|
|
83
|
-
* ```typescript
|
|
84
|
-
* // Todos los usuarios activos ordenados por nombre
|
|
85
|
-
* const users = await firestoreService.getDocs<User>('users', {
|
|
86
|
-
* where: [{ field: 'active', operator: '==', value: true }],
|
|
87
|
-
* orderBy: [{ field: 'name', direction: 'asc' }],
|
|
88
|
-
* limit: 50
|
|
89
|
-
* });
|
|
90
|
-
* ```
|
|
91
|
-
*/
|
|
92
|
-
async getDocs(collectionPath, options) {
|
|
93
|
-
const collectionRef = collection(this.firestore, collectionPath);
|
|
94
|
-
const constraints = this.buildQueryConstraints(options);
|
|
95
|
-
const q = query(collectionRef, ...constraints);
|
|
96
|
-
const snapshot = await getDocs(q);
|
|
97
|
-
return snapshot.docs.map((doc) => this.mapDocument(doc));
|
|
98
|
-
}
|
|
99
|
-
/**
|
|
100
|
-
* Obtiene documentos con paginación basada en cursores.
|
|
101
|
-
*
|
|
102
|
-
* @param collectionPath - Ruta de la colección
|
|
103
|
-
* @param options - Opciones de query (debe incluir limit)
|
|
104
|
-
* @returns Resultado paginado con cursor para la siguiente página
|
|
105
|
-
*
|
|
106
|
-
* @example
|
|
107
|
-
* ```typescript
|
|
108
|
-
* // Primera página
|
|
109
|
-
* const page1 = await firestoreService.getPaginated<User>('users', {
|
|
110
|
-
* orderBy: [{ field: 'createdAt', direction: 'desc' }],
|
|
111
|
-
* limit: 10
|
|
112
|
-
* });
|
|
113
|
-
*
|
|
114
|
-
* // Siguiente página
|
|
115
|
-
* if (page1.hasMore) {
|
|
116
|
-
* const page2 = await firestoreService.getPaginated<User>('users', {
|
|
117
|
-
* orderBy: [{ field: 'createdAt', direction: 'desc' }],
|
|
118
|
-
* limit: 10,
|
|
119
|
-
* startAfter: page1.lastDoc
|
|
120
|
-
* });
|
|
121
|
-
* }
|
|
122
|
-
* ```
|
|
123
|
-
*/
|
|
124
|
-
async getPaginated(collectionPath, options) {
|
|
125
|
-
const collectionRef = collection(this.firestore, collectionPath);
|
|
126
|
-
const constraints = this.buildQueryConstraints(options);
|
|
127
|
-
// Pedir uno más para saber si hay más páginas
|
|
128
|
-
const q = query(collectionRef, ...constraints, limit(options.limit + 1));
|
|
129
|
-
const snapshot = await getDocs(q);
|
|
130
|
-
const docs = snapshot.docs;
|
|
131
|
-
const hasMore = docs.length > options.limit;
|
|
132
|
-
// Si hay más, remover el documento extra
|
|
133
|
-
const resultDocs = hasMore ? docs.slice(0, -1) : docs;
|
|
134
|
-
const lastDoc = resultDocs.length > 0 ? resultDocs[resultDocs.length - 1] : null;
|
|
135
|
-
return {
|
|
136
|
-
data: resultDocs.map((doc) => this.mapDocument(doc)),
|
|
137
|
-
hasMore,
|
|
138
|
-
lastDoc,
|
|
139
|
-
};
|
|
140
|
-
}
|
|
141
|
-
/**
|
|
142
|
-
* Verifica si un documento existe.
|
|
143
|
-
*
|
|
144
|
-
* @param collectionPath - Ruta de la colección
|
|
145
|
-
* @param docId - ID del documento
|
|
146
|
-
* @returns true si el documento existe
|
|
147
|
-
*/
|
|
148
|
-
async exists(collectionPath, docId) {
|
|
149
|
-
const docRef = doc(this.firestore, collectionPath, docId);
|
|
150
|
-
const snapshot = await getDoc(docRef);
|
|
151
|
-
return snapshot.exists();
|
|
152
|
-
}
|
|
153
|
-
// ===========================================================================
|
|
154
|
-
// SUBSCRIPCIONES REAL-TIME (Observable)
|
|
155
|
-
// ===========================================================================
|
|
156
|
-
/**
|
|
157
|
-
* Suscribe a cambios de un documento (real-time).
|
|
158
|
-
*
|
|
159
|
-
* @param collectionPath - Ruta de la colección
|
|
160
|
-
* @param docId - ID del documento
|
|
161
|
-
* @returns Observable que emite cuando el documento cambia
|
|
162
|
-
*
|
|
163
|
-
* @example
|
|
164
|
-
* ```typescript
|
|
165
|
-
* // En el componente
|
|
166
|
-
* user$ = this.firestoreService.docChanges<User>('users', this.userId);
|
|
167
|
-
*
|
|
168
|
-
* // En el template
|
|
169
|
-
* @if (user$ | async; as user) {
|
|
170
|
-
* <p>{{ user.name }}</p>
|
|
171
|
-
* }
|
|
172
|
-
* ```
|
|
173
|
-
*/
|
|
174
|
-
docChanges(collectionPath, docId) {
|
|
175
|
-
const docRef = doc(this.firestore, collectionPath, docId);
|
|
176
|
-
return docData(docRef, { idField: 'id' }).pipe(map((data) => {
|
|
177
|
-
if (!data)
|
|
178
|
-
return null;
|
|
179
|
-
return this.convertTimestamps(data);
|
|
180
|
-
}));
|
|
181
|
-
}
|
|
182
|
-
/**
|
|
183
|
-
* Suscribe a cambios de una colección (real-time).
|
|
184
|
-
*
|
|
185
|
-
* @param collectionPath - Ruta de la colección
|
|
186
|
-
* @param options - Opciones de query
|
|
187
|
-
* @returns Observable que emite cuando la colección cambia
|
|
188
|
-
*
|
|
189
|
-
* @example
|
|
190
|
-
* ```typescript
|
|
191
|
-
* // Usuarios activos en tiempo real
|
|
192
|
-
* activeUsers$ = this.firestoreService.collectionChanges<User>('users', {
|
|
193
|
-
* where: [{ field: 'status', operator: '==', value: 'online' }]
|
|
194
|
-
* });
|
|
195
|
-
* ```
|
|
196
|
-
*/
|
|
197
|
-
collectionChanges(collectionPath, options) {
|
|
198
|
-
const collectionRef = collection(this.firestore, collectionPath);
|
|
199
|
-
const constraints = this.buildQueryConstraints(options);
|
|
200
|
-
const q = query(collectionRef, ...constraints);
|
|
201
|
-
return collectionData(q, { idField: 'id' }).pipe(map((docs) => docs.map((doc) => this.convertTimestamps(doc))));
|
|
202
|
-
}
|
|
203
|
-
// ===========================================================================
|
|
204
|
-
// ESCRITURA
|
|
205
|
-
// ===========================================================================
|
|
206
|
-
/**
|
|
207
|
-
* Agrega un documento con ID auto-generado.
|
|
208
|
-
*
|
|
209
|
-
* @param collectionPath - Ruta de la colección
|
|
210
|
-
* @param data - Datos del documento (sin id, createdAt, updatedAt)
|
|
211
|
-
* @returns Documento creado con su ID
|
|
212
|
-
*
|
|
213
|
-
* @example
|
|
214
|
-
* ```typescript
|
|
215
|
-
* const newUser = await firestoreService.addDoc<User>('users', {
|
|
216
|
-
* name: 'John Doe',
|
|
217
|
-
* email: 'john@example.com',
|
|
218
|
-
* role: 'user'
|
|
219
|
-
* });
|
|
220
|
-
* console.log('Created user with ID:', newUser.id);
|
|
221
|
-
* ```
|
|
222
|
-
*/
|
|
223
|
-
async addDoc(collectionPath, data) {
|
|
224
|
-
const collectionRef = collection(this.firestore, collectionPath);
|
|
225
|
-
const timestamp = serverTimestamp();
|
|
226
|
-
const docData = {
|
|
227
|
-
...data,
|
|
228
|
-
createdAt: timestamp,
|
|
229
|
-
updatedAt: timestamp,
|
|
230
|
-
};
|
|
231
|
-
const docRef = await addDoc(collectionRef, docData);
|
|
232
|
-
// Obtener el documento creado para retornarlo con timestamps resueltos
|
|
233
|
-
const snapshot = await getDoc(docRef);
|
|
234
|
-
return this.mapDocument(snapshot);
|
|
235
|
-
}
|
|
236
|
-
/**
|
|
237
|
-
* Crea o sobrescribe un documento con ID específico.
|
|
238
|
-
*
|
|
239
|
-
* @param collectionPath - Ruta de la colección
|
|
240
|
-
* @param docId - ID del documento
|
|
241
|
-
* @param data - Datos del documento
|
|
242
|
-
* @param options - Opciones (merge: true para merge en lugar de sobrescribir)
|
|
243
|
-
*
|
|
244
|
-
* @example
|
|
245
|
-
* ```typescript
|
|
246
|
-
* // Sobrescribir completamente
|
|
247
|
-
* await firestoreService.setDoc<User>('users', 'user123', userData);
|
|
248
|
-
*
|
|
249
|
-
* // Merge con datos existentes
|
|
250
|
-
* await firestoreService.setDoc<User>('users', 'user123', { name: 'New Name' }, { merge: true });
|
|
251
|
-
* ```
|
|
252
|
-
*/
|
|
253
|
-
async setDoc(collectionPath, docId, data, options) {
|
|
254
|
-
const docRef = doc(this.firestore, collectionPath, docId);
|
|
255
|
-
const timestamp = serverTimestamp();
|
|
256
|
-
const docData = {
|
|
257
|
-
...data,
|
|
258
|
-
updatedAt: timestamp,
|
|
259
|
-
...(options?.merge ? {} : { createdAt: timestamp }),
|
|
260
|
-
};
|
|
261
|
-
await setDoc(docRef, docData, { merge: options?.merge ?? false });
|
|
262
|
-
}
|
|
263
|
-
/**
|
|
264
|
-
* Actualiza campos específicos de un documento.
|
|
265
|
-
*
|
|
266
|
-
* @param collectionPath - Ruta de la colección
|
|
267
|
-
* @param docId - ID del documento
|
|
268
|
-
* @param data - Campos a actualizar
|
|
269
|
-
*
|
|
270
|
-
* @example
|
|
271
|
-
* ```typescript
|
|
272
|
-
* await firestoreService.updateDoc<User>('users', 'user123', {
|
|
273
|
-
* name: 'Updated Name',
|
|
274
|
-
* lastLogin: new Date()
|
|
275
|
-
* });
|
|
276
|
-
* ```
|
|
277
|
-
*/
|
|
278
|
-
async updateDoc(collectionPath, docId, data) {
|
|
279
|
-
const docRef = doc(this.firestore, collectionPath, docId);
|
|
280
|
-
await updateDoc(docRef, {
|
|
281
|
-
...data,
|
|
282
|
-
updatedAt: serverTimestamp(),
|
|
283
|
-
});
|
|
284
|
-
}
|
|
285
|
-
/**
|
|
286
|
-
* Elimina un documento.
|
|
287
|
-
*
|
|
288
|
-
* @param collectionPath - Ruta de la colección
|
|
289
|
-
* @param docId - ID del documento
|
|
290
|
-
*
|
|
291
|
-
* @example
|
|
292
|
-
* ```typescript
|
|
293
|
-
* await firestoreService.deleteDoc('users', 'user123');
|
|
294
|
-
* ```
|
|
295
|
-
*/
|
|
296
|
-
async deleteDoc(collectionPath, docId) {
|
|
297
|
-
const docRef = doc(this.firestore, collectionPath, docId);
|
|
298
|
-
await deleteDoc(docRef);
|
|
299
|
-
}
|
|
300
|
-
// ===========================================================================
|
|
301
|
-
// OPERACIONES EN LOTE
|
|
302
|
-
// ===========================================================================
|
|
303
|
-
/**
|
|
304
|
-
* Ejecuta múltiples operaciones de escritura de forma atómica.
|
|
305
|
-
*
|
|
306
|
-
* @param operations - Función que recibe el batch y agrega operaciones
|
|
307
|
-
*
|
|
308
|
-
* @example
|
|
309
|
-
* ```typescript
|
|
310
|
-
* await firestoreService.batch((batch) => {
|
|
311
|
-
* batch.set('users/user1', { name: 'User 1' });
|
|
312
|
-
* batch.update('users/user2', { status: 'inactive' });
|
|
313
|
-
* batch.delete('users/user3');
|
|
314
|
-
* });
|
|
315
|
-
* ```
|
|
316
|
-
*/
|
|
317
|
-
async batch(operations) {
|
|
318
|
-
const batch = writeBatch(this.firestore);
|
|
319
|
-
const batchApi = {
|
|
320
|
-
set: (path, data) => {
|
|
321
|
-
const [collectionPath, docId] = this.splitPath(path);
|
|
322
|
-
const docRef = doc(this.firestore, collectionPath, docId);
|
|
323
|
-
batch.set(docRef, {
|
|
324
|
-
...data,
|
|
325
|
-
createdAt: serverTimestamp(),
|
|
326
|
-
updatedAt: serverTimestamp(),
|
|
327
|
-
});
|
|
328
|
-
},
|
|
329
|
-
update: (path, data) => {
|
|
330
|
-
const [collectionPath, docId] = this.splitPath(path);
|
|
331
|
-
const docRef = doc(this.firestore, collectionPath, docId);
|
|
332
|
-
batch.update(docRef, {
|
|
333
|
-
...data,
|
|
334
|
-
updatedAt: serverTimestamp(),
|
|
335
|
-
});
|
|
336
|
-
},
|
|
337
|
-
delete: (path) => {
|
|
338
|
-
const [collectionPath, docId] = this.splitPath(path);
|
|
339
|
-
const docRef = doc(this.firestore, collectionPath, docId);
|
|
340
|
-
batch.delete(docRef);
|
|
341
|
-
},
|
|
342
|
-
};
|
|
343
|
-
operations(batchApi);
|
|
344
|
-
await batch.commit();
|
|
345
|
-
}
|
|
346
|
-
// ===========================================================================
|
|
347
|
-
// UTILIDADES
|
|
348
|
-
// ===========================================================================
|
|
349
|
-
/**
|
|
350
|
-
* Construye una ruta a partir de un template.
|
|
351
|
-
*
|
|
352
|
-
* @param template - Template con placeholders {param}
|
|
353
|
-
* @param params - Valores para los placeholders
|
|
354
|
-
* @returns Ruta construida
|
|
355
|
-
*
|
|
356
|
-
* @example
|
|
357
|
-
* ```typescript
|
|
358
|
-
* const path = firestoreService.buildPath('users/{userId}/documents/{docId}', {
|
|
359
|
-
* userId: 'user123',
|
|
360
|
-
* docId: 'doc456'
|
|
361
|
-
* });
|
|
362
|
-
* // => 'users/user123/documents/doc456'
|
|
363
|
-
* ```
|
|
364
|
-
*/
|
|
365
|
-
buildPath(template, params) {
|
|
366
|
-
return buildPath(template, params);
|
|
367
|
-
}
|
|
368
|
-
/**
|
|
369
|
-
* Genera un ID único para un documento (sin crearlo).
|
|
370
|
-
*
|
|
371
|
-
* @param collectionPath - Ruta de la colección
|
|
372
|
-
* @returns ID único generado por Firestore
|
|
373
|
-
*/
|
|
374
|
-
generateId(collectionPath) {
|
|
375
|
-
const collectionRef = collection(this.firestore, collectionPath);
|
|
376
|
-
return doc(collectionRef).id;
|
|
377
|
-
}
|
|
378
|
-
/**
|
|
379
|
-
* Retorna un valor de timestamp del servidor.
|
|
380
|
-
* Usar en campos de fecha para que Firestore asigne el timestamp.
|
|
381
|
-
*/
|
|
382
|
-
serverTimestamp() {
|
|
383
|
-
return serverTimestamp();
|
|
384
|
-
}
|
|
385
|
-
/**
|
|
386
|
-
* Retorna un valor para agregar elementos a un array.
|
|
387
|
-
*
|
|
388
|
-
* @example
|
|
389
|
-
* ```typescript
|
|
390
|
-
* await firestoreService.updateDoc('users', 'user123', {
|
|
391
|
-
* tags: firestoreService.arrayUnion('new-tag')
|
|
392
|
-
* });
|
|
393
|
-
* ```
|
|
394
|
-
*/
|
|
395
|
-
arrayUnion(...elements) {
|
|
396
|
-
return arrayUnion(...elements);
|
|
397
|
-
}
|
|
398
|
-
/**
|
|
399
|
-
* Retorna un valor para remover elementos de un array.
|
|
400
|
-
*/
|
|
401
|
-
arrayRemove(...elements) {
|
|
402
|
-
return arrayRemove(...elements);
|
|
403
|
-
}
|
|
404
|
-
/**
|
|
405
|
-
* Retorna un valor para incrementar un campo numérico.
|
|
406
|
-
*
|
|
407
|
-
* @example
|
|
408
|
-
* ```typescript
|
|
409
|
-
* await firestoreService.updateDoc('users', 'user123', {
|
|
410
|
-
* loginCount: firestoreService.increment(1)
|
|
411
|
-
* });
|
|
412
|
-
* ```
|
|
413
|
-
*/
|
|
414
|
-
increment(n) {
|
|
415
|
-
return increment(n);
|
|
416
|
-
}
|
|
417
|
-
// ===========================================================================
|
|
418
|
-
// MÉTODOS PRIVADOS
|
|
419
|
-
// ===========================================================================
|
|
420
|
-
/**
|
|
421
|
-
* Construye los QueryConstraints a partir de QueryOptions
|
|
422
|
-
*/
|
|
423
|
-
buildQueryConstraints(options) {
|
|
424
|
-
const constraints = [];
|
|
425
|
-
if (!options)
|
|
426
|
-
return constraints;
|
|
427
|
-
// Where clauses
|
|
428
|
-
if (options.where) {
|
|
429
|
-
for (const clause of options.where) {
|
|
430
|
-
constraints.push(where(clause.field, clause.operator, clause.value));
|
|
431
|
-
}
|
|
432
|
-
}
|
|
433
|
-
// OrderBy clauses
|
|
434
|
-
if (options.orderBy) {
|
|
435
|
-
for (const clause of options.orderBy) {
|
|
436
|
-
constraints.push(orderBy(clause.field, clause.direction));
|
|
437
|
-
}
|
|
438
|
-
}
|
|
439
|
-
// Cursors para paginación
|
|
440
|
-
if (options.startAfter) {
|
|
441
|
-
constraints.push(startAfter(options.startAfter));
|
|
442
|
-
}
|
|
443
|
-
if (options.startAt) {
|
|
444
|
-
constraints.push(startAt(options.startAt));
|
|
445
|
-
}
|
|
446
|
-
if (options.endBefore) {
|
|
447
|
-
constraints.push(endBefore(options.endBefore));
|
|
448
|
-
}
|
|
449
|
-
if (options.endAt) {
|
|
450
|
-
constraints.push(endAt(options.endAt));
|
|
451
|
-
}
|
|
452
|
-
// Limit (se agrega al final)
|
|
453
|
-
if (options.limit) {
|
|
454
|
-
constraints.push(limit(options.limit));
|
|
455
|
-
}
|
|
456
|
-
return constraints;
|
|
457
|
-
}
|
|
458
|
-
/**
|
|
459
|
-
* Mapea un DocumentSnapshot a nuestro tipo
|
|
460
|
-
*/
|
|
461
|
-
mapDocument(snapshot) {
|
|
462
|
-
const data = snapshot.data();
|
|
463
|
-
if (!data) {
|
|
464
|
-
throw new Error('Documento no tiene datos');
|
|
465
|
-
}
|
|
466
|
-
return {
|
|
467
|
-
id: snapshot.id,
|
|
468
|
-
...this.convertTimestamps(data),
|
|
469
|
-
};
|
|
470
|
-
}
|
|
471
|
-
/**
|
|
472
|
-
* Convierte Timestamps de Firestore a Date de JavaScript
|
|
473
|
-
*/
|
|
474
|
-
convertTimestamps(data) {
|
|
475
|
-
const result = {};
|
|
476
|
-
for (const [key, value] of Object.entries(data)) {
|
|
477
|
-
if (value instanceof Timestamp) {
|
|
478
|
-
result[key] = value.toDate();
|
|
479
|
-
}
|
|
480
|
-
else if (value && typeof value === 'object' && !Array.isArray(value)) {
|
|
481
|
-
result[key] = this.convertTimestamps(value);
|
|
482
|
-
}
|
|
483
|
-
else {
|
|
484
|
-
result[key] = value;
|
|
485
|
-
}
|
|
486
|
-
}
|
|
487
|
-
return result;
|
|
488
|
-
}
|
|
489
|
-
/**
|
|
490
|
-
* Divide una ruta de documento en colección e ID
|
|
491
|
-
*/
|
|
492
|
-
splitPath(path) {
|
|
493
|
-
const segments = path.split('/');
|
|
494
|
-
if (segments.length < 2 || segments.length % 2 !== 0) {
|
|
495
|
-
throw new Error(`Ruta de documento inválida: ${path}`);
|
|
496
|
-
}
|
|
497
|
-
const docId = segments.pop();
|
|
498
|
-
const collectionPath = segments.join('/');
|
|
499
|
-
return [collectionPath, docId];
|
|
500
|
-
}
|
|
501
|
-
static { this.ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "18.2.14", ngImport: i0, type: FirestoreService, deps: [], target: i0.ɵɵFactoryTarget.Injectable }); }
|
|
502
|
-
static { this.ɵprov = i0.ɵɵngDeclareInjectable({ minVersion: "12.0.0", version: "18.2.14", ngImport: i0, type: FirestoreService, providedIn: 'root' }); }
|
|
503
|
-
}
|
|
504
|
-
i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "18.2.14", ngImport: i0, type: FirestoreService, decorators: [{
|
|
505
|
-
type: Injectable,
|
|
506
|
-
args: [{ providedIn: 'root' }]
|
|
507
|
-
}] });
|
|
508
|
-
//# sourceMappingURL=data:application/json;base64,eyJ2ZXJzaW9uIjozLCJmaWxlIjoiZmlyZXN0b3JlLnNlcnZpY2UuanMiLCJzb3VyY2VSb290IjoiIiwic291cmNlcyI6WyIuLi8uLi8uLi8uLi8uLi8uLi9zcmMvbGliL3NlcnZpY2VzL2ZpcmViYXNlL2ZpcmVzdG9yZS5zZXJ2aWNlLnRzIl0sIm5hbWVzIjpbXSwibWFwcGluZ3MiOiJBQUFBOzs7OztHQUtHO0FBRUgsT0FBTyxFQUFFLE1BQU0sRUFBRSxVQUFVLEVBQUUsTUFBTSxlQUFlLENBQUM7QUFDbkQsT0FBTyxFQUNMLE1BQU0sRUFDTixVQUFVLEVBQ1YsY0FBYyxFQUNkLFNBQVMsRUFDVCxHQUFHLEVBQ0gsT0FBTyxFQUlQLFNBQVMsRUFDVCxNQUFNLEVBQ04sT0FBTyxFQUNQLEtBQUssRUFDTCxPQUFPLEVBQ1AsS0FBSyxFQUVMLGVBQWUsRUFDZixNQUFNLEVBQ04sVUFBVSxFQUNWLE9BQU8sRUFDUCxTQUFTLEVBQ1QsS0FBSyxFQUNMLFNBQVMsRUFDVCxTQUFTLEVBQ1QsS0FBSyxFQUNMLFVBQVUsRUFDVixTQUFTLEVBQ1QsVUFBVSxFQUNWLFdBQVcsR0FFWixNQUFNLHlCQUF5QixDQUFDO0FBQ2pDLE9BQU8sRUFBRSxHQUFHLEVBQWMsTUFBTSxNQUFNLENBQUM7QUFHdkMsT0FBTyxFQUFFLFNBQVMsRUFBRSxNQUFNLHNCQUFzQixDQUFDOztBQUVqRDs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7R0FnQ0c7QUFFSCxNQUFNLE9BQU8sZ0JBQWdCO0lBRDdCO1FBRVUsY0FBUyxHQUFHLE1BQU0sQ0FBQyxTQUFTLENBQUMsQ0FBQztLQTRoQnZDO0lBMWhCQyw4RUFBOEU7SUFDOUUsOEJBQThCO0lBQzlCLDhFQUE4RTtJQUU5RTs7Ozs7Ozs7Ozs7Ozs7T0FjRztJQUNILEtBQUssQ0FBQyxNQUFNLENBQ1YsY0FBc0IsRUFDdEIsS0FBYTtRQUViLE1BQU0sTUFBTSxHQUFHLEdBQUcsQ0FBQyxJQUFJLENBQUMsU0FBUyxFQUFFLGNBQWMsRUFBRSxLQUFLLENBQUMsQ0FBQztRQUMxRCxN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LENBQUM7K0dBNWhCVSxnQkFBZ0I7bUhBQWhCLGdCQUFnQixjQURILE1BQU07OzRGQUNuQixnQkFBZ0I7a0JBRDVCLFVBQVU7bUJBQUMsRUFBRSxVQUFVLEVBQUUsTUFBTSxFQUFFIiwic291cmNlc0NvbnRlbnQiOlsiLyoqXG4gKiBGaXJlc3RvcmUgU2VydmljZVxuICpcbiAqIFNlcnZpY2lvIGdlbsOpcmljbyBwYXJhIG9wZXJhY2lvbmVzIENSVUQgZW4gRmlyZXN0b3JlLlxuICogU29wb3J0YSBsZWN0dXJhcyBvbmUtdGltZSwgc3Vic2NyaXBjaW9uZXMgcmVhbC10aW1lLCBwYWdpbmFjacOzbiB5IHF1ZXJpZXMgY29tcGxlamFzLlxuICovXG5cbmltcG9ydCB7IGluamVjdCwgSW5qZWN0YWJsZSB9IGZyb20gJ0Bhbmd1bGFyL2NvcmUnO1xuaW1wb3J0IHtcbiAgYWRkRG9jLFxuICBjb2xsZWN0aW9uLFxuICBjb2xsZWN0aW9uRGF0YSxcbiAgZGVsZXRlRG9jLFxuICBkb2MsXG4gIGRvY0RhdGEsXG4gIERvY3VtZW50RGF0YSxcbiAgRG9jdW1lbnRSZWZlcmVuY2UsXG4gIERvY3VtZW50U25hcHNob3QsXG4gIEZpcmVzdG9yZSxcbiAgZ2V0RG9jLFxuICBnZXREb2NzLFxuICBsaW1pdCxcbiAgb3JkZXJCeSxcbiAgcXVlcnksXG4gIFF1ZXJ5Q29uc3RyYWludCxcbiAgc2VydmVyVGltZXN0YW1wLFxuICBzZXREb2MsXG4gIHN0YXJ0QWZ0ZXIsXG4gIHN0YXJ0QXQsXG4gIGVuZEJlZm9yZSxcbiAgZW5kQXQsXG4gIFRpbWVzdGFtcCxcbiAgdXBkYXRlRG9jLFxuICB3aGVyZSxcbiAgd3JpdGVCYXRjaCxcbiAgaW5jcmVtZW50LFxuICBhcnJheVVuaW9uLFxuICBhcnJheVJlbW92ZSxcbiAgRmllbGRWYWx1ZSxcbn0gZnJvbSAnQGFuZ3VsYXIvZmlyZS9maXJlc3RvcmUnO1xuaW1wb3J0IHsgbWFwLCBPYnNlcnZhYmxlIH0gZnJvbSAncnhqcyc7XG5cbmltcG9ydCB7IEZpcmVzdG9yZURvY3VtZW50LCBQYWdpbmF0ZWRSZXN1bHQsIFF1ZXJ5T3B0aW9ucyB9IGZyb20gJy4vdHlwZXMnO1xuaW1wb3J0IHsgYnVpbGRQYXRoIH0gZnJvbSAnLi91dGlscy9wYXRoLWJ1aWxkZXInO1xuXG4vKipcbiAqIFNlcnZpY2lvIHBhcmEgb3BlcmFjaW9uZXMgQ1JVRCBlbiBGaXJlc3RvcmUuXG4gKlxuICogQGV4YW1wbGVcbiAqIGBgYHR5cGVzY3JpcHRcbiAqIGludGVyZmFjZSBVc2VyIGV4dGVuZHMgRmlyZXN0b3JlRG9jdW1lbnQge1xuICogICBuYW1lOiBzdHJpbmc7XG4gKiAgIGVtYWlsOiBzdHJpbmc7XG4gKiAgIHJvbGU6ICdhZG1pbicgfCAndXNlcic7XG4gKiB9XG4gKlxuICogQENvbXBvbmVudCh7Li4ufSlcbiAqIGV4cG9ydCBjbGFzcyBVc2Vyc0NvbXBvbmVudCB7XG4gKiAgIHByaXZhdGUgZmlyZXN0b3JlID0gaW5qZWN0KEZpcmVzdG9yZVNlcnZpY2UpO1xuICpcbiAqICAgLy8gTGVjdHVyYSBvbmUtdGltZVxuICogICBhc3luYyBsb2FkVXNlcihpZDogc3RyaW5nKSB7XG4gKiAgICAgY29uc3QgdXNlciA9IGF3YWl0IHRoaXMuZmlyZXN0b3JlLmdldERvYzxVc2VyPigndXNlcnMnLCBpZCk7XG4gKiAgIH1cbiAqXG4gKiAgIC8vIFN1YnNjcmlwY2nDs24gcmVhbC10aW1lXG4gKiAgIHVzZXJzJCA9IHRoaXMuZmlyZXN0b3JlLmNvbGxlY3Rpb25DaGFuZ2VzPFVzZXI+KCd1c2VycycsIHtcbiAqICAgICB3aGVyZTogW3sgZmllbGQ6ICdyb2xlJywgb3BlcmF0b3I6ICc9PScsIHZhbHVlOiAnYWRtaW4nIH1dLFxuICogICAgIG9yZGVyQnk6IFt7IGZpZWxkOiAnbmFtZScsIGRpcmVjdGlvbjogJ2FzYycgfV1cbiAqICAgfSk7XG4gKlxuICogICAvLyBDcmVhciBkb2N1bWVudG9cbiAqICAgYXN5bmMgY3JlYXRlVXNlcihkYXRhOiBPbWl0PFVzZXIsICdpZCc+KSB7XG4gKiAgICAgY29uc3QgdXNlciA9IGF3YWl0IHRoaXMuZmlyZXN0b3JlLmFkZERvYzxVc2VyPigndXNlcnMnLCBkYXRhKTtcbiAqICAgfVxuICogfVxuICogYGBgXG4gKi9cbkBJbmplY3RhYmxlKHsgcHJvdmlkZWRJbjogJ3Jvb3QnIH0pXG5leHBvcnQgY2xhc3MgRmlyZXN0b3JlU2VydmljZSB7XG4gIHByaXZhdGUgZmlyZXN0b3JlID0gaW5qZWN0KEZpcmVzdG9yZSk7XG5cbiAgLy8gPT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09XG4gIC8vIExFQ1RVUkFTIE9ORS1USU1FIChQcm9taXNlKVxuICAvLyA9PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT1cblxuICAvKipcbiAgICogT2J0aWVuZSB1biBkb2N1bWVudG8gcG9yIElEIChsZWN0dXJhIMO6bmljYSkuXG4gICAqXG4gICAqIEBwYXJhbSBjb2xsZWN0aW9uUGF0aCAtIFJ1dGEgZGUgbGEgY29sZWNjacOzblxuICAgKiBAcGFyYW0gZG9jSWQgLSBJRCBkZWwgZG9jdW1lbnRvXG4gICAqIEByZXR1cm5zIERvY3VtZW50byBvIG51bGwgc2kgbm8gZXhpc3RlXG4gICAqXG4gICAqIEBleGFtcGxlXG4gICAqIGBgYHR5cGVzY3JpcHRcbiAgICogY29uc3QgdXNlciA9IGF3YWl0IGZpcmVzdG9yZVNlcnZpY2UuZ2V0RG9jPFVzZXI+KCd1c2VycycsICdhYmMxMjMnKTtcbiAgICogaWYgKHVzZXIpIHtcbiAgICogICBjb25zb2xlLmxvZyh1c2VyLm5hbWUpO1xuICAgKiB9XG4gICAqIGBgYFxuICAgKi9cbiAgYXN5bmMgZ2V0RG9jPFQgZXh0ZW5kcyBGaXJlc3RvcmVEb2N1bWVudD4oXG4gICAgY29sbGVjdGlvblBhdGg6IHN0cmluZyxcbiAgICBkb2NJZDogc3RyaW5nXG4gICk6IFByb21pc2U8VCB8IG51bGw+IHtcbiAgICBjb25zdCBkb2NSZWYgPSBkb2ModGhpcy5maXJlc3RvcmUsIGNvbGxlY3Rpb25QYXRoLCBkb2NJZCk7XG4gICAgY29uc3Qgc25hcHNob3QgPSBhd2FpdCBnZXREb2MoZG9jUmVmKTtcblxuICAgIGlmICghc25hcHNob3QuZXhpc3RzKCkpIHtcbiAgICAgIHJldHVybiBudWxsO1xuICAgIH1cblxuICAgIHJldHVybiB0aGlzLm1hcERvY3VtZW50PFQ+KHNuYXBzaG90KTtcbiAgfVxuXG4gIC8qKlxuICAgKiBPYnRpZW5lIG3Dumx0aXBsZXMgZG9jdW1lbnRvcyBjb24gb3BjaW9uZXMgZGUgcXVlcnkuXG4gICAqXG4gICAqIEBwYXJhbSBjb2xsZWN0aW9uUGF0aCAtIFJ1dGEgZGUgbGEgY29sZWNjacOzblxuICAgKiBAcGFyYW0gb3B0aW9ucyAtIE9wY2lvbmVzIGRlIHF1ZXJ5ICh3aGVyZSwgb3JkZXJCeSwgbGltaXQpXG4gICAqIEByZXR1cm5zIEFycmF5IGRlIGRvY3VtZW50b3NcbiAgICpcbiAgICogQGV4YW1wbGVcbiAgICogYGBgdHlwZXNjcmlwdFxuICAgKiAvLyBUb2RvcyBsb3MgdXN1YXJpb3MgYWN0aXZvcyBvcmRlbmFkb3MgcG9yIG5vbWJyZVxuICAgKiBjb25zdCB1c2VycyA9IGF3YWl0IGZpcmVzdG9yZVNlcnZpY2UuZ2V0RG9jczxVc2VyPigndXNlcnMnLCB7XG4gICAqICAgd2hlcmU6IFt7IGZpZWxkOiAnYWN0aXZlJywgb3BlcmF0b3I6ICc9PScsIHZhbHVlOiB0cnVlIH1dLFxuICAgKiAgIG9yZGVyQnk6IFt7IGZpZWxkOiAnbmFtZScsIGRpcmVjdGlvbjogJ2FzYycgfV0sXG4gICAqICAgbGltaXQ6IDUwXG4gICAqIH0pO1xuICAgKiBgYGBcbiAgICovXG4gIGFzeW5jIGdldERvY3M8VCBleHRlbmRzIEZpcmVzdG9yZURvY3VtZW50PihcbiAgICBjb2xsZWN0aW9uUGF0aDogc3RyaW5nLFxuICAgIG9wdGlvbnM/OiBRdWVyeU9wdGlvbnNcbiAgKTogUHJvbWlzZTxUW10+IHtcbiAgICBjb25zdCBjb2xsZWN0aW9uUmVmID0gY29sbGVjdGlvbih0aGlzLmZpcmVzdG9yZSwgY29sbGVjdGlvblBhdGgpO1xuICAgIGNvbnN0IGNvbnN0cmFpbnRzID0gdGhpcy5idWlsZFF1ZXJ5Q29uc3RyYWludHMob3B0aW9ucyk7XG4gICAgY29uc3QgcSA9IHF1ZXJ5KGNvbGxlY3Rpb25SZWYsIC4uLmNvbnN0cmFpbnRzKTtcbiAgICBjb25zdCBzbmFwc2hvdCA9IGF3YWl0IGdldERvY3MocSk7XG5cbiAgICByZXR1cm4gc25hcHNob3QuZG9jcy5tYXAoKGRvYykgPT4gdGhpcy5tYXBEb2N1bWVudDxUPihkb2MpKTtcbiAgfVxuXG4gIC8qKlxuICAgKiBPYnRpZW5lIGRvY3VtZW50b3MgY29uIHBhZ2luYWNpw7NuIGJhc2FkYSBlbiBjdXJzb3Jlcy5cbiAgICpcbiAgICogQHBhcmFtIGNvbGxlY3Rpb25QYXRoIC0gUnV0YSBkZSBsYSBjb2xlY2Npw7NuXG4gICAqIEBwYXJhbSBvcHRpb25zIC0gT3BjaW9uZXMgZGUgcXVlcnkgKGRlYmUgaW5jbHVpciBsaW1pdClcbiAgICogQHJldHVybnMgUmVzdWx0YWRvIHBhZ2luYWRvIGNvbiBjdXJzb3IgcGFyYSBsYSBzaWd1aWVudGUgcMOhZ2luYVxuICAgKlxuICAgKiBAZXhhbXBsZVxuICAgKiBgYGB0eXBlc2NyaXB0XG4gICAqIC8vIFByaW1lcmEgcMOhZ2luYVxuICAgKiBjb25zdCBwYWdlMSA9IGF3YWl0IGZpcmVzdG9yZVNlcnZpY2UuZ2V0UGFnaW5hdGVkPFVzZXI+KCd1c2VycycsIHtcbiAgICogICBvcmRlckJ5OiBbeyBmaWVsZDogJ2NyZWF0ZWRBdCcsIGRpcmVjdGlvbjogJ2Rlc2MnIH1dLFxuICAgKiAgIGxpbWl0OiAxMFxuICAgKiB9KTtcbiAgICpcbiAgICogLy8gU2lndWllbnRlIHDDoWdpbmFcbiAgICogaWYgKHBhZ2UxLmhhc01vcmUpIHtcbiAgICogICBjb25zdCBwYWdlMiA9IGF3YWl0IGZpcmVzdG9yZVNlcnZpY2UuZ2V0UGFnaW5hdGVkPFVzZXI+KCd1c2VycycsIHtcbiAgICogICAgIG9yZGVyQnk6IFt7IGZpZWxkOiAnY3JlYXRlZEF0JywgZGlyZWN0aW9uOiAnZGVzYycgfV0sXG4gICAqICAgICBsaW1pdDogMTAsXG4gICAqICAgICBzdGFydEFmdGVyOiBwYWdlMS5sYXN0RG9jXG4gICAqICAgfSk7XG4gICAqIH1cbiAgICogYGBgXG4gICAqL1xuICBhc3luYyBnZXRQYWdpbmF0ZWQ8VCBleHRlbmRzIEZpcmVzdG9yZURvY3VtZW50PihcbiAgICBjb2xsZWN0aW9uUGF0aDogc3RyaW5nLFxuICAgIG9wdGlvbnM6IFF1ZXJ5T3B0aW9ucyAmIHsgbGltaXQ6IG51bWJlciB9XG4gICk6IFByb21pc2U8UGFnaW5hdGVkUmVzdWx0PFQ+PiB7XG4gICAgY29uc3QgY29sbGVjdGlvblJlZiA9IGNvbGxlY3Rpb24odGhpcy5maXJlc3RvcmUsIGNvbGxlY3Rpb25QYXRoKTtcbiAgICBjb25zdCBjb25zdHJhaW50cyA9IHRoaXMuYnVpbGRRdWVyeUNvbnN0cmFpbnRzKG9wdGlvbnMpO1xuXG4gICAgLy8gUGVkaXIgdW5vIG3DoXMgcGFyYSBzYWJlciBzaSBoYXkgbcOhcyBww6FnaW5hc1xuICAgIGNvbnN0IHEgPSBxdWVyeShjb2xsZWN0aW9uUmVmLCAuLi5jb25zdHJhaW50cywgbGltaXQob3B0aW9ucy5saW1pdCArIDEpKTtcbiAgICBjb25zdCBzbmFwc2hvdCA9IGF3YWl0IGdldERvY3MocSk7XG5cbiAgICBjb25zdCBkb2NzID0gc25hcHNob3QuZG9jcztcbiAgICBjb25zdCBoYXNNb3JlID0gZG9jcy5sZW5ndGggPiBvcHRpb25zLmxpbWl0O1xuXG4gICAgLy8gU2kgaGF5IG3DoXMsIHJlbW92ZXIgZWwgZG9jdW1lbnRvIGV4dHJhXG4gICAgY29uc3QgcmVzdWx0RG9jcyA9IGhhc01vcmUgPyBkb2NzLnNsaWNlKDAsIC0xKSA6IGRvY3M7XG4gICAgY29uc3QgbGFzdERvYyA9IHJlc3VsdERvY3MubGVuZ3RoID4gMCA/IHJlc3VsdERvY3NbcmVzdWx0RG9jcy5sZW5ndGggLSAxXSA6IG51bGw7XG5cbiAgICByZXR1cm4ge1xuICAgICAgZGF0YTogcmVzdWx0RG9jcy5tYXAoKGRvYykgPT4gdGhpcy5tYXBEb2N1bWVudDxUPihkb2MpKSxcbiAgICAgIGhhc01vcmUsXG4gICAgICBsYXN0RG9jLFxuICAgIH07XG4gIH1cblxuICAvKipcbiAgICogVmVyaWZpY2Egc2kgdW4gZG9jdW1lbnRvIGV4aXN0ZS5cbiAgICpcbiAgICogQHBhcmFtIGNvbGxlY3Rpb25QYXRoIC0gUnV0YSBkZSBsYSBjb2xlY2Npw7NuXG4gICAqIEBwYXJhbSBkb2NJZCAtIElEIGRlbCBkb2N1bWVudG9cbiAgICogQHJldHVybnMgdHJ1ZSBzaSBlbCBkb2N1bWVudG8gZXhpc3RlXG4gICAqL1xuICBhc3luYyBleGlzdHMoY29sbGVjdGlvblBhdGg6IHN0cmluZywgZG9jSWQ6IHN0cmluZyk6IFByb21pc2U8Ym9vbGVhbj4ge1xuICAgIGNvbnN0IGRvY1JlZiA9IGRvYyh0aGlzLmZpcmVzdG9yZSwgY29sbGVjdGlvblBhdGgsIGRvY0lkKTtcbiAgICBjb25zdCBzbmFwc2hvdCA9IGF3YWl0IGdldERvYyhkb2NSZWYpO1xuICAgIHJldHVybiBzbmFwc2hvdC5leGlzdHMoKTtcbiAgfVxuXG4gIC8vID09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PVxuICAvLyBTVUJTQ1JJUENJT05FUyBSRUFMLVRJTUUgKE9ic2VydmFibGUpXG4gIC8vID09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PVxuXG4gIC8qKlxuICAgKiBTdXNjcmliZSBhIGNhbWJpb3MgZGUgdW4gZG9jdW1lbnRvIChyZWFsLXRpbWUpLlxuICAgKlxuICAgKiBAcGFyYW0gY29sbGVjdGlvblBhdGggLSBSdXRhIGRlIGxhIGNvbGVjY2nDs25cbiAgICogQHBhcmFtIGRvY0lkIC0gSUQgZGVsIGRvY3VtZW50b1xuICAgKiBAcmV0dXJucyBPYnNlcnZhYmxlIHF1ZSBlbWl0ZSBjdWFuZG8gZWwgZG9jdW1lbnRvIGNhbWJpYVxuICAgKlxuICAgKiBAZXhhbXBsZVxuICAgKiBgYGB0eXBlc2NyaXB0XG4gICAqIC8vIEVuIGVsIGNvbXBvbmVudGVcbiAgICogdXNlciQgPSB0aGlzLmZpcmVzdG9yZVNlcnZpY2UuZG9jQ2hhbmdlczxVc2VyPigndXNlcnMnLCB0aGlzLnVzZXJJZCk7XG4gICAqXG4gICAqIC8vIEVuIGVsIHRlbXBsYXRlXG4gICAqIEBpZiAodXNlciQgfCBhc3luYzsgYXMgdXNlcikge1xuICAgKiAgIDxwPnt7IHVzZXIubmFtZSB9fTwvcD5cbiAgICogfVxuICAgKiBgYGBcbiAgICovXG4gIGRvY0NoYW5nZXM8VCBleHRlbmRzIEZpcmVzdG9yZURvY3VtZW50PihcbiAgICBjb2xsZWN0aW9uUGF0aDogc3RyaW5nLFxuICAgIGRvY0lkOiBzdHJpbmdcbiAgKTogT2JzZXJ2YWJsZTxUIHwgbnVsbD4ge1xuICAgIGNvbnN0IGRvY1JlZiA9IGRvYyh0aGlzLmZpcmVzdG9yZSwgY29sbGVjdGlvblBhdGgsIGRvY0lkKTtcbiAgICByZXR1cm4gZG9jRGF0YShkb2NSZWYsIHsgaWRGaWVsZDogJ2lkJyB9KS5waXBlKFxuICAgICAgbWFwKChkYXRhKSA9PiB7XG4gICAgICAgIGlmICghZGF0YSkgcmV0dXJuIG51bGw7XG4gICAgICAgIHJldHVybiB0aGlzLmNvbnZlcnRUaW1lc3RhbXBzKGRhdGEgYXMgRG9jdW1lbnREYXRhKSBhcyBUO1xuICAgICAgfSlcbiAgICApO1xuICB9XG5cbiAgLyoqXG4gICAqIFN1c2NyaWJlIGEgY2FtYmlvcyBkZSB1bmEgY29sZWNjacOzbiAocmVhbC10aW1lKS5cbiAgICpcbiAgICogQHBhcmFtIGNvbGxlY3Rpb25QYXRoIC0gUnV0YSBkZSBsYSBjb2xlY2Npw7NuXG4gICAqIEBwYXJhbSBvcHRpb25zIC0gT3BjaW9uZXMgZGUgcXVlcnlcbiAgICogQHJldHVybnMgT2JzZXJ2YWJsZSBxdWUgZW1pdGUgY3VhbmRvIGxhIGNvbGVjY2nDs24gY2FtYmlhXG4gICAqXG4gICAqIEBleGFtcGxlXG4gICAqIGBgYHR5cGVzY3JpcHRcbiAgICogLy8gVXN1YXJpb3MgYWN0aXZvcyBlbiB0aWVtcG8gcmVhbFxuICAgKiBhY3RpdmVVc2VycyQgPSB0aGlzLmZpcmVzdG9yZVNlcnZpY2UuY29sbGVjdGlvbkNoYW5nZXM8VXNlcj4oJ3VzZXJzJywge1xuICAgKiAgIHdoZXJlOiBbeyBmaWVsZDogJ3N0YXR1cycsIG9wZXJhdG9yOiAnPT0nLCB2YWx1ZTogJ29ubGluZScgfV1cbiAgICogfSk7XG4gICAqIGBgYFxuICAgKi9cbiAgY29sbGVjdGlvbkNoYW5nZXM8VCBleHRlbmRzIEZpcmVzdG9yZURvY3VtZW50PihcbiAgICBjb2xsZWN0aW9uUGF0aDogc3RyaW5nLFxuICAgIG9wdGlvbnM/OiBRdWVyeU9wdGlvbnNcbiAgKTogT2JzZXJ2YWJsZTxUW10+IHtcbiAgICBjb25zdCBjb2xsZWN0aW9uUmVmID0gY29sbGVjdGlvbih0aGlzLmZpcmVzdG9yZSwgY29sbGVjdGlvblBhdGgpO1xuICAgIGNvbnN0IGNvbnN0cmFpbnRzID0gdGhpcy5idWlsZFF1ZXJ5Q29uc3RyYWludHMob3B0aW9ucyk7XG4gICAgY29uc3QgcSA9IHF1ZXJ5KGNvbGxlY3Rpb25SZWYsIC4uLmNvbnN0cmFpbnRzKTtcblxuICAgIHJldHVybiBjb2xsZWN0aW9uRGF0YShxLCB7IGlkRmllbGQ6ICdpZCcgfSkucGlwZShcbiAgICAgIG1hcCgoZG9jcykgPT4gZG9jcy5tYXAoKGRvYykgPT4gdGhpcy5jb252ZXJ0VGltZXN0YW1wcyhkb2MpIGFzIFQpKVxuICAgICk7XG4gIH1cblxuICAvLyA9PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT1cbiAgLy8gRVNDUklUVVJBXG4gIC8vID09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PVxuXG4gIC8qKlxuICAgKiBBZ3JlZ2EgdW4gZG9jdW1lbnRvIGNvbiBJRCBhdXRvLWdlbmVyYWRvLlxuICAgKlxuICAgKiBAcGFyYW0gY29sbGVjdGlvblBhdGggLSBSdXRhIGRlIGxhIGNvbGVjY2nDs25cbiAgICogQHBhcmFtIGRhdGEgLSBEYXRvcyBkZWwgZG9jdW1lbnRvIChzaW4gaWQsIGNyZWF0ZWRBdCwgdXBkYXRlZEF0KVxuICAgKiBAcmV0dXJucyBEb2N1bWVudG8gY3JlYWRvIGNvbiBzdSBJRFxuICAgKlxuICAgKiBAZXhhbXBsZVxuICAgKiBgYGB0eXBlc2NyaXB0XG4gICAqIGNvbnN0IG5ld1VzZXIgPSBhd2FpdCBmaXJlc3RvcmVTZXJ2aWNlLmFkZERvYzxVc2VyPigndXNlcnMnLCB7XG4gICAqICAgbmFtZTogJ0pvaG4gRG9lJyxcbiAgICogICBlbWFpbDogJ2pvaG5AZXhhbXBsZS5jb20nLFxuICAgKiAgIHJvbGU6ICd1c2VyJ1xuICAgKiB9KTtcbiAgICogY29uc29sZS5sb2coJ0NyZWF0ZWQgdXNlciB3aXRoIElEOicsIG5ld1VzZXIuaWQpO1xuICAgKiBgYGBcbiAgICovXG4gIGFzeW5jIGFkZERvYzxUIGV4dGVuZHMgRmlyZXN0b3JlRG9jdW1lbnQ+KFxuICAgIGNvbGxlY3Rpb25QYXRoOiBzdHJpbmcsXG4gICAgZGF0YTogT21pdDxULCAnaWQnIHwgJ2NyZWF0ZWRBdCcgfCAndXBkYXRlZEF0Jz5cbiAgKTogUHJvbWlzZTxUPiB7XG4gICAgY29uc3QgY29sbGVjdGlvblJlZiA9IGNvbGxlY3Rpb24odGhpcy5maXJlc3RvcmUsIGNvbGxlY3Rpb25QYXRoKTtcbiAgICBjb25zdCB0aW1lc3RhbXAgPSBzZXJ2ZXJUaW1lc3RhbXAoKTtcblxuICAgIGNvbnN0IGRvY0RhdGEgPSB7XG4gICAgICAuLi5kYXRhLFxuICAgICAgY3JlYXRlZEF0OiB0aW1lc3RhbXAsXG4gICAgICB1cGRhdGVkQXQ6IHRpbWVzdGFtcCxcbiAgICB9O1xuXG4gICAgY29uc3QgZG9jUmVmID0gYXdhaXQgYWRkRG9jKGNvbGxlY3Rpb25SZWYsIGRvY0RhdGEpO1xuXG4gICAgLy8gT2J0ZW5lciBlbCBkb2N1bWVudG8gY3JlYWRvIHBhcmEgcmV0b3JuYXJsbyBjb24gdGltZXN0YW1wcyByZXN1ZWx0b3NcbiAgICBjb25zdCBzbmFwc2hvdCA9IGF3YWl0IGdldERvYyhkb2NSZWYpO1xuICAgIHJldHVybiB0aGlzLm1hcERvY3VtZW50PFQ+KHNuYXBzaG90KTtcbiAgfVxuXG4gIC8qKlxuICAgKiBDcmVhIG8gc29icmVzY3JpYmUgdW4gZG9jdW1lbnRvIGNvbiBJRCBlc3BlY8OtZmljby5cbiAgICpcbiAgICogQHBhcmFtIGNvbGxlY3Rpb25QYXRoIC0gUnV0YSBkZSBsYSBjb2xlY2Npw7NuXG4gICAqIEBwYXJhbSBkb2NJZCAtIElEIGRlbCBkb2N1bWVudG9cbiAgICogQHBhcmFtIGRhdGEgLSBEYXRvcyBkZWwgZG9jdW1lbnRvXG4gICAqIEBwYXJhbSBvcHRpb25zIC0gT3BjaW9uZXMgKG1lcmdlOiB0cnVlIHBhcmEgbWVyZ2UgZW4gbHVnYXIgZGUgc29icmVzY3JpYmlyKVxuICAgKlxuICAgKiBAZXhhbXBsZVxuICAgKiBgYGB0eXBlc2NyaXB0XG4gICAqIC8vIFNvYnJlc2NyaWJpciBjb21wbGV0YW1lbnRlXG4gICAqIGF3YWl0IGZpcmVzdG9yZVNlcnZpY2Uuc2V0RG9jPFVzZXI+KCd1c2VycycsICd1c2VyMTIzJywgdXNlckRhdGEpO1xuICAgKlxuICAgKiAvLyBNZXJnZSBjb24gZGF0b3MgZXhpc3RlbnRlc1xuICAgKiBhd2FpdCBmaXJlc3RvcmVTZXJ2aWNlLnNldERvYzxVc2VyPigndXNlcnMnLCAndXNlcjEyMycsIHsgbmFtZTogJ05ldyBOYW1lJyB9LCB7IG1lcmdlOiB0cnVlIH0pO1xuICAgKiBgYGBcbiAgICovXG4gIGFzeW5jIHNldERvYzxUIGV4dGVuZHMgRmlyZXN0b3JlRG9jdW1lbnQ+KFxuICAgIGNvbGxlY3Rpb25QYXRoOiBzdHJpbmcsXG4gICAgZG9jSWQ6IHN0cmluZyxcbiAgICBkYXRhOiBPbWl0PFQsICdpZCc+LFxuICAgIG9wdGlvbnM/OiB7IG1lcmdlPzogYm9vbGVhbiB9XG4gICk6IFByb21pc2U8dm9pZD4ge1xuICAgIGNvbnN0IGRvY1JlZiA9IGRvYyh0aGlzLmZpcmVzdG9yZSwgY29sbGVjdGlvblBhdGgsIGRvY0lkKTtcbiAgICBjb25zdCB0aW1lc3RhbXAgPSBzZXJ2ZXJUaW1lc3RhbXAoKTtcblxuICAgIGNvbnN0IGRvY0RhdGEgPSB7XG4gICAgICAuLi5kYXRhLFxuICAgICAgdXBkYXRlZEF0OiB0aW1lc3RhbXAsXG4gICAgICAuLi4ob3B0aW9ucz8ubWVyZ2UgPyB7fSA6IHsgY3JlYXRlZEF0OiB0aW1lc3RhbXAgfSksXG4gICAgfTtcblxuICAgIGF3YWl0IHNldERvYyhkb2NSZWYsIGRvY0RhdGEsIHsgbWVyZ2U6IG9wdGlvbnM/Lm1lcmdlID8/IGZhbHNlIH0pO1xuICB9XG5cbiAgLyoqXG4gICAqIEFjdHVhbGl6YSBjYW1wb3MgZXNwZWPDrWZpY29zIGRlIHVuIGRvY3VtZW50by5cbiAgICpcbiAgICogQHBhcmFtIGNvbGxlY3Rpb25QYXRoIC0gUnV0YSBkZSBsYSBjb2xlY2Npw7NuXG4gICAqIEBwYXJhbSBkb2NJZCAtIElEIGRlbCBkb2N1bWVudG9cbiAgICogQHBhcmFtIGRhdGEgLSBDYW1wb3MgYSBhY3R1YWxpemFyXG4gICAqXG4gICAqIEBleGFtcGxlXG4gICAqIGBgYHR5cGVzY3JpcHRcbiAgICogYXdhaXQgZmlyZXN0b3JlU2VydmljZS51cGRhdGVEb2M8VXNlcj4oJ3VzZXJzJywgJ3VzZXIxMjMnLCB7XG4gICAqICAgbmFtZTogJ1VwZGF0ZWQgTmFtZScsXG4gICAqICAgbGFzdExvZ2luOiBuZXcgRGF0ZSgpXG4gICAqIH0pO1xuICAgKiBgYGBcbiAgICovXG4gIGFzeW5jIHVwZGF0ZURvYzxUIGV4dGVuZHMgRmlyZXN0b3JlRG9jdW1lbnQ+KFxuICAgIGNvbGxlY3Rpb25QYXRoOiBzdHJpbmcsXG4gICAgZG9jSWQ6IHN0cmluZyxcbiAgICBkYXRhOiBQYXJ0aWFsPE9taXQ8VCwgJ2lkJyB8ICdjcmVhdGVkQXQnPj5cbiAgKTogUHJvbWlzZTx2b2lkPiB7XG4gICAgY29uc3QgZG9jUmVmID0gZG9jKHRoaXMuZmlyZXN0b3JlLCBjb2xsZWN0aW9uUGF0aCwgZG9jSWQpO1xuXG4gICAgYXdhaXQgdXBkYXRlRG9jKGRvY1JlZiwge1xuICAgICAgLi4uZGF0YSxcbiAgICAgIHVwZGF0ZWRBdDogc2VydmVyVGltZXN0YW1wKCksXG4gICAgfSk7XG4gIH1cblxuICAvKipcbiAgICogRWxpbWluYSB1biBkb2N1bWVudG8uXG4gICAqXG4gICAqIEBwYXJhbSBjb2xsZWN0aW9uUGF0aCAtIFJ1dGEgZGUgbGEgY29sZWNjacOzblxuICAgKiBAcGFyYW0gZG9jSWQgLSBJRCBkZWwgZG9jdW1lbnRvXG4gICAqXG4gICAqIEBleGFtcGxlXG4gICAqIGBgYHR5cGVzY3JpcHRcbiAgICogYXdhaXQgZmlyZXN0b3JlU2VydmljZS5kZWxldGVEb2MoJ3VzZXJzJywgJ3VzZXIxMjMnKTtcbiAgICogYGBgXG4gICAqL1xuICBhc3luYyBkZWxldGVEb2MoY29sbGVjdGlvblBhdGg6IHN0cmluZywgZG9jSWQ6IHN0cmluZyk6IFByb21pc2U8dm9pZD4ge1xuICAgIGNvbnN0IGRvY1JlZiA9IGRvYyh0aGlzLmZpcmVzdG9yZSwgY29sbGVjdGlvblBhdGgsIGRvY0lkKTtcbiAgICBhd2FpdCBkZWxldGVEb2MoZG9jUmVmKTtcbiAgfVxuXG4gIC8vID09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PVxuICAvLyBPUEVSQUNJT05FUyBFTiBMT1RFXG4gIC8vID09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PVxuXG4gIC8qKlxuICAgKiBFamVjdXRhIG3Dumx0aXBsZXMgb3BlcmFjaW9uZXMgZGUgZXNjcml0dXJhIGRlIGZvcm1hIGF0w7NtaWNhLlxuICAgKlxuICAgKiBAcGFyYW0gb3BlcmF0aW9ucyAtIEZ1bmNpw7NuIHF1ZSByZWNpYmUgZWwgYmF0Y2ggeSBhZ3JlZ2Egb3BlcmFjaW9uZXNcbiAgICpcbiAgICogQGV4YW1wbGVcbiAgICogYGBgdHlwZXNjcmlwdFxuICAgKiBhd2FpdCBmaXJlc3RvcmVTZXJ2aWNlLmJhdGNoKChiYXRjaCkgPT4ge1xuICAgKiAgIGJhdGNoLnNldCgndXNlcnMvdXNlcjEnLCB7IG5hbWU6ICdVc2VyIDEnIH0pO1xuICAgKiAgIGJhdGNoLnVwZGF0ZSgndXNlcnMvdXNlcjInLCB7IHN0YXR1czogJ2luYWN0aXZlJyB9KTtcbiAgICogICBiYXRjaC5kZWxldGUoJ3VzZXJzL3VzZXIzJyk7XG4gICAqIH0pO1xuICAgKiBgYGBcbiAgICovXG4gIGFzeW5jIGJhdGNoKFxuICAgIG9wZXJhdGlvbnM6IChiYXRjaDoge1xuICAgICAgc2V0OiA8VD4ocGF0aDogc3RyaW5nLCBkYXRhOiBUKSA9PiB2b2lkO1xuICAgICAgdXBkYXRlOiA8VD4ocGF0aDogc3RyaW5nLCBkYXRhOiBQYXJ0aWFsPFQ+KSA9PiB2b2lkO1xuICAgICAgZGVsZXRlOiAocGF0aDogc3RyaW5nKSA9PiB2b2lkO1xuICAgIH0pID0+IHZvaWRcbiAgKTogUHJvbWlzZTx2b2lkPiB7XG4gICAgY29uc3QgYmF0Y2ggPSB3cml0ZUJhdGNoKHRoaXMuZmlyZXN0b3JlKTtcblxuICAgIGNvbnN0IGJhdGNoQXBpID0ge1xuICAgICAgc2V0OiA8VD4ocGF0aDogc3RyaW5nLCBkYXRhOiBUKSA9PiB7XG4gICAgICAgIGNvbnN0IFtjb2xsZWN0aW9uUGF0aCwgZG9jSWRdID0gdGhpcy5zcGxpdFBhdGgocGF0aCk7XG4gICAgICAgIGNvbnN0IGRvY1JlZiA9IGRvYyh0aGlzLmZpcmVzdG9yZSwgY29sbGVjdGlvblBhdGgsIGRvY0lkKTtcbiAgICAgICAgYmF0Y2guc2V0KGRvY1JlZiwge1xuICAgICAgICAgIC4uLmRhdGEsXG4gICAgICAgICAgY3JlYXRlZEF0OiBzZXJ2ZXJUaW1lc3RhbXAoKSxcbiAgICAgICAgICB1cGRhdGVkQXQ6IHNlcnZlclRpbWVzdGFtcCgpLFxuICAgICAgICB9IGFzIERvY3VtZW50RGF0YSk7XG4gICAgICB9LFxuICAgICAgdXBkYXRlOiA8VD4ocGF0aDogc3RyaW5nLCBkYXRhOiBQYXJ0aWFsPFQ+KSA9PiB7XG4gICAgICAgIGNvbnN0IFtjb2xsZWN0aW9uUGF0aCwgZG9jSWRdID0gdGhpcy5zcGxpdFBhdGgocGF0aCk7XG4gICAgICAgIGNvbnN0IGRvY1JlZiA9IGRvYyh0aGlzLmZpcmVzdG9yZSwgY29sbGVjdGlvblBhdGgsIGRvY0lkKTtcbiAgICAgICAgYmF0Y2gudXBkYXRlKGRvY1JlZiwge1xuICAgICAgICAgIC4uLmRhdGEsXG4gICAgICAgICAgdXBkYXRlZEF0OiBzZXJ2ZXJUaW1lc3RhbXAoKSxcbiAgICAgICAgfSBhcyBEb2N1bWVudERhdGEpO1xuICAgICAgfSxcbiAgICAgIGRlbGV0ZTogKHBhdGg6IHN0cmluZykgPT4ge1xuICAgICAgICBjb25zdCBbY29sbGVjdGlvblBhdGgsIGRvY0lkXSA9IHRoaXMuc3BsaXRQYXRoKHBhdGgpO1xuICAgICAgICBjb25zdCBkb2NSZWYgPSBkb2ModGhpcy5maXJlc3RvcmUsIGNvbGxlY3Rpb25QYXRoLCBkb2NJZCk7XG4gICAgICAgIGJhdGNoLmRlbGV0ZShkb2NSZWYpO1xuICAgICAgfSxcbiAgICB9O1xuXG4gICAgb3BlcmF0aW9ucyhiYXRjaEFwaSk7XG4gICAgYXdhaXQgYmF0Y2guY29tbWl0KCk7XG4gIH1cblxuICAvLyA9PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT1cbiAgLy8gVVRJTElEQURFU1xuICAvLyA9PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT1cblxuICAvKipcbiAgICogQ29uc3RydXllIHVuYSBydXRhIGEgcGFydGlyIGRlIHVuIHRlbXBsYXRlLlxuICAgKlxuICAgKiBAcGFyYW0gdGVtcGxhdGUgLSBUZW1wbGF0ZSBjb24gcGxhY2Vob2xkZXJzIHtwYXJhbX1cbiAgICogQHBhcmFtIHBhcmFtcyAtIFZhbG9yZXMgcGFyYSBsb3MgcGxhY2Vob2xkZXJzXG4gICAqIEByZXR1cm5zIFJ1dGEgY29uc3RydWlkYVxuICAgKlxuICAgKiBAZXhhbXBsZVxuICAgKiBgYGB0eXBlc2NyaXB0XG4gICAqIGNvbnN0IHBhdGggPSBmaXJlc3RvcmVTZXJ2aWNlLmJ1aWxkUGF0aCgndXNlcnMve3VzZXJJZH0vZG9jdW1lbnRzL3tkb2NJZH0nLCB7XG4gICAqICAgdXNlcklkOiAndXNlcjEyMycsXG4gICAqICAgZG9jSWQ6ICdkb2M0NTYnXG4gICAqIH0pO1xuICAgKiAvLyA9PiAndXNlcnMvdXNlcjEyMy9kb2N1bWVudHMvZG9jNDU2J1xuICAgKiBgYGBcbiAgICovXG4gIGJ1aWxkUGF0aCh0ZW1wbGF0ZTogc3RyaW5nLCBwYXJhbXM6IFJlY29yZDxzdHJpbmcsIHN0cmluZz4pOiBzdHJpbmcge1xuICAgIHJldHVybiBidWlsZFBhdGgodGVtcGxhdGUsIHBhcmFtcyk7XG4gIH1cblxuICAvKipcbiAgICogR2VuZXJhIHVuIElEIMO6bmljbyBwYXJhIHVuIGRvY3VtZW50byAoc2luIGNyZWFybG8pLlxuICAgKlxuICAgKiBAcGFyYW0gY29sbGVjdGlvblBhdGggLSBSdXRhIGRlIGxhIGNvbGVjY2nDs25cbiAgICogQHJldHVybnMgSUQgw7puaWNvIGdlbmVyYWRvIHBvciBGaXJlc3RvcmVcbiAgICovXG4gIGdlbmVyYXRlSWQoY29sbGVjdGlvblBhdGg6IHN0cmluZyk6IHN0cmluZyB7XG4gICAgY29uc3QgY29sbGVjdGlvblJlZiA9IGNvbGxlY3Rpb24odGhpcy5maXJlc3RvcmUsIGNvbGxlY3Rpb25QYXRoKTtcbiAgICByZXR1cm4gZG9jKGNvbGxlY3Rpb25SZWYpLmlkO1xuICB9XG5cbiAgLyoqXG4gICAqIFJldG9ybmEgdW4gdmFsb3IgZGUgdGltZXN0YW1wIGRlbCBzZXJ2aWRvci5cbiAgICogVXNhciBlbiBjYW1wb3MgZGUgZmVjaGEgcGFyYSBxdWUgRmlyZXN0b3JlIGFzaWduZSBlbCB0aW1lc3RhbXAuXG4gICAqL1xuICBzZXJ2ZXJUaW1lc3RhbXAoKTogRmllbGRWYWx1ZSB7XG4gICAgcmV0dXJuIHNlcnZlclRpbWVzdGFtcCgpO1xuICB9XG5cbiAgLyoqXG4gICAqIFJldG9ybmEgdW4gdmFsb3IgcGFyYSBhZ3JlZ2FyIGVsZW1lbnRvcyBhIHVuIGFycmF5LlxuICAgKlxuICAgKiBAZXhhbXBsZVxuICAgKiBgYGB0eXBlc2NyaXB0XG4gICAqIGF3YWl0IGZpcmVzdG9yZVNlcnZpY2UudXBkYXRlRG9jKCd1c2VycycsICd1c2VyMTIzJywge1xuICAgKiAgIHRhZ3M6IGZpcmVzdG9yZVNlcnZpY2UuYXJyYXlVbmlvbignbmV3LXRhZycpXG4gICAqIH0pO1xuICAgKiBgYGBcbiAgICovXG4gIGFycmF5VW5pb24oLi4uZWxlbWVudHM6IHVua25vd25bXSk6IEZpZWxkVmFsdWUge1xuICAgIHJldHVybiBhcnJheVVuaW9uKC4uLmVsZW1lbnRzKTtcbiAgfVxuXG4gIC8qKlxuICAgKiBSZXRvcm5hIHVuIHZhbG9yIHBhcmEgcmVtb3ZlciBlbGVtZW50b3MgZGUgdW4gYXJyYXkuXG4gICAqL1xuICBhcnJheVJlbW92ZSguLi5lbGVtZW50czogdW5rbm93bltdKTogRmllbGRWYWx1ZSB7XG4gICAgcmV0dXJuIGFycmF5UmVtb3ZlKC4uLmVsZW1lbnRzKTtcbiAgfVxuXG4gIC8qKlxuICAgKiBSZXRvcm5hIHVuIHZhbG9yIHBhcmEgaW5jcmVtZW50YXIgdW4gY2FtcG8gbnVtw6lyaWNvLlxuICAgKlxuICAgKiBAZXhhbXBsZVxuICAgKiBgYGB0eXBlc2NyaXB0XG4gICAqIGF3YWl0IGZpcmVzdG9yZVNlcnZpY2UudXBkYXRlRG9jKCd1c2VycycsICd1c2VyMTIzJywge1xuICAgKiAgIGxvZ2luQ291bnQ6IGZpcmVzdG9yZVNlcnZpY2UuaW5jcmVtZW50KDEpXG4gICAqIH0pO1xuICAgKiBgYGBcbiAgICovXG4gIGluY3JlbWVudChuOiBudW1iZXIpOiBGaWVsZFZhbHVlIHtcbiAgICByZXR1cm4gaW5jcmVtZW50KG4pO1xuICB9XG5cbiAgLy8gPT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09XG4gIC8vIE3DiVRPRE9TIFBSSVZBRE9TXG4gIC8vID09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PVxuXG4gIC8qKlxuICAgKiBDb25zdHJ1eWUgbG9zIFF1ZXJ5Q29uc3RyYWludHMgYSBwYXJ0aXIgZGUgUXVlcnlPcHRpb25zXG4gICAqL1xuICBwcml2YXRlIGJ1aWxkUXVlcnlDb25zdHJhaW50cyhvcHRpb25zPzogUXVlcnlPcHRpb25zKTogUXVlcnlDb25zdHJhaW50W10ge1xuICAgIGNvbnN0IGNvbnN0cmFpbnRzOiBRdWVyeUNvbnN0cmFpbnRbXSA9IFtdO1xuXG4gICAgaWYgKCFvcHRpb25zKSByZXR1cm4gY29uc3RyYWludHM7XG5cbiAgICAvLyBXaGVyZSBjbGF1c2VzXG4gICAgaWYgKG9wdGlvbnMud2hlcmUpIHtcbiAgICAgIGZvciAoY29uc3QgY2xhdXNlIG9mIG9wdGlvbnMud2hlcmUpIHtcbiAgICAgICAgY29uc3RyYWludHMucHVzaCh3aGVyZShjbGF1c2UuZmllbGQsIGNsYXVzZS5vcGVyYXRvciwgY2xhdXNlLnZhbHVlKSk7XG4gICAgICB9XG4gICAgfVxuXG4gICAgLy8gT3JkZXJCeSBjbGF1c2VzXG4gICAgaWYgKG9wdGlvbnMub3JkZXJCeSkge1xuICAgICAgZm9yIChjb25zdCBjbGF1c2Ugb2Ygb3B0aW9ucy5vcmRlckJ5KSB7XG4gICAgICAgIGNvbnN0cmFpbnRzLnB1c2gob3JkZXJCeShjbGF1c2UuZmllbGQsIGNsYXVzZS5kaXJlY3Rpb24pKTtcbiAgICAgIH1cbiAgICB9XG5cbiAgICAvLyBDdXJzb3JzIHBhcmEgcGFnaW5hY2nDs25cbiAgICBpZiAob3B0aW9ucy5zdGFydEFmdGVyKSB7XG4gICAgICBjb25zdHJhaW50cy5wdXNoKHN0YXJ0QWZ0ZXIob3B0aW9ucy5zdGFydEFmdGVyKSk7XG4gICAgfVxuICAgIGlmIChvcHRpb25zLnN0YXJ0QXQpIHtcbiAgICAgIGNvbnN0cmFpbnRzLnB1c2goc3RhcnRBdChvcHRpb25zLnN0YXJ0QXQpKTtcbiAgICB9XG4gICAgaWYgKG9wdGlvbnMuZW5kQmVmb3JlKSB7XG4gICAgICBjb25zdHJhaW50cy5wdXNoKGVuZEJlZm9yZShvcHRpb25zLmVuZEJlZm9yZSkpO1xuICAgIH1cbiAgICBpZiAob3B0aW9ucy5lbmRBdCkge1xuICAgICAgY29uc3RyYWludHMucHVzaChlbmRBdChvcHRpb25zLmVuZEF0KSk7XG4gICAgfVxuXG4gICAgLy8gTGltaXQgKHNlIGFncmVnYSBhbCBmaW5hbClcbiAgICBpZiAob3B0aW9ucy5saW1pdCkge1xuICAgICAgY29uc3RyYWludHMucHVzaChsaW1pdChvcHRpb25zLmxpbWl0KSk7XG4gICAgfVxuXG4gICAgcmV0dXJuIGNvbnN0cmFpbnRzO1xuICB9XG5cbiAgLyoqXG4gICAqIE1hcGVhIHVuIERvY3VtZW50U25hcHNob3QgYSBudWVzdHJvIHRpcG9cbiAgICovXG4gIHByaXZhdGUgbWFwRG9jdW1lbnQ8VCBleHRlbmRzIEZpcmVzdG9yZURvY3VtZW50PihcbiAgICBzbmFwc2hvdDogRG9jdW1lbnRTbmFwc2hvdDxEb2N1bWVudERhdGE+XG4gICk6IFQge1xuICAgIGNvbnN0IGRhdGEgPSBzbmFwc2hvdC5kYXRhKCk7XG4gICAgaWYgKCFkYXRhKSB7XG4gICAgICB0aHJvdyBuZXcgRXJyb3IoJ0RvY3VtZW50byBubyB0aWVuZSBkYXRvcycpO1xuICAgIH1cblxuICAgIHJldHVybiB7XG4gICAgICBpZDogc25hcHNob3QuaWQsXG4gICAgICAuLi50aGlzLmNvbnZlcnRUaW1lc3RhbXBzKGRhdGEpLFxuICAgIH0gYXMgVDtcbiAgfVxuXG4gIC8qKlxuICAgKiBDb252aWVydGUgVGltZXN0YW1wcyBkZSBGaXJlc3RvcmUgYSBEYXRlIGRlIEphdmFTY3JpcHRcbiAgICovXG4gIHByaXZhdGUgY29udmVydFRpbWVzdGFtcHMoZGF0YTogRG9jdW1lbnREYXRhKTogRG9jdW1lbnREYXRhIHtcbiAgICBjb25zdCByZXN1bHQ6IERvY3VtZW50RGF0YSA9IHt9O1xuXG4gICAgZm9yIChjb25zdCBba2V5LCB2YWx1ZV0gb2YgT2JqZWN0LmVudHJpZXMoZGF0YSkpIHtcbiAgICAgIGlmICh2YWx1ZSBpbnN0YW5jZW9mIFRpbWVzdGFtcCkge1xuICAgICAgICByZXN1bHRba2V5XSA9IHZhbHVlLnRvRGF0ZSgpO1xuICAgICAgfSBlbHNlIGlmICh2YWx1ZSAmJiB0eXBlb2YgdmFsdWUgPT09ICdvYmplY3QnICYmICFBcnJheS5pc0FycmF5KHZhbHVlKSkge1xuICAgICAgICByZXN1bHRba2V5XSA9IHRoaXMuY29udmVydFRpbWVzdGFtcHModmFsdWUpO1xuICAgICAgfSBlbHNlIHtcbiAgICAgICAgcmVzdWx0W2tleV0gPSB2YWx1ZTtcbiAgICAgIH1cbiAgICB9XG5cbiAgICByZXR1cm4gcmVzdWx0O1xuICB9XG5cbiAgLyoqXG4gICAqIERpdmlkZSB1bmEgcnV0YSBkZSBkb2N1bWVudG8gZW4gY29sZWNjacOzbiBlIElEXG4gICAqL1xuICBwcml2YXRlIHNwbGl0UGF0aChwYXRoOiBzdHJpbmcpOiBbc3RyaW5nLCBzdHJpbmddIHtcbiAgICBjb25zdCBzZWdtZW50cyA9IHBhdGguc3BsaXQoJy8nKTtcbiAgICBpZiAoc2VnbWVudHMubGVuZ3RoIDwgMiB8fCBzZWdtZW50cy5sZW5ndGggJSAyICE9PSAwKSB7XG4gICAgICB0aHJvdyBuZXcgRXJyb3IoYFJ1dGEgZGUgZG9jdW1lbnRvIGludsOhbGlkYTogJHtwYXRofWApO1xuICAgIH1cbiAgICBjb25zdCBkb2NJZCA9IHNlZ21lbnRzLnBvcCgpITtcbiAgICBjb25zdCBjb2xsZWN0aW9uUGF0aCA9IHNlZ21lbnRzLmpvaW4oJy8nKTtcbiAgICByZXR1cm4gW2NvbGxlY3Rpb25QYXRoLCBkb2NJZF07XG4gIH1cbn1cbiJdfQ==
|
|
@@ -1,46 +0,0 @@
|
|
|
1
|
-
/**
|
|
2
|
-
* Firebase Services
|
|
3
|
-
*
|
|
4
|
-
* Servicios reutilizables para integración con Firebase.
|
|
5
|
-
*
|
|
6
|
-
* @example
|
|
7
|
-
* ```typescript
|
|
8
|
-
* // En main.ts
|
|
9
|
-
* import { provideValtechFirebase } from 'valtech-components';
|
|
10
|
-
*
|
|
11
|
-
* bootstrapApplication(AppComponent, {
|
|
12
|
-
* providers: [
|
|
13
|
-
* provideValtechFirebase({
|
|
14
|
-
* firebase: environment.firebase,
|
|
15
|
-
* persistence: true,
|
|
16
|
-
* }),
|
|
17
|
-
* ],
|
|
18
|
-
* });
|
|
19
|
-
*
|
|
20
|
-
* // En componentes
|
|
21
|
-
* import { FirebaseService, FirestoreService } from 'valtech-components';
|
|
22
|
-
*
|
|
23
|
-
* @Component({...})
|
|
24
|
-
* export class MyComponent {
|
|
25
|
-
* private firebase = inject(FirebaseService);
|
|
26
|
-
* private firestore = inject(FirestoreService);
|
|
27
|
-
* }
|
|
28
|
-
* ```
|
|
29
|
-
*/
|
|
30
|
-
// Tipos
|
|
31
|
-
export * from './types';
|
|
32
|
-
// Configuración
|
|
33
|
-
export { VALTECH_FIREBASE_CONFIG, hasEmulators, provideValtechFirebase } from './config';
|
|
34
|
-
// Servicios
|
|
35
|
-
export { FirebaseService } from './firebase.service';
|
|
36
|
-
// Firestore
|
|
37
|
-
export { FirestoreService } from './firestore.service';
|
|
38
|
-
export { FirestoreCollection } from './firestore-collection';
|
|
39
|
-
// Utilidades
|
|
40
|
-
export { QueryBuilder, query } from './utils/query-builder';
|
|
41
|
-
export { buildPath, extractPathParams, getCollectionPath, getDocumentId, isCollectionPath, isDocumentPath, isValidPath, joinPath, } from './utils/path-builder';
|
|
42
|
-
// Storage
|
|
43
|
-
export { StorageService } from './storage.service';
|
|
44
|
-
// Messaging (FCM)
|
|
45
|
-
export { MessagingService } from './messaging.service';
|
|
46
|
-
//# sourceMappingURL=data:application/json;base64,eyJ2ZXJzaW9uIjozLCJmaWxlIjoiaW5kZXguanMiLCJzb3VyY2VSb290IjoiIiwic291cmNlcyI6WyIuLi8uLi8uLi8uLi8uLi8uLi9zcmMvbGliL3NlcnZpY2VzL2ZpcmViYXNlL2luZGV4LnRzIl0sIm5hbWVzIjpbXSwibWFwcGluZ3MiOiJBQUFBOzs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7O0dBNEJHO0FBRUgsUUFBUTtBQUNSLGNBQWMsU0FBUyxDQUFDO0FBRXhCLGdCQUFnQjtBQUNoQixPQUFPLEVBQUUsdUJBQXVCLEVBQUUsWUFBWSxFQUFFLHNCQUFzQixFQUFFLE1BQU0sVUFBVSxDQUFDO0FBRXpGLFlBQVk7QUFDWixPQUFPLEVBQUUsZUFBZSxFQUFFLE1BQU0sb0JBQW9CLENBQUM7QUFFckQsWUFBWTtBQUNaLE9BQU8sRUFBRSxnQkFBZ0IsRUFBRSxNQUFNLHFCQUFxQixDQUFDO0FBQ3ZELE9BQU8sRUFBcUIsbUJBQW1CLEVBQW9CLE1BQU0sd0JBQXdCLENBQUM7QUFFbEcsYUFBYTtBQUNiLE9BQU8sRUFBRSxZQUFZLEVBQUUsS0FBSyxFQUFFLE1BQU0sdUJBQXVCLENBQUM7QUFDNUQsT0FBTyxFQUNMLFNBQVMsRUFDVCxpQkFBaUIsRUFDakIsaUJBQWlCLEVBQ2pCLGFBQWEsRUFDYixnQkFBZ0IsRUFDaEIsY0FBYyxFQUNkLFdBQVcsRUFDWCxRQUFRLEdBQ1QsTUFBTSxzQkFBc0IsQ0FBQztBQUU5QixVQUFVO0FBQ1YsT0FBTyxFQUFFLGNBQWMsRUFBRSxNQUFNLG1CQUFtQixDQUFDO0FBRW5ELGtCQUFrQjtBQUNsQixPQUFPLEVBQUUsZ0JBQWdCLEVBQUUsTUFBTSxxQkFBcUIsQ0FBQyIsInNvdXJjZXNDb250ZW50IjpbIi8qKlxuICogRmlyZWJhc2UgU2VydmljZXNcbiAqXG4gKiBTZXJ2aWNpb3MgcmV1dGlsaXphYmxlcyBwYXJhIGludGVncmFjacOzbiBjb24gRmlyZWJhc2UuXG4gKlxuICogQGV4YW1wbGVcbiAqIGBgYHR5cGVzY3JpcHRcbiAqIC8vIEVuIG1haW4udHNcbiAqIGltcG9ydCB7IHByb3ZpZGVWYWx0ZWNoRmlyZWJhc2UgfSBmcm9tICd2YWx0ZWNoLWNvbXBvbmVudHMnO1xuICpcbiAqIGJvb3RzdHJhcEFwcGxpY2F0aW9uKEFwcENvbXBvbmVudCwge1xuICogICBwcm92aWRlcnM6IFtcbiAqICAgICBwcm92aWRlVmFsdGVjaEZpcmViYXNlKHtcbiAqICAgICAgIGZpcmViYXNlOiBlbnZpcm9ubWVudC5maXJlYmFzZSxcbiAqICAgICAgIHBlcnNpc3RlbmNlOiB0cnVlLFxuICogICAgIH0pLFxuICogICBdLFxuICogfSk7XG4gKlxuICogLy8gRW4gY29tcG9uZW50ZXNcbiAqIGltcG9ydCB7IEZpcmViYXNlU2VydmljZSwgRmlyZXN0b3JlU2VydmljZSB9IGZyb20gJ3ZhbHRlY2gtY29tcG9uZW50cyc7XG4gKlxuICogQENvbXBvbmVudCh7Li4ufSlcbiAqIGV4cG9ydCBjbGFzcyBNeUNvbXBvbmVudCB7XG4gKiAgIHByaXZhdGUgZmlyZWJhc2UgPSBpbmplY3QoRmlyZWJhc2VTZXJ2aWNlKTtcbiAqICAgcHJpdmF0ZSBmaXJlc3RvcmUgPSBpbmplY3QoRmlyZXN0b3JlU2VydmljZSk7XG4gKiB9XG4gKiBgYGBcbiAqL1xuXG4vLyBUaXBvc1xuZXhwb3J0ICogZnJvbSAnLi90eXBlcyc7XG5cbi8vIENvbmZpZ3VyYWNpw7NuXG5leHBvcnQgeyBWQUxURUNIX0ZJUkVCQVNFX0NPTkZJRywgaGFzRW11bGF0b3JzLCBwcm92aWRlVmFsdGVjaEZpcmViYXNlIH0gZnJvbSAnLi9jb25maWcnO1xuXG4vLyBTZXJ2aWNpb3NcbmV4cG9ydCB7IEZpcmViYXNlU2VydmljZSB9IGZyb20gJy4vZmlyZWJhc2Uuc2VydmljZSc7XG5cbi8vIEZpcmVzdG9yZVxuZXhwb3J0IHsgRmlyZXN0b3JlU2VydmljZSB9IGZyb20gJy4vZmlyZXN0b3JlLnNlcnZpY2UnO1xuZXhwb3J0IHsgQ29sbGVjdGlvbk9wdGlvbnMsIEZpcmVzdG9yZUNvbGxlY3Rpb24sIFN1YkNvbGxlY3Rpb25SZWYgfSBmcm9tICcuL2ZpcmVzdG9yZS1jb2xsZWN0aW9uJztcblxuLy8gVXRpbGlkYWRlc1xuZXhwb3J0IHsgUXVlcnlCdWlsZGVyLCBxdWVyeSB9IGZyb20gJy4vdXRpbHMvcXVlcnktYnVpbGRlcic7XG5leHBvcnQge1xuICBidWlsZFBhdGgsXG4gIGV4dHJhY3RQYXRoUGFyYW1zLFxuICBnZXRDb2xsZWN0aW9uUGF0aCxcbiAgZ2V0RG9jdW1lbnRJZCxcbiAgaXNDb2xsZWN0aW9uUGF0aCxcbiAgaXNEb2N1bWVudFBhdGgsXG4gIGlzVmFsaWRQYXRoLFxuICBqb2luUGF0aCxcbn0gZnJvbSAnLi91dGlscy9wYXRoLWJ1aWxkZXInO1xuXG4vLyBTdG9yYWdlXG5leHBvcnQgeyBTdG9yYWdlU2VydmljZSB9IGZyb20gJy4vc3RvcmFnZS5zZXJ2aWNlJztcblxuLy8gTWVzc2FnaW5nIChGQ00pXG5leHBvcnQgeyBNZXNzYWdpbmdTZXJ2aWNlIH0gZnJvbSAnLi9tZXNzYWdpbmcuc2VydmljZSc7XG4iXX0=
|