valtech-components 2.0.498 → 2.0.501

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 (49) hide show
  1. package/esm2022/lib/components/atoms/button/button.component.mjs +87 -48
  2. package/esm2022/lib/components/molecules/action-header/action-header.component.mjs +1 -1
  3. package/esm2022/lib/components/molecules/ad-slot/ad-slot.component.mjs +249 -0
  4. package/esm2022/lib/components/molecules/button-group/button-group.component.mjs +1 -1
  5. package/esm2022/lib/components/molecules/card/card.component.mjs +2 -2
  6. package/esm2022/lib/components/molecules/file-input/file-input.component.mjs +1 -1
  7. package/esm2022/lib/components/molecules/raffle-status-card/raffle-status-card.component.mjs +2 -2
  8. package/esm2022/lib/components/organisms/article/article.component.mjs +2 -2
  9. package/esm2022/lib/components/organisms/menu/menu.component.mjs +1 -1
  10. package/esm2022/lib/components/templates/page-template/page-template.component.mjs +1 -1
  11. package/esm2022/lib/services/ads/ads-consent.service.mjs +152 -0
  12. package/esm2022/lib/services/ads/ads-loader.service.mjs +160 -0
  13. package/esm2022/lib/services/ads/ads.service.mjs +449 -0
  14. package/esm2022/lib/services/ads/config.mjs +118 -0
  15. package/esm2022/lib/services/ads/index.mjs +14 -0
  16. package/esm2022/lib/services/ads/types.mjs +23 -0
  17. package/esm2022/lib/services/auth/auth.service.mjs +103 -6
  18. package/esm2022/lib/services/auth/index.mjs +4 -1
  19. package/esm2022/lib/services/auth/oauth-callback.component.mjs +141 -0
  20. package/esm2022/lib/services/auth/oauth.service.mjs +250 -0
  21. package/esm2022/lib/services/auth/types.mjs +1 -1
  22. package/esm2022/lib/services/firebase/analytics-error-handler.mjs +141 -0
  23. package/esm2022/lib/services/firebase/analytics-router-tracker.mjs +99 -0
  24. package/esm2022/lib/services/firebase/analytics.service.mjs +597 -0
  25. package/esm2022/lib/services/firebase/config.mjs +21 -2
  26. package/esm2022/lib/services/firebase/index.mjs +6 -1
  27. package/esm2022/public-api.mjs +6 -1
  28. package/fesm2022/valtech-components.mjs +2739 -239
  29. package/fesm2022/valtech-components.mjs.map +1 -1
  30. package/lib/components/atoms/button/button.component.d.ts +30 -6
  31. package/lib/components/molecules/ad-slot/ad-slot.component.d.ts +78 -0
  32. package/lib/components/organisms/article/article.component.d.ts +3 -3
  33. package/lib/services/ads/ads-consent.service.d.ts +59 -0
  34. package/lib/services/ads/ads-loader.service.d.ts +46 -0
  35. package/lib/services/ads/ads.service.d.ts +123 -0
  36. package/lib/services/ads/config.d.ts +69 -0
  37. package/lib/services/ads/index.d.ts +10 -0
  38. package/lib/services/ads/types.d.ts +163 -0
  39. package/lib/services/auth/auth.service.d.ts +56 -3
  40. package/lib/services/auth/index.d.ts +2 -0
  41. package/lib/services/auth/oauth-callback.component.d.ts +34 -0
  42. package/lib/services/auth/oauth.service.d.ts +90 -0
  43. package/lib/services/auth/types.d.ts +69 -0
  44. package/lib/services/firebase/analytics-error-handler.d.ts +54 -0
  45. package/lib/services/firebase/analytics-router-tracker.d.ts +51 -0
  46. package/lib/services/firebase/analytics.service.d.ts +256 -0
  47. package/lib/services/firebase/index.d.ts +4 -0
  48. package/package.json +1 -1
  49. package/public-api.d.ts +2 -0
@@ -0,0 +1,141 @@
1
+ /**
2
+ * Analytics Error Handler
3
+ *
4
+ * ErrorHandler personalizado que envía errores no capturados a Firebase Analytics.
5
+ * Se activa si enableErrorTracking=true en analyticsConfig.
6
+ */
7
+ import { ErrorHandler, Injectable, inject } from '@angular/core';
8
+ import { AnalyticsService } from './analytics.service';
9
+ import * as i0 from "@angular/core";
10
+ /**
11
+ * ErrorHandler que trackea errores en Firebase Analytics.
12
+ *
13
+ * Captura errores no manejados de la aplicación y los envía a GA4
14
+ * como eventos 'error_occurred'. También delega al ErrorHandler
15
+ * default para mantener el comportamiento de console.error.
16
+ *
17
+ * @example
18
+ * ```typescript
19
+ * // Se activa automáticamente si enableErrorTracking=true
20
+ * provideValtechFirebase({
21
+ * firebase: environment.firebase,
22
+ * enableAnalytics: true,
23
+ * analyticsConfig: {
24
+ * enableErrorTracking: true,
25
+ * },
26
+ * });
27
+ * ```
28
+ */
29
+ export class AnalyticsErrorHandler {
30
+ constructor() {
31
+ this.analytics = inject(AnalyticsService);
32
+ this.defaultHandler = new ErrorHandler();
33
+ }
34
+ /**
35
+ * Maneja un error no capturado.
36
+ * Envía el error a Analytics y luego al handler default.
37
+ */
38
+ handleError(error) {
39
+ // Enviar a Analytics
40
+ try {
41
+ this.trackError(error);
42
+ }
43
+ catch (trackingError) {
44
+ // No fallar si el tracking falla
45
+ console.warn('[AnalyticsErrorHandler] Error tracking failed:', trackingError);
46
+ }
47
+ // Delegar al handler default (console.error)
48
+ this.defaultHandler.handleError(error);
49
+ }
50
+ /**
51
+ * Trackea el error en Analytics
52
+ */
53
+ trackError(error) {
54
+ // Extraer información del error
55
+ const errorInfo = this.extractErrorInfo(error);
56
+ this.analytics.logError(errorInfo.error, {
57
+ source: 'uncaught',
58
+ url: this.getCurrentUrl(),
59
+ ...errorInfo.context,
60
+ });
61
+ }
62
+ /**
63
+ * Extrae información útil del error
64
+ */
65
+ extractErrorInfo(error) {
66
+ const context = {};
67
+ // Error estándar
68
+ if (error instanceof Error) {
69
+ // Detectar errores de chunk loading (lazy loading)
70
+ if (error.message.includes('Loading chunk')) {
71
+ context['error_category'] = 'chunk_loading';
72
+ }
73
+ // Detectar errores de red
74
+ if (error.message.includes('NetworkError') || error.message.includes('Failed to fetch')) {
75
+ context['error_category'] = 'network';
76
+ }
77
+ return { error, context };
78
+ }
79
+ // ErrorEvent (ej: errores de script)
80
+ if (typeof ErrorEvent !== 'undefined' && error instanceof ErrorEvent) {
81
+ return {
82
+ error: new Error(error.message || 'Script error'),
83
+ context: {
84
+ filename: error.filename || 'unknown',
85
+ lineno: String(error.lineno || 0),
86
+ colno: String(error.colno || 0),
87
+ },
88
+ };
89
+ }
90
+ // PromiseRejection
91
+ if (this.isPromiseRejection(error)) {
92
+ const reason = error.reason;
93
+ if (reason instanceof Error) {
94
+ return {
95
+ error: reason,
96
+ context: { error_category: 'unhandled_promise' },
97
+ };
98
+ }
99
+ return {
100
+ error: new Error(String(reason) || 'Unhandled promise rejection'),
101
+ context: { error_category: 'unhandled_promise' },
102
+ };
103
+ }
104
+ // Objeto con message
105
+ if (error && typeof error === 'object' && 'message' in error) {
106
+ return {
107
+ error: new Error(String(error.message)),
108
+ context,
109
+ };
110
+ }
111
+ // Fallback: convertir a string
112
+ return {
113
+ error: new Error(String(error) || 'Unknown error'),
114
+ context,
115
+ };
116
+ }
117
+ /**
118
+ * Verifica si es un PromiseRejectionEvent
119
+ */
120
+ isPromiseRejection(error) {
121
+ return (typeof PromiseRejectionEvent !== 'undefined' &&
122
+ error instanceof PromiseRejectionEvent);
123
+ }
124
+ /**
125
+ * Obtiene la URL actual de forma segura
126
+ */
127
+ getCurrentUrl() {
128
+ try {
129
+ return window?.location?.href || 'unknown';
130
+ }
131
+ catch {
132
+ return 'unknown';
133
+ }
134
+ }
135
+ static { this.ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "18.2.14", ngImport: i0, type: AnalyticsErrorHandler, deps: [], target: i0.ɵɵFactoryTarget.Injectable }); }
136
+ static { this.ɵprov = i0.ɵɵngDeclareInjectable({ minVersion: "12.0.0", version: "18.2.14", ngImport: i0, type: AnalyticsErrorHandler }); }
137
+ }
138
+ i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "18.2.14", ngImport: i0, type: AnalyticsErrorHandler, decorators: [{
139
+ type: Injectable
140
+ }] });
141
+ //# sourceMappingURL=data:application/json;base64,eyJ2ZXJzaW9uIjozLCJmaWxlIjoiYW5hbHl0aWNzLWVycm9yLWhhbmRsZXIuanMiLCJzb3VyY2VSb290IjoiIiwic291cmNlcyI6WyIuLi8uLi8uLi8uLi8uLi8uLi9zcmMvbGliL3NlcnZpY2VzL2ZpcmViYXNlL2FuYWx5dGljcy1lcnJvci1oYW5kbGVyLnRzIl0sIm5hbWVzIjpbXSwibWFwcGluZ3MiOiJBQUFBOzs7OztHQUtHO0FBRUgsT0FBTyxFQUFFLFlBQVksRUFBRSxVQUFVLEVBQUUsTUFBTSxFQUFFLE1BQU0sZUFBZSxDQUFDO0FBQ2pFLE9BQU8sRUFBRSxnQkFBZ0IsRUFBRSxNQUFNLHFCQUFxQixDQUFDOztBQUV2RDs7Ozs7Ozs7Ozs7Ozs7Ozs7O0dBa0JHO0FBRUgsTUFBTSxPQUFPLHFCQUFxQjtJQURsQztRQUVtQixjQUFTLEdBQUcsTUFBTSxDQUFDLGdCQUFnQixDQUFDLENBQUM7UUFDckMsbUJBQWMsR0FBRyxJQUFJLFlBQVksRUFBRSxDQUFDO0tBMEh0RDtJQXhIQzs7O09BR0c7SUFDSCxXQUFXLENBQUMsS0FBYztRQUN4QixxQkFBcUI7UUFDckIsSUFBSSxDQUFDO1lBQ0gsSUFBSSxDQUFDLFVBQVUsQ0FBQyxLQUFLLENBQUMsQ0FBQztRQUN6QixDQUFDO1FBQUMsT0FBTyxhQUFhLEVBQUUsQ0FBQztZQUN2QixpQ0FBaUM7WUFDakMsT0FBTyxDQUFDLElBQUksQ0FBQyxnREFBZ0QsRUFBRSxhQUFhLENBQUMsQ0FBQztRQUNoRixDQUFDO1FBRUQsNkNBQTZDO1FBQzdDLElBQUksQ0FBQyxjQUFjLENBQUMsV0FBVyxDQUFDLEtBQUssQ0FBQyxDQUFDO0lBQ3pDLENBQUM7SUFFRDs7T0FFRztJQUNLLFVBQVUsQ0FBQyxLQUFjO1FBQy9CLGdDQUFnQztRQUNoQyxNQUFNLFNBQVMsR0FBRyxJQUFJLENBQUMsZ0JBQWdCLENBQUMsS0FBSyxDQUFDLENBQUM7UUFFL0MsSUFBSSxDQUFDLFNBQVMsQ0FBQyxRQUFRLENBQ3JCLFNBQVMsQ0FBQyxLQUFLLEVBQ2Y7WUFDRSxNQUFNLEVBQUUs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QUFDO1FBQzdDLENBQUM7UUFBQyxNQUFNLENBQUM7WUFDUCxPQUFPLFNBQVMsQ0FBQztRQUNuQixDQUFDO0lBQ0gsQ0FBQzsrR0EzSFUscUJBQXFCO21IQUFyQixxQkFBcUI7OzRGQUFyQixxQkFBcUI7a0JBRGpDLFVBQVUiLCJzb3VyY2VzQ29udGVudCI6WyIvKipcbiAqIEFuYWx5dGljcyBFcnJvciBIYW5kbGVyXG4gKlxuICogRXJyb3JIYW5kbGVyIHBlcnNvbmFsaXphZG8gcXVlIGVudsOtYSBlcnJvcmVzIG5vIGNhcHR1cmFkb3MgYSBGaXJlYmFzZSBBbmFseXRpY3MuXG4gKiBTZSBhY3RpdmEgc2kgZW5hYmxlRXJyb3JUcmFja2luZz10cnVlIGVuIGFuYWx5dGljc0NvbmZpZy5cbiAqL1xuXG5pbXBvcnQgeyBFcnJvckhhbmRsZXIsIEluamVjdGFibGUsIGluamVjdCB9IGZyb20gJ0Bhbmd1bGFyL2NvcmUnO1xuaW1wb3J0IHsgQW5hbHl0aWNzU2VydmljZSB9IGZyb20gJy4vYW5hbHl0aWNzLnNlcnZpY2UnO1xuXG4vKipcbiAqIEVycm9ySGFuZGxlciBxdWUgdHJhY2tlYSBlcnJvcmVzIGVuIEZpcmViYXNlIEFuYWx5dGljcy5cbiAqXG4gKiBDYXB0dXJhIGVycm9yZXMgbm8gbWFuZWphZG9zIGRlIGxhIGFwbGljYWNpw7NuIHkgbG9zIGVudsOtYSBhIEdBNFxuICogY29tbyBldmVudG9zICdlcnJvcl9vY2N1cnJlZCcuIFRhbWJpw6luIGRlbGVnYSBhbCBFcnJvckhhbmRsZXJcbiAqIGRlZmF1bHQgcGFyYSBtYW50ZW5lciBlbCBjb21wb3J0YW1pZW50byBkZSBjb25zb2xlLmVycm9yLlxuICpcbiAqIEBleGFtcGxlXG4gKiBgYGB0eXBlc2NyaXB0XG4gKiAvLyBTZSBhY3RpdmEgYXV0b23DoXRpY2FtZW50ZSBzaSBlbmFibGVFcnJvclRyYWNraW5nPXRydWVcbiAqIHByb3ZpZGVWYWx0ZWNoRmlyZWJhc2Uoe1xuICogICBmaXJlYmFzZTogZW52aXJvbm1lbnQuZmlyZWJhc2UsXG4gKiAgIGVuYWJsZUFuYWx5dGljczogdHJ1ZSxcbiAqICAgYW5hbHl0aWNzQ29uZmlnOiB7XG4gKiAgICAgZW5hYmxlRXJyb3JUcmFja2luZzogdHJ1ZSxcbiAqICAgfSxcbiAqIH0pO1xuICogYGBgXG4gKi9cbkBJbmplY3RhYmxlKClcbmV4cG9ydCBjbGFzcyBBbmFseXRpY3NFcnJvckhhbmRsZXIgaW1wbGVtZW50cyBFcnJvckhhbmRsZXIge1xuICBwcml2YXRlIHJlYWRvbmx5IGFuYWx5dGljcyA9IGluamVjdChBbmFseXRpY3NTZXJ2aWNlKTtcbiAgcHJpdmF0ZSByZWFkb25seSBkZWZhdWx0SGFuZGxlciA9IG5ldyBFcnJvckhhbmRsZXIoKTtcblxuICAvKipcbiAgICogTWFuZWphIHVuIGVycm9yIG5vIGNhcHR1cmFkby5cbiAgICogRW52w61hIGVsIGVycm9yIGEgQW5hbHl0aWNzIHkgbHVlZ28gYWwgaGFuZGxlciBkZWZhdWx0LlxuICAgKi9cbiAgaGFuZGxlRXJyb3IoZXJyb3I6IHVua25vd24pOiB2b2lkIHtcbiAgICAvLyBFbnZpYXIgYSBBbmFseXRpY3NcbiAgICB0cnkge1xuICAgICAgdGhpcy50cmFja0Vycm9yKGVycm9yKTtcbiAgICB9IGNhdGNoICh0cmFja2luZ0Vycm9yKSB7XG4gICAgICAvLyBObyBmYWxsYXIgc2kgZWwgdHJhY2tpbmcgZmFsbGFcbiAgICAgIGNvbnNvbGUud2FybignW0FuYWx5dGljc0Vycm9ySGFuZGxlcl0gRXJyb3IgdHJhY2tpbmcgZmFpbGVkOicsIHRyYWNraW5nRXJyb3IpO1xuICAgIH1cblxuICAgIC8vIERlbGVnYXIgYWwgaGFuZGxlciBkZWZhdWx0IChjb25zb2xlLmVycm9yKVxuICAgIHRoaXMuZGVmYXVsdEhhbmRsZXIuaGFuZGxlRXJyb3IoZXJyb3IpO1xuICB9XG5cbiAgLyoqXG4gICAqIFRyYWNrZWEgZWwgZXJyb3IgZW4gQW5hbHl0aWNzXG4gICAqL1xuICBwcml2YXRlIHRyYWNrRXJyb3IoZXJyb3I6IHVua25vd24pOiB2b2lkIHtcbiAgICAvLyBFeHRyYWVyIGluZm9ybWFjacOzbiBkZWwgZXJyb3JcbiAgICBjb25zdCBlcnJvckluZm8gPSB0aGlzLmV4dHJhY3RFcnJvckluZm8oZXJyb3IpO1xuXG4gICAgdGhpcy5hbmFseXRpY3MubG9nRXJyb3IoXG4gICAgICBlcnJvckluZm8uZXJyb3IsXG4gICAgICB7XG4gICAgICAgIHNvdXJjZTogJ3VuY2F1Z2h0JyxcbiAgICAgICAgdXJsOiB0aGlzLmdldEN1cnJlbnRVcmwoKSxcbiAgICAgICAgLi4uZXJyb3JJbmZvLmNvbnRleHQsXG4gICAgICB9XG4gICAgKTtcbiAgfVxuXG4gIC8qKlxuICAgKiBFeHRyYWUgaW5mb3JtYWNpw7NuIMO6dGlsIGRlbCBlcnJvclxuICAgKi9cbiAgcHJpdmF0ZSBleHRyYWN0RXJyb3JJbmZvKGVycm9yOiB1bmtub3duKToge1xuICAgIGVycm9yOiBFcnJvcjtcbiAgICBjb250ZXh0OiBSZWNvcmQ8c3RyaW5nLCBzdHJpbmc+O1xuICB9IHtcbiAgICBjb25zdCBjb250ZXh0OiBSZWNvcmQ8c3RyaW5nLCBzdHJpbmc+ID0ge307XG5cbiAgICAvLyBFcnJvciBlc3TDoW5kYXJcbiAgICBpZiAoZXJyb3IgaW5zdGFuY2VvZiBFcnJvcikge1xuICAgICAgLy8gRGV0ZWN0YXIgZXJyb3JlcyBkZSBjaHVuayBsb2FkaW5nIChsYXp5IGxvYWRpbmcpXG4gICAgICBpZiAoZXJyb3IubWVzc2FnZS5pbmNsdWRlcygnTG9hZGluZyBjaHVuaycpKSB7XG4gICAgICAgIGNvbnRleHRbJ2Vycm9yX2NhdGVnb3J5J10gPSAnY2h1bmtfbG9hZGluZyc7XG4gICAgICB9XG5cbiAgICAgIC8vIERldGVjdGFyIGVycm9yZXMgZGUgcmVkXG4gICAgICBpZiAoZXJyb3IubWVzc2FnZS5pbmNsdWRlcygnTmV0d29ya0Vycm9yJykgfHwgZXJyb3IubWVzc2FnZS5pbmNsdWRlcygnRmFpbGVkIHRvIGZldGNoJykpIHtcbiAgICAgICAgY29udGV4dFsnZXJyb3JfY2F0ZWdvcnknXSA9ICduZXR3b3JrJztcbiAgICAgIH1cblxuICAgICAgcmV0dXJuIHsgZXJyb3IsIGNvbnRleHQgfTtcbiAgICB9XG5cbiAgICAvLyBFcnJvckV2ZW50IChlajogZXJyb3JlcyBkZSBzY3JpcHQpXG4gICAgaWYgKHR5cGVvZiBFcnJvckV2ZW50ICE9PSAndW5kZWZpbmVkJyAmJiBlcnJvciBpbnN0YW5jZW9mIEVycm9yRXZlbnQpIHtcbiAgICAgIHJldHVybiB7XG4gICAgICAgIGVycm9yOiBuZXcgRXJyb3IoZXJyb3IubWVzc2FnZSB8fCAnU2NyaXB0IGVycm9yJyksXG4gICAgICAgIGNvbnRleHQ6IHtcbiAgICAgICAgICBmaWxlbmFtZTogZXJyb3IuZmlsZW5hbWUgfHwgJ3Vua25vd24nLFxuICAgICAgICAgIGxpbmVubzogU3RyaW5nKGVycm9yLmxpbmVubyB8fCAwKSxcbiAgICAgICAgICBjb2xubzogU3RyaW5nKGVycm9yLmNvbG5vIHx8IDApLFxuICAgICAgICB9LFxuICAgICAgfTtcbiAgICB9XG5cbiAgICAvLyBQcm9taXNlUmVqZWN0aW9uXG4gICAgaWYgKHRoaXMuaXNQcm9taXNlUmVqZWN0aW9uKGVycm9yKSkge1xuICAgICAgY29uc3QgcmVhc29uID0gKGVycm9yIGFzIFByb21pc2VSZWplY3Rpb25FdmVudCkucmVhc29uO1xuICAgICAgaWYgKHJlYXNvbiBpbnN0YW5jZW9mIEVycm9yKSB7XG4gICAgICAgIHJldHVybiB7XG4gICAgICAgICAgZXJyb3I6IHJlYXNvbixcbiAgICAgICAgICBjb250ZXh0OiB7IGVycm9yX2NhdGVnb3J5OiAndW5oYW5kbGVkX3Byb21pc2UnIH0sXG4gICAgICAgIH07XG4gICAgICB9XG4gICAgICByZXR1cm4ge1xuICAgICAgICBlcnJvcjogbmV3IEVycm9yKFN0cmluZyhyZWFzb24pIHx8ICdVbmhhbmRsZWQgcHJvbWlzZSByZWplY3Rpb24nKSxcbiAgICAgICAgY29udGV4dDogeyBlcnJvcl9jYXRlZ29yeTogJ3VuaGFuZGxlZF9wcm9taXNlJyB9LFxuICAgICAgfTtcbiAgICB9XG5cbiAgICAvLyBPYmpldG8gY29uIG1lc3NhZ2VcbiAgICBpZiAoZXJyb3IgJiYgdHlwZW9mIGVycm9yID09PSAnb2JqZWN0JyAmJiAnbWVzc2FnZScgaW4gZXJyb3IpIHtcbiAgICAgIHJldHVybiB7XG4gICAgICAgIGVycm9yOiBuZXcgRXJyb3IoU3RyaW5nKChlcnJvciBhcyB7IG1lc3NhZ2U6IHVua25vd24gfSkubWVzc2FnZSkpLFxuICAgICAgICBjb250ZXh0LFxuICAgICAgfTtcbiAgICB9XG5cbiAgICAvLyBGYWxsYmFjazogY29udmVydGlyIGEgc3RyaW5nXG4gICAgcmV0dXJuIHtcbiAgICAgIGVycm9yOiBuZXcgRXJyb3IoU3RyaW5nKGVycm9yKSB8fCAnVW5rbm93biBlcnJvcicpLFxuICAgICAgY29udGV4dCxcbiAgICB9O1xuICB9XG5cbiAgLyoqXG4gICAqIFZlcmlmaWNhIHNpIGVzIHVuIFByb21pc2VSZWplY3Rpb25FdmVudFxuICAgKi9cbiAgcHJpdmF0ZSBpc1Byb21pc2VSZWplY3Rpb24oZXJyb3I6IHVua25vd24pOiBib29sZWFuIHtcbiAgICByZXR1cm4gKFxuICAgICAgdHlwZW9mIFByb21pc2VSZWplY3Rpb25FdmVudCAhPT0gJ3VuZGVmaW5lZCcgJiZcbiAgICAgIGVycm9yIGluc3RhbmNlb2YgUHJvbWlzZVJlamVjdGlvbkV2ZW50XG4gICAgKTtcbiAgfVxuXG4gIC8qKlxuICAgKiBPYnRpZW5lIGxhIFVSTCBhY3R1YWwgZGUgZm9ybWEgc2VndXJhXG4gICAqL1xuICBwcml2YXRlIGdldEN1cnJlbnRVcmwoKTogc3RyaW5nIHtcbiAgICB0cnkge1xuICAgICAgcmV0dXJuIHdpbmRvdz8ubG9jYXRpb24/LmhyZWYgfHwgJ3Vua25vd24nO1xuICAgIH0gY2F0Y2gge1xuICAgICAgcmV0dXJuICd1bmtub3duJztcbiAgICB9XG4gIH1cbn1cbiJdfQ==
@@ -0,0 +1,99 @@
1
+ /**
2
+ * Analytics Router Tracker
3
+ *
4
+ * Servicio que trackea automáticamente page views cuando el usuario navega.
5
+ * Se activa automáticamente si enablePageViewTracking=true en analyticsConfig.
6
+ */
7
+ import { DestroyRef, Inject, Injectable, inject } from '@angular/core';
8
+ import { takeUntilDestroyed } from '@angular/core/rxjs-interop';
9
+ import { NavigationEnd, Router } from '@angular/router';
10
+ import { filter } from 'rxjs/operators';
11
+ import { VALTECH_FIREBASE_CONFIG } from './config';
12
+ import { AnalyticsService } from './analytics.service';
13
+ import * as i0 from "@angular/core";
14
+ /**
15
+ * Tracker automático de page views via Router.
16
+ *
17
+ * Este servicio escucha eventos de navegación del Router y registra
18
+ * page views automáticamente en Firebase Analytics.
19
+ *
20
+ * Se excluyen rutas configuradas en `analyticsConfig.excludeRoutes`.
21
+ *
22
+ * @example
23
+ * ```typescript
24
+ * // Se activa automáticamente si enablePageViewTracking=true
25
+ * provideValtechFirebase({
26
+ * firebase: environment.firebase,
27
+ * enableAnalytics: true,
28
+ * analyticsConfig: {
29
+ * enablePageViewTracking: true,
30
+ * excludeRoutes: ['/admin/*', '/debug/*'],
31
+ * },
32
+ * });
33
+ * ```
34
+ */
35
+ export class AnalyticsRouterTracker {
36
+ constructor(config) {
37
+ this.config = config;
38
+ this.analytics = inject(AnalyticsService);
39
+ this.router = inject(Router);
40
+ this.destroyRef = inject(DestroyRef);
41
+ const analyticsConfig = config.analyticsConfig ?? {};
42
+ this.enabled = analyticsConfig.enablePageViewTracking !== false;
43
+ this.excludePatterns = this.compileExcludePatterns(analyticsConfig.excludeRoutes ?? []);
44
+ if (this.enabled && config.enableAnalytics) {
45
+ this.startTracking();
46
+ }
47
+ }
48
+ /**
49
+ * Inicia el tracking de navegación
50
+ */
51
+ startTracking() {
52
+ this.router.events
53
+ .pipe(filter((event) => event instanceof NavigationEnd), filter((event) => !this.isExcluded(event.urlAfterRedirects)), takeUntilDestroyed(this.destroyRef))
54
+ .subscribe((event) => {
55
+ this.analytics.logPageView(event.urlAfterRedirects);
56
+ });
57
+ }
58
+ /**
59
+ * Compila patrones de exclusión a RegExp
60
+ */
61
+ compileExcludePatterns(patterns) {
62
+ return patterns.map((pattern) => {
63
+ // Convertir glob pattern a regex
64
+ // Ej: '/admin/*' -> /^\/admin\/.*$/
65
+ const regexPattern = pattern
66
+ .replace(/[.+?^${}()|[\]\\]/g, '\\$&') // Escapar caracteres especiales
67
+ .replace(/\*/g, '.*'); // Convertir * a .*
68
+ return new RegExp(`^${regexPattern}$`);
69
+ });
70
+ }
71
+ /**
72
+ * Verifica si una URL debe ser excluida del tracking
73
+ */
74
+ isExcluded(url) {
75
+ // Remover query params para la comparación
76
+ const path = url.split('?')[0];
77
+ return this.excludePatterns.some((pattern) => pattern.test(path));
78
+ }
79
+ /**
80
+ * Registra un page view manualmente.
81
+ * Útil para casos donde necesitas trackear manualmente.
82
+ */
83
+ trackPageView(path, title) {
84
+ if (this.isExcluded(path)) {
85
+ return;
86
+ }
87
+ this.analytics.logPageView(path, title);
88
+ }
89
+ static { this.ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "18.2.14", ngImport: i0, type: AnalyticsRouterTracker, deps: [{ token: VALTECH_FIREBASE_CONFIG }], target: i0.ɵɵFactoryTarget.Injectable }); }
90
+ static { this.ɵprov = i0.ɵɵngDeclareInjectable({ minVersion: "12.0.0", version: "18.2.14", ngImport: i0, type: AnalyticsRouterTracker, providedIn: 'root' }); }
91
+ }
92
+ i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "18.2.14", ngImport: i0, type: AnalyticsRouterTracker, decorators: [{
93
+ type: Injectable,
94
+ args: [{ providedIn: 'root' }]
95
+ }], ctorParameters: () => [{ type: undefined, decorators: [{
96
+ type: Inject,
97
+ args: [VALTECH_FIREBASE_CONFIG]
98
+ }] }] });
99
+ //# sourceMappingURL=data:application/json;base64,eyJ2ZXJzaW9uIjozLCJmaWxlIjoiYW5hbHl0aWNzLXJvdXRlci10cmFja2VyLmpzIiwic291cmNlUm9vdCI6IiIsInNvdXJjZXMiOlsiLi4vLi4vLi4vLi4vLi4vLi4vc3JjL2xpYi9zZXJ2aWNlcy9maXJlYmFzZS9hbmFseXRpY3Mtcm91dGVyLXRyYWNrZXIudHMiXSwibmFtZXMiOltdLCJtYXBwaW5ncyI6IkFBQUE7Ozs7O0dBS0c7QUFFSCxPQUFPLEVBQUUsVUFBVSxFQUFFLE1BQU0sRUFBRSxVQUFVLEVBQUUsTUFBTSxFQUFFLE1BQU0sZUFBZSxDQUFDO0FBQ3ZFLE9BQU8sRUFBRSxrQkFBa0IsRUFBRSxNQUFNLDRCQUE0QixDQUFDO0FBQ2hFLE9BQU8sRUFBRSxhQUFhLEVBQUUsTUFBTSxFQUFFLE1BQU0saUJBQWlCLENBQUM7QUFDeEQsT0FBTyxFQUFFLE1BQU0sRUFBRSxNQUFNLGdCQUFnQixDQUFDO0FBRXhDLE9BQU8sRUFBRSx1QkFBdUIsRUFBRSxNQUFNLFVBQVUsQ0FBQztBQUVuRCxPQUFPLEVBQUUsZ0JBQWdCLEVBQUUsTUFBTSxxQkFBcUIsQ0FBQzs7QUFFdkQ7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7O0dBb0JHO0FBRUgsTUFBTSxPQUFPLHNCQUFzQjtJQVFqQyxZQUMyQyxNQUE2QjtRQUE3QixXQUFNLEdBQU4sTUFBTSxDQUF1QjtRQVJ2RCxjQUFTLEdBQUcsTUFBTSxDQUFDLGdCQUFnQixDQUFDLENBQUM7UUFDckMsV0FBTSxHQUFHLE1BQU0sQ0FBQyxNQUFNLENBQUMsQ0FBQztRQUN4QixlQUFVLEdBQUcsTUFBTSxDQUFDLFVBQVUsQ0FBQyxDQUFDO1FBUS9DLE1BQU0sZUFBZSxHQUFHLE1BQU0sQ0FBQyxlQUFlLElBQUksRUFBRSxDQUFDO1FBQ3JELElBQUksQ0FBQyxPQUFPLEdBQUcsZUFBZSxDQUFDLHNCQUFzQixLQUFLLEtBQUssQ0FBQztRQUNoRSxJQUFJLENBQUMsZUFBZSxHQUFHLElBQUksQ0FBQyxzQkFBc0IsQ0FBQyxlQUFlLENBQUMsYUFBYSxJQUFJLEVBQUUsQ0FBQyxDQUFDO1FBRXhGLElBQUksSUFBSSxDQUFDLE9BQU8sSUFBSSxNQUFNLENBQUMsZUFBZSxFQUFFLENBQUM7WUFDM0MsSUFBSSxDQUFDLGFBQWEsRUFBRSxDQUFDO1FBQ3ZCLENBQUM7SUFDSCxDQUFDO0lBRUQ7O09BRUc7SUFDSyxhQUFhO1FBQ25CLElBQUksQ0FBQyxNQUFNLENBQUMsTUFBTTthQUNmLElBQUksQ0FDSCxNQUFNLENBQUMsQ0FBQyxLQUFLLEVBQTBCLEVBQUUsQ0FBQyxLQUFLLFlBQVksYUFBYSxDQUFDLEVBQ3pFLE1BQU0sQ0FBQyxDQUFDLEtBQUssRUFBRSxFQUFFLENBQUMsQ0FBQyxJQUFJLENBQUMsVUFBVSxDQUFDLEtBQUssQ0FBQyxpQkFBaUIsQ0FBQyxDQUFDLEVBQzVELGtCQUFrQixDQUFDLElBQUksQ0FBQyxVQUFVLENBQUMsQ0FDcEM7YUFDQSxTQUFTLENBQUMsQ0FBQyxLQUFLLEVBQUUsRUFBRTtZQUNuQixJQUFJLENBQUMsU0FBUyxDQUFDLFdBQVcsQ0FBQyxLQUFLLENBQUMsaUJBQWlCLENBQUMsQ0FBQztRQUN0RCxDQUFDLENBQUMsQ0FBQztJQUNQLENBQUM7SUFFRDs7T0FFRztJQUNLLHNCQUFzQixDQUFDLFFBQWtCO1FBQy9DLE9BQU8sUUFBUSxDQUFDLEdBQUcsQ0FBQyxDQUFDLE9BQU8sRUFBRSxFQUFFO1lBQzlCLGlDQUFpQztZQUNqQyxvQ0FBb0M7WUFDcEMsTUFBTSxZQUFZLEdBQUcsT0FBTztpQkFDekIsT0FBTyxDQUFDLG9CQUFvQixFQUFFLE1BQU0sQ0FBQyxDQUFDLGdDQUFnQztpQkFDdEUsT0FBTyxDQUFDLEtBQUssRUFBRSxJQUFJLENBQUMsQ0FBQyxDQUFDLG1CQUFtQjtZQUU1QyxPQUFPLElBQUksTUFBTSxDQUFDLElBQUksWUFBWSxHQUFHLENBQUMsQ0FBQztRQUN6QyxDQUFDLENBQUMsQ0FBQztJQUNMLENBQUM7SUFFRDs7T0FFRztJQUNLLFVBQVUsQ0FBQyxHQUFXO1FBQzVCLDJDQUEyQztRQUMzQyxNQUFNLElBQUksR0FBRyxHQUFHLENBQUMsS0FBSyxDQUFDLEdBQUcsQ0FBQyxDQUFDLENBQUMsQ0FBQyxDQUFDO1FBRS9CLE9BQU8sSUFBSSxDQUFDLGVBQWUsQ0FBQyxJQUFJLENBQUMsQ0FBQyxPQUFPLEVBQUUsRUFBRSxDQUFDLE9BQU8sQ0FBQyxJQUFJLENBQUMsSUFBSSxDQUFDLENBQUMsQ0FBQztJQUNwRSxDQUFDO0lBRUQ7OztPQUdHO0lBQ0gsYUFBYSxDQUFDLElBQVksRUFBRSxLQUFjO1FBQ3hDLElBQUksSUFBSSxDQUFDLFVBQVUsQ0FBQyxJQUFJLENBQUMsRUFBRSxDQUFDO1lBQzFCLE9BQU87UUFDVCxDQUFDO1FBQ0QsSUFBSSxDQUFDLFNBQVMsQ0FBQyxXQUFXLENBQUMsSUFBSSxFQUFFLEtBQUssQ0FBQyxDQUFDO0lBQzFDLENBQUM7K0dBckVVLHNCQUFzQixrQkFTdkIsdUJBQXVCO21IQVR0QixzQkFBc0IsY0FEVCxNQUFNOzs0RkFDbkIsc0JBQXNCO2tCQURsQyxVQUFVO21CQUFDLEVBQUUsVUFBVSxFQUFFLE1BQU0sRUFBRTs7MEJBVTdCLE1BQU07MkJBQUMsdUJBQXVCIiwic291cmNlc0NvbnRlbnQiOlsiLyoqXG4gKiBBbmFseXRpY3MgUm91dGVyIFRyYWNrZXJcbiAqXG4gKiBTZXJ2aWNpbyBxdWUgdHJhY2tlYSBhdXRvbcOhdGljYW1lbnRlIHBhZ2Ugdmlld3MgY3VhbmRvIGVsIHVzdWFyaW8gbmF2ZWdhLlxuICogU2UgYWN0aXZhIGF1dG9tw6F0aWNhbWVudGUgc2kgZW5hYmxlUGFnZVZpZXdUcmFja2luZz10cnVlIGVuIGFuYWx5dGljc0NvbmZpZy5cbiAqL1xuXG5pbXBvcnQgeyBEZXN0cm95UmVmLCBJbmplY3QsIEluamVjdGFibGUsIGluamVjdCB9IGZyb20gJ0Bhbmd1bGFyL2NvcmUnO1xuaW1wb3J0IHsgdGFrZVVudGlsRGVzdHJveWVkIH0gZnJvbSAnQGFuZ3VsYXIvY29yZS9yeGpzLWludGVyb3AnO1xuaW1wb3J0IHsgTmF2aWdhdGlvbkVuZCwgUm91dGVyIH0gZnJvbSAnQGFuZ3VsYXIvcm91dGVyJztcbmltcG9ydCB7IGZpbHRlciB9IGZyb20gJ3J4anMvb3BlcmF0b3JzJztcblxuaW1wb3J0IHsgVkFMVEVDSF9GSVJFQkFTRV9DT05GSUcgfSBmcm9tICcuL2NvbmZpZyc7XG5pbXBvcnQgeyBWYWx0ZWNoRmlyZWJhc2VDb25maWcgfSBmcm9tICcuL3R5cGVzJztcbmltcG9ydCB7IEFuYWx5dGljc1NlcnZpY2UgfSBmcm9tICcuL2FuYWx5dGljcy5zZXJ2aWNlJztcblxuLyoqXG4gKiBUcmFja2VyIGF1dG9tw6F0aWNvIGRlIHBhZ2Ugdmlld3MgdmlhIFJvdXRlci5cbiAqXG4gKiBFc3RlIHNlcnZpY2lvIGVzY3VjaGEgZXZlbnRvcyBkZSBuYXZlZ2FjacOzbiBkZWwgUm91dGVyIHkgcmVnaXN0cmFcbiAqIHBhZ2Ugdmlld3MgYXV0b23DoXRpY2FtZW50ZSBlbiBGaXJlYmFzZSBBbmFseXRpY3MuXG4gKlxuICogU2UgZXhjbHV5ZW4gcnV0YXMgY29uZmlndXJhZGFzIGVuIGBhbmFseXRpY3NDb25maWcuZXhjbHVkZVJvdXRlc2AuXG4gKlxuICogQGV4YW1wbGVcbiAqIGBgYHR5cGVzY3JpcHRcbiAqIC8vIFNlIGFjdGl2YSBhdXRvbcOhdGljYW1lbnRlIHNpIGVuYWJsZVBhZ2VWaWV3VHJhY2tpbmc9dHJ1ZVxuICogcHJvdmlkZVZhbHRlY2hGaXJlYmFzZSh7XG4gKiAgIGZpcmViYXNlOiBlbnZpcm9ubWVudC5maXJlYmFzZSxcbiAqICAgZW5hYmxlQW5hbHl0aWNzOiB0cnVlLFxuICogICBhbmFseXRpY3NDb25maWc6IHtcbiAqICAgICBlbmFibGVQYWdlVmlld1RyYWNraW5nOiB0cnVlLFxuICogICAgIGV4Y2x1ZGVSb3V0ZXM6IFsnL2FkbWluLyonLCAnL2RlYnVnLyonXSxcbiAqICAgfSxcbiAqIH0pO1xuICogYGBgXG4gKi9cbkBJbmplY3RhYmxlKHsgcHJvdmlkZWRJbjogJ3Jvb3QnIH0pXG5leHBvcnQgY2xhc3MgQW5hbHl0aWNzUm91dGVyVHJhY2tlciB7XG4gIHByaXZhdGUgcmVhZG9ubHkgYW5hbHl0aWNzID0gaW5qZWN0KEFuYWx5dGljc1NlcnZpY2UpO1xuICBwcml2YXRlIHJlYWRvbmx5IHJvdXRlciA9IGluamVjdChSb3V0ZXIpO1xuICBwcml2YXRlIHJlYWRvbmx5IGRlc3Ryb3lSZWYgPSBpbmplY3QoRGVzdHJveVJlZik7XG5cbiAgcHJpdmF0ZSByZWFkb25seSBleGNsdWRlUGF0dGVybnM6IFJlZ0V4cFtdO1xuICBwcml2YXRlIHJlYWRvbmx5IGVuYWJsZWQ6IGJvb2xlYW47XG5cbiAgY29uc3RydWN0b3IoXG4gICAgQEluamVjdChWQUxURUNIX0ZJUkVCQVNFX0NPTkZJRykgcHJpdmF0ZSBjb25maWc6IFZhbHRlY2hGaXJlYmFzZUNvbmZpZ1xuICApIHtcbiAgICBjb25zdCBhbmFseXRpY3NDb25maWcgPSBjb25maWcuYW5hbHl0aWNzQ29uZmlnID8/IHt9O1xuICAgIHRoaXMuZW5hYmxlZCA9IGFuYWx5dGljc0NvbmZpZy5lbmFibGVQYWdlVmlld1RyYWNraW5nICE9PSBmYWxzZTtcbiAgICB0aGlzLmV4Y2x1ZGVQYXR0ZXJucyA9IHRoaXMuY29tcGlsZUV4Y2x1ZGVQYXR0ZXJucyhhbmFseXRpY3NDb25maWcuZXhjbHVkZVJvdXRlcyA/PyBbXSk7XG5cbiAgICBpZiAodGhpcy5lbmFibGVkICYmIGNvbmZpZy5lbmFibGVBbmFseXRpY3MpIHtcbiAgICAgIHRoaXMuc3RhcnRUcmFja2luZygpO1xuICAgIH1cbiAgfVxuXG4gIC8qKlxuICAgKiBJbmljaWEgZWwgdHJhY2tpbmcgZGUgbmF2ZWdhY2nDs25cbiAgICovXG4gIHByaXZhdGUgc3RhcnRUcmFja2luZygpOiB2b2lkIHtcbiAgICB0aGlzLnJvdXRlci5ldmVudHNcbiAgICAgIC5waXBlKFxuICAgICAgICBmaWx0ZXIoKGV2ZW50KTogZXZlbnQgaXMgTmF2aWdhdGlvbkVuZCA9PiBldmVudCBpbnN0YW5jZW9mIE5hdmlnYXRpb25FbmQpLFxuICAgICAgICBmaWx0ZXIoKGV2ZW50KSA9PiAhdGhpcy5pc0V4Y2x1ZGVkKGV2ZW50LnVybEFmdGVyUmVkaXJlY3RzKSksXG4gICAgICAgIHRha2VVbnRpbERlc3Ryb3llZCh0aGlzLmRlc3Ryb3lSZWYpXG4gICAgICApXG4gICAgICAuc3Vic2NyaWJlKChldmVudCkgPT4ge1xuICAgICAgICB0aGlzLmFuYWx5dGljcy5sb2dQYWdlVmlldyhldmVudC51cmxBZnRlclJlZGlyZWN0cyk7XG4gICAgICB9KTtcbiAgfVxuXG4gIC8qKlxuICAgKiBDb21waWxhIHBhdHJvbmVzIGRlIGV4Y2x1c2nDs24gYSBSZWdFeHBcbiAgICovXG4gIHByaXZhdGUgY29tcGlsZUV4Y2x1ZGVQYXR0ZXJucyhwYXR0ZXJuczogc3RyaW5nW10pOiBSZWdFeHBbXSB7XG4gICAgcmV0dXJuIHBhdHRlcm5zLm1hcCgocGF0dGVybikgPT4ge1xuICAgICAgLy8gQ29udmVydGlyIGdsb2IgcGF0dGVybiBhIHJlZ2V4XG4gICAgICAvLyBFajogJy9hZG1pbi8qJyAtPiAvXlxcL2FkbWluXFwvLiokL1xuICAgICAgY29uc3QgcmVnZXhQYXR0ZXJuID0gcGF0dGVyblxuICAgICAgICAucmVwbGFjZSgvWy4rP14ke30oKXxbXFxdXFxcXF0vZywgJ1xcXFwkJicpIC8vIEVzY2FwYXIgY2FyYWN0ZXJlcyBlc3BlY2lhbGVzXG4gICAgICAgIC5yZXBsYWNlKC9cXCovZywgJy4qJyk7IC8vIENvbnZlcnRpciAqIGEgLipcblxuICAgICAgcmV0dXJuIG5ldyBSZWdFeHAoYF4ke3JlZ2V4UGF0dGVybn0kYCk7XG4gICAgfSk7XG4gIH1cblxuICAvKipcbiAgICogVmVyaWZpY2Egc2kgdW5hIFVSTCBkZWJlIHNlciBleGNsdWlkYSBkZWwgdHJhY2tpbmdcbiAgICovXG4gIHByaXZhdGUgaXNFeGNsdWRlZCh1cmw6IHN0cmluZyk6IGJvb2xlYW4ge1xuICAgIC8vIFJlbW92ZXIgcXVlcnkgcGFyYW1zIHBhcmEgbGEgY29tcGFyYWNpw7NuXG4gICAgY29uc3QgcGF0aCA9IHVybC5zcGxpdCgnPycpWzBdO1xuXG4gICAgcmV0dXJuIHRoaXMuZXhjbHVkZVBhdHRlcm5zLnNvbWUoKHBhdHRlcm4pID0+IHBhdHRlcm4udGVzdChwYXRoKSk7XG4gIH1cblxuICAvKipcbiAgICogUmVnaXN0cmEgdW4gcGFnZSB2aWV3IG1hbnVhbG1lbnRlLlxuICAgKiDDmnRpbCBwYXJhIGNhc29zIGRvbmRlIG5lY2VzaXRhcyB0cmFja2VhciBtYW51YWxtZW50ZS5cbiAgICovXG4gIHRyYWNrUGFnZVZpZXcocGF0aDogc3RyaW5nLCB0aXRsZT86IHN0cmluZyk6IHZvaWQge1xuICAgIGlmICh0aGlzLmlzRXhjbHVkZWQocGF0aCkpIHtcbiAgICAgIHJldHVybjtcbiAgICB9XG4gICAgdGhpcy5hbmFseXRpY3MubG9nUGFnZVZpZXcocGF0aCwgdGl0bGUpO1xuICB9XG59XG4iXX0=