valtech-components 2.0.426 → 2.0.428

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 (31) hide show
  1. package/esm2022/lib/components/molecules/glow-card/glow-card.component.mjs +49 -20
  2. package/esm2022/lib/components/molecules/glow-card/types.mjs +1 -1
  3. package/esm2022/lib/components/organisms/article/article.component.mjs +33 -6
  4. package/esm2022/lib/services/firebase/config.mjs +108 -0
  5. package/esm2022/lib/services/firebase/firebase.service.mjs +285 -0
  6. package/esm2022/lib/services/firebase/firestore-collection.mjs +266 -0
  7. package/esm2022/lib/services/firebase/firestore.service.mjs +508 -0
  8. package/esm2022/lib/services/firebase/index.mjs +46 -0
  9. package/esm2022/lib/services/firebase/messaging.service.mjs +503 -0
  10. package/esm2022/lib/services/firebase/storage.service.mjs +421 -0
  11. package/esm2022/lib/services/firebase/types.mjs +8 -0
  12. package/esm2022/lib/services/firebase/utils/path-builder.mjs +195 -0
  13. package/esm2022/lib/services/firebase/utils/query-builder.mjs +302 -0
  14. package/esm2022/public-api.mjs +3 -4
  15. package/fesm2022/valtech-components.mjs +2890 -233
  16. package/fesm2022/valtech-components.mjs.map +1 -1
  17. package/lib/components/molecules/glow-card/glow-card.component.d.ts +1 -0
  18. package/lib/components/molecules/glow-card/types.d.ts +7 -5
  19. package/lib/components/organisms/article/article.component.d.ts +6 -1
  20. package/lib/services/firebase/config.d.ts +49 -0
  21. package/lib/services/firebase/firebase.service.d.ts +140 -0
  22. package/lib/services/firebase/firestore-collection.d.ts +195 -0
  23. package/lib/services/firebase/firestore.service.d.ts +303 -0
  24. package/lib/services/firebase/index.d.ts +38 -0
  25. package/lib/services/firebase/messaging.service.d.ts +254 -0
  26. package/lib/services/firebase/storage.service.d.ts +204 -0
  27. package/lib/services/firebase/types.d.ts +281 -0
  28. package/lib/services/firebase/utils/path-builder.d.ts +132 -0
  29. package/lib/services/firebase/utils/query-builder.d.ts +210 -0
  30. package/package.json +11 -1
  31. package/public-api.d.ts +1 -0
@@ -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==