@glideidentity/web-client-sdk 5.0.1 → 5.1.1-beta.3
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/README.md +8 -108
- package/dist/adapters/angular/index.js +1 -0
- package/dist/adapters/angular/phone-auth.service.d.ts +18 -0
- package/dist/adapters/angular/phone-auth.service.js +26 -0
- package/dist/adapters/react/index.js +3 -0
- package/dist/adapters/react/useClient.js +1 -0
- package/dist/adapters/react/usePhoneAuth.js +16 -1
- package/dist/adapters/vanilla/client.js +1 -0
- package/dist/adapters/vanilla/index.js +1 -0
- package/dist/adapters/vanilla/phone-auth.js +31 -0
- package/dist/adapters/vue/index.js +4 -0
- package/dist/adapters/vue/useClient.js +5 -0
- package/dist/adapters/vue/usePhoneAuth.js +20 -1
- package/dist/browser/web-client-sdk.min.js +1 -2
- package/dist/browser.js +6 -0
- package/dist/core/client.js +12 -0
- package/dist/core/logger.js +81 -1
- package/dist/core/phone-auth/api-types.d.ts +1 -6
- package/dist/core/phone-auth/api-types.js +83 -0
- package/dist/core/phone-auth/client.js +374 -38
- package/dist/core/phone-auth/error-utils.js +83 -1
- package/dist/core/phone-auth/index.d.ts +1 -1
- package/dist/core/phone-auth/index.js +2 -2
- package/dist/core/phone-auth/status-types.d.ts +78 -0
- package/dist/core/phone-auth/status-types.js +17 -0
- package/dist/core/phone-auth/strategies/desktop.d.ts +2 -0
- package/dist/core/phone-auth/strategies/desktop.js +136 -13
- package/dist/core/phone-auth/strategies/index.d.ts +4 -0
- package/dist/core/phone-auth/strategies/index.js +4 -0
- package/dist/core/phone-auth/strategies/link.d.ts +2 -0
- package/dist/core/phone-auth/strategies/link.js +97 -13
- package/dist/core/phone-auth/strategies/ts43.d.ts +19 -0
- package/dist/core/phone-auth/strategies/ts43.js +33 -2
- package/dist/core/phone-auth/strategies/types.js +4 -0
- package/dist/core/phone-auth/type-guards.js +131 -0
- package/dist/core/phone-auth/types.d.ts +5 -0
- package/dist/core/phone-auth/types.js +32 -0
- package/dist/core/phone-auth/ui/mobile-debug-console.js +28 -2
- package/dist/core/phone-auth/ui/modal.d.ts +55 -33
- package/dist/core/phone-auth/ui/modal.js +422 -889
- package/dist/core/phone-auth/validation-utils.d.ts +0 -9
- package/dist/core/phone-auth/validation-utils.js +34 -25
- package/dist/core/version.js +2 -1
- package/dist/esm/adapters/angular/index.js +1 -0
- package/dist/esm/adapters/angular/phone-auth.service.d.ts +18 -0
- package/dist/esm/adapters/angular/phone-auth.service.js +26 -0
- package/dist/esm/adapters/react/index.js +3 -0
- package/dist/esm/adapters/react/useClient.js +1 -0
- package/dist/esm/adapters/react/usePhoneAuth.js +16 -1
- package/dist/esm/adapters/vanilla/client.js +1 -0
- package/dist/esm/adapters/vanilla/index.js +1 -0
- package/dist/esm/adapters/vanilla/phone-auth.d.ts +24 -0
- package/dist/esm/adapters/vanilla/phone-auth.js +31 -0
- package/dist/esm/adapters/vue/index.js +4 -0
- package/dist/esm/adapters/vue/useClient.js +5 -0
- package/dist/esm/adapters/vue/usePhoneAuth.js +20 -1
- package/dist/esm/browser.js +6 -0
- package/dist/esm/core/client.d.ts +10 -0
- package/dist/esm/core/client.js +12 -0
- package/dist/esm/core/logger.d.ts +53 -0
- package/dist/esm/core/logger.js +81 -1
- package/dist/esm/core/phone-auth/api-types.d.ts +312 -2
- package/dist/esm/core/phone-auth/api-types.js +83 -0
- package/dist/esm/core/phone-auth/client.d.ts +144 -0
- package/dist/esm/core/phone-auth/client.js +375 -39
- package/dist/esm/core/phone-auth/error-utils.d.ts +29 -0
- package/dist/esm/core/phone-auth/error-utils.js +83 -1
- package/dist/esm/core/phone-auth/index.d.ts +1 -1
- package/dist/esm/core/phone-auth/index.js +4 -2
- package/dist/esm/core/phone-auth/status-types.d.ts +78 -0
- package/dist/esm/core/phone-auth/status-types.js +17 -0
- package/dist/esm/core/phone-auth/strategies/desktop.d.ts +65 -0
- package/dist/esm/core/phone-auth/strategies/desktop.js +136 -13
- package/dist/esm/core/phone-auth/strategies/index.d.ts +4 -0
- package/dist/esm/core/phone-auth/strategies/index.js +4 -0
- package/dist/esm/core/phone-auth/strategies/link.d.ts +50 -0
- package/dist/esm/core/phone-auth/strategies/link.js +97 -13
- package/dist/esm/core/phone-auth/strategies/ts43.d.ts +19 -0
- package/dist/esm/core/phone-auth/strategies/ts43.js +33 -2
- package/dist/esm/core/phone-auth/strategies/types.d.ts +13 -0
- package/dist/esm/core/phone-auth/strategies/types.js +4 -0
- package/dist/esm/core/phone-auth/type-guards.d.ts +128 -0
- package/dist/esm/core/phone-auth/type-guards.js +131 -0
- package/dist/esm/core/phone-auth/types.d.ts +113 -0
- package/dist/esm/core/phone-auth/types.js +32 -0
- package/dist/esm/core/phone-auth/ui/mobile-debug-console.d.ts +4 -0
- package/dist/esm/core/phone-auth/ui/mobile-debug-console.js +28 -2
- package/dist/esm/core/phone-auth/ui/modal.d.ts +68 -27
- package/dist/esm/core/phone-auth/ui/modal.js +422 -889
- package/dist/esm/core/phone-auth/validation-utils.d.ts +26 -4
- package/dist/esm/core/phone-auth/validation-utils.js +34 -24
- package/dist/esm/core/types.d.ts +35 -0
- package/dist/esm/core/version.js +2 -1
- package/dist/esm/index.js +9 -1
- package/dist/index.js +7 -0
- package/package.json +1 -1
- package/dist/browser/web-client-sdk.min.js.LICENSE.txt +0 -1
|
@@ -65,14 +65,43 @@ export declare const PhoneAuthErrorCode: {
|
|
|
65
65
|
};
|
|
66
66
|
export type PhoneAuthErrorCode = typeof PhoneAuthErrorCode[keyof typeof PhoneAuthErrorCode];
|
|
67
67
|
import type { AuthError } from './types';
|
|
68
|
+
/**
|
|
69
|
+
* Type guard to check if an error is a PhoneAuthError
|
|
70
|
+
*/
|
|
68
71
|
export declare function isPhoneAuthError(error: any): error is AuthError;
|
|
72
|
+
/**
|
|
73
|
+
* Check if error should be shown to user
|
|
74
|
+
*/
|
|
69
75
|
export declare function isUserError(error: AuthError): boolean;
|
|
76
|
+
/**
|
|
77
|
+
* Get user-friendly error message
|
|
78
|
+
*/
|
|
70
79
|
export declare function getUserMessage(error: AuthError): string;
|
|
80
|
+
/**
|
|
81
|
+
* Check if error matches a specific code
|
|
82
|
+
*/
|
|
71
83
|
export declare function isErrorCode(error: AuthError, code: PhoneAuthErrorCode): boolean;
|
|
84
|
+
/**
|
|
85
|
+
* Get retry delay for rate-limited requests
|
|
86
|
+
*/
|
|
72
87
|
export declare function getRetryDelay(error: AuthError): number | null;
|
|
88
|
+
/**
|
|
89
|
+
* Check if error is retryable
|
|
90
|
+
*/
|
|
73
91
|
export declare function isRetryableError(error: AuthError): boolean;
|
|
92
|
+
/**
|
|
93
|
+
* Parse error response from backend API
|
|
94
|
+
*/
|
|
74
95
|
export declare function parseBackendError(response: any): AuthError;
|
|
96
|
+
/**
|
|
97
|
+
* Serialize error for logging/observability tools like Sentry
|
|
98
|
+
* This ensures all error details are captured in a format that can be sent over the network
|
|
99
|
+
*/
|
|
75
100
|
export declare function serializeError(error: AuthError): Record<string, any>;
|
|
101
|
+
/**
|
|
102
|
+
* Create a breadcrumb trail for error tracking
|
|
103
|
+
* Useful for understanding the sequence of events leading to an error
|
|
104
|
+
*/
|
|
76
105
|
export declare function createErrorBreadcrumb(error: AuthError): {
|
|
77
106
|
category: string;
|
|
78
107
|
message: string;
|
|
@@ -1,29 +1,36 @@
|
|
|
1
1
|
import { SDK_VERSION } from '../version';
|
|
2
|
+
// Error constants matching the backend for consistency
|
|
2
3
|
export const PhoneAuthErrorCode = {
|
|
4
|
+
// 400 Bad Request errors
|
|
3
5
|
BAD_REQUEST: 'BAD_REQUEST',
|
|
4
6
|
VALIDATION_ERROR: 'VALIDATION_ERROR',
|
|
5
7
|
INVALID_PARAMETERS: 'INVALID_PARAMETERS',
|
|
6
8
|
MISSING_PARAMETERS: 'MISSING_PARAMETERS',
|
|
7
9
|
INVALID_PHONE_NUMBER: 'INVALID_PHONE_NUMBER',
|
|
8
10
|
INVALID_MCC_MNC: 'INVALID_MCC_MNC',
|
|
11
|
+
// 401 Unauthorized errors
|
|
9
12
|
UNAUTHORIZED: 'UNAUTHORIZED',
|
|
10
13
|
INVALID_CREDENTIALS: 'INVALID_CREDENTIALS',
|
|
11
14
|
EXPIRED_TOKEN: 'EXPIRED_TOKEN',
|
|
12
15
|
TOKEN_ACQUISITION_FAILED: 'TOKEN_ACQUISITION_FAILED',
|
|
13
16
|
INVALID_API_KEY: 'INVALID_API_KEY',
|
|
14
17
|
MISSING_AUTH_HEADER: 'MISSING_AUTH_HEADER',
|
|
18
|
+
// 403 Forbidden errors
|
|
15
19
|
FORBIDDEN: 'FORBIDDEN',
|
|
16
20
|
INSUFFICIENT_PERMISSIONS: 'INSUFFICIENT_PERMISSIONS',
|
|
17
21
|
ACCESS_DENIED: 'ACCESS_DENIED',
|
|
22
|
+
// 404 Not Found errors
|
|
18
23
|
NOT_FOUND: 'NOT_FOUND',
|
|
19
24
|
RESOURCE_NOT_FOUND: 'RESOURCE_NOT_FOUND',
|
|
20
25
|
SESSION_NOT_FOUND: 'SESSION_NOT_FOUND',
|
|
21
26
|
CARRIER_NOT_FOUND: 'CARRIER_NOT_FOUND',
|
|
22
27
|
ENDPOINT_NOT_FOUND: 'ENDPOINT_NOT_FOUND',
|
|
28
|
+
// 409 Conflict errors
|
|
23
29
|
CONFLICT: 'CONFLICT',
|
|
24
30
|
RESOURCE_ALREADY_EXISTS: 'RESOURCE_ALREADY_EXISTS',
|
|
25
31
|
DUPLICATE_SESSION: 'DUPLICATE_SESSION',
|
|
26
32
|
CONCURRENT_MODIFICATION: 'CONCURRENT_MODIFICATION',
|
|
33
|
+
// 422 Unprocessable Entity errors
|
|
27
34
|
UNPROCESSABLE_ENTITY: 'UNPROCESSABLE_ENTITY',
|
|
28
35
|
UNSUPPORTED_VERIFICATION: 'UNSUPPORTED_VERIFICATION',
|
|
29
36
|
INVALID_VERIFICATION: 'INVALID_VERIFICATION',
|
|
@@ -39,117 +46,160 @@ export const PhoneAuthErrorCode = {
|
|
|
39
46
|
INVALID_SESSION_STATE: 'INVALID_SESSION_STATE',
|
|
40
47
|
PHONE_NUMBER_MISMATCH: 'PHONE_NUMBER_MISMATCH',
|
|
41
48
|
INVALID_CREDENTIAL_FORMAT: 'INVALID_CREDENTIAL_FORMAT',
|
|
49
|
+
// 429 Too Many Requests errors
|
|
42
50
|
RATE_LIMIT_EXCEEDED: 'RATE_LIMIT_EXCEEDED',
|
|
43
51
|
TOO_MANY_REQUESTS: 'TOO_MANY_REQUESTS',
|
|
44
52
|
QUOTA_EXCEEDED: 'QUOTA_EXCEEDED',
|
|
53
|
+
// 500 Internal Server errors
|
|
45
54
|
INTERNAL_SERVER_ERROR: 'INTERNAL_SERVER_ERROR',
|
|
46
55
|
CIRCUIT_BREAKER_CONFIGURATION_ERROR: 'CIRCUIT_BREAKER_CONFIGURATION_ERROR',
|
|
47
56
|
DATABASE_ERROR: 'DATABASE_ERROR',
|
|
48
57
|
CACHE_ERROR: 'CACHE_ERROR',
|
|
49
58
|
SERIALIZATION_ERROR: 'SERIALIZATION_ERROR',
|
|
50
59
|
CRYPTO_ERROR: 'CRYPTO_ERROR',
|
|
60
|
+
// 502 Bad Gateway errors
|
|
51
61
|
BAD_GATEWAY: 'BAD_GATEWAY',
|
|
52
62
|
UPSTREAM_ERROR: 'UPSTREAM_ERROR',
|
|
53
63
|
INVALID_RESPONSE: 'INVALID_RESPONSE',
|
|
64
|
+
// 503 Service Unavailable errors
|
|
54
65
|
SERVICE_UNAVAILABLE: 'SERVICE_UNAVAILABLE',
|
|
55
66
|
DOWNSTREAM_SERVICE_ERROR: 'DOWNSTREAM_SERVICE_ERROR',
|
|
56
67
|
PROVIDER_ERROR: 'PROVIDER_ERROR',
|
|
57
68
|
CIRCUIT_BREAKER_OPEN: 'CIRCUIT_BREAKER_OPEN',
|
|
58
69
|
MAINTENANCE_MODE: 'MAINTENANCE_MODE',
|
|
70
|
+
// 504 Gateway Timeout errors
|
|
59
71
|
GATEWAY_TIMEOUT: 'GATEWAY_TIMEOUT',
|
|
60
72
|
REQUEST_TIMEOUT: 'REQUEST_TIMEOUT',
|
|
61
73
|
UPSTREAM_TIMEOUT: 'UPSTREAM_TIMEOUT',
|
|
62
74
|
DEADLINE_EXCEEDED: 'DEADLINE_EXCEEDED',
|
|
75
|
+
// Browser-specific errors (never thrown by backend)
|
|
63
76
|
BROWSER_NOT_SUPPORTED: 'BROWSER_NOT_SUPPORTED',
|
|
64
77
|
USER_DENIED: 'USER_DENIED',
|
|
65
78
|
NETWORK_ERROR: 'NETWORK_ERROR',
|
|
66
79
|
};
|
|
80
|
+
// User-facing error messages - NEVER expose carrier names or phone numbers
|
|
67
81
|
const USER_ERROR_MESSAGES = {
|
|
82
|
+
// Privacy-conscious messages - no carrier/phone info exposed
|
|
68
83
|
CARRIER_NOT_ELIGIBLE: 'Your carrier is not eligible for this verification method.',
|
|
69
84
|
CARRIER_IDENTIFICATION_FAILED: 'Unable to identify carrier for the provided phone number.',
|
|
70
85
|
CARRIER_NOT_FOUND: 'Carrier information not available.',
|
|
71
86
|
UNSUPPORTED_CARRIER: 'This carrier is not supported.',
|
|
87
|
+
// Rate limiting
|
|
72
88
|
RATE_LIMIT_EXCEEDED: 'Too many attempts. Please wait a moment and try again.',
|
|
73
89
|
TOO_MANY_REQUESTS: 'Too many requests. Please slow down and try again.',
|
|
74
90
|
QUOTA_EXCEEDED: 'Usage limit reached. Please try again later.',
|
|
91
|
+
// Session errors
|
|
75
92
|
SESSION_NOT_FOUND: 'Your session has expired. Please start over.',
|
|
76
93
|
INVALID_SESSION_STATE: 'Invalid session state. Please start over.',
|
|
77
94
|
DUPLICATE_SESSION: 'A session already exists. Please complete or cancel it first.',
|
|
95
|
+
// Browser/platform errors
|
|
78
96
|
BROWSER_NOT_SUPPORTED: 'Digital Credentials API is not available. Please enable the #web-identity-digital-credentials flag in chrome://flags',
|
|
79
97
|
UNSUPPORTED_PLATFORM: 'This platform is not supported for authentication.',
|
|
80
98
|
UNSUPPORTED_STRATEGY: 'This authentication method is not available.',
|
|
81
99
|
USER_DENIED: 'Authentication was cancelled. Please try again when you\'re ready.',
|
|
100
|
+
// Service availability
|
|
82
101
|
SERVICE_UNAVAILABLE: 'The service is temporarily unavailable. Please try again later.',
|
|
83
102
|
CIRCUIT_BREAKER_OPEN: 'Service is experiencing issues. Please try again later.',
|
|
84
103
|
MAINTENANCE_MODE: 'Service is under maintenance. Please try again later.',
|
|
85
104
|
DOWNSTREAM_SERVICE_ERROR: 'A required service is unavailable. Please try again later.',
|
|
105
|
+
// Authentication errors
|
|
86
106
|
TOKEN_ACQUISITION_FAILED: 'Failed to acquire authentication token. Please try again.',
|
|
87
107
|
EXPIRED_TOKEN: 'Your authentication has expired. Please start over.',
|
|
88
108
|
INVALID_CREDENTIALS: 'Invalid credentials provided.',
|
|
109
|
+
// Validation errors
|
|
89
110
|
INVALID_PHONE_NUMBER: 'Please enter a valid phone number.',
|
|
90
111
|
PHONE_NUMBER_MISMATCH: 'Phone number mismatch. Please verify your number.',
|
|
91
112
|
INVALID_PARAMETERS: 'Invalid parameters provided.',
|
|
92
113
|
MISSING_PARAMETERS: 'Required information is missing.',
|
|
93
114
|
VALIDATION_ERROR: 'Validation failed. Please check your input.',
|
|
115
|
+
// Network errors
|
|
94
116
|
NETWORK_ERROR: 'Network connection failed. Please check your connection and try again.',
|
|
95
117
|
GATEWAY_TIMEOUT: 'Request timed out. Please try again.',
|
|
96
118
|
REQUEST_TIMEOUT: 'Request timed out. Please try again.',
|
|
97
119
|
DEADLINE_EXCEEDED: 'Operation took too long. Please try again.',
|
|
120
|
+
// Verification errors
|
|
98
121
|
VERIFICATION_FAILED: 'Verification failed. Please try again.',
|
|
99
122
|
INVALID_VERIFICATION: 'Invalid verification response.',
|
|
100
123
|
INVALID_CREDENTIAL_FORMAT: 'Invalid credential format.',
|
|
124
|
+
// Generic fallbacks
|
|
101
125
|
BAD_REQUEST: 'Invalid request. Please try again.',
|
|
102
126
|
UNAUTHORIZED: 'Authentication required.',
|
|
103
127
|
FORBIDDEN: 'Access denied.',
|
|
104
128
|
NOT_FOUND: 'Resource not found.',
|
|
105
129
|
INTERNAL_SERVER_ERROR: 'An error occurred. Please try again later.',
|
|
106
130
|
};
|
|
131
|
+
// Errors that should be shown to users vs logged internally
|
|
107
132
|
const USER_FACING_ERRORS = new Set([
|
|
133
|
+
// Carrier errors (privacy-safe messages)
|
|
108
134
|
'CARRIER_NOT_ELIGIBLE',
|
|
109
135
|
'CARRIER_IDENTIFICATION_FAILED',
|
|
110
136
|
'CARRIER_NOT_FOUND',
|
|
111
137
|
'UNSUPPORTED_CARRIER',
|
|
138
|
+
// Rate limiting
|
|
112
139
|
'RATE_LIMIT_EXCEEDED',
|
|
113
140
|
'TOO_MANY_REQUESTS',
|
|
114
141
|
'QUOTA_EXCEEDED',
|
|
142
|
+
// Browser/platform
|
|
115
143
|
'BROWSER_NOT_SUPPORTED',
|
|
116
144
|
'UNSUPPORTED_PLATFORM',
|
|
117
145
|
'UNSUPPORTED_STRATEGY',
|
|
118
146
|
'USER_DENIED',
|
|
147
|
+
// Session
|
|
119
148
|
'SESSION_NOT_FOUND',
|
|
120
149
|
'INVALID_SESSION_STATE',
|
|
121
150
|
'EXPIRED_TOKEN',
|
|
151
|
+
// Service availability
|
|
122
152
|
'SERVICE_UNAVAILABLE',
|
|
123
153
|
'CIRCUIT_BREAKER_OPEN',
|
|
124
154
|
'MAINTENANCE_MODE',
|
|
155
|
+
// Network
|
|
125
156
|
'NETWORK_ERROR',
|
|
126
157
|
'GATEWAY_TIMEOUT',
|
|
127
158
|
'REQUEST_TIMEOUT',
|
|
159
|
+
// Validation
|
|
128
160
|
'INVALID_PHONE_NUMBER',
|
|
129
161
|
'PHONE_NUMBER_MISMATCH',
|
|
130
162
|
'MISSING_PARAMETERS',
|
|
131
163
|
'VALIDATION_ERROR',
|
|
132
164
|
]);
|
|
165
|
+
/**
|
|
166
|
+
* Type guard to check if an error is a PhoneAuthError
|
|
167
|
+
*/
|
|
133
168
|
export function isPhoneAuthError(error) {
|
|
134
169
|
return error &&
|
|
135
170
|
typeof error.code === 'string' &&
|
|
136
171
|
typeof error.message === 'string';
|
|
137
172
|
}
|
|
173
|
+
/**
|
|
174
|
+
* Check if error should be shown to user
|
|
175
|
+
*/
|
|
138
176
|
export function isUserError(error) {
|
|
139
177
|
return USER_FACING_ERRORS.has(error.code);
|
|
140
178
|
}
|
|
179
|
+
/**
|
|
180
|
+
* Get user-friendly error message
|
|
181
|
+
*/
|
|
141
182
|
export function getUserMessage(error) {
|
|
142
183
|
return USER_ERROR_MESSAGES[error.code] || 'An unexpected error occurred. Please try again.';
|
|
143
184
|
}
|
|
185
|
+
/**
|
|
186
|
+
* Check if error matches a specific code
|
|
187
|
+
*/
|
|
144
188
|
export function isErrorCode(error, code) {
|
|
145
189
|
return error.code === code;
|
|
146
190
|
}
|
|
191
|
+
/**
|
|
192
|
+
* Get retry delay for rate-limited requests
|
|
193
|
+
*/
|
|
147
194
|
export function getRetryDelay(error) {
|
|
148
195
|
if (error.code === PhoneAuthErrorCode.RATE_LIMIT_EXCEEDED && error.retryAfter) {
|
|
149
|
-
return error.retryAfter * 1000;
|
|
196
|
+
return error.retryAfter * 1000; // Convert to milliseconds
|
|
150
197
|
}
|
|
151
198
|
return null;
|
|
152
199
|
}
|
|
200
|
+
/**
|
|
201
|
+
* Check if error is retryable
|
|
202
|
+
*/
|
|
153
203
|
export function isRetryableError(error) {
|
|
154
204
|
const retryableCodes = [
|
|
155
205
|
PhoneAuthErrorCode.NETWORK_ERROR,
|
|
@@ -159,8 +209,12 @@ export function isRetryableError(error) {
|
|
|
159
209
|
];
|
|
160
210
|
return retryableCodes.includes(error.code);
|
|
161
211
|
}
|
|
212
|
+
/**
|
|
213
|
+
* Parse error response from backend API
|
|
214
|
+
*/
|
|
162
215
|
export function parseBackendError(response) {
|
|
163
216
|
var _a, _b;
|
|
217
|
+
// Direct error structure from backend
|
|
164
218
|
if (response && typeof response === 'object' && (response.code || response.error)) {
|
|
165
219
|
const errorCode = response.code || response.error;
|
|
166
220
|
const error = {
|
|
@@ -170,15 +224,18 @@ export function parseBackendError(response) {
|
|
|
170
224
|
requestId: response.requestId || response.request_id,
|
|
171
225
|
timestamp: response.timestamp,
|
|
172
226
|
details: response.details,
|
|
227
|
+
// Include trace info for observability
|
|
173
228
|
traceId: response.trace_id || response.traceId,
|
|
174
229
|
spanId: response.span_id || response.spanId,
|
|
175
230
|
service: response.service
|
|
176
231
|
};
|
|
232
|
+
// Extract retryAfter from details if present
|
|
177
233
|
if ((_a = response.details) === null || _a === void 0 ? void 0 : _a.retryAfter) {
|
|
178
234
|
error.retryAfter = response.details.retryAfter;
|
|
179
235
|
}
|
|
180
236
|
return error;
|
|
181
237
|
}
|
|
238
|
+
// Handle HTTP response with error
|
|
182
239
|
if (response && response.status) {
|
|
183
240
|
const code = mapStatusToErrorCode(response.status);
|
|
184
241
|
return {
|
|
@@ -188,12 +245,16 @@ export function parseBackendError(response) {
|
|
|
188
245
|
requestId: (_b = response.headers) === null || _b === void 0 ? void 0 : _b['x-request-id']
|
|
189
246
|
};
|
|
190
247
|
}
|
|
248
|
+
// Default to unexpected error
|
|
191
249
|
return {
|
|
192
250
|
code: PhoneAuthErrorCode.INTERNAL_SERVER_ERROR,
|
|
193
251
|
message: 'An unexpected error occurred',
|
|
194
252
|
status: 500
|
|
195
253
|
};
|
|
196
254
|
}
|
|
255
|
+
/**
|
|
256
|
+
* Map HTTP status to error code
|
|
257
|
+
*/
|
|
197
258
|
function mapStatusToErrorCode(status) {
|
|
198
259
|
switch (status) {
|
|
199
260
|
case 400: return PhoneAuthErrorCode.BAD_REQUEST;
|
|
@@ -210,35 +271,56 @@ function mapStatusToErrorCode(status) {
|
|
|
210
271
|
default: return PhoneAuthErrorCode.INTERNAL_SERVER_ERROR;
|
|
211
272
|
}
|
|
212
273
|
}
|
|
274
|
+
/**
|
|
275
|
+
* Serialize error for logging/observability tools like Sentry
|
|
276
|
+
* This ensures all error details are captured in a format that can be sent over the network
|
|
277
|
+
*/
|
|
213
278
|
export function serializeError(error) {
|
|
214
279
|
return {
|
|
280
|
+
// Core error info
|
|
215
281
|
code: error.code,
|
|
216
282
|
message: error.message,
|
|
283
|
+
// Backend error details
|
|
217
284
|
status: error.status,
|
|
218
285
|
requestId: error.requestId,
|
|
219
286
|
timestamp: error.timestamp,
|
|
287
|
+
// Trace context for distributed tracing
|
|
220
288
|
traceId: error.traceId,
|
|
221
289
|
spanId: error.spanId,
|
|
222
290
|
service: error.service,
|
|
291
|
+
// Specific error fields
|
|
223
292
|
retryAfter: error.retryAfter,
|
|
293
|
+
// Browser error details
|
|
224
294
|
browserError: error.browserError,
|
|
295
|
+
// Context
|
|
225
296
|
context: error.context,
|
|
297
|
+
// Additional details (sanitized - no sensitive info)
|
|
226
298
|
details: sanitizeDetails(error.details),
|
|
299
|
+
// SDK metadata
|
|
227
300
|
sdkVersion: SDK_VERSION,
|
|
228
301
|
errorCapturedAt: new Date().toISOString()
|
|
229
302
|
};
|
|
230
303
|
}
|
|
304
|
+
/**
|
|
305
|
+
* Sanitize error details to remove sensitive information
|
|
306
|
+
*/
|
|
231
307
|
function sanitizeDetails(details) {
|
|
232
308
|
if (!details || typeof details !== 'object') {
|
|
233
309
|
return details;
|
|
234
310
|
}
|
|
311
|
+
// Clone the object
|
|
235
312
|
const sanitized = JSON.parse(JSON.stringify(details));
|
|
313
|
+
// Remove sensitive fields
|
|
236
314
|
const sensitiveFields = ['carrier', 'phone_number', 'mnc', 'mcc', 'carrier_name'];
|
|
237
315
|
for (const field of sensitiveFields) {
|
|
238
316
|
delete sanitized[field];
|
|
239
317
|
}
|
|
240
318
|
return sanitized;
|
|
241
319
|
}
|
|
320
|
+
/**
|
|
321
|
+
* Create a breadcrumb trail for error tracking
|
|
322
|
+
* Useful for understanding the sequence of events leading to an error
|
|
323
|
+
*/
|
|
242
324
|
export function createErrorBreadcrumb(error) {
|
|
243
325
|
var _a, _b, _c;
|
|
244
326
|
return {
|
|
@@ -2,6 +2,6 @@ export { PhoneAuthClient } from './client';
|
|
|
2
2
|
export * from './types';
|
|
3
3
|
export { PhoneAuthErrorCode, isPhoneAuthError, isUserError, getUserMessage, isErrorCode, getRetryDelay, isRetryableError, serializeError, createErrorBreadcrumb } from './error-utils';
|
|
4
4
|
export type { PhoneAuthErrorCode as PhoneAuthErrorCodeType } from './error-utils';
|
|
5
|
-
export { validatePhoneNumber, validatePlmn, validateUseCaseRequirements
|
|
5
|
+
export { validatePhoneNumber, validatePlmn, validateUseCaseRequirements } from './validation-utils';
|
|
6
6
|
export { MobileDebugConsole } from './ui/mobile-debug-console';
|
|
7
7
|
export { isExtendedResponse, isCredential, isAuthCredential, isLinkStrategy, isTS43Strategy, isDesktopStrategy, getStrategy, hasPollingControls, hasTrigger, isHeadlessResult, requiresPolling, requiresUserAction } from './type-guards';
|
|
@@ -1,6 +1,8 @@
|
|
|
1
1
|
export { PhoneAuthClient } from './client';
|
|
2
2
|
export * from './types';
|
|
3
3
|
export { PhoneAuthErrorCode, isPhoneAuthError, isUserError, getUserMessage, isErrorCode, getRetryDelay, isRetryableError, serializeError, createErrorBreadcrumb } from './error-utils';
|
|
4
|
-
export { validatePhoneNumber, validatePlmn, validateUseCaseRequirements
|
|
4
|
+
export { validatePhoneNumber, validatePlmn, validateUseCaseRequirements } from './validation-utils';
|
|
5
5
|
export { MobileDebugConsole } from './ui/mobile-debug-console';
|
|
6
|
-
export { isExtendedResponse, isCredential, isAuthCredential, isLinkStrategy, isTS43Strategy, isDesktopStrategy, getStrategy, hasPollingControls, hasTrigger,
|
|
6
|
+
export { isExtendedResponse, isCredential, isAuthCredential, isLinkStrategy, isTS43Strategy, isDesktopStrategy, getStrategy, hasPollingControls, hasTrigger,
|
|
7
|
+
// Deprecated aliases
|
|
8
|
+
isHeadlessResult, requiresPolling, requiresUserAction } from './type-guards';
|
|
@@ -1,12 +1,69 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Status Types for Public Status Endpoint
|
|
3
|
+
*
|
|
4
|
+
* These types define the response format for the public status endpoint
|
|
5
|
+
* Used for polling authentication status without exposing sensitive data
|
|
6
|
+
*/
|
|
7
|
+
/**
|
|
8
|
+
* Status values returned by the public endpoint (HTTP 200 only)
|
|
9
|
+
*/
|
|
1
10
|
export type AuthenticationStatus = 'pending' | 'completed';
|
|
11
|
+
/**
|
|
12
|
+
* Authentication protocol/strategy used
|
|
13
|
+
*/
|
|
2
14
|
export type AuthenticationProtocol = 'ts43' | 'link' | 'desktop';
|
|
15
|
+
/**
|
|
16
|
+
* Public Status Response (HTTP 200 OK)
|
|
17
|
+
*
|
|
18
|
+
* This response is only returned with HTTP 200 status code
|
|
19
|
+
* Failed/expired sessions return HTTP 4xx with ErrorResponse
|
|
20
|
+
*
|
|
21
|
+
* @example
|
|
22
|
+
* ```typescript
|
|
23
|
+
* // Public endpoint (no auth required)
|
|
24
|
+
* const response = await fetch('/public/public/status/{sessionKey}');
|
|
25
|
+
*
|
|
26
|
+
* if (response.status === 200) {
|
|
27
|
+
* const status: StatusResponse = await response.json();
|
|
28
|
+
* if (status.status === 'completed') {
|
|
29
|
+
* // Authentication successful - now call process endpoint
|
|
30
|
+
* const result = await processAuthentication(sessionKey);
|
|
31
|
+
* }
|
|
32
|
+
* } else if (response.status === 410) {
|
|
33
|
+
* // Session expired
|
|
34
|
+
* } else if (response.status === 422) {
|
|
35
|
+
* // Authentication failed (user cancelled, etc.)
|
|
36
|
+
* }
|
|
37
|
+
* ```
|
|
38
|
+
*/
|
|
3
39
|
export interface StatusResponse {
|
|
40
|
+
/**
|
|
41
|
+
* The session key/identifier
|
|
42
|
+
*/
|
|
4
43
|
session_key: string;
|
|
44
|
+
/**
|
|
45
|
+
* Current status of the authentication (only successful states)
|
|
46
|
+
*/
|
|
5
47
|
status: AuthenticationStatus;
|
|
48
|
+
/**
|
|
49
|
+
* Protocol/strategy used for authentication
|
|
50
|
+
* Optional - may not be present during pending state
|
|
51
|
+
*/
|
|
6
52
|
protocol?: AuthenticationProtocol;
|
|
53
|
+
/**
|
|
54
|
+
* ISO 8601 timestamp when session was created
|
|
55
|
+
*/
|
|
7
56
|
created_at: string;
|
|
57
|
+
/**
|
|
58
|
+
* ISO 8601 timestamp of last status update
|
|
59
|
+
*/
|
|
8
60
|
last_updated: string;
|
|
9
61
|
}
|
|
62
|
+
/**
|
|
63
|
+
* Error Response (HTTP 4xx)
|
|
64
|
+
*
|
|
65
|
+
* Returned when session is expired, failed, or not found
|
|
66
|
+
*/
|
|
10
67
|
export interface StatusErrorResponse {
|
|
11
68
|
code: 'SESSION_EXPIRED' | 'USER_CANCELLED' | 'AUTHENTICATION_FAILED' | 'SESSION_NOT_FOUND' | 'INVALID_SESSION_KEY';
|
|
12
69
|
message: string;
|
|
@@ -19,11 +76,32 @@ export interface StatusErrorResponse {
|
|
|
19
76
|
duration_seconds?: number;
|
|
20
77
|
};
|
|
21
78
|
}
|
|
79
|
+
/**
|
|
80
|
+
* Type guard to check if authentication was successful
|
|
81
|
+
*/
|
|
22
82
|
export declare function isSuccessStatus(status: AuthenticationStatus): boolean;
|
|
83
|
+
/**
|
|
84
|
+
* Helper to determine if polling should continue based on HTTP status
|
|
85
|
+
*/
|
|
23
86
|
export declare function shouldContinuePolling(httpStatus: number, response?: StatusResponse): boolean;
|
|
87
|
+
/**
|
|
88
|
+
* Helper to determine if session is terminated based on HTTP status
|
|
89
|
+
*/
|
|
24
90
|
export declare function isTerminalHttpStatus(httpStatus: number): boolean;
|
|
91
|
+
/**
|
|
92
|
+
* Session binding types for parent-child relationships
|
|
93
|
+
*/
|
|
25
94
|
export interface SessionBinding {
|
|
95
|
+
/**
|
|
96
|
+
* Parent session ID (desktop QR code session)
|
|
97
|
+
*/
|
|
26
98
|
parent_session_id?: string;
|
|
99
|
+
/**
|
|
100
|
+
* Child session ID (mobile authentication session)
|
|
101
|
+
*/
|
|
27
102
|
child_session_id?: string;
|
|
103
|
+
/**
|
|
104
|
+
* Whether this is a parent or child session
|
|
105
|
+
*/
|
|
28
106
|
session_type?: 'parent' | 'child';
|
|
29
107
|
}
|
|
@@ -1,9 +1,26 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Status Types for Public Status Endpoint
|
|
3
|
+
*
|
|
4
|
+
* These types define the response format for the public status endpoint
|
|
5
|
+
* Used for polling authentication status without exposing sensitive data
|
|
6
|
+
*/
|
|
7
|
+
/**
|
|
8
|
+
* Type guard to check if authentication was successful
|
|
9
|
+
*/
|
|
1
10
|
export function isSuccessStatus(status) {
|
|
2
11
|
return status === 'completed';
|
|
3
12
|
}
|
|
13
|
+
/**
|
|
14
|
+
* Helper to determine if polling should continue based on HTTP status
|
|
15
|
+
*/
|
|
4
16
|
export function shouldContinuePolling(httpStatus, response) {
|
|
17
|
+
// Only continue if HTTP 200 and status is pending
|
|
5
18
|
return httpStatus === 200 && (response === null || response === void 0 ? void 0 : response.status) === 'pending';
|
|
6
19
|
}
|
|
20
|
+
/**
|
|
21
|
+
* Helper to determine if session is terminated based on HTTP status
|
|
22
|
+
*/
|
|
7
23
|
export function isTerminalHttpStatus(httpStatus) {
|
|
24
|
+
// 410 Gone (expired), 422 Unprocessable (failed), 404 Not Found
|
|
8
25
|
return httpStatus === 410 || httpStatus === 422 || httpStatus === 404;
|
|
9
26
|
}
|
|
@@ -1,5 +1,13 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Desktop Strategy Handler
|
|
3
|
+
* Handles QR code-based authentication for desktop browsers
|
|
4
|
+
* Manages QR code display and polling for authentication status
|
|
5
|
+
*/
|
|
1
6
|
import type { StrategyHandler } from './types';
|
|
2
7
|
import type { PrepareResponse } from '../types';
|
|
8
|
+
/**
|
|
9
|
+
* QR code data structure for dual-platform support
|
|
10
|
+
*/
|
|
3
11
|
export interface QRCodeData {
|
|
4
12
|
iosQRCode: string;
|
|
5
13
|
androidQRCode?: string;
|
|
@@ -7,24 +15,41 @@ export interface QRCodeData {
|
|
|
7
15
|
androidUrl?: string;
|
|
8
16
|
}
|
|
9
17
|
export interface DesktopAuthOptions {
|
|
18
|
+
/** Custom polling interval in milliseconds (overrides server-provided value) */
|
|
10
19
|
pollingInterval?: number;
|
|
20
|
+
/** Maximum polling attempts before timeout (default: 30 = 1 minute with 2s interval) */
|
|
11
21
|
maxPollingAttempts?: number;
|
|
22
|
+
/** Custom polling endpoint (overrides backend-provided or uses configured endpoint) */
|
|
12
23
|
pollingEndpoint?: string;
|
|
24
|
+
/** Developer environment (adds 'developer' header to requests) */
|
|
25
|
+
devEnv?: string;
|
|
26
|
+
/** Callback when QR code is ready to display */
|
|
13
27
|
onQRCodeReady?: (qrCodeData: string | QRCodeData) => void;
|
|
28
|
+
/** Callback for polling status updates */
|
|
14
29
|
onStatusUpdate?: (status: PollingStatus) => void;
|
|
30
|
+
/** Callback when authentication expires */
|
|
15
31
|
onExpired?: () => void;
|
|
32
|
+
/** Callback when authentication is cancelled by user */
|
|
16
33
|
onCancel?: () => void;
|
|
34
|
+
/** Callback when polling times out (max attempts reached) */
|
|
17
35
|
onTimeout?: () => void;
|
|
18
36
|
}
|
|
19
37
|
export interface PollingStatus {
|
|
38
|
+
/** Current status of the authentication */
|
|
20
39
|
status: 'pending' | 'authenticated' | 'expired' | 'cancelled' | 'error';
|
|
40
|
+
/** Optional message */
|
|
21
41
|
message?: string;
|
|
42
|
+
/** Authentication result data if status is 'authenticated' */
|
|
22
43
|
data?: any;
|
|
23
44
|
}
|
|
24
45
|
export interface DesktopAuthResult {
|
|
46
|
+
/** Whether authentication was successful */
|
|
25
47
|
authenticated: boolean;
|
|
48
|
+
/** Authentication credential if successful */
|
|
26
49
|
credential?: string;
|
|
50
|
+
/** Session info for subsequent requests */
|
|
27
51
|
session?: any;
|
|
52
|
+
/** Error message if authentication failed */
|
|
28
53
|
error?: string;
|
|
29
54
|
}
|
|
30
55
|
export declare class DesktopHandler implements StrategyHandler {
|
|
@@ -34,22 +59,62 @@ export declare class DesktopHandler implements StrategyHandler {
|
|
|
34
59
|
private onCancel?;
|
|
35
60
|
private pollingReject?;
|
|
36
61
|
private isPollingInProgress;
|
|
62
|
+
/**
|
|
63
|
+
* Maps backend HTTP status codes to client status
|
|
64
|
+
* @param httpStatus HTTP status code from backend
|
|
65
|
+
* @param bodyStatus Optional status from response body (for 200 OK responses)
|
|
66
|
+
* @returns Mapped status string for client use
|
|
67
|
+
*/
|
|
37
68
|
private mapBackendStatus;
|
|
69
|
+
/**
|
|
70
|
+
* Invoke desktop authentication with QR code
|
|
71
|
+
* Returns QR code data for display and starts polling if endpoint is provided
|
|
72
|
+
*/
|
|
38
73
|
invoke(data: PrepareResponse, options?: DesktopAuthOptions): Promise<DesktopAuthResult>;
|
|
74
|
+
/**
|
|
75
|
+
* Start polling for authentication status
|
|
76
|
+
*/
|
|
39
77
|
private startPolling;
|
|
78
|
+
/**
|
|
79
|
+
* Stop polling
|
|
80
|
+
*/
|
|
40
81
|
private stopPolling;
|
|
82
|
+
/**
|
|
83
|
+
* Check if polling is currently active
|
|
84
|
+
*/
|
|
41
85
|
isPolling(): boolean;
|
|
86
|
+
/**
|
|
87
|
+
* Format response for backend processing
|
|
88
|
+
* Desktop strategy typically returns the credential from mobile authentication
|
|
89
|
+
*/
|
|
42
90
|
formatResponse(response: DesktopAuthResult): any;
|
|
91
|
+
/**
|
|
92
|
+
* Check if desktop authentication is supported
|
|
93
|
+
* Desktop auth with QR codes works in any modern browser
|
|
94
|
+
*/
|
|
43
95
|
isSupported(): boolean;
|
|
96
|
+
/**
|
|
97
|
+
* Clean up resources (stop polling if active)
|
|
98
|
+
*/
|
|
44
99
|
cleanup(): void;
|
|
100
|
+
/**
|
|
101
|
+
* Cancel the ongoing authentication
|
|
102
|
+
*/
|
|
45
103
|
cancel(): void;
|
|
46
104
|
}
|
|
105
|
+
/**
|
|
106
|
+
* Helper function to display QR code in a modal or inline
|
|
107
|
+
*/
|
|
47
108
|
export declare function createQRCodeDisplay(qrCodeData: string | QRCodeData, options?: {
|
|
48
109
|
container?: HTMLElement;
|
|
49
110
|
size?: number;
|
|
50
111
|
title?: string;
|
|
51
112
|
description?: string;
|
|
52
113
|
}): HTMLElement;
|
|
114
|
+
/**
|
|
115
|
+
* Helper function to create a modal for QR code display
|
|
116
|
+
* Supports both string QR codes and QRCodeData objects for dual-platform support
|
|
117
|
+
*/
|
|
53
118
|
export declare function showQRCodeModal(qrCodeData: string | QRCodeData, options?: {
|
|
54
119
|
title?: string;
|
|
55
120
|
description?: string;
|