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,195 @@
1
+ /**
2
+ * Path Builder
3
+ *
4
+ * Utilidades para construir rutas de Firestore con templates.
5
+ * Soporta rutas multi-nivel y anidadas.
6
+ */
7
+ /**
8
+ * Construye una ruta de Firestore reemplazando placeholders.
9
+ *
10
+ * @param template - Template con placeholders en formato {param}
11
+ * @param params - Objeto con los valores a reemplazar
12
+ * @returns Ruta construida
13
+ * @throws Error si faltan parámetros requeridos
14
+ *
15
+ * @example
16
+ * ```typescript
17
+ * // Ruta simple
18
+ * buildPath('users/{userId}', { userId: 'abc123' });
19
+ * // => 'users/abc123'
20
+ *
21
+ * // Ruta anidada
22
+ * buildPath('users/{userId}/documents/{docId}', {
23
+ * userId: 'abc123',
24
+ * docId: 'doc456'
25
+ * });
26
+ * // => 'users/abc123/documents/doc456'
27
+ *
28
+ * // Múltiples niveles
29
+ * buildPath('orgs/{orgId}/teams/{teamId}/members/{memberId}', {
30
+ * orgId: 'org1',
31
+ * teamId: 'team2',
32
+ * memberId: 'member3'
33
+ * });
34
+ * // => 'orgs/org1/teams/team2/members/member3'
35
+ * ```
36
+ */
37
+ export function buildPath(template, params) {
38
+ let result = template;
39
+ // Encontrar todos los placeholders
40
+ const placeholders = template.match(/\{([^}]+)\}/g);
41
+ if (!placeholders) {
42
+ return template;
43
+ }
44
+ for (const placeholder of placeholders) {
45
+ const key = placeholder.slice(1, -1); // Remover { y }
46
+ const value = params[key];
47
+ if (value === undefined || value === null) {
48
+ throw new Error(`Parámetro requerido '${key}' no proporcionado para la ruta: ${template}`);
49
+ }
50
+ if (typeof value !== 'string' || value.trim() === '') {
51
+ throw new Error(`El parámetro '${key}' debe ser un string no vacío`);
52
+ }
53
+ // Validar que no contenga caracteres inválidos para Firestore
54
+ if (value.includes('/')) {
55
+ throw new Error(`El parámetro '${key}' no puede contener '/'`);
56
+ }
57
+ result = result.replace(placeholder, value);
58
+ }
59
+ return result;
60
+ }
61
+ /**
62
+ * Extrae los nombres de los parámetros de un template de ruta.
63
+ *
64
+ * @param template - Template de ruta
65
+ * @returns Array con los nombres de los parámetros
66
+ *
67
+ * @example
68
+ * ```typescript
69
+ * extractParams('users/{userId}/documents/{docId}');
70
+ * // => ['userId', 'docId']
71
+ * ```
72
+ */
73
+ export function extractPathParams(template) {
74
+ const matches = template.match(/\{([^}]+)\}/g);
75
+ if (!matches)
76
+ return [];
77
+ return matches.map((m) => m.slice(1, -1));
78
+ }
79
+ /**
80
+ * Valida que una ruta de Firestore sea válida.
81
+ *
82
+ * @param path - Ruta a validar
83
+ * @returns true si la ruta es válida
84
+ *
85
+ * @example
86
+ * ```typescript
87
+ * isValidPath('users/abc123'); // true
88
+ * isValidPath('users/abc123/documents'); // true
89
+ * isValidPath('users//documents'); // false (segmento vacío)
90
+ * isValidPath(''); // false (vacío)
91
+ * ```
92
+ */
93
+ export function isValidPath(path) {
94
+ if (!path || path.trim() === '')
95
+ return false;
96
+ const segments = path.split('/');
97
+ // No puede tener segmentos vacíos
98
+ if (segments.some((s) => s.trim() === ''))
99
+ return false;
100
+ // No puede empezar o terminar con /
101
+ if (path.startsWith('/') || path.endsWith('/'))
102
+ return false;
103
+ return true;
104
+ }
105
+ /**
106
+ * Obtiene la ruta de la colección padre de un documento.
107
+ *
108
+ * @param documentPath - Ruta completa del documento
109
+ * @returns Ruta de la colección padre
110
+ *
111
+ * @example
112
+ * ```typescript
113
+ * getCollectionPath('users/abc123');
114
+ * // => 'users'
115
+ *
116
+ * getCollectionPath('users/abc123/documents/doc456');
117
+ * // => 'users/abc123/documents'
118
+ * ```
119
+ */
120
+ export function getCollectionPath(documentPath) {
121
+ const segments = documentPath.split('/');
122
+ if (segments.length < 2) {
123
+ throw new Error(`Ruta de documento inválida: ${documentPath}`);
124
+ }
125
+ return segments.slice(0, -1).join('/');
126
+ }
127
+ /**
128
+ * Obtiene el ID del documento de una ruta.
129
+ *
130
+ * @param documentPath - Ruta completa del documento
131
+ * @returns ID del documento
132
+ *
133
+ * @example
134
+ * ```typescript
135
+ * getDocumentId('users/abc123');
136
+ * // => 'abc123'
137
+ *
138
+ * getDocumentId('users/abc123/documents/doc456');
139
+ * // => 'doc456'
140
+ * ```
141
+ */
142
+ export function getDocumentId(documentPath) {
143
+ const segments = documentPath.split('/');
144
+ if (segments.length < 2 || segments.length % 2 !== 0) {
145
+ throw new Error(`Ruta de documento inválida: ${documentPath}`);
146
+ }
147
+ return segments[segments.length - 1];
148
+ }
149
+ /**
150
+ * Verifica si una ruta apunta a un documento (número par de segmentos).
151
+ *
152
+ * @param path - Ruta a verificar
153
+ * @returns true si es una ruta de documento
154
+ *
155
+ * @example
156
+ * ```typescript
157
+ * isDocumentPath('users/abc123'); // true
158
+ * isDocumentPath('users'); // false (colección)
159
+ * isDocumentPath('users/abc123/documents'); // false (colección)
160
+ * ```
161
+ */
162
+ export function isDocumentPath(path) {
163
+ const segments = path.split('/').filter((s) => s.trim() !== '');
164
+ return segments.length > 0 && segments.length % 2 === 0;
165
+ }
166
+ /**
167
+ * Verifica si una ruta apunta a una colección (número impar de segmentos).
168
+ *
169
+ * @param path - Ruta a verificar
170
+ * @returns true si es una ruta de colección
171
+ */
172
+ export function isCollectionPath(path) {
173
+ const segments = path.split('/').filter((s) => s.trim() !== '');
174
+ return segments.length > 0 && segments.length % 2 !== 0;
175
+ }
176
+ /**
177
+ * Combina una ruta base con segmentos adicionales.
178
+ *
179
+ * @param basePath - Ruta base
180
+ * @param segments - Segmentos adicionales
181
+ * @returns Ruta combinada
182
+ *
183
+ * @example
184
+ * ```typescript
185
+ * joinPath('users', 'abc123', 'documents');
186
+ * // => 'users/abc123/documents'
187
+ * ```
188
+ */
189
+ export function joinPath(...segments) {
190
+ return segments
191
+ .filter((s) => s && s.trim() !== '')
192
+ .map((s) => s.replace(/^\/+|\/+$/g, '')) // Remover / al inicio y final
193
+ .join('/');
194
+ }
195
+ //# sourceMappingURL=data:application/json;base64,eyJ2ZXJzaW9uIjozLCJmaWxlIjoicGF0aC1idWlsZGVyLmpzIiwic291cmNlUm9vdCI6IiIsInNvdXJjZXMiOlsiLi4vLi4vLi4vLi4vLi4vLi4vLi4vc3JjL2xpYi9zZXJ2aWNlcy9maXJlYmFzZS91dGlscy9wYXRoLWJ1aWxkZXIudHMiXSwibmFtZXMiOltdLCJtYXBwaW5ncyI6IkFBQUE7Ozs7O0dBS0c7QUFFSDs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7R0E2Qkc7QUFDSCxNQUFNLFVBQVUsU0FBUyxDQUFDLFFBQWdCLEVBQUUsTUFBOEI7SUFDeEUsSUFBSSxNQUFNLEdBQUcsUUFBUSxDQUFDO0lBRXRCLG1DQUFtQztJQUNuQyxNQUFNLFlBQVksR0FBRyxRQUFRLENBQUMsS0FBSyxDQUFDLGNBQWMsQ0FBQyxDQUFDO0lBRXBELElBQUksQ0FBQyxZQUFZLEVBQUUsQ0FBQztRQUNsQixPQUFPLFFBQVEsQ0FBQztJQUNsQixDQUFDO0lBRUQsS0FBSyxNQUFNLFdBQVcsSUFBSSxZQUFZLEVBQUUsQ0FBQztRQUN2QyxNQUFNLEdBQUcsR0FBRyxXQUFXLENBQUMsS0FBSyxDQUFDLENBQUMsRUFBRSxDQUFDLENBQUMsQ0FBQyxDQUFDLENBQUMsZ0JBQWdCO1FBQ3RELE1BQU0sS0FBSyxHQUFHLE1BQU0sQ0FBQyxHQUFHLENBQUMsQ0FBQztRQUUxQixJQUFJLEtBQUssS0FBSyxTQUFTLElBQUksS0FBSyxLQUFLLElBQUksRUFBRSxDQUFDO1lBQzFDLE1BQU0sSUFBSSxLQUFLLENBQUMsd0JBQXdCLEdBQUcsb0NBQW9DLFFBQVEsRUFBRSxDQUFDLENBQUM7UUFDN0YsQ0FBQztRQUVELElBQUksT0FBTyxLQUFLLEtBQUssUUFBUSxJQUFJLEtBQUssQ0FBQyxJQUFJLEVBQUUsS0FBSyxFQUFFLEVBQUUsQ0FBQztZQUNyRCxNQUFNLElBQUksS0FBSyxDQUFDLGlCQUFpQixHQUFHLCtCQUErQixDQUFDLENBQUM7UUFDdkUsQ0FBQztRQUVELDhEQUE4RDtRQUM5RCxJQUFJLEtBQUssQ0FBQyxRQUFRLENB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QUMsS0FBSyxDQUFDLENBQUM7QUFDMUQsQ0FBQztBQUVEOzs7OztHQUtHO0FBQ0gsTUFBTSxVQUFVLGdCQUFnQixDQUFDLElBQVk7SUFDM0MsTUFBTSxRQUFRLEdBQUcsSUFBSSxDQUFDLEtBQUssQ0FBQyxHQUFHLENBQUMsQ0FBQyxNQUFNLENBQUMsQ0FBQyxDQUFDLEVBQUUsRUFBRSxDQUFDLENBQUMsQ0FBQyxJQUFJLEVBQUUsS0FBSyxFQUFFLENBQUMsQ0FBQztJQUNoRSxPQUFPLFFBQVEsQ0FBQyxNQUFNLEdBQUcsQ0FBQyxJQUFJLFFBQVEsQ0FBQyxNQUFNLEdBQUcsQ0FBQyxLQUFLLENBQUMsQ0FBQztBQUMxRCxDQUFDO0FBRUQ7Ozs7Ozs7Ozs7OztHQVlHO0FBQ0gsTUFBTSxVQUFVLFFBQVEsQ0FBQyxHQUFHLFFBQWtCO0lBQzVDLE9BQU8sUUFBUTtTQUNaLE1BQU0sQ0FBQyxDQUFDLENBQUMsRUFBRSxFQUFFLENBQUMsQ0FBQyxJQUFJLENBQUMsQ0FBQyxJQUFJLEVBQUUsS0FBSyxFQUFFLENBQUM7U0FDbkMsR0FBRyxDQUFDLENBQUMsQ0FBQyxFQUFFLEVBQUUsQ0FBQyxDQUFDLENBQUMsT0FBTyxDQUFDLFlBQVksRUFBRSxFQUFFLENBQUMsQ0FBQyxDQUFDLDhCQUE4QjtTQUN0RSxJQUFJLENBQUMsR0FBRyxDQUFDLENBQUM7QUFDZixDQUFDIiwic291cmNlc0NvbnRlbnQiOlsiLyoqXG4gKiBQYXRoIEJ1aWxkZXJcbiAqXG4gKiBVdGlsaWRhZGVzIHBhcmEgY29uc3RydWlyIHJ1dGFzIGRlIEZpcmVzdG9yZSBjb24gdGVtcGxhdGVzLlxuICogU29wb3J0YSBydXRhcyBtdWx0aS1uaXZlbCB5IGFuaWRhZGFzLlxuICovXG5cbi8qKlxuICogQ29uc3RydXllIHVuYSBydXRhIGRlIEZpcmVzdG9yZSByZWVtcGxhemFuZG8gcGxhY2Vob2xkZXJzLlxuICpcbiAqIEBwYXJhbSB0ZW1wbGF0ZSAtIFRlbXBsYXRlIGNvbiBwbGFjZWhvbGRlcnMgZW4gZm9ybWF0byB7cGFyYW19XG4gKiBAcGFyYW0gcGFyYW1zIC0gT2JqZXRvIGNvbiBsb3MgdmFsb3JlcyBhIHJlZW1wbGF6YXJcbiAqIEByZXR1cm5zIFJ1dGEgY29uc3RydWlkYVxuICogQHRocm93cyBFcnJvciBzaSBmYWx0YW4gcGFyw6FtZXRyb3MgcmVxdWVyaWRvc1xuICpcbiAqIEBleGFtcGxlXG4gKiBgYGB0eXBlc2NyaXB0XG4gKiAvLyBSdXRhIHNpbXBsZVxuICogYnVpbGRQYXRoKCd1c2Vycy97dXNlcklkfScsIHsgdXNlcklkOiAnYWJjMTIzJyB9KTtcbiAqIC8vID0+ICd1c2Vycy9hYmMxMjMnXG4gKlxuICogLy8gUnV0YSBhbmlkYWRhXG4gKiBidWlsZFBhdGgoJ3VzZXJzL3t1c2VySWR9L2RvY3VtZW50cy97ZG9jSWR9Jywge1xuICogICB1c2VySWQ6ICdhYmMxMjMnLFxuICogICBkb2NJZDogJ2RvYzQ1NidcbiAqIH0pO1xuICogLy8gPT4gJ3VzZXJzL2FiYzEyMy9kb2N1bWVudHMvZG9jNDU2J1xuICpcbiAqIC8vIE3Dumx0aXBsZXMgbml2ZWxlc1xuICogYnVpbGRQYXRoKCdvcmdzL3tvcmdJZH0vdGVhbXMve3RlYW1JZH0vbWVtYmVycy97bWVtYmVySWR9Jywge1xuICogICBvcmdJZDogJ29yZzEnLFxuICogICB0ZWFtSWQ6ICd0ZWFtMicsXG4gKiAgIG1lbWJlcklkOiAnbWVtYmVyMydcbiAqIH0pO1xuICogLy8gPT4gJ29yZ3Mvb3JnMS90ZWFtcy90ZWFtMi9tZW1iZXJzL21lbWJlcjMnXG4gKiBgYGBcbiAqL1xuZXhwb3J0IGZ1bmN0aW9uIGJ1aWxkUGF0aCh0ZW1wbGF0ZTogc3RyaW5nLCBwYXJhbXM6IFJlY29yZDxzdHJpbmcsIHN0cmluZz4pOiBzdHJpbmcge1xuICBsZXQgcmVzdWx0ID0gdGVtcGxhdGU7XG5cbiAgLy8gRW5jb250cmFyIHRvZG9zIGxvcyBwbGFjZWhvbGRlcnNcbiAgY29uc3QgcGxhY2Vob2xkZXJzID0gdGVtcGxhdGUubWF0Y2goL1xceyhbXn1dKylcXH0vZyk7XG5cbiAgaWYgKCFwbGFjZWhvbGRlcnMpIHtcbiAgICByZXR1cm4gdGVtcGxhdGU7XG4gIH1cblxuICBmb3IgKGNvbnN0IHBsYWNlaG9sZGVyIG9mIHBsYWNlaG9sZGVycykge1xuICAgIGNvbnN0IGtleSA9IHBsYWNlaG9sZGVyLnNsaWNlKDEsIC0xKTsgLy8gUmVtb3ZlciB7IHkgfVxuICAgIGNvbnN0IHZhbHVlID0gcGFyYW1zW2tleV07XG5cbiAgICBpZiAodmFsdWUgPT09IHVuZGVmaW5lZCB8fCB2YWx1ZSA9PT0gbnVsbCkge1xuICAgICAgdGhyb3cgbmV3IEVycm9yKGBQYXLDoW1ldHJvIHJlcXVlcmlkbyAnJHtrZXl9JyBubyBwcm9wb3JjaW9uYWRvIHBhcmEgbGEgcnV0YTogJHt0ZW1wbGF0ZX1gKTtcbiAgICB9XG5cbiAgICBpZiAodHlwZW9mIHZhbHVlICE9PSAnc3RyaW5nJyB8fCB2YWx1ZS50cmltKCkgPT09ICcnKSB7XG4gICAgICB0aHJvdyBuZXcgRXJyb3IoYEVsIHBhcsOhbWV0cm8gJyR7a2V5fScgZGViZSBzZXIgdW4gc3RyaW5nIG5vIHZhY8Otb2ApO1xuICAgIH1cblxuICAgIC8vIFZhbGlkYXIgcXVlIG5vIGNvbnRlbmdhIGNhcmFjdGVyZXMgaW52w6FsaWRvcyBwYXJhIEZpcmVzdG9yZVxuICAgIGlmICh2YWx1ZS5pbmNsdWRlcygnLycpKSB7XG4gICAgICB0aHJvdyBuZXcgRXJyb3IoYEVsIHBhcsOhbWV0cm8gJyR7a2V5fScgbm8gcHVlZGUgY29udGVuZXIgJy8nYCk7XG4gICAgfVxuXG4gICAgcmVzdWx0ID0gcmVzdWx0LnJlcGxhY2UocGxhY2Vob2xkZXIsIHZhbHVlKTtcbiAgfVxuXG4gIHJldHVybiByZXN1bHQ7XG59XG5cbi8qKlxuICogRXh0cmFlIGxvcyBub21icmVzIGRlIGxvcyBwYXLDoW1ldHJvcyBkZSB1biB0ZW1wbGF0ZSBkZSBydXRhLlxuICpcbiAqIEBwYXJhbSB0ZW1wbGF0ZSAtIFRlbXBsYXRlIGRlIHJ1dGFcbiAqIEByZXR1cm5zIEFycmF5IGNvbiBsb3Mgbm9tYnJlcyBkZSBsb3MgcGFyw6FtZXRyb3NcbiAqXG4gKiBAZXhhbXBsZVxuICogYGBgdHlwZXNjcmlwdFxuICogZXh0cmFjdFBhcmFtcygndXNlcnMve3VzZXJJZH0vZG9jdW1lbnRzL3tkb2NJZH0nKTtcbiAqIC8vID0+IFsndXNlcklkJywgJ2RvY0lkJ11cbiAqIGBgYFxuICovXG5leHBvcnQgZnVuY3Rpb24gZXh0cmFjdFBhdGhQYXJhbXModGVtcGxhdGU6IHN0cmluZyk6IHN0cmluZ1tdIHtcbiAgY29uc3QgbWF0Y2hlcyA9IHRlbXBsYXRlLm1hdGNoKC9cXHsoW159XSspXFx9L2cpO1xuICBpZiAoIW1hdGNoZXMpIHJldHVybiBbXTtcbiAgcmV0dXJuIG1hdGNoZXMubWFwKChtKSA9PiBtLnNsaWNlKDEsIC0xKSk7XG59XG5cbi8qKlxuICogVmFsaWRhIHF1ZSB1bmEgcnV0YSBkZSBGaXJlc3RvcmUgc2VhIHbDoWxpZGEuXG4gKlxuICogQHBhcmFtIHBhdGggLSBSdXRhIGEgdmFsaWRhclxuICogQHJldHVybnMgdHJ1ZSBzaSBsYSBydXRhIGVzIHbDoWxpZGFcbiAqXG4gKiBAZXhhbXBsZVxuICogYGBgdHlwZXNjcmlwdFxuICogaXNWYWxpZFBhdGgoJ3VzZXJzL2FiYzEyMycpOyAgICAgICAgICAgLy8gdHJ1ZVxuICogaXNWYWxpZFBhdGgoJ3VzZXJzL2FiYzEyMy9kb2N1bWVudHMnKTsgLy8gdHJ1ZVxuICogaXNWYWxpZFBhdGgoJ3VzZXJzLy9kb2N1bWVudHMnKTsgICAgICAgLy8gZmFsc2UgKHNlZ21lbnRvIHZhY8OtbylcbiAqIGlzVmFsaWRQYXRoKCcnKTsgICAgICAgICAgICAgICAgICAgICAgIC8vIGZhbHNlICh2YWPDrW8pXG4gKiBgYGBcbiAqL1xuZXhwb3J0IGZ1bmN0aW9uIGlzVmFsaWRQYXRoKHBhdGg6IHN0cmluZyk6IGJvb2xlYW4ge1xuICBpZiAoIXBhdGggfHwgcGF0aC50cmltKCkgPT09ICcnKSByZXR1cm4gZmFsc2U7XG5cbiAgY29uc3Qgc2VnbWVudHMgPSBwYXRoLnNwbGl0KCcvJyk7XG5cbiAgLy8gTm8gcHVlZGUgdGVuZXIgc2VnbWVudG9zIHZhY8Otb3NcbiAgaWYgKHNlZ21lbnRzLnNvbWUoKHMpID0+IHMudHJpbSgpID09PSAnJykpIHJldHVybiBmYWxzZTtcblxuICAvLyBObyBwdWVkZSBlbXBlemFyIG8gdGVybWluYXIgY29uIC9cbiAgaWYgKHBhdGguc3RhcnRzV2l0aCgnLycpIHx8IHBhdGguZW5kc1dpdGgoJy8nKSkgcmV0dXJuIGZhbHNlO1xuXG4gIHJldHVybiB0cnVlO1xufVxuXG4vKipcbiAqIE9idGllbmUgbGEgcnV0YSBkZSBsYSBjb2xlY2Npw7NuIHBhZHJlIGRlIHVuIGRvY3VtZW50by5cbiAqXG4gKiBAcGFyYW0gZG9jdW1lbnRQYXRoIC0gUnV0YSBjb21wbGV0YSBkZWwgZG9jdW1lbnRvXG4gKiBAcmV0dXJucyBSdXRhIGRlIGxhIGNvbGVjY2nDs24gcGFkcmVcbiAqXG4gKiBAZXhhbXBsZVxuICogYGBgdHlwZXNjcmlwdFxuICogZ2V0Q29sbGVjdGlvblBhdGgoJ3VzZXJzL2FiYzEyMycpO1xuICogLy8gPT4gJ3VzZXJzJ1xuICpcbiAqIGdldENvbGxlY3Rpb25QYXRoKCd1c2Vycy9hYmMxMjMvZG9jdW1lbnRzL2RvYzQ1NicpO1xuICogLy8gPT4gJ3VzZXJzL2FiYzEyMy9kb2N1bWVudHMnXG4gKiBgYGBcbiAqL1xuZXhwb3J0IGZ1bmN0aW9uIGdldENvbGxlY3Rpb25QYXRoKGRvY3VtZW50UGF0aDogc3RyaW5nKTogc3RyaW5nIHtcbiAgY29uc3Qgc2VnbWVudHMgPSBkb2N1bWVudFBhdGguc3BsaXQoJy8nKTtcbiAgaWYgKHNlZ21lbnRzLmxlbmd0aCA8IDIpIHtcbiAgICB0aHJvdyBuZXcgRXJyb3IoYFJ1dGEgZGUgZG9jdW1lbnRvIGludsOhbGlkYTogJHtkb2N1bWVudFBhdGh9YCk7XG4gIH1cbiAgcmV0dXJuIHNlZ21lbnRzLnNsaWNlKDAsIC0xKS5qb2luKCcvJyk7XG59XG5cbi8qKlxuICogT2J0aWVuZSBlbCBJRCBkZWwgZG9jdW1lbnRvIGRlIHVuYSBydXRhLlxuICpcbiAqIEBwYXJhbSBkb2N1bWVudFBhdGggLSBSdXRhIGNvbXBsZXRhIGRlbCBkb2N1bWVudG9cbiAqIEByZXR1cm5zIElEIGRlbCBkb2N1bWVudG9cbiAqXG4gKiBAZXhhbXBsZVxuICogYGBgdHlwZXNjcmlwdFxuICogZ2V0RG9jdW1lbnRJZCgndXNlcnMvYWJjMTIzJyk7XG4gKiAvLyA9PiAnYWJjMTIzJ1xuICpcbiAqIGdldERvY3VtZW50SWQoJ3VzZXJzL2FiYzEyMy9kb2N1bWVudHMvZG9jNDU2Jyk7XG4gKiAvLyA9PiAnZG9jNDU2J1xuICogYGBgXG4gKi9cbmV4cG9ydCBmdW5jdGlvbiBnZXREb2N1bWVudElkKGRvY3VtZW50UGF0aDogc3RyaW5nKTogc3RyaW5nIHtcbiAgY29uc3Qgc2VnbWVudHMgPSBkb2N1bWVudFBhdGguc3BsaXQoJy8nKTtcbiAgaWYgKHNlZ21lbnRzLmxlbmd0aCA8IDIgfHwgc2VnbWVudHMubGVuZ3RoICUgMiAhPT0gMCkge1xuICAgIHRocm93IG5ldyBFcnJvcihgUnV0YSBkZSBkb2N1bWVudG8gaW52w6FsaWRhOiAke2RvY3VtZW50UGF0aH1gKTtcbiAgfVxuICByZXR1cm4gc2VnbWVudHNbc2VnbWVudHMubGVuZ3RoIC0gMV07XG59XG5cbi8qKlxuICogVmVyaWZpY2Egc2kgdW5hIHJ1dGEgYXB1bnRhIGEgdW4gZG9jdW1lbnRvIChuw7ptZXJvIHBhciBkZSBzZWdtZW50b3MpLlxuICpcbiAqIEBwYXJhbSBwYXRoIC0gUnV0YSBhIHZlcmlmaWNhclxuICogQHJldHVybnMgdHJ1ZSBzaSBlcyB1bmEgcnV0YSBkZSBkb2N1bWVudG9cbiAqXG4gKiBAZXhhbXBsZVxuICogYGBgdHlwZXNjcmlwdFxuICogaXNEb2N1bWVudFBhdGgoJ3VzZXJzL2FiYzEyMycpOyAgICAgICAgICAgLy8gdHJ1ZVxuICogaXNEb2N1bWVudFBhdGgoJ3VzZXJzJyk7ICAgICAgICAgICAgICAgICAgLy8gZmFsc2UgKGNvbGVjY2nDs24pXG4gKiBpc0RvY3VtZW50UGF0aCgndXNlcnMvYWJjMTIzL2RvY3VtZW50cycpOyAvLyBmYWxzZSAoY29sZWNjacOzbilcbiAqIGBgYFxuICovXG5leHBvcnQgZnVuY3Rpb24gaXNEb2N1bWVudFBhdGgocGF0aDogc3RyaW5nKTogYm9vbGVhbiB7XG4gIGNvbnN0IHNlZ21lbnRzID0gcGF0aC5zcGxpdCgnLycpLmZpbHRlcigocykgPT4gcy50cmltKCkgIT09ICcnKTtcbiAgcmV0dXJuIHNlZ21lbnRzLmxlbmd0aCA+IDAgJiYgc2VnbWVudHMubGVuZ3RoICUgMiA9PT0gMDtcbn1cblxuLyoqXG4gKiBWZXJpZmljYSBzaSB1bmEgcnV0YSBhcHVudGEgYSB1bmEgY29sZWNjacOzbiAobsO6bWVybyBpbXBhciBkZSBzZWdtZW50b3MpLlxuICpcbiAqIEBwYXJhbSBwYXRoIC0gUnV0YSBhIHZlcmlmaWNhclxuICogQHJldHVybnMgdHJ1ZSBzaSBlcyB1bmEgcnV0YSBkZSBjb2xlY2Npw7NuXG4gKi9cbmV4cG9ydCBmdW5jdGlvbiBpc0NvbGxlY3Rpb25QYXRoKHBhdGg6IHN0cmluZyk6IGJvb2xlYW4ge1xuICBjb25zdCBzZWdtZW50cyA9IHBhdGguc3BsaXQoJy8nKS5maWx0ZXIoKHMpID0+IHMudHJpbSgpICE9PSAnJyk7XG4gIHJldHVybiBzZWdtZW50cy5sZW5ndGggPiAwICYmIHNlZ21lbnRzLmxlbmd0aCAlIDIgIT09IDA7XG59XG5cbi8qKlxuICogQ29tYmluYSB1bmEgcnV0YSBiYXNlIGNvbiBzZWdtZW50b3MgYWRpY2lvbmFsZXMuXG4gKlxuICogQHBhcmFtIGJhc2VQYXRoIC0gUnV0YSBiYXNlXG4gKiBAcGFyYW0gc2VnbWVudHMgLSBTZWdtZW50b3MgYWRpY2lvbmFsZXNcbiAqIEByZXR1cm5zIFJ1dGEgY29tYmluYWRhXG4gKlxuICogQGV4YW1wbGVcbiAqIGBgYHR5cGVzY3JpcHRcbiAqIGpvaW5QYXRoKCd1c2VycycsICdhYmMxMjMnLCAnZG9jdW1lbnRzJyk7XG4gKiAvLyA9PiAndXNlcnMvYWJjMTIzL2RvY3VtZW50cydcbiAqIGBgYFxuICovXG5leHBvcnQgZnVuY3Rpb24gam9pblBhdGgoLi4uc2VnbWVudHM6IHN0cmluZ1tdKTogc3RyaW5nIHtcbiAgcmV0dXJuIHNlZ21lbnRzXG4gICAgLmZpbHRlcigocykgPT4gcyAmJiBzLnRyaW0oKSAhPT0gJycpXG4gICAgLm1hcCgocykgPT4gcy5yZXBsYWNlKC9eXFwvK3xcXC8rJC9nLCAnJykpIC8vIFJlbW92ZXIgLyBhbCBpbmljaW8geSBmaW5hbFxuICAgIC5qb2luKCcvJyk7XG59XG4iXX0=
@@ -0,0 +1,302 @@
1
+ /**
2
+ * Query Builder
3
+ *
4
+ * Builder fluido para construir queries de Firestore de manera legible.
5
+ * Alternativa más expresiva a pasar objetos QueryOptions directamente.
6
+ */
7
+ /**
8
+ * Builder fluido para queries de Firestore.
9
+ *
10
+ * @example
11
+ * ```typescript
12
+ * // Construir query con builder
13
+ * const options = new QueryBuilder()
14
+ * .where('status', '==', 'active')
15
+ * .where('age', '>=', 18)
16
+ * .orderBy('createdAt', 'desc')
17
+ * .limit(10)
18
+ * .build();
19
+ *
20
+ * // Usar con FirestoreService
21
+ * const users = await firestoreService.getDocs<User>('users', options);
22
+ *
23
+ * // O con método estático
24
+ * const options2 = QueryBuilder.create()
25
+ * .where('category', '==', 'electronics')
26
+ * .orderBy('price', 'asc')
27
+ * .build();
28
+ * ```
29
+ */
30
+ export class QueryBuilder {
31
+ constructor() {
32
+ this.whereConditions = [];
33
+ this.orderByConditions = [];
34
+ }
35
+ /**
36
+ * Crea una nueva instancia del builder (método estático alternativo).
37
+ */
38
+ static create() {
39
+ return new QueryBuilder();
40
+ }
41
+ /**
42
+ * Agrega una condición where.
43
+ *
44
+ * @param field - Campo a filtrar
45
+ * @param operator - Operador de comparación
46
+ * @param value - Valor a comparar
47
+ *
48
+ * @example
49
+ * ```typescript
50
+ * builder.where('status', '==', 'active')
51
+ * builder.where('price', '>=', 100)
52
+ * builder.where('tags', 'array-contains', 'featured')
53
+ * builder.where('category', 'in', ['electronics', 'books'])
54
+ * ```
55
+ */
56
+ where(field, operator, value) {
57
+ this.whereConditions.push({ field, operator, value });
58
+ return this;
59
+ }
60
+ /**
61
+ * Shortcut para where con operador '=='.
62
+ *
63
+ * @example
64
+ * ```typescript
65
+ * builder.whereEquals('status', 'active')
66
+ * // equivalente a: builder.where('status', '==', 'active')
67
+ * ```
68
+ */
69
+ whereEquals(field, value) {
70
+ return this.where(field, '==', value);
71
+ }
72
+ /**
73
+ * Shortcut para where con operador '!='.
74
+ */
75
+ whereNotEquals(field, value) {
76
+ return this.where(field, '!=', value);
77
+ }
78
+ /**
79
+ * Shortcut para where con operador '>'.
80
+ */
81
+ whereGreaterThan(field, value) {
82
+ return this.where(field, '>', value);
83
+ }
84
+ /**
85
+ * Shortcut para where con operador '>='.
86
+ */
87
+ whereGreaterOrEqual(field, value) {
88
+ return this.where(field, '>=', value);
89
+ }
90
+ /**
91
+ * Shortcut para where con operador '<'.
92
+ */
93
+ whereLessThan(field, value) {
94
+ return this.where(field, '<', value);
95
+ }
96
+ /**
97
+ * Shortcut para where con operador '<='.
98
+ */
99
+ whereLessOrEqual(field, value) {
100
+ return this.where(field, '<=', value);
101
+ }
102
+ /**
103
+ * Shortcut para where con operador 'array-contains'.
104
+ *
105
+ * @example
106
+ * ```typescript
107
+ * builder.whereArrayContains('tags', 'featured')
108
+ * ```
109
+ */
110
+ whereArrayContains(field, value) {
111
+ return this.where(field, 'array-contains', value);
112
+ }
113
+ /**
114
+ * Shortcut para where con operador 'array-contains-any'.
115
+ *
116
+ * @example
117
+ * ```typescript
118
+ * builder.whereArrayContainsAny('tags', ['featured', 'new'])
119
+ * ```
120
+ */
121
+ whereArrayContainsAny(field, values) {
122
+ return this.where(field, 'array-contains-any', values);
123
+ }
124
+ /**
125
+ * Shortcut para where con operador 'in'.
126
+ *
127
+ * @example
128
+ * ```typescript
129
+ * builder.whereIn('status', ['active', 'pending'])
130
+ * ```
131
+ */
132
+ whereIn(field, values) {
133
+ return this.where(field, 'in', values);
134
+ }
135
+ /**
136
+ * Shortcut para where con operador 'not-in'.
137
+ */
138
+ whereNotIn(field, values) {
139
+ return this.where(field, 'not-in', values);
140
+ }
141
+ /**
142
+ * Agrega ordenamiento por un campo.
143
+ *
144
+ * @param field - Campo por el cual ordenar
145
+ * @param direction - Dirección: 'asc' o 'desc' (default: 'asc')
146
+ *
147
+ * @example
148
+ * ```typescript
149
+ * builder.orderBy('createdAt', 'desc')
150
+ * builder.orderBy('name') // asc por defecto
151
+ * ```
152
+ */
153
+ orderBy(field, direction = 'asc') {
154
+ this.orderByConditions.push({ field, direction });
155
+ return this;
156
+ }
157
+ /**
158
+ * Shortcut para orderBy descendente.
159
+ */
160
+ orderByDesc(field) {
161
+ return this.orderBy(field, 'desc');
162
+ }
163
+ /**
164
+ * Shortcut para orderBy ascendente.
165
+ */
166
+ orderByAsc(field) {
167
+ return this.orderBy(field, 'asc');
168
+ }
169
+ /**
170
+ * Limita el número de resultados.
171
+ *
172
+ * @param count - Número máximo de documentos
173
+ *
174
+ * @example
175
+ * ```typescript
176
+ * builder.limit(10)
177
+ * ```
178
+ */
179
+ limit(count) {
180
+ if (count <= 0) {
181
+ throw new Error('El límite debe ser mayor a 0');
182
+ }
183
+ this.limitValue = count;
184
+ return this;
185
+ }
186
+ /**
187
+ * Cursor para paginación: empezar después de un documento.
188
+ *
189
+ * @param cursor - Documento o snapshot desde donde continuar
190
+ *
191
+ * @example
192
+ * ```typescript
193
+ * // Primera página
194
+ * const page1 = await service.getPaginated('users', builder.limit(10).build());
195
+ *
196
+ * // Siguiente página
197
+ * const page2 = await service.getPaginated('users',
198
+ * builder.startAfter(page1.lastDoc).limit(10).build()
199
+ * );
200
+ * ```
201
+ */
202
+ startAfter(cursor) {
203
+ this.startAfterValue = cursor;
204
+ return this;
205
+ }
206
+ /**
207
+ * Cursor para paginación: empezar en un documento.
208
+ */
209
+ startAt(cursor) {
210
+ this.startAtValue = cursor;
211
+ return this;
212
+ }
213
+ /**
214
+ * Cursor para paginación: terminar antes de un documento.
215
+ */
216
+ endBefore(cursor) {
217
+ this.endBeforeValue = cursor;
218
+ return this;
219
+ }
220
+ /**
221
+ * Cursor para paginación: terminar en un documento.
222
+ */
223
+ endAt(cursor) {
224
+ this.endAtValue = cursor;
225
+ return this;
226
+ }
227
+ /**
228
+ * Construye el objeto QueryOptions.
229
+ *
230
+ * @returns QueryOptions para usar con FirestoreService
231
+ */
232
+ build() {
233
+ const options = {};
234
+ if (this.whereConditions.length > 0) {
235
+ options.where = [...this.whereConditions];
236
+ }
237
+ if (this.orderByConditions.length > 0) {
238
+ options.orderBy = [...this.orderByConditions];
239
+ }
240
+ if (this.limitValue !== undefined) {
241
+ options.limit = this.limitValue;
242
+ }
243
+ if (this.startAfterValue !== undefined) {
244
+ options.startAfter = this.startAfterValue;
245
+ }
246
+ if (this.startAtValue !== undefined) {
247
+ options.startAt = this.startAtValue;
248
+ }
249
+ if (this.endBeforeValue !== undefined) {
250
+ options.endBefore = this.endBeforeValue;
251
+ }
252
+ if (this.endAtValue !== undefined) {
253
+ options.endAt = this.endAtValue;
254
+ }
255
+ return options;
256
+ }
257
+ /**
258
+ * Resetea el builder para reutilización.
259
+ */
260
+ reset() {
261
+ this.whereConditions = [];
262
+ this.orderByConditions = [];
263
+ this.limitValue = undefined;
264
+ this.startAfterValue = undefined;
265
+ this.startAtValue = undefined;
266
+ this.endBeforeValue = undefined;
267
+ this.endAtValue = undefined;
268
+ return this;
269
+ }
270
+ /**
271
+ * Clona el builder actual.
272
+ */
273
+ clone() {
274
+ const cloned = new QueryBuilder();
275
+ cloned.whereConditions = [...this.whereConditions];
276
+ cloned.orderByConditions = [...this.orderByConditions];
277
+ cloned.limitValue = this.limitValue;
278
+ cloned.startAfterValue = this.startAfterValue;
279
+ cloned.startAtValue = this.startAtValue;
280
+ cloned.endBeforeValue = this.endBeforeValue;
281
+ cloned.endAtValue = this.endAtValue;
282
+ return cloned;
283
+ }
284
+ }
285
+ /**
286
+ * Función helper para crear un QueryBuilder.
287
+ *
288
+ * @example
289
+ * ```typescript
290
+ * import { query } from 'valtech-components';
291
+ *
292
+ * const options = query()
293
+ * .where('status', '==', 'active')
294
+ * .orderBy('createdAt', 'desc')
295
+ * .limit(10)
296
+ * .build();
297
+ * ```
298
+ */
299
+ export function query() {
300
+ return new QueryBuilder();
301
+ }
302
+ //# sourceMappingURL=data:application/json;base64,eyJ2ZXJzaW9uIjozLCJmaWxlIjoicXVlcnktYnVpbGRlci5qcyIsInNvdXJjZVJvb3QiOiIiLCJzb3VyY2VzIjpbIi4uLy4uLy4uLy4uLy4uLy4uLy4uL3NyYy9saWIvc2VydmljZXMvZmlyZWJhc2UvdXRpbHMvcXVlcnktYnVpbGRlci50cyJdLCJuYW1lcyI6W10sIm1hcHBpbmdzIjoiQUFBQTs7Ozs7R0FLRztBQUlIOzs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7O0dBc0JHO0FBQ0gsTUFBTSxPQUFPLFlBQVk7SUFBekI7UUFDVSxvQkFBZSxHQUFrQixFQUFFLENBQUM7UUFDcEMsc0JBQWlCLEdBQW9CLEVBQUUsQ0FBQztJQThSbEQsQ0FBQztJQXZSQzs7T0FFRztJQUNILE1BQU0sQ0FBQyxNQUFNO1FBQ1gsT0FBTyxJQUFJLFlBQVksRUFBRSxDQUFDO0lBQzVCLENBQUM7SUFFRDs7Ozs7Ozs7Ozs7Ozs7T0FjRztJQUNILEtBQUssQ0FBQyxLQUFhLEVBQUUsUUFBdUIsRUFBRSxLQUFjO1FBQzFELElBQUksQ0FBQyxlQUFlLENBQUMsSUFBSSxDQUFDLEVBQUUsS0FBSyxFQUFFLFFBQVEsRUFBRSxLQUFLLEVBQUUsQ0FBQyxDQUFDO1FBQ3RELE9BQU8sSUFBSSxDQUFDO0lBQ2QsQ0FBQztJQUVEOzs7Ozs7OztPQVFHO0lBQ0gsV0FBVyxDQUFDLEtBQWEsRUFBRSxLQUFjO1FBQ3ZDLE9BQU8sSUFBSSxDQUFDLEtBQUssQ0FBQyxLQUFLLEVBQUUsSUFBSSxFQUFFLEtBQUssQ0FBQyxDQUFDO0lBQ3hDLENBQUM7SUFFRDs7T0FFRztJQUNILGNBQWMsQ0FBQyxLQUFhLEVBQUUsS0FBYztRQUMxQyxPQUFPLElBQUksQ0FBQyxLQUFLLENBQUMsS0FBSyxFQUFFLElBQUksRUFBRSxLQUFLLENBQUMsQ0FBQztJQUN4QyxDQUFDO0lBRUQ7O09BRUc7SUFDSCxnQkFBZ0IsQ0FBQyxLQUFhLEVBQUUsS0FBYztRQUM1QyxPQUFPLElBQUksQ0FBQyxLQUFLLENBQUMsS0FBSyxFQUFFLEdBQUcsRUFBRSxLQUFLLENBQUMsQ0FB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Q0gsSUFBSSxDQUFDLGVBQWUsR0FBRyxFQUFFLENBQUM7UUFDMUIsSUFBSSxDQUFDLGlCQUFpQixHQUFHLEVBQUUsQ0FBQztRQUM1QixJQUFJLENBQUMsVUFBVSxHQUFHLFNBQVMsQ0FBQztRQUM1QixJQUFJLENBQUMsZUFBZSxHQUFHLFNBQVMsQ0FBQztRQUNqQyxJQUFJLENBQUMsWUFBWSxHQUFHLFNBQVMsQ0FBQztRQUM5QixJQUFJLENBQUMsY0FBYyxHQUFHLFNBQVMsQ0FBQztRQUNoQyxJQUFJLENBQUMsVUFBVSxHQUFHLFNBQVMsQ0FBQztRQUM1QixPQUFPLElBQUksQ0FBQztJQUNkLENBQUM7SUFFRDs7T0FFRztJQUNILEtBQUs7UUFDSCxNQUFNLE1BQU0sR0FBRyxJQUFJLFlBQVksRUFBRSxDQUFDO1FBQ2xDLE1BQU0sQ0FBQyxlQUFlLEdBQUcsQ0FBQyxHQUFHLElBQUksQ0FBQyxlQUFlLENBQUMsQ0FBQztRQUNuRCxNQUFNLENBQUMsaUJBQWlCLEdBQUcsQ0FBQyxHQUFHLElBQUksQ0FBQyxpQkFBaUIsQ0FBQyxDQUFDO1FBQ3ZELE1BQU0sQ0FBQyxVQUFVLEdBQUcsSUFBSSxDQUFDLFVBQVUsQ0FBQztRQUNwQyxNQUFNLENBQUMsZUFBZSxHQUFHLElBQUksQ0FBQyxlQUFlLENBQUM7UUFDOUMsTUFBTSxDQUFDLFlBQVksR0FBRyxJQUFJLENBQUMsWUFBWSxDQUFDO1FBQ3hDLE1BQU0sQ0FBQyxjQUFjLEdBQUcsSUFBSSxDQUFDLGNBQWMsQ0FBQztRQUM1QyxNQUFNLENBQUMsVUFBVSxHQUFHLElBQUksQ0FBQyxVQUFVLENBQUM7UUFDcEMsT0FBTyxNQUFNLENBQUM7SUFDaEIsQ0FBQztDQUNGO0FBRUQ7Ozs7Ozs7Ozs7Ozs7R0FhRztBQUNILE1BQU0sVUFBVSxLQUFLO0lBQ25CLE9BQU8sSUFBSSxZQUFZLEVBQUUsQ0FBQztBQUM1QixDQUFDIiwic291cmNlc0NvbnRlbnQiOlsiLyoqXG4gKiBRdWVyeSBCdWlsZGVyXG4gKlxuICogQnVpbGRlciBmbHVpZG8gcGFyYSBjb25zdHJ1aXIgcXVlcmllcyBkZSBGaXJlc3RvcmUgZGUgbWFuZXJhIGxlZ2libGUuXG4gKiBBbHRlcm5hdGl2YSBtw6FzIGV4cHJlc2l2YSBhIHBhc2FyIG9iamV0b3MgUXVlcnlPcHRpb25zIGRpcmVjdGFtZW50ZS5cbiAqL1xuXG5pbXBvcnQgeyBPcmRlckJ5Q2xhdXNlLCBPcmRlckRpcmVjdGlvbiwgUXVlcnlPcHRpb25zLCBXaGVyZUNsYXVzZSwgV2hlcmVPcGVyYXRvciB9IGZyb20gJy4uL3R5cGVzJztcblxuLyoqXG4gKiBCdWlsZGVyIGZsdWlkbyBwYXJhIHF1ZXJpZXMgZGUgRmlyZXN0b3JlLlxuICpcbiAqIEBleGFtcGxlXG4gKiBgYGB0eXBlc2NyaXB0XG4gKiAvLyBDb25zdHJ1aXIgcXVlcnkgY29uIGJ1aWxkZXJcbiAqIGNvbnN0IG9wdGlvbnMgPSBuZXcgUXVlcnlCdWlsZGVyKClcbiAqICAgLndoZXJlKCdzdGF0dXMnLCAnPT0nLCAnYWN0aXZlJylcbiAqICAgLndoZXJlKCdhZ2UnLCAnPj0nLCAxOClcbiAqICAgLm9yZGVyQnkoJ2NyZWF0ZWRBdCcsICdkZXNjJylcbiAqICAgLmxpbWl0KDEwKVxuICogICAuYnVpbGQoKTtcbiAqXG4gKiAvLyBVc2FyIGNvbiBGaXJlc3RvcmVTZXJ2aWNlXG4gKiBjb25zdCB1c2VycyA9IGF3YWl0IGZpcmVzdG9yZVNlcnZpY2UuZ2V0RG9jczxVc2VyPigndXNlcnMnLCBvcHRpb25zKTtcbiAqXG4gKiAvLyBPIGNvbiBtw6l0b2RvIGVzdMOhdGljb1xuICogY29uc3Qgb3B0aW9uczIgPSBRdWVyeUJ1aWxkZXIuY3JlYXRlKClcbiAqICAgLndoZXJlKCdjYXRlZ29yeScsICc9PScsICdlbGVjdHJvbmljcycpXG4gKiAgIC5vcmRlckJ5KCdwcmljZScsICdhc2MnKVxuICogICAuYnVpbGQoKTtcbiAqIGBgYFxuICovXG5leHBvcnQgY2xhc3MgUXVlcnlCdWlsZGVyIHtcbiAgcHJpdmF0ZSB3aGVyZUNvbmRpdGlvbnM6IFdoZXJlQ2xhdXNlW10gPSBbXTtcbiAgcHJpdmF0ZSBvcmRlckJ5Q29uZGl0aW9uczogT3JkZXJCeUNsYXVzZVtdID0gW107XG4gIHByaXZhdGUgbGltaXRWYWx1ZT86IG51bWJlcjtcbiAgcHJpdmF0ZSBzdGFydEFmdGVyVmFsdWU/OiB1bmtub3duO1xuICBwcml2YXRlIHN0YXJ0QXRWYWx1ZT86IHVua25vd247XG4gIHByaXZhdGUgZW5kQmVmb3JlVmFsdWU/OiB1bmtub3duO1xuICBwcml2YXRlIGVuZEF0VmFsdWU/OiB1bmtub3duO1xuXG4gIC8qKlxuICAgKiBDcmVhIHVuYSBudWV2YSBpbnN0YW5jaWEgZGVsIGJ1aWxkZXIgKG3DqXRvZG8gZXN0w6F0aWNvIGFsdGVybmF0aXZvKS5cbiAgICovXG4gIHN0YXRpYyBjcmVhdGUoKTogUXVlcnlCdWlsZGVyIHtcbiAgICByZXR1cm4gbmV3IFF1ZXJ5QnVpbGRlcigpO1xuICB9XG5cbiAgLyoqXG4gICAqIEFncmVnYSB1bmEgY29uZGljacOzbiB3aGVyZS5cbiAgICpcbiAgICogQHBhcmFtIGZpZWxkIC0gQ2FtcG8gYSBmaWx0cmFyXG4gICAqIEBwYXJhbSBvcGVyYXRvciAtIE9wZXJhZG9yIGRlIGNvbXBhcmFjacOzblxuICAgKiBAcGFyYW0gdmFsdWUgLSBWYWxvciBhIGNvbXBhcmFyXG4gICAqXG4gICAqIEBleGFtcGxlXG4gICAqIGBgYHR5cGVzY3JpcHRcbiAgICogYnVpbGRlci53aGVyZSgnc3RhdHVzJywgJz09JywgJ2FjdGl2ZScpXG4gICAqIGJ1aWxkZXIud2hlcmUoJ3ByaWNlJywgJz49JywgMTAwKVxuICAgKiBidWlsZGVyLndoZXJlKCd0YWdzJywgJ2FycmF5LWNvbnRhaW5zJywgJ2ZlYXR1cmVkJylcbiAgICogYnVpbGRlci53aGVyZSgnY2F0ZWdvcnknLCAnaW4nLCBbJ2VsZWN0cm9uaWNzJywgJ2Jvb2tzJ10pXG4gICAqIGBgYFxuICAgKi9cbiAgd2hlcmUoZmllbGQ6IHN0cmluZywgb3BlcmF0b3I6IFdoZXJlT3BlcmF0b3IsIHZhbHVlOiB1bmtub3duKTogUXVlcnlCdWlsZGVyIHtcbiAgICB0aGlzLndoZXJlQ29uZGl0aW9ucy5wdXNoKHsgZmllbGQsIG9wZXJhdG9yLCB2YWx1ZSB9KTtcbiAgICByZXR1cm4gdGhpcztcbiAgfVxuXG4gIC8qKlxuICAgKiBTaG9ydGN1dCBwYXJhIHdoZXJlIGNvbiBvcGVyYWRvciAnPT0nLlxuICAgKlxuICAgKiBAZXhhbXBsZVxuICAgKiBgYGB0eXBlc2NyaXB0XG4gICAqIGJ1aWxkZXIud2hlcmVFcXVhbHMoJ3N0YXR1cycsICdhY3RpdmUnKVxuICAgKiAvLyBlcXVpdmFsZW50ZSBhOiBidWlsZGVyLndoZXJlKCdzdGF0dXMnLCAnPT0nLCAnYWN0aXZlJylcbiAgICogYGBgXG4gICAqL1xuICB3aGVyZUVxdWFscyhmaWVsZDogc3RyaW5nLCB2YWx1ZTogdW5rbm93bik6IFF1ZXJ5QnVpbGRlciB7XG4gICAgcmV0dXJuIHRoaXMud2hlcmUoZmllbGQsICc9PScsIHZhbHVlKTtcbiAgfVxuXG4gIC8qKlxuICAgKiBTaG9ydGN1dCBwYXJhIHdoZXJlIGNvbiBvcGVyYWRvciAnIT0nLlxuICAgKi9cbiAgd2hlcmVOb3RFcXVhbHMoZmllbGQ6IHN0cmluZywgdmFsdWU6IHVua25vd24pOiBRdWVyeUJ1aWxkZXIge1xuICAgIHJldHVybiB0aGlzLndoZXJlKGZpZWxkLCAnIT0nLCB2YWx1ZSk7XG4gIH1cblxuICAvKipcbiAgICogU2hvcnRjdXQgcGFyYSB3aGVyZSBjb24gb3BlcmFkb3IgJz4nLlxuICAgKi9cbiAgd2hlcmVHcmVhdGVyVGhhbihmaWVsZDogc3RyaW5nLCB2YWx1ZTogdW5rbm93bik6IFF1ZXJ5QnVpbGRlciB7XG4gICAgcmV0dXJuIHRoaXMud2hlcmUoZmllbGQsICc+JywgdmFsdWUpO1xuICB9XG5cbiAgLyoqXG4gICAqIFNob3J0Y3V0IHBhcmEgd2hlcmUgY29uIG9wZXJhZG9yICc+PScuXG4gICAqL1xuICB3aGVyZUdyZWF0ZXJPckVxdWFsKGZpZWxkOiBzdHJpbmcsIHZhbHVlOiB1bmtub3duKTogUXVlcnlCdWlsZGVyIHtcbiAgICByZXR1cm4gdGhpcy53aGVyZShmaWVsZCwgJz49JywgdmFsdWUpO1xuICB9XG5cbiAgLyoqXG4gICAqIFNob3J0Y3V0IHBhcmEgd2hlcmUgY29uIG9wZXJhZG9yICc8Jy5cbiAgICovXG4gIHdoZXJlTGVzc1RoYW4oZmllbGQ6IHN0cmluZywgdmFsdWU6IHVua25vd24pOiBRdWVyeUJ1aWxkZXIge1xuICAgIHJldHVybiB0aGlzLndoZXJlKGZpZWxkLCAnPCcsIHZhbHVlKTtcbiAgfVxuXG4gIC8qKlxuICAgKiBTaG9ydGN1dCBwYXJhIHdoZXJlIGNvbiBvcGVyYWRvciAnPD0nLlxuICAgKi9cbiAgd2hlcmVMZXNzT3JFcXVhbChmaWVsZDogc3RyaW5nLCB2YWx1ZTogdW5rbm93bik6IFF1ZXJ5QnVpbGRlciB7XG4gICAgcmV0dXJuIHRoaXMud2hlcmUoZmllbGQsICc8PScsIHZhbHVlKTtcbiAgfVxuXG4gIC8qKlxuICAgKiBTaG9ydGN1dCBwYXJhIHdoZXJlIGNvbiBvcGVyYWRvciAnYXJyYXktY29udGFpbnMnLlxuICAgKlxuICAgKiBAZXhhbXBsZVxuICAgKiBgYGB0eXBlc2NyaXB0XG4gICAqIGJ1aWxkZXIud2hlcmVBcnJheUNvbnRhaW5zKCd0YWdzJywgJ2ZlYXR1cmVkJylcbiAgICogYGBgXG4gICAqL1xuICB3aGVyZUFycmF5Q29udGFpbnMoZmllbGQ6IHN0cmluZywgdmFsdWU6IHVua25vd24pOiBRdWVyeUJ1aWxkZXIge1xuICAgIHJldHVybiB0aGlzLndoZXJlKGZpZWxkLCAnYXJyYXktY29udGFpbnMnLCB2YWx1ZSk7XG4gIH1cblxuICAvKipcbiAgICogU2hvcnRjdXQgcGFyYSB3aGVyZSBjb24gb3BlcmFkb3IgJ2FycmF5LWNvbnRhaW5zLWFueScuXG4gICAqXG4gICAqIEBleGFtcGxlXG4gICAqIGBgYHR5cGVzY3JpcHRcbiAgICogYnVpbGRlci53aGVyZUFycmF5Q29udGFpbnNBbnkoJ3RhZ3MnLCBbJ2ZlYXR1cmVkJywgJ25ldyddKVxuICAgKiBgYGBcbiAgICovXG4gIHdoZXJlQXJyYXlDb250YWluc0FueShmaWVsZDogc3RyaW5nLCB2YWx1ZXM6IHVua25vd25bXSk6IFF1ZXJ5QnVpbGRlciB7XG4gICAgcmV0dXJuIHRoaXMud2hlcmUoZmllbGQsICdhcnJheS1jb250YWlucy1hbnknLCB2YWx1ZXMpO1xuICB9XG5cbiAgLyoqXG4gICAqIFNob3J0Y3V0IHBhcmEgd2hlcmUgY29uIG9wZXJhZG9yICdpbicuXG4gICAqXG4gICAqIEBleGFtcGxlXG4gICAqIGBgYHR5cGVzY3JpcHRcbiAgICogYnVpbGRlci53aGVyZUluKCdzdGF0dXMnLCBbJ2FjdGl2ZScsICdwZW5kaW5nJ10pXG4gICAqIGBgYFxuICAgKi9cbiAgd2hlcmVJbihmaWVsZDogc3RyaW5nLCB2YWx1ZXM6IHVua25vd25bXSk6IFF1ZXJ5QnVpbGRlciB7XG4gICAgcmV0dXJuIHRoaXMud2hlcmUoZmllbGQsICdpbicsIHZhbHVlcyk7XG4gIH1cblxuICAvKipcbiAgICogU2hvcnRjdXQgcGFyYSB3aGVyZSBjb24gb3BlcmFkb3IgJ25vdC1pbicuXG4gICAqL1xuICB3aGVyZU5vdEluKGZpZWxkOiBzdHJpbmcsIHZhbHVlczogdW5rbm93bltdKTogUXVlcnlCdWlsZGVyIHtcbiAgICByZXR1cm4gdGhpcy53aGVyZShmaWVsZCwgJ25vdC1pbicsIHZhbHVlcyk7XG4gIH1cblxuICAvKipcbiAgICogQWdyZWdhIG9yZGVuYW1pZW50byBwb3IgdW4gY2FtcG8uXG4gICAqXG4gICAqIEBwYXJhbSBmaWVsZCAtIENhbXBvIHBvciBlbCBjdWFsIG9yZGVuYXJcbiAgICogQHBhcmFtIGRpcmVjdGlvbiAtIERpcmVjY2nDs246ICdhc2MnIG8gJ2Rlc2MnIChkZWZhdWx0OiAnYXNjJylcbiAgICpcbiAgICogQGV4YW1wbGVcbiAgICogYGBgdHlwZXNjcmlwdFxuICAgKiBidWlsZGVyLm9yZGVyQnkoJ2NyZWF0ZWRBdCcsICdkZXNjJylcbiAgICogYnVpbGRlci5vcmRlckJ5KCduYW1lJykgLy8gYXNjIHBvciBkZWZlY3RvXG4gICAqIGBgYFxuICAgKi9cbiAgb3JkZXJCeShmaWVsZDogc3RyaW5nLCBkaXJlY3Rpb246IE9yZGVyRGlyZWN0aW9uID0gJ2FzYycpOiBRdWVyeUJ1aWxkZXIge1xuICAgIHRoaXMub3JkZXJCeUNvbmRpdGlvbnMucHVzaCh7IGZpZWxkLCBkaXJlY3Rpb24gfSk7XG4gICAgcmV0dXJuIHRoaXM7XG4gIH1cblxuICAvKipcbiAgICogU2hvcnRjdXQgcGFyYSBvcmRlckJ5IGRlc2NlbmRlbnRlLlxuICAgKi9cbiAgb3JkZXJCeURlc2MoZmllbGQ6IHN0cmluZyk6IFF1ZXJ5QnVpbGRlciB7XG4gICAgcmV0dXJuIHRoaXMub3JkZXJCeShmaWVsZCwgJ2Rlc2MnKTtcbiAgfVxuXG4gIC8qKlxuICAgKiBTaG9ydGN1dCBwYXJhIG9yZGVyQnkgYXNjZW5kZW50ZS5cbiAgICovXG4gIG9yZGVyQnlBc2MoZmllbGQ6IHN0cmluZyk6IFF1ZXJ5QnVpbGRlciB7XG4gICAgcmV0dXJuIHRoaXMub3JkZXJCeShmaWVsZCwgJ2FzYycpO1xuICB9XG5cbiAgLyoqXG4gICAqIExpbWl0YSBlbCBuw7ptZXJvIGRlIHJlc3VsdGFkb3MuXG4gICAqXG4gICAqIEBwYXJhbSBjb3VudCAtIE7Dum1lcm8gbcOheGltbyBkZSBkb2N1bWVudG9zXG4gICAqXG4gICAqIEBleGFtcGxlXG4gICAqIGBgYHR5cGVzY3JpcHRcbiAgICogYnVpbGRlci5saW1pdCgxMClcbiAgICogYGBgXG4gICAqL1xuICBsaW1pdChjb3VudDogbnVtYmVyKTogUXVlcnlCdWlsZGVyIHtcbiAgICBpZiAoY291bnQgPD0gMCkge1xuICAgICAgdGhyb3cgbmV3IEVycm9yKCdFbCBsw61taXRlIGRlYmUgc2VyIG1heW9yIGEgMCcpO1xuICAgIH1cbiAgICB0aGlzLmxpbWl0VmFsdWUgPSBjb3VudDtcbiAgICByZXR1cm4gdGhpcztcbiAgfVxuXG4gIC8qKlxuICAgKiBDdXJzb3IgcGFyYSBwYWdpbmFjacOzbjogZW1wZXphciBkZXNwdcOpcyBkZSB1biBkb2N1bWVudG8uXG4gICAqXG4gICAqIEBwYXJhbSBjdXJzb3IgLSBEb2N1bWVudG8gbyBzbmFwc2hvdCBkZXNkZSBkb25kZSBjb250aW51YXJcbiAgICpcbiAgICogQGV4YW1wbGVcbiAgICogYGBgdHlwZXNjcmlwdFxuICAgKiAvLyBQcmltZXJhIHDDoWdpbmFcbiAgICogY29uc3QgcGFnZTEgPSBhd2FpdCBzZXJ2aWNlLmdldFBhZ2luYXRlZCgndXNlcnMnLCBidWlsZGVyLmxpbWl0KDEwKS5idWlsZCgpKTtcbiAgICpcbiAgICogLy8gU2lndWllbnRlIHDDoWdpbmFcbiAgICogY29uc3QgcGFnZTIgPSBhd2FpdCBzZXJ2aWNlLmdldFBhZ2luYXRlZCgndXNlcnMnLFxuICAgKiAgIGJ1aWxkZXIuc3RhcnRBZnRlcihwYWdlMS5sYXN0RG9jKS5saW1pdCgxMCkuYnVpbGQoKVxuICAgKiApO1xuICAgKiBgYGBcbiAgICovXG4gIHN0YXJ0QWZ0ZXIoY3Vyc29yOiB1bmtub3duKTogUXVlcnlCdWlsZGVyIHtcbiAgICB0aGlzLnN0YXJ0QWZ0ZXJWYWx1ZSA9IGN1cnNvcjtcbiAgICByZXR1cm4gdGhpcztcbiAgfVxuXG4gIC8qKlxuICAgKiBDdXJzb3IgcGFyYSBwYWdpbmFjacOzbjogZW1wZXphciBlbiB1biBkb2N1bWVudG8uXG4gICAqL1xuICBzdGFydEF0KGN1cnNvcjogdW5rbm93bik6IFF1ZXJ5QnVpbGRlciB7XG4gICAgdGhpcy5zdGFydEF0VmFsdWUgPSBjdXJzb3I7XG4gICAgcmV0dXJuIHRoaXM7XG4gIH1cblxuICAvKipcbiAgICogQ3Vyc29yIHBhcmEgcGFnaW5hY2nDs246IHRlcm1pbmFyIGFudGVzIGRlIHVuIGRvY3VtZW50by5cbiAgICovXG4gIGVuZEJlZm9yZShjdXJzb3I6IHVua25vd24pOiBRdWVyeUJ1aWxkZXIge1xuICAgIHRoaXMuZW5kQmVmb3JlVmFsdWUgPSBjdXJzb3I7XG4gICAgcmV0dXJuIHRoaXM7XG4gIH1cblxuICAvKipcbiAgICogQ3Vyc29yIHBhcmEgcGFnaW5hY2nDs246IHRlcm1pbmFyIGVuIHVuIGRvY3VtZW50by5cbiAgICovXG4gIGVuZEF0KGN1cnNvcjogdW5rbm93bik6IFF1ZXJ5QnVpbGRlciB7XG4gICAgdGhpcy5lbmRBdFZhbHVlID0gY3Vyc29yO1xuICAgIHJldHVybiB0aGlzO1xuICB9XG5cbiAgLyoqXG4gICAqIENvbnN0cnV5ZSBlbCBvYmpldG8gUXVlcnlPcHRpb25zLlxuICAgKlxuICAgKiBAcmV0dXJucyBRdWVyeU9wdGlvbnMgcGFyYSB1c2FyIGNvbiBGaXJlc3RvcmVTZXJ2aWNlXG4gICAqL1xuICBidWlsZCgpOiBRdWVyeU9wdGlvbnMge1xuICAgIGNvbnN0IG9wdGlvbnM6IFF1ZXJ5T3B0aW9ucyA9IHt9O1xuXG4gICAgaWYgKHRoaXMud2hlcmVDb25kaXRpb25zLmxlbmd0aCA+IDApIHtcbiAgICAgIG9wdGlvbnMud2hlcmUgPSBbLi4udGhpcy53aGVyZUNvbmRpdGlvbnNdO1xuICAgIH1cblxuICAgIGlmICh0aGlzLm9yZGVyQnlDb25kaXRpb25zLmxlbmd0aCA+IDApIHtcbiAgICAgIG9wdGlvbnMub3JkZXJCeSA9IFsuLi50aGlzLm9yZGVyQnlDb25kaXRpb25zXTtcbiAgICB9XG5cbiAgICBpZiAodGhpcy5saW1pdFZhbHVlICE9PSB1bmRlZmluZWQpIHtcbiAgICAgIG9wdGlvbnMubGltaXQgPSB0aGlzLmxpbWl0VmFsdWU7XG4gICAgfVxuXG4gICAgaWYgKHRoaXMuc3RhcnRBZnRlclZhbHVlICE9PSB1bmRlZmluZWQpIHtcbiAgICAgIG9wdGlvbnMuc3RhcnRBZnRlciA9IHRoaXMuc3RhcnRBZnRlclZhbHVlO1xuICAgIH1cblxuICAgIGlmICh0aGlzLnN0YXJ0QXRWYWx1ZSAhPT0gdW5kZWZpbmVkKSB7XG4gICAgICBvcHRpb25zLnN0YXJ0QXQgPSB0aGlzLnN0YXJ0QXRWYWx1ZTtcbiAgICB9XG5cbiAgICBpZiAodGhpcy5lbmRCZWZvcmVWYWx1ZSAhPT0gdW5kZWZpbmVkKSB7XG4gICAgICBvcHRpb25zLmVuZEJlZm9yZSA9IHRoaXMuZW5kQmVmb3JlVmFsdWU7XG4gICAgfVxuXG4gICAgaWYgKHRoaXMuZW5kQXRWYWx1ZSAhPT0gdW5kZWZpbmVkKSB7XG4gICAgICBvcHRpb25zLmVuZEF0ID0gdGhpcy5lbmRBdFZhbHVlO1xuICAgIH1cblxuICAgIHJldHVybiBvcHRpb25zO1xuICB9XG5cbiAgLyoqXG4gICAqIFJlc2V0ZWEgZWwgYnVpbGRlciBwYXJhIHJldXRpbGl6YWNpw7NuLlxuICAgKi9cbiAgcmVzZXQoKTogUXVlcnlCdWlsZGVyIHtcbiAgICB0aGlzLndoZXJlQ29uZGl0aW9ucyA9IFtdO1xuICAgIHRoaXMub3JkZXJCeUNvbmRpdGlvbnMgPSBbXTtcbiAgICB0aGlzLmxpbWl0VmFsdWUgPSB1bmRlZmluZWQ7XG4gICAgdGhpcy5zdGFydEFmdGVyVmFsdWUgPSB1bmRlZmluZWQ7XG4gICAgdGhpcy5zdGFydEF0VmFsdWUgPSB1bmRlZmluZWQ7XG4gICAgdGhpcy5lbmRCZWZvcmVWYWx1ZSA9IHVuZGVmaW5lZDtcbiAgICB0aGlzLmVuZEF0VmFsdWUgPSB1bmRlZmluZWQ7XG4gICAgcmV0dXJuIHRoaXM7XG4gIH1cblxuICAvKipcbiAgICogQ2xvbmEgZWwgYnVpbGRlciBhY3R1YWwuXG4gICAqL1xuICBjbG9uZSgpOiBRdWVyeUJ1aWxkZXIge1xuICAgIGNvbnN0IGNsb25lZCA9IG5ldyBRdWVyeUJ1aWxkZXIoKTtcbiAgICBjbG9uZWQud2hlcmVDb25kaXRpb25zID0gWy4uLnRoaXMud2hlcmVDb25kaXRpb25zXTtcbiAgICBjbG9uZWQub3JkZXJCeUNvbmRpdGlvbnMgPSBbLi4udGhpcy5vcmRlckJ5Q29uZGl0aW9uc107XG4gICAgY2xvbmVkLmxpbWl0VmFsdWUgPSB0aGlzLmxpbWl0VmFsdWU7XG4gICAgY2xvbmVkLnN0YXJ0QWZ0ZXJWYWx1ZSA9IHRoaXMuc3RhcnRBZnRlclZhbHVlO1xuICAgIGNsb25lZC5zdGFydEF0VmFsdWUgPSB0aGlzLnN0YXJ0QXRWYWx1ZTtcbiAgICBjbG9uZWQuZW5kQmVmb3JlVmFsdWUgPSB0aGlzLmVuZEJlZm9yZVZhbHVlO1xuICAgIGNsb25lZC5lbmRBdFZhbHVlID0gdGhpcy5lbmRBdFZhbHVlO1xuICAgIHJldHVybiBjbG9uZWQ7XG4gIH1cbn1cblxuLyoqXG4gKiBGdW5jacOzbiBoZWxwZXIgcGFyYSBjcmVhciB1biBRdWVyeUJ1aWxkZXIuXG4gKlxuICogQGV4YW1wbGVcbiAqIGBgYHR5cGVzY3JpcHRcbiAqIGltcG9ydCB7IHF1ZXJ5IH0gZnJvbSAndmFsdGVjaC1jb21wb25lbnRzJztcbiAqXG4gKiBjb25zdCBvcHRpb25zID0gcXVlcnkoKVxuICogICAud2hlcmUoJ3N0YXR1cycsICc9PScsICdhY3RpdmUnKVxuICogICAub3JkZXJCeSgnY3JlYXRlZEF0JywgJ2Rlc2MnKVxuICogICAubGltaXQoMTApXG4gKiAgIC5idWlsZCgpO1xuICogYGBgXG4gKi9cbmV4cG9ydCBmdW5jdGlvbiBxdWVyeSgpOiBRdWVyeUJ1aWxkZXIge1xuICByZXR1cm4gbmV3IFF1ZXJ5QnVpbGRlcigpO1xufVxuIl19