@glideidentity/web-client-sdk 5.0.0 → 5.0.1-beta.0

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 (89) hide show
  1. package/README.md +108 -8
  2. package/dist/adapters/angular/index.js +0 -1
  3. package/dist/adapters/angular/phone-auth.service.d.ts +0 -18
  4. package/dist/adapters/angular/phone-auth.service.js +0 -26
  5. package/dist/adapters/react/index.js +0 -3
  6. package/dist/adapters/react/useClient.js +0 -1
  7. package/dist/adapters/react/usePhoneAuth.js +1 -16
  8. package/dist/adapters/vanilla/client.js +0 -1
  9. package/dist/adapters/vanilla/index.js +0 -1
  10. package/dist/adapters/vanilla/phone-auth.js +0 -31
  11. package/dist/adapters/vue/index.js +0 -4
  12. package/dist/adapters/vue/useClient.js +0 -5
  13. package/dist/adapters/vue/usePhoneAuth.js +1 -20
  14. package/dist/browser/web-client-sdk.min.js +1 -1
  15. package/dist/browser.js +0 -6
  16. package/dist/core/client.js +0 -12
  17. package/dist/core/logger.js +1 -81
  18. package/dist/core/phone-auth/api-types.js +0 -83
  19. package/dist/core/phone-auth/client.js +27 -366
  20. package/dist/core/phone-auth/error-utils.js +1 -83
  21. package/dist/core/phone-auth/index.js +0 -1
  22. package/dist/core/phone-auth/status-types.d.ts +0 -78
  23. package/dist/core/phone-auth/status-types.js +0 -17
  24. package/dist/core/phone-auth/strategies/desktop.js +8 -126
  25. package/dist/core/phone-auth/strategies/index.d.ts +0 -4
  26. package/dist/core/phone-auth/strategies/index.js +0 -4
  27. package/dist/core/phone-auth/strategies/link.js +10 -88
  28. package/dist/core/phone-auth/strategies/ts43.d.ts +0 -19
  29. package/dist/core/phone-auth/strategies/ts43.js +2 -33
  30. package/dist/core/phone-auth/strategies/types.js +0 -4
  31. package/dist/core/phone-auth/type-guards.js +0 -131
  32. package/dist/core/phone-auth/types.js +0 -32
  33. package/dist/core/phone-auth/ui/mobile-debug-console.js +2 -28
  34. package/dist/core/phone-auth/ui/modal.d.ts +33 -55
  35. package/dist/core/phone-auth/ui/modal.js +889 -422
  36. package/dist/core/phone-auth/validation-utils.js +2 -40
  37. package/dist/core/version.js +1 -2
  38. package/dist/esm/adapters/angular/index.js +0 -1
  39. package/dist/esm/adapters/angular/phone-auth.service.d.ts +0 -18
  40. package/dist/esm/adapters/angular/phone-auth.service.js +0 -26
  41. package/dist/esm/adapters/react/index.js +0 -3
  42. package/dist/esm/adapters/react/useClient.js +0 -1
  43. package/dist/esm/adapters/react/usePhoneAuth.js +1 -16
  44. package/dist/esm/adapters/vanilla/client.js +0 -1
  45. package/dist/esm/adapters/vanilla/index.js +0 -1
  46. package/dist/esm/adapters/vanilla/phone-auth.d.ts +0 -24
  47. package/dist/esm/adapters/vanilla/phone-auth.js +0 -31
  48. package/dist/esm/adapters/vue/index.js +0 -4
  49. package/dist/esm/adapters/vue/useClient.js +0 -5
  50. package/dist/esm/adapters/vue/usePhoneAuth.js +1 -20
  51. package/dist/esm/browser.js +0 -6
  52. package/dist/esm/core/client.d.ts +0 -10
  53. package/dist/esm/core/client.js +0 -12
  54. package/dist/esm/core/logger.d.ts +0 -53
  55. package/dist/esm/core/logger.js +1 -81
  56. package/dist/esm/core/phone-auth/api-types.d.ts +0 -315
  57. package/dist/esm/core/phone-auth/api-types.js +0 -83
  58. package/dist/esm/core/phone-auth/client.d.ts +0 -144
  59. package/dist/esm/core/phone-auth/client.js +27 -366
  60. package/dist/esm/core/phone-auth/error-utils.d.ts +0 -29
  61. package/dist/esm/core/phone-auth/error-utils.js +1 -83
  62. package/dist/esm/core/phone-auth/index.js +1 -3
  63. package/dist/esm/core/phone-auth/status-types.d.ts +0 -78
  64. package/dist/esm/core/phone-auth/status-types.js +0 -17
  65. package/dist/esm/core/phone-auth/strategies/desktop.d.ts +0 -63
  66. package/dist/esm/core/phone-auth/strategies/desktop.js +8 -126
  67. package/dist/esm/core/phone-auth/strategies/index.d.ts +0 -4
  68. package/dist/esm/core/phone-auth/strategies/index.js +0 -4
  69. package/dist/esm/core/phone-auth/strategies/link.d.ts +0 -48
  70. package/dist/esm/core/phone-auth/strategies/link.js +10 -88
  71. package/dist/esm/core/phone-auth/strategies/ts43.d.ts +0 -19
  72. package/dist/esm/core/phone-auth/strategies/ts43.js +2 -33
  73. package/dist/esm/core/phone-auth/strategies/types.d.ts +0 -13
  74. package/dist/esm/core/phone-auth/strategies/types.js +0 -4
  75. package/dist/esm/core/phone-auth/type-guards.d.ts +0 -128
  76. package/dist/esm/core/phone-auth/type-guards.js +0 -131
  77. package/dist/esm/core/phone-auth/types.d.ts +0 -108
  78. package/dist/esm/core/phone-auth/types.js +0 -32
  79. package/dist/esm/core/phone-auth/ui/mobile-debug-console.d.ts +0 -4
  80. package/dist/esm/core/phone-auth/ui/mobile-debug-console.js +2 -28
  81. package/dist/esm/core/phone-auth/ui/modal.d.ts +27 -68
  82. package/dist/esm/core/phone-auth/ui/modal.js +889 -422
  83. package/dist/esm/core/phone-auth/validation-utils.d.ts +0 -31
  84. package/dist/esm/core/phone-auth/validation-utils.js +2 -40
  85. package/dist/esm/core/types.d.ts +0 -35
  86. package/dist/esm/core/version.js +1 -2
  87. package/dist/esm/index.js +1 -9
  88. package/dist/index.js +0 -7
  89. package/package.json +1 -1
@@ -1,8 +1,3 @@
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
- */
6
1
  var __awaiter = (this && this.__awaiter) || function (thisArg, _arguments, P, generator) {
7
2
  function adopt(value) { return value instanceof P ? value : new P(function (resolve) { resolve(value); }); }
8
3
  return new (P || (P = Promise))(function (resolve, reject) {
@@ -18,49 +13,33 @@ export class DesktopHandler {
18
13
  this.isCancelled = false;
19
14
  this.isPollingInProgress = false;
20
15
  }
21
- /**
22
- * Maps backend HTTP status codes to client status
23
- * @param httpStatus HTTP status code from backend
24
- * @param bodyStatus Optional status from response body (for 200 OK responses)
25
- * @returns Mapped status string for client use
26
- */
27
16
  mapBackendStatus(httpStatus, bodyStatus) {
28
17
  switch (httpStatus) {
29
18
  case 200:
30
- // For 200 OK, check the body status
31
19
  return bodyStatus === 'completed' ? 'authenticated' : 'pending';
32
20
  case 410:
33
21
  return 'expired';
34
22
  case 422:
35
- return 'error'; // Failed or cancelled
23
+ return 'error';
36
24
  case 404:
37
- return 'error'; // Session not found
25
+ return 'error';
38
26
  case 400:
39
- return 'error'; // Invalid session key
27
+ return 'error';
40
28
  default:
41
29
  return 'error';
42
30
  }
43
31
  }
44
- /**
45
- * Invoke desktop authentication with QR code
46
- * Returns QR code data for display and starts polling if endpoint is provided
47
- */
48
32
  invoke(data, options) {
49
33
  return __awaiter(this, void 0, void 0, function* () {
50
34
  const desktopData = data.data;
51
- // Extract QR code from nested or flat structure, checking multiple field names
52
35
  let qrCode;
53
36
  let sessionId;
54
37
  let pollingEndpoint;
55
38
  let pollingInterval;
56
39
  let expiresIn;
57
- // Check nested structure first (data.data.qr_code_image or data.data.qr_code)
58
40
  if (desktopData && desktopData.data && typeof desktopData.data === 'object') {
59
41
  const innerData = desktopData.data;
60
- // Try to extract from inner data
61
- // Support both single QR (qr_code_image) and dual-platform QR (ios/android)
62
42
  if (innerData.ios_qr_image && innerData.android_qr_image) {
63
- // Dual-platform QR format - both must be present
64
43
  qrCode = {
65
44
  iosQRCode: innerData.ios_qr_image,
66
45
  androidQRCode: innerData.android_qr_image,
@@ -69,11 +48,9 @@ export class DesktopHandler {
69
48
  };
70
49
  }
71
50
  else if (innerData.ios_qr_image || innerData.android_qr_image) {
72
- // Only one platform QR - use as single QR format
73
51
  qrCode = innerData.ios_qr_image || innerData.android_qr_image;
74
52
  }
75
53
  else {
76
- // Single QR format (legacy)
77
54
  qrCode = innerData.qr_code_image || innerData.qr_code;
78
55
  }
79
56
  sessionId = innerData.session_id;
@@ -81,7 +58,6 @@ export class DesktopHandler {
81
58
  pollingInterval = innerData.polling_interval;
82
59
  expiresIn = innerData.expires_in;
83
60
  }
84
- // Fall back to flat structure if no QR code found
85
61
  if (!qrCode && desktopData) {
86
62
  qrCode = desktopData.qr_code_image || desktopData.qr_code;
87
63
  sessionId = sessionId || desktopData.session_id;
@@ -89,65 +65,47 @@ export class DesktopHandler {
89
65
  pollingInterval = pollingInterval || desktopData.polling_interval;
90
66
  expiresIn = expiresIn || desktopData.expires_in;
91
67
  }
92
- // Validate QR code exists
93
68
  if (!qrCode) {
94
69
  throw new Error('Invalid desktop authentication data: missing QR code');
95
70
  }
96
- // Validate session ID exists
97
71
  if (!sessionId) {
98
72
  throw new Error('Invalid desktop authentication data: missing session ID');
99
73
  }
100
- // Notify that QR code is ready
101
74
  if (options === null || options === void 0 ? void 0 : options.onQRCodeReady) {
102
75
  options.onQRCodeReady(qrCode);
103
76
  }
104
- // Use polling endpoint with this priority:
105
- // 1. Developer-provided endpoint from options (highest priority)
106
- // 2. Backend-provided endpoint
107
- // 3. Hardcoded fallback
108
77
  console.log('[Desktop QR] Polling endpoint selection:');
109
78
  console.log(' - options?.pollingEndpoint:', options === null || options === void 0 ? void 0 : options.pollingEndpoint);
110
79
  console.log(' - backend pollingEndpoint:', pollingEndpoint);
111
80
  let finalPollingEndpoint = options === null || options === void 0 ? void 0 : options.pollingEndpoint;
112
81
  let endpointSource = 'options';
113
82
  if (!finalPollingEndpoint) {
114
- finalPollingEndpoint = pollingEndpoint; // Backend-provided status_url
83
+ finalPollingEndpoint = pollingEndpoint;
115
84
  endpointSource = 'backend';
116
85
  }
117
86
  if (!finalPollingEndpoint) {
118
- // Use hardcoded fallback - this will be constructed in the polling function
119
87
  console.log('[Desktop QR] No polling endpoint provided, will use hardcoded fallback');
120
88
  endpointSource = 'fallback';
121
89
  }
122
90
  console.log('[Desktop QR] Selected endpoint:', finalPollingEndpoint, 'from source:', endpointSource);
123
- // Start polling for authentication status
124
91
  const finalPollingInterval = (options === null || options === void 0 ? void 0 : options.pollingInterval) || pollingInterval || 2000;
125
- const maxAttempts = (options === null || options === void 0 ? void 0 : options.maxPollingAttempts) || 30; // Default to 1 minute
92
+ const maxAttempts = (options === null || options === void 0 ? void 0 : options.maxPollingAttempts) || 30;
126
93
  console.log(`[Desktop QR] Starting polling - endpoint source: ${endpointSource}, interval: ${finalPollingInterval}ms, max attempts: ${maxAttempts}`);
127
- return this.startPolling(finalPollingEndpoint || '', // Pass empty string if undefined, will use fallback
128
- sessionId, finalPollingInterval, maxAttempts, expiresIn || 300, // Default 5 minutes expiry
129
- options, endpointSource // Pass the endpoint source for logging
130
- );
94
+ return this.startPolling(finalPollingEndpoint || '', sessionId, finalPollingInterval, maxAttempts, expiresIn || 300, options, endpointSource);
131
95
  });
132
96
  }
133
- /**
134
- * Start polling for authentication status
135
- */
136
97
  startPolling(endpoint_1, sessionId_1, interval_1, maxAttempts_1, expiresIn_1, options_1) {
137
98
  return __awaiter(this, arguments, void 0, function* (endpoint, sessionId, interval, maxAttempts, expiresIn, options, endpointSource = 'unknown') {
138
99
  const startTime = Date.now();
139
100
  const expiryTime = startTime + (expiresIn * 1000);
140
101
  return new Promise((resolve, reject) => {
141
- // Store the reject function so we can call it from cancel()
142
102
  this.pollingReject = reject;
143
103
  const poll = () => __awaiter(this, void 0, void 0, function* () {
144
- // Skip if another poll is already in progress
145
104
  if (this.isPollingInProgress) {
146
105
  return;
147
106
  }
148
107
  try {
149
108
  this.isPollingInProgress = true;
150
- // Check if cancelled
151
109
  if (this.isCancelled) {
152
110
  this.stopPolling();
153
111
  if (options === null || options === void 0 ? void 0 : options.onCancel) {
@@ -159,14 +117,12 @@ export class DesktopHandler {
159
117
  message: 'Authentication cancelled'
160
118
  });
161
119
  }
162
- // Reject the promise with a cancellation error
163
120
  reject({
164
121
  code: 'USER_DENIED',
165
122
  message: 'Authentication cancelled by user'
166
123
  });
167
124
  return;
168
125
  }
169
- // Check if expired
170
126
  if (Date.now() > expiryTime) {
171
127
  this.stopPolling();
172
128
  if (options === null || options === void 0 ? void 0 : options.onExpired) {
@@ -184,7 +140,6 @@ export class DesktopHandler {
184
140
  });
185
141
  return;
186
142
  }
187
- // Check max attempts
188
143
  if (this.pollingAttempts >= maxAttempts) {
189
144
  this.stopPolling();
190
145
  if (options === null || options === void 0 ? void 0 : options.onTimeout) {
@@ -202,53 +157,35 @@ export class DesktopHandler {
202
157
  });
203
158
  return;
204
159
  }
205
- // Build public status endpoint URL - use relative path for proxied requests
206
160
  let statusUrl;
207
- // Extract base URL and construct public endpoint
208
161
  if (endpoint && (endpoint.startsWith('http://') || endpoint.startsWith('https://'))) {
209
- // Full URL provided - extract base and use public endpoint
210
162
  const url = new URL(endpoint);
211
163
  statusUrl = `${url.protocol}//${url.host}/public/public/status/${sessionId}`;
212
164
  }
213
165
  else if (endpoint && endpoint !== '') {
214
- // Relative path provided (e.g. '/api/phone-auth/status')
215
- // Append session ID to the provided endpoint
216
166
  statusUrl = `${endpoint}/${sessionId}`;
217
167
  }
218
168
  else {
219
- // No endpoint provided - use hardcoded fallback
220
- // This ensures it goes through the same domain and uses the app's API configuration
221
169
  statusUrl = `/api/phone-auth/status/${sessionId}`;
222
170
  }
223
- // Poll the public endpoint - no authentication required
224
171
  console.log(`[Desktop QR] Polling status (attempt ${this.pollingAttempts}/${maxAttempts})`);
225
172
  console.log(`[Desktop QR] Using ${endpointSource} endpoint: ${statusUrl}`);
226
173
  const response = yield fetch(statusUrl, {
227
174
  method: 'GET',
228
175
  headers: {
229
176
  'Accept': 'application/json'
230
- // No Authorization header needed for public endpoint
231
177
  }
232
178
  });
233
179
  console.log(`[Desktop QR] Status response: ${response.status} ${response.statusText}`);
234
- // Backend Status Code Mapping:
235
- // - 200 OK: Session exists (body has 'pending' or 'completed' status)
236
- // - 410 Gone: Session expired after timeout
237
- // - 422 Unprocessable Entity: Authentication failed or cancelled
238
- // - 404 Not Found: Session doesn't exist
239
- // - 400 Bad Request: Invalid session key format
240
- // Handle response based on HTTP status code
241
180
  if (response.status === 200) {
242
181
  const result = yield response.json();
243
182
  if (result.status === 'completed') {
244
- // Authentication completed successfully
245
183
  this.stopPolling();
246
- // Close the modal if it exists
247
184
  const modal = document.querySelector('[style*="position: fixed"]');
248
185
  if (modal && modal.querySelector('#desktop-auth-status')) {
249
186
  setTimeout(() => {
250
187
  modal.remove();
251
- }, 500); // Brief delay to show success message
188
+ }, 500);
252
189
  }
253
190
  if (options === null || options === void 0 ? void 0 : options.onStatusUpdate) {
254
191
  options.onStatusUpdate({
@@ -257,8 +194,7 @@ export class DesktopHandler {
257
194
  data: result
258
195
  });
259
196
  }
260
- // Return the session data for next steps
261
- this.pollingReject = undefined; // Clear the reject function on success
197
+ this.pollingReject = undefined;
262
198
  resolve({
263
199
  authenticated: true,
264
200
  credential: result.credential || result.session_key || sessionId,
@@ -272,7 +208,6 @@ export class DesktopHandler {
272
208
  });
273
209
  }
274
210
  else if (result.status === 'pending') {
275
- // Continue polling
276
211
  this.pollingAttempts++;
277
212
  if (options === null || options === void 0 ? void 0 : options.onStatusUpdate) {
278
213
  options.onStatusUpdate({
@@ -283,10 +218,8 @@ export class DesktopHandler {
283
218
  }
284
219
  }
285
220
  else if (response.status === 410) {
286
- // Session expired
287
221
  this.stopPolling();
288
222
  const errorData = yield response.json().catch(() => ({ message: 'Session expired' }));
289
- // Close the modal on error
290
223
  const modal = document.querySelector('[style*="position: fixed"]');
291
224
  if (modal && modal.querySelector('#desktop-auth-status')) {
292
225
  setTimeout(() => {
@@ -308,10 +241,8 @@ export class DesktopHandler {
308
241
  });
309
242
  }
310
243
  else if (response.status === 422) {
311
- // Authentication failed
312
244
  this.stopPolling();
313
245
  const errorData = yield response.json().catch(() => ({ message: 'Authentication failed' }));
314
- // Close the modal on error
315
246
  const modal = document.querySelector('[style*="position: fixed"]');
316
247
  if (modal && modal.querySelector('#desktop-auth-status')) {
317
248
  setTimeout(() => {
@@ -333,7 +264,6 @@ export class DesktopHandler {
333
264
  });
334
265
  }
335
266
  else if (response.status === 404) {
336
- // Session not found
337
267
  this.stopPolling();
338
268
  if (options === null || options === void 0 ? void 0 : options.onStatusUpdate) {
339
269
  options.onStatusUpdate({
@@ -347,7 +277,6 @@ export class DesktopHandler {
347
277
  });
348
278
  }
349
279
  else if (response.status === 400) {
350
- // Invalid session key
351
280
  this.stopPolling();
352
281
  const errorData = yield response.json().catch(() => ({ message: 'Invalid session key' }));
353
282
  resolve({
@@ -356,12 +285,10 @@ export class DesktopHandler {
356
285
  });
357
286
  }
358
287
  else {
359
- // Unexpected status - continue polling
360
288
  this.pollingAttempts++;
361
289
  }
362
290
  }
363
291
  catch (error) {
364
- // Network or other error - continue polling
365
292
  this.pollingAttempts++;
366
293
  if (options === null || options === void 0 ? void 0 : options.onStatusUpdate) {
367
294
  options.onStatusUpdate({
@@ -371,20 +298,14 @@ export class DesktopHandler {
371
298
  }
372
299
  }
373
300
  finally {
374
- // Always clear the polling flag when done
375
301
  this.isPollingInProgress = false;
376
302
  }
377
303
  });
378
- // Start initial poll
379
304
  poll();
380
- // Set up interval for subsequent polls
381
305
  this.pollingIntervalId = setInterval(poll, interval);
382
306
  });
383
307
  });
384
308
  }
385
- /**
386
- * Stop polling
387
- */
388
309
  stopPolling() {
389
310
  if (this.pollingIntervalId) {
390
311
  console.log('[Desktop QR] Stopping polling');
@@ -393,18 +314,10 @@ export class DesktopHandler {
393
314
  }
394
315
  this.pollingAttempts = 0;
395
316
  this.isPollingInProgress = false;
396
- // Don't clear pollingReject here - it's needed by cancel()
397
317
  }
398
- /**
399
- * Check if polling is currently active
400
- */
401
318
  isPolling() {
402
319
  return this.pollingIntervalId !== undefined;
403
320
  }
404
- /**
405
- * Format response for backend processing
406
- * Desktop strategy typically returns the credential from mobile authentication
407
- */
408
321
  formatResponse(response) {
409
322
  if (!response.authenticated || !response.credential) {
410
323
  throw new Error('Authentication not completed');
@@ -414,35 +327,23 @@ export class DesktopHandler {
414
327
  session: response.session
415
328
  };
416
329
  }
417
- /**
418
- * Check if desktop authentication is supported
419
- * Desktop auth with QR codes works in any modern browser
420
- */
421
330
  isSupported() {
422
- // Check for required browser APIs
423
331
  return typeof window !== 'undefined' &&
424
332
  typeof fetch !== 'undefined' &&
425
333
  typeof Promise !== 'undefined';
426
334
  }
427
- /**
428
- * Clean up resources (stop polling if active)
429
- */
430
335
  cleanup() {
431
336
  this.stopPolling();
432
337
  this.isCancelled = false;
433
338
  this.onCancel = undefined;
434
339
  this.pollingReject = undefined;
435
340
  }
436
- /**
437
- * Cancel the ongoing authentication
438
- */
439
341
  cancel() {
440
342
  var _a;
441
343
  console.log('[Desktop QR] Cancelling authentication');
442
344
  this.isCancelled = true;
443
345
  this.stopPolling();
444
346
  (_a = this.onCancel) === null || _a === void 0 ? void 0 : _a.call(this);
445
- // Immediately reject the polling promise
446
347
  if (this.pollingReject) {
447
348
  this.pollingReject({
448
349
  code: 'USER_DENIED',
@@ -452,20 +353,14 @@ export class DesktopHandler {
452
353
  }
453
354
  }
454
355
  }
455
- /**
456
- * Helper function to display QR code in a modal or inline
457
- */
458
356
  export function createQRCodeDisplay(qrCodeData, options) {
459
357
  const container = (options === null || options === void 0 ? void 0 : options.container) || document.createElement('div');
460
358
  container.className = 'phone-auth-qr-container';
461
- // Determine QR code to display
462
359
  let qrCodeSrc;
463
360
  if (typeof qrCodeData === 'string') {
464
- // Simple string QR code
465
361
  qrCodeSrc = qrCodeData;
466
362
  }
467
363
  else if (qrCodeData && typeof qrCodeData === 'object') {
468
- // QRCodeData object - prefer iOS QR if available
469
364
  if (qrCodeData.iosQRCode) {
470
365
  qrCodeSrc = qrCodeData.iosQRCode;
471
366
  }
@@ -479,7 +374,6 @@ export function createQRCodeDisplay(qrCodeData, options) {
479
374
  else {
480
375
  throw new Error('Invalid qrCodeData: must be string or QRCodeData object');
481
376
  }
482
- // Create QR code image
483
377
  const img = document.createElement('img');
484
378
  img.src = qrCodeSrc;
485
379
  img.alt = 'QR Code for authentication';
@@ -487,7 +381,6 @@ export function createQRCodeDisplay(qrCodeData, options) {
487
381
  img.style.height = `${(options === null || options === void 0 ? void 0 : options.size) || 256}px`;
488
382
  img.style.display = 'block';
489
383
  img.style.margin = '0 auto';
490
- // Add title if provided
491
384
  if (options === null || options === void 0 ? void 0 : options.title) {
492
385
  const title = document.createElement('h3');
493
386
  title.textContent = options.title;
@@ -496,7 +389,6 @@ export function createQRCodeDisplay(qrCodeData, options) {
496
389
  container.appendChild(title);
497
390
  }
498
391
  container.appendChild(img);
499
- // Add description if provided
500
392
  if (options === null || options === void 0 ? void 0 : options.description) {
501
393
  const desc = document.createElement('p');
502
394
  desc.textContent = options.description;
@@ -507,12 +399,7 @@ export function createQRCodeDisplay(qrCodeData, options) {
507
399
  }
508
400
  return container;
509
401
  }
510
- /**
511
- * Helper function to create a modal for QR code display
512
- * Supports both string QR codes and QRCodeData objects for dual-platform support
513
- */
514
402
  export function showQRCodeModal(qrCodeData, options) {
515
- // Create modal overlay
516
403
  const overlay = document.createElement('div');
517
404
  overlay.style.cssText = `
518
405
  position: fixed;
@@ -526,7 +413,6 @@ export function showQRCodeModal(qrCodeData, options) {
526
413
  justify-content: center;
527
414
  z-index: 9999;
528
415
  `;
529
- // Create modal content
530
416
  const modal = document.createElement('div');
531
417
  modal.style.cssText = `
532
418
  background: white;
@@ -535,7 +421,6 @@ export function showQRCodeModal(qrCodeData, options) {
535
421
  max-width: 400px;
536
422
  position: relative;
537
423
  `;
538
- // Add close button
539
424
  const closeBtn = document.createElement('button');
540
425
  closeBtn.textContent = '×';
541
426
  closeBtn.style.cssText = `
@@ -555,13 +440,11 @@ export function showQRCodeModal(qrCodeData, options) {
555
440
  }
556
441
  };
557
442
  modal.appendChild(closeBtn);
558
- // Add QR code display
559
443
  const qrDisplay = createQRCodeDisplay(qrCodeData, {
560
444
  title: (options === null || options === void 0 ? void 0 : options.title) || 'Scan QR Code to Authenticate',
561
445
  description: (options === null || options === void 0 ? void 0 : options.description) || 'Use your mobile device to scan this QR code'
562
446
  });
563
447
  modal.appendChild(qrDisplay);
564
- // Add loading spinner placeholder
565
448
  const statusDiv = document.createElement('div');
566
449
  statusDiv.id = 'desktop-auth-status';
567
450
  statusDiv.style.cssText = `
@@ -573,7 +456,6 @@ export function showQRCodeModal(qrCodeData, options) {
573
456
  modal.appendChild(statusDiv);
574
457
  overlay.appendChild(modal);
575
458
  document.body.appendChild(overlay);
576
- // Close modal on overlay click
577
459
  overlay.onclick = (e) => {
578
460
  if (e.target === overlay) {
579
461
  document.body.removeChild(overlay);
@@ -1,7 +1,3 @@
1
- /**
2
- * Strategy Handlers Export
3
- * Provides implementations for TS43, Link, and Desktop authentication strategies
4
- */
5
1
  export type { StrategyHandler } from './types';
6
2
  export { TS43Handler } from './ts43';
7
3
  export { LinkHandler } from './link';
@@ -1,7 +1,3 @@
1
- /**
2
- * Strategy Handlers Export
3
- * Provides implementations for TS43, Link, and Desktop authentication strategies
4
- */
5
1
  export { TS43Handler } from './ts43';
6
2
  export { LinkHandler } from './link';
7
3
  export { DesktopHandler, createQRCodeDisplay, showQRCodeModal } from './desktop';
@@ -1,42 +1,23 @@
1
- /**
2
- * Link Strategy Handler
3
- * Handles authentication via app links (iOS and Android)
4
- * Opens authentication app while keeping user on current page
5
- */
6
1
  import type { StrategyHandler } from './types';
7
2
  import type { PrepareResponse } from '../types';
8
3
  export interface LinkAuthOptions {
9
- /** Fixed polling interval in milliseconds (default: 2000) */
10
4
  pollingInterval?: number;
11
- /** Maximum polling attempts before timeout (default: 30 = 1 minute with 2s interval) */
12
5
  maxPollingAttempts?: number;
13
- /** Custom polling endpoint (overrides backend-provided or configured endpoint) */
14
6
  pollingEndpoint?: string;
15
- /** Callback when link is opened */
16
7
  onLinkOpened?: () => void;
17
- /** Callback for polling status updates */
18
8
  onStatusUpdate?: (status: PollingStatus) => void;
19
- /** Callback when authentication times out */
20
9
  onTimeout?: () => void;
21
- /** Callback when authentication is cancelled by user */
22
10
  onCancel?: () => void;
23
11
  }
24
12
  export interface PollingStatus {
25
- /** Current status of the authentication */
26
13
  status: 'pending' | 'authenticated' | 'expired' | 'cancelled' | 'error';
27
- /** Optional message */
28
14
  message?: string;
29
- /** Authentication result data if status is 'authenticated' */
30
15
  data?: any;
31
16
  }
32
17
  export interface LinkAuthResult {
33
- /** Whether authentication was successful */
34
18
  authenticated: boolean;
35
- /** Authentication credential if successful */
36
19
  credential?: string;
37
- /** Session info for subsequent requests */
38
20
  session?: any;
39
- /** Error message if authentication failed */
40
21
  error?: string;
41
22
  }
42
23
  export declare class LinkHandler implements StrategyHandler {
@@ -46,42 +27,13 @@ export declare class LinkHandler implements StrategyHandler {
46
27
  private onCancel?;
47
28
  private pollingReject?;
48
29
  private isPollingInProgress;
49
- /**
50
- * Invoke link-based authentication
51
- * Opens authentication app while keeping user on current page
52
- */
53
30
  invoke(data: PrepareResponse, options?: LinkAuthOptions): Promise<LinkAuthResult>;
54
- /**
55
- * Open authentication link without navigating away
56
- */
57
31
  private openAuthenticationLink;
58
- /**
59
- * Start polling for authentication status with constant interval
60
- */
61
32
  private startPolling;
62
- /**
63
- * Stop polling
64
- */
65
33
  private stopPolling;
66
- /**
67
- * Format response for backend processing
68
- */
69
34
  formatResponse(response: LinkAuthResult): any;
70
- /**
71
- * Check if link strategy is supported
72
- * Returns true for mobile devices (iOS and Android)
73
- */
74
35
  isSupported(): boolean;
75
- /**
76
- * Clean up resources (stop polling if active)
77
- */
78
36
  cleanup(): void;
79
- /**
80
- * Check if polling is currently active
81
- */
82
37
  isPolling(): boolean;
83
- /**
84
- * Cancel the ongoing authentication
85
- */
86
38
  cancel(): void;
87
39
  }