valtech-components 2.0.590 → 2.0.592

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.
@@ -0,0 +1,47 @@
1
+ import { OnDestroy, OnInit } from '@angular/core';
2
+ import { RotatingTextMetadata, RotatingTextMessage } from './types';
3
+ import * as i0 from "@angular/core";
4
+ /**
5
+ * val-rotating-text
6
+ *
7
+ * A component that rotates through an array of text messages with smooth animations.
8
+ * Features entrance/exit animations with fade, blur, and scale effects.
9
+ *
10
+ * @example
11
+ * <val-rotating-text
12
+ * [props]="{
13
+ * messages: [
14
+ * { aboveTitle: 'Welcome', title: 'Hello World' },
15
+ * { aboveTitle: 'Tip:', title: 'Stay curious' }
16
+ * ],
17
+ * interval: 4000,
18
+ * showDots: true
19
+ * }"
20
+ * ></val-rotating-text>
21
+ *
22
+ * @input props - Configuration for the rotating text component
23
+ */
24
+ export declare class RotatingTextComponent implements OnInit, OnDestroy {
25
+ private intervalId;
26
+ /**
27
+ * Component configuration.
28
+ */
29
+ props: RotatingTextMetadata;
30
+ currentIndex: import("@angular/core").WritableSignal<number>;
31
+ isEntering: import("@angular/core").WritableSignal<boolean>;
32
+ isExiting: import("@angular/core").WritableSignal<boolean>;
33
+ currentMessage: import("@angular/core").Signal<RotatingTextMessage>;
34
+ get aboveTitleColorValue(): string;
35
+ get titleColorValue(): string;
36
+ ngOnInit(): void;
37
+ ngOnDestroy(): void;
38
+ private startRotation;
39
+ private stopRotation;
40
+ private rotateToNext;
41
+ /**
42
+ * Navigate to a specific message by index.
43
+ */
44
+ goToMessage(index: number): void;
45
+ static ɵfac: i0.ɵɵFactoryDeclaration<RotatingTextComponent, never>;
46
+ static ɵcmp: i0.ɵɵComponentDeclaration<RotatingTextComponent, "val-rotating-text", never, { "props": { "alias": "props"; "required": false; }; }, {}, never, never, true, never>;
47
+ }
@@ -0,0 +1,28 @@
1
+ /**
2
+ * A single message to display in the rotating text component.
3
+ *
4
+ * @property aboveTitle - Small text displayed above the main title.
5
+ * @property title - The main title text.
6
+ */
7
+ export interface RotatingTextMessage {
8
+ aboveTitle: string;
9
+ title: string;
10
+ }
11
+ /**
12
+ * Props for val-rotating-text component.
13
+ *
14
+ * @property messages - Array of messages to rotate through.
15
+ * @property interval - Time in milliseconds between rotations (default: 4000).
16
+ * @property showDots - Whether to show navigation dots (default: true).
17
+ * @property aboveTitleColor - Color for above title text (default: 'medium').
18
+ * @property titleColor - Color for main title text (default: 'dark').
19
+ * @property backgroundColor - Background color for the section.
20
+ */
21
+ export interface RotatingTextMetadata {
22
+ messages: RotatingTextMessage[];
23
+ interval?: number;
24
+ showDots?: boolean;
25
+ aboveTitleColor?: string;
26
+ titleColor?: string;
27
+ backgroundColor?: string;
28
+ }
@@ -0,0 +1,36 @@
1
+ import { OnInit } from '@angular/core';
2
+ import { Terminal404Metadata } from './types';
3
+ import * as i0 from "@angular/core";
4
+ /**
5
+ * val-terminal-404
6
+ *
7
+ * A fun, terminal-styled 404 page component with typing animations.
8
+ *
9
+ * Features:
10
+ * - Terminal window aesthetic with colored dots
11
+ * - Typing animation effect with sequential line reveals
12
+ * - Blinking cursor
13
+ * - Customizable colors to match brand
14
+ * - Shows the attempted path
15
+ *
16
+ * @example
17
+ * <val-terminal-404
18
+ * [props]="{
19
+ * primaryColor: '#4a1d96',
20
+ * homeRoute: '/',
21
+ * homeButtonText: 'cd /home'
22
+ * }"
23
+ * ></val-terminal-404>
24
+ */
25
+ export declare class Terminal404Component implements OnInit {
26
+ props: Terminal404Metadata;
27
+ requestedPath: import("@angular/core").WritableSignal<string>;
28
+ get backgroundGradient(): string;
29
+ ngOnInit(): void;
30
+ /**
31
+ * Lighten a hex color for hover states
32
+ */
33
+ lightenColor(hex: string): string;
34
+ static ɵfac: i0.ɵɵFactoryDeclaration<Terminal404Component, never>;
35
+ static ɵcmp: i0.ɵɵComponentDeclaration<Terminal404Component, "val-terminal-404", never, { "props": { "alias": "props"; "required": false; }; }, {}, never, never, true, never>;
36
+ }
@@ -0,0 +1,22 @@
1
+ /**
2
+ * Configuration for terminal 404 page component.
3
+ *
4
+ * @property backgroundColor - Background gradient colors (default: lavender purple)
5
+ * @property primaryColor - Main brand color for 404 text and button (default: #4a1d96)
6
+ * @property terminalBackground - Terminal window background (default: #0d1117)
7
+ * @property homeRoute - Route for the home button (default: '/')
8
+ * @property homeButtonText - Text for home button (default: 'cd /home')
9
+ * @property showLanguageSelector - Show language selector in header (default: true)
10
+ */
11
+ export interface Terminal404Metadata {
12
+ backgroundColor?: {
13
+ start: string;
14
+ middle: string;
15
+ end: string;
16
+ };
17
+ primaryColor?: string;
18
+ terminalBackground?: string;
19
+ homeRoute?: string;
20
+ homeButtonText?: string;
21
+ showLanguageSelector?: boolean;
22
+ }
@@ -155,15 +155,15 @@ export declare class AuthService implements OnDestroy {
155
155
  */
156
156
  refreshAccessToken(): Observable<RefreshResponse>;
157
157
  /**
158
- * Maneja autenticación exitosa desde fuentes externas (OAuth, Google Native, etc).
158
+ * Maneja autenticación exitosa desde fuentes externas (OAuth, etc).
159
159
  * Guarda tokens, actualiza estado, inicia Firebase si corresponde.
160
160
  *
161
161
  * @param authResult - Resultado de autenticación con tokens
162
162
  *
163
163
  * @example
164
164
  * ```typescript
165
- * // Desde GoogleAuthService
166
- * googleAuth.signIn().subscribe({
165
+ * // Desde un flujo OAuth externo
166
+ * externalOAuth.signIn().subscribe({
167
167
  * next: (result) => {
168
168
  * this.authService.setExternalAuth(result);
169
169
  * }
@@ -81,4 +81,3 @@ export { DeviceService } from './device.service';
81
81
  export { SessionService } from './session.service';
82
82
  export { OAuthService } from './oauth.service';
83
83
  export { OAuthCallbackComponent } from './oauth-callback.component';
84
- export { GoogleAuthService } from './google-auth.service';
@@ -766,55 +766,3 @@ export interface HasPasswordResponse {
766
766
  operationId: string;
767
767
  hasPassword: boolean;
768
768
  }
769
- /**
770
- * Configuración para Google Sign-In nativo.
771
- */
772
- export interface GoogleAuthConfig {
773
- /** Google Client ID para web (obtenido de Google Cloud Console) */
774
- clientId: string;
775
- /** Scopes adicionales a solicitar (default: ['email', 'profile']) */
776
- scopes?: string[];
777
- }
778
- /**
779
- * Usuario de Google obtenido del SDK nativo.
780
- */
781
- export interface GoogleUser {
782
- /** ID único de Google */
783
- id: string;
784
- /** Email del usuario */
785
- email: string;
786
- /** Nombre completo */
787
- name: string;
788
- /** URL de imagen de perfil */
789
- imageUrl?: string;
790
- /** ID token JWT (para enviar al backend) */
791
- idToken: string;
792
- /** Access token de Google (opcional) */
793
- accessToken?: string;
794
- }
795
- /**
796
- * Request para verificar Google ID token en el backend.
797
- */
798
- export interface VerifyGoogleTokenRequest {
799
- /** ID token de Google obtenido del SDK nativo */
800
- idToken: string;
801
- /** ID del dispositivo (opcional, para tracking) */
802
- deviceId?: string;
803
- /** Info del dispositivo (opcional) */
804
- deviceInfo?: string;
805
- }
806
- /**
807
- * Response de verificación de Google ID token.
808
- */
809
- export interface VerifyGoogleTokenResponse {
810
- operationId: string;
811
- accessToken: string;
812
- refreshToken: string;
813
- firebaseToken?: string;
814
- expiresIn: number;
815
- tokenType: string;
816
- isNewUser: boolean;
817
- wasLinked: boolean;
818
- roles?: string[];
819
- permissions?: string[];
820
- }
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "valtech-components",
3
- "version": "2.0.590",
3
+ "version": "2.0.592",
4
4
  "private": false,
5
5
  "bin": {
6
6
  "valtech-firebase-config": "./src/lib/services/firebase/scripts/generate-sw-config.js"
@@ -15,7 +15,6 @@
15
15
  "@angular/core": "^18.0.0",
16
16
  "@angular/fire": "^18.0.1",
17
17
  "@capacitor/clipboard": "^6.0.1",
18
- "@codetrix-studio/capacitor-google-auth": "^3.4.0-rc.4",
19
18
  "@ionic/angular": "^8.0.0",
20
19
  "firebase": "^10.0.0",
21
20
  "ionicons": "^7.2.1",
@@ -24,11 +23,6 @@
24
23
  "rxjs": "~7.8.0",
25
24
  "swiper": "^11.2.8"
26
25
  },
27
- "peerDependenciesMeta": {
28
- "@codetrix-studio/capacitor-google-auth": {
29
- "optional": true
30
- }
31
- },
32
26
  "dependencies": {
33
27
  "@capacitor/browser": "^6.0.3",
34
28
  "ng-otp-input": "^1.9.3",
package/public-api.d.ts CHANGED
@@ -198,6 +198,10 @@ export * from './lib/components/organisms/infinite-list/infinite-list.component'
198
198
  export * from './lib/components/organisms/infinite-list/types';
199
199
  export * from './lib/components/organisms/login/login.component';
200
200
  export * from './lib/components/organisms/login/types';
201
+ export * from './lib/components/organisms/rotating-text/rotating-text.component';
202
+ export * from './lib/components/organisms/rotating-text/types';
203
+ export * from './lib/components/organisms/terminal-404/terminal-404.component';
204
+ export * from './lib/components/organisms/terminal-404/types';
201
205
  export * from './lib/components/templates/layout/layout.component';
202
206
  export * from './lib/components/templates/simple/simple.component';
203
207
  export * from './lib/components/templates/simple/types';
@@ -1,221 +0,0 @@
1
- import { Injectable, Inject, signal, computed } from '@angular/core';
2
- import { from, throwError } from 'rxjs';
3
- import { catchError, switchMap, tap } from 'rxjs/operators';
4
- import { GoogleAuth } from '@codetrix-studio/capacitor-google-auth';
5
- import { VALTECH_AUTH_CONFIG } from './config';
6
- import * as i0 from "@angular/core";
7
- import * as i1 from "@angular/common/http";
8
- /**
9
- * Servicio de autenticación con Google usando SDK nativo.
10
- *
11
- * Este servicio utiliza `@codetrix-studio/capacitor-google-auth` que funciona
12
- * tanto en web como en aplicaciones Capacitor (iOS/Android).
13
- *
14
- * Para web, utiliza el popup nativo de Google Sign-In.
15
- * Para mobile, utiliza el SDK nativo de Google.
16
- *
17
- * @example
18
- * ```typescript
19
- * // En main.ts o app.config.ts
20
- * import { provideGoogleAuth } from 'valtech-components';
21
- *
22
- * export const appConfig: ApplicationConfig = {
23
- * providers: [
24
- * provideGoogleAuth({
25
- * clientId: 'your-google-client-id.apps.googleusercontent.com'
26
- * })
27
- * ]
28
- * };
29
- *
30
- * // En el componente
31
- * import { GoogleAuthService, AuthService } from 'valtech-components';
32
- *
33
- * @Component({...})
34
- * export class LoginComponent {
35
- * private googleAuth = inject(GoogleAuthService);
36
- * private auth = inject(AuthService);
37
- *
38
- * async signInWithGoogle() {
39
- * this.googleAuth.signIn().subscribe({
40
- * next: (result) => {
41
- * // Tokens recibidos del backend
42
- * this.auth.handleOAuthSuccess(result);
43
- * this.router.navigate(['/']);
44
- * },
45
- * error: (error) => {
46
- * console.error('Google sign-in failed:', error);
47
- * }
48
- * });
49
- * }
50
- * }
51
- * ```
52
- */
53
- export class GoogleAuthService {
54
- constructor(config, http) {
55
- this.config = config;
56
- this.http = http;
57
- this.initialized = signal(false);
58
- this.googleConfig = null;
59
- /** Indica si el servicio está inicializado */
60
- this.isInitialized = computed(() => this.initialized());
61
- }
62
- /**
63
- * Inicializa el SDK de Google Sign-In.
64
- * Debe llamarse una vez, idealmente en APP_INITIALIZER.
65
- *
66
- * @param googleConfig - Configuración de Google Auth
67
- */
68
- async initialize(googleConfig) {
69
- if (this.initialized()) {
70
- console.log('[GoogleAuth] Already initialized');
71
- return;
72
- }
73
- this.googleConfig = googleConfig;
74
- try {
75
- await GoogleAuth.initialize({
76
- clientId: googleConfig.clientId,
77
- scopes: googleConfig.scopes || ['email', 'profile'],
78
- grantOfflineAccess: true,
79
- });
80
- this.initialized.set(true);
81
- console.log('[GoogleAuth] Initialized successfully');
82
- }
83
- catch (error) {
84
- console.error('[GoogleAuth] Initialization failed:', error);
85
- throw error;
86
- }
87
- }
88
- /**
89
- * Inicia el flujo de Google Sign-In y obtiene tokens del backend.
90
- *
91
- * El flujo es:
92
- * 1. Abre popup/SDK nativo de Google
93
- * 2. Usuario autoriza
94
- * 3. Obtiene ID token de Google
95
- * 4. Envía ID token al backend para verificación
96
- * 5. Backend verifica con Google y retorna nuestros JWT tokens
97
- *
98
- * @returns Observable con la respuesta del backend (tokens)
99
- */
100
- signIn() {
101
- if (!this.initialized()) {
102
- return throwError(() => ({
103
- code: 'NOT_INITIALIZED',
104
- message: 'GoogleAuthService no está inicializado. Llama a initialize() primero.',
105
- }));
106
- }
107
- return from(this.performGoogleSignIn()).pipe(tap(googleUser => {
108
- console.log('[GoogleAuth] Google sign-in successful:', {
109
- email: googleUser.email,
110
- hasIdToken: !!googleUser.idToken,
111
- idTokenLength: googleUser.idToken?.length || 0,
112
- });
113
- }), switchMap(googleUser => this.verifyWithBackend(googleUser)), catchError(error => {
114
- console.error('[GoogleAuth] Sign-in error:', error);
115
- // Handle Google SDK specific errors
116
- if (error?.message?.includes('popup_closed') || error?.code === 'popup_closed_by_user') {
117
- return throwError(() => ({
118
- code: 'POPUP_CLOSED',
119
- message: 'Se cerró la ventana de autenticación de Google',
120
- }));
121
- }
122
- if (error?.message?.includes('access_denied') || error?.code === 'access_denied') {
123
- return throwError(() => ({
124
- code: 'ACCESS_DENIED',
125
- message: 'El usuario denegó el acceso a Google',
126
- }));
127
- }
128
- // Backend errors pass through
129
- if (error.code && error.message) {
130
- return throwError(() => error);
131
- }
132
- return throwError(() => ({
133
- code: 'GOOGLE_AUTH_ERROR',
134
- message: error?.message || 'Error al iniciar sesión con Google',
135
- }));
136
- }));
137
- }
138
- /**
139
- * Cierra la sesión de Google.
140
- * Nota: Esto solo cierra la sesión del SDK de Google,
141
- * NO cierra la sesión del backend. Usa AuthService.logout() para eso.
142
- */
143
- async signOut() {
144
- try {
145
- await GoogleAuth.signOut();
146
- console.log('[GoogleAuth] Signed out from Google');
147
- }
148
- catch (error) {
149
- console.warn('[GoogleAuth] Sign out error:', error);
150
- }
151
- }
152
- /**
153
- * Obtiene el token de autenticación refrescado (si existe sesión).
154
- * Nota: GoogleAuth.refresh() solo retorna tokens, no info del usuario.
155
- */
156
- async refreshToken() {
157
- try {
158
- const auth = await GoogleAuth.refresh();
159
- if (auth?.idToken) {
160
- return {
161
- idToken: auth.idToken,
162
- accessToken: auth.accessToken,
163
- };
164
- }
165
- return null;
166
- }
167
- catch {
168
- return null;
169
- }
170
- }
171
- /**
172
- * Realiza el sign-in con Google usando el SDK nativo.
173
- */
174
- async performGoogleSignIn() {
175
- const user = await GoogleAuth.signIn();
176
- if (!user?.authentication?.idToken) {
177
- throw new Error('No se obtuvo ID token de Google');
178
- }
179
- return {
180
- id: user.id || '',
181
- email: user.email || '',
182
- name: user.name || '',
183
- imageUrl: user.imageUrl,
184
- idToken: user.authentication.idToken,
185
- accessToken: user.authentication.accessToken,
186
- };
187
- }
188
- /**
189
- * Verifica el ID token de Google con nuestro backend.
190
- */
191
- verifyWithBackend(googleUser) {
192
- const request = {
193
- idToken: googleUser.idToken,
194
- };
195
- const url = `${this.config.apiUrl}/v2/auth/oauth/google/verify`;
196
- return this.http.post(url, request).pipe(tap(response => {
197
- console.log('[GoogleAuth] Backend verification successful:', {
198
- hasAccessToken: !!response.accessToken,
199
- hasFirebaseToken: !!response.firebaseToken,
200
- isNewUser: response.isNewUser,
201
- });
202
- }), catchError(error => {
203
- console.error('[GoogleAuth] Backend verification failed:', error);
204
- const authError = {
205
- code: error.error?.code || 'VERIFICATION_ERROR',
206
- message: error.error?.message || 'Error al verificar credenciales de Google',
207
- };
208
- return throwError(() => authError);
209
- }));
210
- }
211
- static { this.ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "18.2.14", ngImport: i0, type: GoogleAuthService, deps: [{ token: VALTECH_AUTH_CONFIG }, { token: i1.HttpClient }], target: i0.ɵɵFactoryTarget.Injectable }); }
212
- static { this.ɵprov = i0.ɵɵngDeclareInjectable({ minVersion: "12.0.0", version: "18.2.14", ngImport: i0, type: GoogleAuthService, providedIn: 'root' }); }
213
- }
214
- i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "18.2.14", ngImport: i0, type: GoogleAuthService, decorators: [{
215
- type: Injectable,
216
- args: [{ providedIn: 'root' }]
217
- }], ctorParameters: () => [{ type: undefined, decorators: [{
218
- type: Inject,
219
- args: [VALTECH_AUTH_CONFIG]
220
- }] }, { type: i1.HttpClient }] });
221
- //# sourceMappingURL=data:application/json;base64,eyJ2ZXJzaW9uIjozLCJmaWxlIjoiZ29vZ2xlLWF1dGguc2VydmljZS5qcyIsInNvdXJjZVJvb3QiOiIiLCJzb3VyY2VzIjpbIi4uLy4uLy4uLy4uLy4uLy4uL3NyYy9saWIvc2VydmljZXMvYXV0aC9nb29nbGUtYXV0aC5zZXJ2aWNlLnRzIl0sIm5hbWVzIjpbXSwibWFwcGluZ3MiOiJBQUFBLE9BQU8sRUFBRSxVQUFVLEVBQUUsTUFBTSxFQUFFLE1BQU0sRUFBRSxRQUFRLEVBQUUsTUFBTSxlQUFlLENBQUM7QUFFckUsT0FBTyxFQUFjLElBQUksRUFBRSxVQUFVLEVBQUUsTUFBTSxNQUFNLENBQUM7QUFDcEQsT0FBTyxFQUFPLFVBQVUsRUFBRSxTQUFTLEVBQUUsR0FBRyxFQUFFLE1BQU0sZ0JBQWdCLENBQUM7QUFDakUsT0FBTyxFQUFFLFVBQVUsRUFBRSxNQUFNLHdDQUF3QyxDQUFDO0FBQ3BFLE9BQU8sRUFBRSxtQkFBbUIsRUFBRSxNQUFNLFVBQVUsQ0FBQzs7O0FBVS9DOzs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7OztHQTRDRztBQUVILE1BQU0sT0FBTyxpQkFBaUI7SUFPNUIsWUFDdUMsTUFBeUIsRUFDdEQsSUFBZ0I7UUFEYSxXQUFNLEdBQU4sTUFBTSxDQUFtQjtRQUN0RCxTQUFJLEdBQUosSUFBSSxDQUFZO1FBUmxCLGdCQUFXLEdBQUcsTUFBTSxDQUFDLEtBQUssQ0FBQyxDQUFDO1FBQzVCLGlCQUFZLEdBQTRCLElBQUksQ0FBQztRQUVyRCw4Q0FBOEM7UUFDckMsa0JBQWEsR0FBRyxRQUFRLENBQUMsR0FBRyxFQUFFLENBQUMsSUFBSSxDQUFDLFdBQVcsRUFBRSxDQUFDLENBQUM7SUFLekQsQ0FBQztJQUVKOzs7OztPQUtHO0lBQ0gsS0FBSyxDQUFDLFVBQVUsQ0FBQyxZQUE4QjtRQUM3QyxJQUFJLElBQUksQ0FBQyxXQUFXLEVBQUUsRUFBRSxDQUFDO1lBQ3ZCLE9BQU8sQ0FBQyxHQUFHLENBQUMsa0NBQWtDLENBQUMsQ0FBQztZQUNoRCxPQUFPO1FB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QUFtQjttSEFSbEIsaUJBQWlCLGNBREosTUFBTTs7NEZBQ25CLGlCQUFpQjtrQkFEN0IsVUFBVTttQkFBQyxFQUFFLFVBQVUsRUFBRSxNQUFNLEVBQUU7OzBCQVM3QixNQUFNOzJCQUFDLG1CQUFtQiIsInNvdXJjZXNDb250ZW50IjpbImltcG9ydCB7IEluamVjdGFibGUsIEluamVjdCwgc2lnbmFsLCBjb21wdXRlZCB9IGZyb20gJ0Bhbmd1bGFyL2NvcmUnO1xuaW1wb3J0IHsgSHR0cENsaWVudCB9IGZyb20gJ0Bhbmd1bGFyL2NvbW1vbi9odHRwJztcbmltcG9ydCB7IE9ic2VydmFibGUsIGZyb20sIHRocm93RXJyb3IgfSBmcm9tICdyeGpzJztcbmltcG9ydCB7IG1hcCwgY2F0Y2hFcnJvciwgc3dpdGNoTWFwLCB0YXAgfSBmcm9tICdyeGpzL29wZXJhdG9ycyc7XG5pbXBvcnQgeyBHb29nbGVBdXRoIH0gZnJvbSAnQGNvZGV0cml4LXN0dWRpby9jYXBhY2l0b3ItZ29vZ2xlLWF1dGgnO1xuaW1wb3J0IHsgVkFMVEVDSF9BVVRIX0NPTkZJRyB9IGZyb20gJy4vY29uZmlnJztcbmltcG9ydCB7XG4gIFZhbHRlY2hBdXRoQ29uZmlnLFxuICBHb29nbGVBdXRoQ29uZmlnLFxuICBHb29nbGVVc2VyLFxuICBWZXJpZnlHb29nbGVUb2tlblJlcXVlc3QsXG4gIFZlcmlmeUdvb2dsZVRva2VuUmVzcG9uc2UsXG4gIEF1dGhFcnJvcixcbn0gZnJvbSAnLi90eXBlcyc7XG5cbi8qKlxuICogU2VydmljaW8gZGUgYXV0ZW50aWNhY2nDs24gY29uIEdvb2dsZSB1c2FuZG8gU0RLIG5hdGl2by5cbiAqXG4gKiBFc3RlIHNlcnZpY2lvIHV0aWxpemEgYEBjb2RldHJpeC1zdHVkaW8vY2FwYWNpdG9yLWdvb2dsZS1hdXRoYCBxdWUgZnVuY2lvbmFcbiAqIHRhbnRvIGVuIHdlYiBjb21vIGVuIGFwbGljYWNpb25lcyBDYXBhY2l0b3IgKGlPUy9BbmRyb2lkKS5cbiAqXG4gKiBQYXJhIHdlYiwgdXRpbGl6YSBlbCBwb3B1cCBuYXRpdm8gZGUgR29vZ2xlIFNpZ24tSW4uXG4gKiBQYXJhIG1vYmlsZSwgdXRpbGl6YSBlbCBTREsgbmF0aXZvIGRlIEdvb2dsZS5cbiAqXG4gKiBAZXhhbXBsZVxuICogYGBgdHlwZXNjcmlwdFxuICogLy8gRW4gbWFpbi50cyBvIGFwcC5jb25maWcudHNcbiAqIGltcG9ydCB7IHByb3ZpZGVHb29nbGVBdXRoIH0gZnJvbSAndmFsdGVjaC1jb21wb25lbnRzJztcbiAqXG4gKiBleHBvcnQgY29uc3QgYXBwQ29uZmlnOiBBcHBsaWNhdGlvbkNvbmZpZyA9IHtcbiAqICAgcHJvdmlkZXJzOiBbXG4gKiAgICAgcHJvdmlkZUdvb2dsZUF1dGgoe1xuICogICAgICAgY2xpZW50SWQ6ICd5b3VyLWdvb2dsZS1jbGllbnQtaWQuYXBwcy5nb29nbGV1c2VyY29udGVudC5jb20nXG4gKiAgICAgfSlcbiAqICAgXVxuICogfTtcbiAqXG4gKiAvLyBFbiBlbCBjb21wb25lbnRlXG4gKiBpbXBvcnQgeyBHb29nbGVBdXRoU2VydmljZSwgQXV0aFNlcnZpY2UgfSBmcm9tICd2YWx0ZWNoLWNvbXBvbmVudHMnO1xuICpcbiAqIEBDb21wb25lbnQoey4uLn0pXG4gKiBleHBvcnQgY2xhc3MgTG9naW5Db21wb25lbnQge1xuICogICBwcml2YXRlIGdvb2dsZUF1dGggPSBpbmplY3QoR29vZ2xlQXV0aFNlcnZpY2UpO1xuICogICBwcml2YXRlIGF1dGggPSBpbmplY3QoQXV0aFNlcnZpY2UpO1xuICpcbiAqICAgYXN5bmMgc2lnbkluV2l0aEdvb2dsZSgpIHtcbiAqICAgICB0aGlzLmdvb2dsZUF1dGguc2lnbkluKCkuc3Vic2NyaWJlKHtcbiAqICAgICAgIG5leHQ6IChyZXN1bHQpID0+IHtcbiAqICAgICAgICAgLy8gVG9rZW5zIHJlY2liaWRvcyBkZWwgYmFja2VuZFxuICogICAgICAgICB0aGlzLmF1dGguaGFuZGxlT0F1dGhTdWNjZXNzKHJlc3VsdCk7XG4gKiAgICAgICAgIHRoaXMucm91dGVyLm5hdmlnYXRlKFsnLyddKTtcbiAqICAgICAgIH0sXG4gKiAgICAgICBlcnJvcjogKGVycm9yKSA9PiB7XG4gKiAgICAgICAgIGNvbnNvbGUuZXJyb3IoJ0dvb2dsZSBzaWduLWluIGZhaWxlZDonLCBlcnJvcik7XG4gKiAgICAgICB9XG4gKiAgICAgfSk7XG4gKiAgIH1cbiAqIH1cbiAqIGBgYFxuICovXG5ASW5qZWN0YWJsZSh7IHByb3ZpZGVkSW46ICdyb290JyB9KVxuZXhwb3J0IGNsYXNzIEdvb2dsZUF1dGhTZXJ2aWNlIHtcbiAgcHJpdmF0ZSBpbml0aWFsaXplZCA9IHNpZ25hbChmYWxzZSk7XG4gIHByaXZhdGUgZ29vZ2xlQ29uZmlnOiBHb29nbGVBdXRoQ29uZmlnIHwgbnVsbCA9IG51bGw7XG5cbiAgLyoqIEluZGljYSBzaSBlbCBzZXJ2aWNpbyBlc3TDoSBpbmljaWFsaXphZG8gKi9cbiAgcmVhZG9ubHkgaXNJbml0aWFsaXplZCA9IGNvbXB1dGVkKCgpID0+IHRoaXMuaW5pdGlhbGl6ZWQoKSk7XG5cbiAgY29uc3RydWN0b3IoXG4gICAgQEluamVjdChWQUxURUNIX0FVVEhfQ09ORklHKSBwcml2YXRlIGNvbmZpZzogVmFsdGVjaEF1dGhDb25maWcsXG4gICAgcHJpdmF0ZSBodHRwOiBIdHRwQ2xpZW50XG4gICkge31cblxuICAvKipcbiAgICogSW5pY2lhbGl6YSBlbCBTREsgZGUgR29vZ2xlIFNpZ24tSW4uXG4gICAqIERlYmUgbGxhbWFyc2UgdW5hIHZleiwgaWRlYWxtZW50ZSBlbiBBUFBfSU5JVElBTElaRVIuXG4gICAqXG4gICAqIEBwYXJhbSBnb29nbGVDb25maWcgLSBDb25maWd1cmFjacOzbiBkZSBHb29nbGUgQXV0aFxuICAgKi9cbiAgYXN5bmMgaW5pdGlhbGl6ZShnb29nbGVDb25maWc6IEdvb2dsZUF1dGhDb25maWcpOiBQcm9taXNlPHZvaWQ+IHtcbiAgICBpZiAodGhpcy5pbml0aWFsaXplZCgpKSB7XG4gICAgICBjb25zb2xlLmxvZygnW0dvb2dsZUF1dGhdIEFscmVhZHkgaW5pdGlhbGl6ZWQnKTtcbiAgICAgIHJldHVybjtcbiAgICB9XG5cbiAgICB0aGlzLmdvb2dsZUNvbmZpZyA9IGdvb2dsZUNvbmZpZztcblxuICAgIHRyeSB7XG4gICAgICBhd2FpdCBHb29nbGVBdXRoLmluaXRpYWxpemUoe1xuICAgICAgICBjbGllbnRJZDogZ29vZ2xlQ29uZmlnLmNsaWVudElkLFxuICAgICAgICBzY29wZXM6IGdvb2dsZUNvbmZpZy5zY29wZXMgfHwgWydlbWFpbCcsICdwcm9maWxlJ10sXG4gICAgICAgIGdyYW50T2ZmbGluZUFjY2VzczogdHJ1ZSxcbiAgICAgIH0pO1xuXG4gICAgICB0aGlzLmluaXRpYWxpemVkLnNldCh0cnVlKTtcbiAgICAgIGNvbnNvbGUubG9nKCdbR29vZ2xlQXV0aF0gSW5pdGlhbGl6ZWQgc3VjY2Vzc2Z1bGx5Jyk7XG4gICAgfSBjYXRjaCAoZXJyb3IpIHtcbiAgICAgIGNvbnNvbGUuZXJyb3IoJ1tHb29nbGVBdXRoXSBJbml0aWFsaXphdGlvbiBmYWlsZWQ6JywgZXJyb3IpO1xuICAgICAgdGhyb3cgZXJyb3I7XG4gICAgfVxuICB9XG5cbiAgLyoqXG4gICAqIEluaWNpYSBlbCBmbHVqbyBkZSBHb29nbGUgU2lnbi1JbiB5IG9idGllbmUgdG9rZW5zIGRlbCBiYWNrZW5kLlxuICAgKlxuICAgKiBFbCBmbHVqbyBlczpcbiAgICogMS4gQWJyZSBwb3B1cC9TREsgbmF0aXZvIGRlIEdvb2dsZVxuICAgKiAyLiBVc3VhcmlvIGF1dG9yaXphXG4gICAqIDMuIE9idGllbmUgSUQgdG9rZW4gZGUgR29vZ2xlXG4gICAqIDQuIEVudsOtYSBJRCB0b2tlbiBhbCBiYWNrZW5kIHBhcmEgdmVyaWZpY2FjacOzblxuICAgKiA1LiBCYWNrZW5kIHZlcmlmaWNhIGNvbiBHb29nbGUgeSByZXRvcm5hIG51ZXN0cm9zIEpXVCB0b2tlbnNcbiAgICpcbiAgICogQHJldHVybnMgT2JzZXJ2YWJsZSBjb24gbGEgcmVzcHVlc3RhIGRlbCBiYWNrZW5kICh0b2tlbnMpXG4gICAqL1xuICBzaWduSW4oKTogT2JzZXJ2YWJsZTxWZXJpZnlHb29nbGVUb2tlblJlc3BvbnNlPiB7XG4gICAgaWYgKCF0aGlzLmluaXRpYWxpemVkKCkpIHtcbiAgICAgIHJldHVybiB0aHJvd0Vycm9yKCgpID0+ICh7XG4gICAgICAgIGNvZGU6ICdOT1RfSU5JVElBTElaRUQnLFxuICAgICAgICBtZXNzYWdlOiAnR29vZ2xlQXV0aFNlcnZpY2Ugbm8gZXN0w6EgaW5pY2lhbGl6YWRvLiBMbGFtYSBhIGluaXRpYWxpemUoKSBwcmltZXJvLicsXG4gICAgICB9IGFzIEF1dGhFcnJvcikpO1xuICAgIH1cblxuICAgIHJldHVybiBmcm9tKHRoaXMucGVyZm9ybUdvb2dsZVNpZ25JbigpKS5waXBlKFxuICAgICAgdGFwKGdvb2dsZVVzZXIgPT4ge1xuICAgICAgICBjb25zb2xlLmxvZygnW0dvb2dsZUF1dGhdIEdvb2dsZSBzaWduLWluIHN1Y2Nlc3NmdWw6Jywge1xuICAgICAgICAgIGVtYWlsOiBnb29nbGVVc2VyLmVtYWlsLFxuICAgICAgICAgIGhhc0lkVG9rZW46ICEhZ29vZ2xlVXNlci5pZFRva2VuLFxuICAgICAgICAgIGlkVG9rZW5MZW5ndGg6IGdvb2dsZVVzZXIuaWRUb2tlbj8ubGVuZ3RoIHx8IDAsXG4gICAgICAgIH0pO1xuICAgICAgfSksXG4gICAgICBzd2l0Y2hNYXAoZ29vZ2xlVXNlciA9PiB0aGlzLnZlcmlmeVdpdGhCYWNrZW5kKGdvb2dsZVVzZXIpKSxcbiAgICAgIGNhdGNoRXJyb3IoZXJyb3IgPT4ge1xuICAgICAgICBjb25zb2xlLmVycm9yKCdbR29vZ2xlQXV0aF0gU2lnbi1pbiBlcnJvcjonLCBlcnJvcik7XG5cbiAgICAgICAgLy8gSGFuZGxlIEdvb2dsZSBTREsgc3BlY2lmaWMgZXJyb3JzXG4gICAgICAgIGlmIChlcnJvcj8ubWVzc2FnZT8uaW5jbHVkZXMoJ3BvcHVwX2Nsb3NlZCcpIHx8IGVycm9yPy5jb2RlID09PSAncG9wdXBfY2xvc2VkX2J5X3VzZXInKSB7XG4gICAgICAgICAgcmV0dXJuIHRocm93RXJyb3IoKCkgPT4gKHtcbiAgICAgICAgICAgIGNvZGU6ICdQT1BVUF9DTE9TRUQnLFxuICAgICAgICAgICAgbWVzc2FnZTogJ1NlIGNlcnLDsyBsYSB2ZW50YW5hIGRlIGF1dGVudGljYWNpw7NuIGRlIEdvb2dsZScsXG4gICAgICAgICAgfSBhcyBBdXRoRXJyb3IpKTtcbiAgICAgICAgfVxuXG4gICAgICAgIGlmIChlcnJvcj8ubWVzc2FnZT8uaW5jbHVkZXMoJ2FjY2Vzc19kZW5pZWQnKSB8fCBlcnJvcj8uY29kZSA9PT0gJ2FjY2Vzc19kZW5pZWQnKSB7XG4gICAgICAgICAgcmV0dXJuIHRocm93RXJyb3IoKCkgPT4gKHtcbiAgICAgICAgICAgIGNvZGU6ICdBQ0NFU1NfREVOSUVEJyxcbiAgICAgICAgICAgIG1lc3NhZ2U6ICdFbCB1c3VhcmlvIGRlbmVnw7MgZWwgYWNjZXNvIGEgR29vZ2xlJyxcbiAgICAgICAgICB9IGFzIEF1dGhFcnJvcikpO1xuICAgICAgICB9XG5cbiAgICAgICAgLy8gQmFja2VuZCBlcnJvcnMgcGFzcyB0aHJvdWdoXG4gICAgICAgIGlmIChlcnJvci5jb2RlICYmIGVycm9yLm1lc3NhZ2UpIHtcbiAgICAgICAgICByZXR1cm4gdGhyb3dFcnJvcigoKSA9PiBlcnJvcik7XG4gICAgICAgIH1cblxuICAgICAgICByZXR1cm4gdGhyb3dFcnJvcigoKSA9PiAoe1xuICAgICAgICAgIGNvZGU6ICdHT09HTEVfQVVUSF9FUlJPUicsXG4gICAgICAgICAgbWVzc2FnZTogZXJyb3I/Lm1lc3NhZ2UgfHwgJ0Vycm9yIGFsIGluaWNpYXIgc2VzacOzbiBjb24gR29vZ2xlJyxcbiAgICAgICAgfSBhcyBBdXRoRXJyb3IpKTtcbiAgICAgIH0pXG4gICAgKTtcbiAgfVxuXG4gIC8qKlxuICAgKiBDaWVycmEgbGEgc2VzacOzbiBkZSBHb29nbGUuXG4gICAqIE5vdGE6IEVzdG8gc29sbyBjaWVycmEgbGEgc2VzacOzbiBkZWwgU0RLIGRlIEdvb2dsZSxcbiAgICogTk8gY2llcnJhIGxhIHNlc2nDs24gZGVsIGJhY2tlbmQuIFVzYSBBdXRoU2VydmljZS5sb2dvdXQoKSBwYXJhIGVzby5cbiAgICovXG4gIGFzeW5jIHNpZ25PdXQoKTogUHJvbWlzZTx2b2lkPiB7XG4gICAgdHJ5IHtcbiAgICAgIGF3YWl0IEdvb2dsZUF1dGguc2lnbk91dCgpO1xuICAgICAgY29uc29sZS5sb2coJ1tHb29nbGVBdXRoXSBTaWduZWQgb3V0IGZyb20gR29vZ2xlJyk7XG4gICAgfSBjYXRjaCAoZXJyb3IpIHtcbiAgICAgIGNvbnNvbGUud2FybignW0dvb2dsZUF1dGhdIFNpZ24gb3V0IGVycm9yOicsIGVycm9yKTtcbiAgICB9XG4gIH1cblxuICAvKipcbiAgICogT2J0aWVuZSBlbCB0b2tlbiBkZSBhdXRlbnRpY2FjacOzbiByZWZyZXNjYWRvIChzaSBleGlzdGUgc2VzacOzbikuXG4gICAqIE5vdGE6IEdvb2dsZUF1dGgucmVmcmVzaCgpIHNvbG8gcmV0b3JuYSB0b2tlbnMsIG5vIGluZm8gZGVsIHVzdWFyaW8uXG4gICAqL1xuICBhc3luYyByZWZyZXNoVG9rZW4oKTogUHJvbWlzZTx7IGlkVG9rZW46IHN0cmluZzsgYWNjZXNzVG9rZW46IHN0cmluZyB9IHwgbnVsbD4ge1xuICAgIHRyeSB7XG4gICAgICBjb25zdCBhdXRoID0gYXdhaXQgR29vZ2xlQXV0aC5yZWZyZXNoKCk7XG4gICAgICBpZiAoYXV0aD8uaWRUb2tlbikge1xuICAgICAgICByZXR1cm4ge1xuICAgICAgICAgIGlkVG9rZW46IGF1dGguaWRUb2tlbixcbiAgICAgICAgICBhY2Nlc3NUb2tlbjogYXV0aC5hY2Nlc3NUb2tlbixcbiAgICAgICAgfTtcbiAgICAgIH1cbiAgICAgIHJldHVybiBudWxsO1xuICAgIH0gY2F0Y2gge1xuICAgICAgcmV0dXJuIG51bGw7XG4gICAgfVxuICB9XG5cbiAgLyoqXG4gICAqIFJlYWxpemEgZWwgc2lnbi1pbiBjb24gR29vZ2xlIHVzYW5kbyBlbCBTREsgbmF0aXZvLlxuICAgKi9cbiAgcHJpdmF0ZSBhc3luYyBwZXJmb3JtR29vZ2xlU2lnbkluKCk6IFByb21pc2U8R29vZ2xlVXNlcj4ge1xuICAgIGNvbnN0IHVzZXIgPSBhd2FpdCBHb29nbGVBdXRoLnNpZ25JbigpO1xuXG4gICAgaWYgKCF1c2VyPy5hdXRoZW50aWNhdGlvbj8uaWRUb2tlbikge1xuICAgICAgdGhyb3cgbmV3IEVycm9yKCdObyBzZSBvYnR1dm8gSUQgdG9rZW4gZGUgR29vZ2xlJyk7XG4gICAgfVxuXG4gICAgcmV0dXJuIHtcbiAgICAgIGlkOiB1c2VyLmlkIHx8ICcnLFxuICAgICAgZW1haWw6IHVzZXIuZW1haWwgfHwgJycsXG4gICAgICBuYW1lOiB1c2VyLm5hbWUgfHwgJycsXG4gICAgICBpbWFnZVVybDogdXNlci5pbWFnZVVybCxcbiAgICAgIGlkVG9rZW46IHVzZXIuYXV0aGVudGljYXRpb24uaWRUb2tlbixcbiAgICAgIGFjY2Vzc1Rva2VuOiB1c2VyLmF1dGhlbnRpY2F0aW9uLmFjY2Vzc1Rva2VuLFxuICAgIH07XG4gIH1cblxuICAvKipcbiAgICogVmVyaWZpY2EgZWwgSUQgdG9rZW4gZGUgR29vZ2xlIGNvbiBudWVzdHJvIGJhY2tlbmQuXG4gICAqL1xuICBwcml2YXRlIHZlcmlmeVdpdGhCYWNrZW5kKGdvb2dsZVVzZXI6IEdvb2dsZVVzZXIpOiBPYnNlcnZhYmxlPFZlcmlmeUdvb2dsZVRva2VuUmVzcG9uc2U+IHtcbiAgICBjb25zdCByZXF1ZXN0OiBWZXJpZnlHb29nbGVUb2tlblJlcXVlc3QgPSB7XG4gICAgICBpZFRva2VuOiBnb29nbGVVc2VyLmlkVG9rZW4sXG4gICAgfTtcblxuICAgIGNvbnN0IHVybCA9IGAke3RoaXMuY29uZmlnLmFwaVVybH0vdjIvYXV0aC9vYXV0aC9nb29nbGUvdmVyaWZ5YDtcblxuICAgIHJldHVybiB0aGlzLmh0dHAucG9zdDxWZXJpZnlHb29nbGVUb2tlblJlc3BvbnNlPih1cmwsIHJlcXVlc3QpLnBpcGUoXG4gICAgICB0YXAocmVzcG9uc2UgPT4ge1xuICAgICAgICBjb25zb2xlLmxvZygnW0dvb2dsZUF1dGhdIEJhY2tlbmQgdmVyaWZpY2F0aW9uIHN1Y2Nlc3NmdWw6Jywge1xuICAgICAgICAgIGhhc0FjY2Vzc1Rva2VuOiAhIXJlc3BvbnNlLmFjY2Vzc1Rva2VuLFxuICAgICAgICAgIGhhc0ZpcmViYXNlVG9rZW46ICEhcmVzcG9uc2UuZmlyZWJhc2VUb2tlbixcbiAgICAgICAgICBpc05ld1VzZXI6IHJlc3BvbnNlLmlzTmV3VXNlcixcbiAgICAgICAgfSk7XG4gICAgICB9KSxcbiAgICAgIGNhdGNoRXJyb3IoZXJyb3IgPT4ge1xuICAgICAgICBjb25zb2xlLmVycm9yKCdbR29vZ2xlQXV0aF0gQmFja2VuZCB2ZXJpZmljYXRpb24gZmFpbGVkOicsIGVycm9yKTtcblxuICAgICAgICBjb25zdCBhdXRoRXJyb3I6IEF1dGhFcnJvciA9IHtcbiAgICAgICAgICBjb2RlOiBlcnJvci5lcnJvcj8uY29kZSB8fCAnVkVSSUZJQ0FUSU9OX0VSUk9SJyxcbiAgICAgICAgICBtZXNzYWdlOiBlcnJvci5lcnJvcj8ubWVzc2FnZSB8fCAnRXJyb3IgYWwgdmVyaWZpY2FyIGNyZWRlbmNpYWxlcyBkZSBHb29nbGUnLFxuICAgICAgICB9O1xuXG4gICAgICAgIHJldHVybiB0aHJvd0Vycm9yKCgpID0+IGF1dGhFcnJvcik7XG4gICAgICB9KVxuICAgICk7XG4gIH1cbn1cbiJdfQ==
@@ -1,102 +0,0 @@
1
- import { HttpClient } from '@angular/common/http';
2
- import { Observable } from 'rxjs';
3
- import { ValtechAuthConfig, GoogleAuthConfig, VerifyGoogleTokenResponse } from './types';
4
- import * as i0 from "@angular/core";
5
- /**
6
- * Servicio de autenticación con Google usando SDK nativo.
7
- *
8
- * Este servicio utiliza `@codetrix-studio/capacitor-google-auth` que funciona
9
- * tanto en web como en aplicaciones Capacitor (iOS/Android).
10
- *
11
- * Para web, utiliza el popup nativo de Google Sign-In.
12
- * Para mobile, utiliza el SDK nativo de Google.
13
- *
14
- * @example
15
- * ```typescript
16
- * // En main.ts o app.config.ts
17
- * import { provideGoogleAuth } from 'valtech-components';
18
- *
19
- * export const appConfig: ApplicationConfig = {
20
- * providers: [
21
- * provideGoogleAuth({
22
- * clientId: 'your-google-client-id.apps.googleusercontent.com'
23
- * })
24
- * ]
25
- * };
26
- *
27
- * // En el componente
28
- * import { GoogleAuthService, AuthService } from 'valtech-components';
29
- *
30
- * @Component({...})
31
- * export class LoginComponent {
32
- * private googleAuth = inject(GoogleAuthService);
33
- * private auth = inject(AuthService);
34
- *
35
- * async signInWithGoogle() {
36
- * this.googleAuth.signIn().subscribe({
37
- * next: (result) => {
38
- * // Tokens recibidos del backend
39
- * this.auth.handleOAuthSuccess(result);
40
- * this.router.navigate(['/']);
41
- * },
42
- * error: (error) => {
43
- * console.error('Google sign-in failed:', error);
44
- * }
45
- * });
46
- * }
47
- * }
48
- * ```
49
- */
50
- export declare class GoogleAuthService {
51
- private config;
52
- private http;
53
- private initialized;
54
- private googleConfig;
55
- /** Indica si el servicio está inicializado */
56
- readonly isInitialized: import("@angular/core").Signal<boolean>;
57
- constructor(config: ValtechAuthConfig, http: HttpClient);
58
- /**
59
- * Inicializa el SDK de Google Sign-In.
60
- * Debe llamarse una vez, idealmente en APP_INITIALIZER.
61
- *
62
- * @param googleConfig - Configuración de Google Auth
63
- */
64
- initialize(googleConfig: GoogleAuthConfig): Promise<void>;
65
- /**
66
- * Inicia el flujo de Google Sign-In y obtiene tokens del backend.
67
- *
68
- * El flujo es:
69
- * 1. Abre popup/SDK nativo de Google
70
- * 2. Usuario autoriza
71
- * 3. Obtiene ID token de Google
72
- * 4. Envía ID token al backend para verificación
73
- * 5. Backend verifica con Google y retorna nuestros JWT tokens
74
- *
75
- * @returns Observable con la respuesta del backend (tokens)
76
- */
77
- signIn(): Observable<VerifyGoogleTokenResponse>;
78
- /**
79
- * Cierra la sesión de Google.
80
- * Nota: Esto solo cierra la sesión del SDK de Google,
81
- * NO cierra la sesión del backend. Usa AuthService.logout() para eso.
82
- */
83
- signOut(): Promise<void>;
84
- /**
85
- * Obtiene el token de autenticación refrescado (si existe sesión).
86
- * Nota: GoogleAuth.refresh() solo retorna tokens, no info del usuario.
87
- */
88
- refreshToken(): Promise<{
89
- idToken: string;
90
- accessToken: string;
91
- } | null>;
92
- /**
93
- * Realiza el sign-in con Google usando el SDK nativo.
94
- */
95
- private performGoogleSignIn;
96
- /**
97
- * Verifica el ID token de Google con nuestro backend.
98
- */
99
- private verifyWithBackend;
100
- static ɵfac: i0.ɵɵFactoryDeclaration<GoogleAuthService, never>;
101
- static ɵprov: i0.ɵɵInjectableDeclaration<GoogleAuthService>;
102
- }