@glideidentity/web-client-sdk 5.0.1 → 5.1.1-beta.1

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 (97) hide show
  1. package/README.md +8 -108
  2. package/dist/adapters/angular/index.js +1 -0
  3. package/dist/adapters/angular/phone-auth.service.d.ts +18 -0
  4. package/dist/adapters/angular/phone-auth.service.js +26 -0
  5. package/dist/adapters/react/index.js +3 -0
  6. package/dist/adapters/react/useClient.js +1 -0
  7. package/dist/adapters/react/usePhoneAuth.js +16 -1
  8. package/dist/adapters/vanilla/client.js +1 -0
  9. package/dist/adapters/vanilla/index.js +1 -0
  10. package/dist/adapters/vanilla/phone-auth.js +31 -0
  11. package/dist/adapters/vue/index.js +4 -0
  12. package/dist/adapters/vue/useClient.js +5 -0
  13. package/dist/adapters/vue/usePhoneAuth.js +20 -1
  14. package/dist/browser/web-client-sdk.min.js +1 -2
  15. package/dist/browser.js +6 -0
  16. package/dist/core/client.js +12 -0
  17. package/dist/core/logger.js +81 -1
  18. package/dist/core/phone-auth/api-types.d.ts +1 -4
  19. package/dist/core/phone-auth/api-types.js +83 -0
  20. package/dist/core/phone-auth/client.js +374 -38
  21. package/dist/core/phone-auth/error-utils.js +83 -1
  22. package/dist/core/phone-auth/index.d.ts +1 -1
  23. package/dist/core/phone-auth/index.js +2 -2
  24. package/dist/core/phone-auth/status-types.d.ts +78 -0
  25. package/dist/core/phone-auth/status-types.js +17 -0
  26. package/dist/core/phone-auth/strategies/desktop.d.ts +2 -0
  27. package/dist/core/phone-auth/strategies/desktop.js +136 -13
  28. package/dist/core/phone-auth/strategies/index.d.ts +4 -0
  29. package/dist/core/phone-auth/strategies/index.js +4 -0
  30. package/dist/core/phone-auth/strategies/link.d.ts +2 -0
  31. package/dist/core/phone-auth/strategies/link.js +97 -13
  32. package/dist/core/phone-auth/strategies/ts43.d.ts +19 -0
  33. package/dist/core/phone-auth/strategies/ts43.js +33 -2
  34. package/dist/core/phone-auth/strategies/types.js +4 -0
  35. package/dist/core/phone-auth/type-guards.js +131 -0
  36. package/dist/core/phone-auth/types.d.ts +5 -0
  37. package/dist/core/phone-auth/types.js +32 -0
  38. package/dist/core/phone-auth/ui/mobile-debug-console.js +28 -2
  39. package/dist/core/phone-auth/ui/modal.d.ts +55 -33
  40. package/dist/core/phone-auth/ui/modal.js +422 -889
  41. package/dist/core/phone-auth/validation-utils.d.ts +0 -9
  42. package/dist/core/phone-auth/validation-utils.js +34 -25
  43. package/dist/core/version.js +2 -1
  44. package/dist/esm/adapters/angular/index.js +1 -0
  45. package/dist/esm/adapters/angular/phone-auth.service.d.ts +18 -0
  46. package/dist/esm/adapters/angular/phone-auth.service.js +26 -0
  47. package/dist/esm/adapters/react/index.js +3 -0
  48. package/dist/esm/adapters/react/useClient.js +1 -0
  49. package/dist/esm/adapters/react/usePhoneAuth.js +16 -1
  50. package/dist/esm/adapters/vanilla/client.js +1 -0
  51. package/dist/esm/adapters/vanilla/index.js +1 -0
  52. package/dist/esm/adapters/vanilla/phone-auth.d.ts +24 -0
  53. package/dist/esm/adapters/vanilla/phone-auth.js +31 -0
  54. package/dist/esm/adapters/vue/index.js +4 -0
  55. package/dist/esm/adapters/vue/useClient.js +5 -0
  56. package/dist/esm/adapters/vue/usePhoneAuth.js +20 -1
  57. package/dist/esm/browser.js +6 -0
  58. package/dist/esm/core/client.d.ts +10 -0
  59. package/dist/esm/core/client.js +12 -0
  60. package/dist/esm/core/logger.d.ts +53 -0
  61. package/dist/esm/core/logger.js +81 -1
  62. package/dist/esm/core/phone-auth/api-types.d.ts +313 -1
  63. package/dist/esm/core/phone-auth/api-types.js +83 -0
  64. package/dist/esm/core/phone-auth/client.d.ts +144 -0
  65. package/dist/esm/core/phone-auth/client.js +375 -39
  66. package/dist/esm/core/phone-auth/error-utils.d.ts +29 -0
  67. package/dist/esm/core/phone-auth/error-utils.js +83 -1
  68. package/dist/esm/core/phone-auth/index.d.ts +1 -1
  69. package/dist/esm/core/phone-auth/index.js +4 -2
  70. package/dist/esm/core/phone-auth/status-types.d.ts +78 -0
  71. package/dist/esm/core/phone-auth/status-types.js +17 -0
  72. package/dist/esm/core/phone-auth/strategies/desktop.d.ts +65 -0
  73. package/dist/esm/core/phone-auth/strategies/desktop.js +136 -13
  74. package/dist/esm/core/phone-auth/strategies/index.d.ts +4 -0
  75. package/dist/esm/core/phone-auth/strategies/index.js +4 -0
  76. package/dist/esm/core/phone-auth/strategies/link.d.ts +50 -0
  77. package/dist/esm/core/phone-auth/strategies/link.js +97 -13
  78. package/dist/esm/core/phone-auth/strategies/ts43.d.ts +19 -0
  79. package/dist/esm/core/phone-auth/strategies/ts43.js +33 -2
  80. package/dist/esm/core/phone-auth/strategies/types.d.ts +13 -0
  81. package/dist/esm/core/phone-auth/strategies/types.js +4 -0
  82. package/dist/esm/core/phone-auth/type-guards.d.ts +128 -0
  83. package/dist/esm/core/phone-auth/type-guards.js +131 -0
  84. package/dist/esm/core/phone-auth/types.d.ts +113 -0
  85. package/dist/esm/core/phone-auth/types.js +32 -0
  86. package/dist/esm/core/phone-auth/ui/mobile-debug-console.d.ts +4 -0
  87. package/dist/esm/core/phone-auth/ui/mobile-debug-console.js +28 -2
  88. package/dist/esm/core/phone-auth/ui/modal.d.ts +68 -27
  89. package/dist/esm/core/phone-auth/ui/modal.js +422 -889
  90. package/dist/esm/core/phone-auth/validation-utils.d.ts +26 -4
  91. package/dist/esm/core/phone-auth/validation-utils.js +34 -24
  92. package/dist/esm/core/types.d.ts +35 -0
  93. package/dist/esm/core/version.js +2 -1
  94. package/dist/esm/index.js +9 -1
  95. package/dist/index.js +7 -0
  96. package/package.json +1 -1
  97. package/dist/browser/web-client-sdk.min.js.LICENSE.txt +0 -1
@@ -1,3 +1,8 @@
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
+ */
1
6
  var __awaiter = (this && this.__awaiter) || function (thisArg, _arguments, P, generator) {
2
7
  function adopt(value) { return value instanceof P ? value : new P(function (resolve) { resolve(value); }); }
3
8
  return new (P || (P = Promise))(function (resolve, reject) {
@@ -13,6 +18,10 @@ export class LinkHandler {
13
18
  this.isCancelled = false;
14
19
  this.isPollingInProgress = false;
15
20
  }
21
+ /**
22
+ * Invoke link-based authentication
23
+ * Opens authentication app while keeping user on current page
24
+ */
16
25
  invoke(data, options) {
17
26
  return __awaiter(this, void 0, void 0, function* () {
18
27
  console.log('[Link Auth] 🔗 invoke() called with data:', JSON.stringify(data, null, 2));
@@ -21,6 +30,7 @@ export class LinkHandler {
21
30
  maxPollingAttempts: options.maxPollingAttempts,
22
31
  pollingEndpoint: options.pollingEndpoint
23
32
  }) : 'none');
33
+ // Extract link data from prepare response
24
34
  const linkData = data.data;
25
35
  if (!linkData || !linkData.url) {
26
36
  throw new Error('Invalid link data: missing URL');
@@ -28,23 +38,36 @@ export class LinkHandler {
28
38
  const sessionKey = data.session.session_key;
29
39
  console.log('[Link Auth] Session key:', sessionKey);
30
40
  console.log('[Link Auth] Link URL:', linkData.url);
41
+ // Open authentication app without navigating away from current page
31
42
  this.openAuthenticationLink(linkData.url);
43
+ // Notify that link was opened
32
44
  if (options === null || options === void 0 ? void 0 : options.onLinkOpened) {
33
45
  options.onLinkOpened();
34
46
  }
47
+ // Start polling for authentication status
48
+ // Use constant interval (no exponential backoff)
35
49
  return this.startPolling(sessionKey, linkData, options);
36
50
  });
37
51
  }
52
+ /**
53
+ * Open authentication link without navigating away
54
+ */
38
55
  openAuthenticationLink(url) {
56
+ // Always use window.open - Works best for App Clips and Android deep links
57
+ // Must be called in direct response to user action to avoid popup blocker
39
58
  const newWindow = window.open(url, '_blank');
40
59
  if (!newWindow || newWindow.closed || typeof newWindow.closed === 'undefined') {
60
+ // Popup was blocked - this can happen if not called from user gesture
41
61
  console.warn('[LinkHandler] Failed to open app link - popup may have been blocked');
42
62
  }
43
63
  }
64
+ /**
65
+ * Start polling for authentication status with constant interval
66
+ */
44
67
  startPolling(sessionKey, linkData, options) {
45
68
  return __awaiter(this, void 0, void 0, function* () {
46
- const interval = (options === null || options === void 0 ? void 0 : options.pollingInterval) || 2000;
47
- const maxAttempts = (options === null || options === void 0 ? void 0 : options.maxPollingAttempts) || 30;
69
+ const interval = (options === null || options === void 0 ? void 0 : options.pollingInterval) || 2000; // Fixed 2 second interval
70
+ const maxAttempts = (options === null || options === void 0 ? void 0 : options.maxPollingAttempts) || 30; // 1 minute with 2s interval
48
71
  let attempts = 0;
49
72
  console.log('[Link Auth] 🚀 Starting polling:', {
50
73
  sessionKey,
@@ -54,22 +77,25 @@ export class LinkHandler {
54
77
  });
55
78
  return new Promise((resolve, reject) => {
56
79
  this.isPollingActive = true;
57
- this.pollingReject = reject;
80
+ this.pollingReject = reject; // Store reject function for cancel()
58
81
  const poll = () => __awaiter(this, void 0, void 0, function* () {
59
82
  if (!this.isPollingActive) {
60
- return;
83
+ return; // Polling was stopped
61
84
  }
85
+ // Skip if another poll is already in progress
62
86
  if (this.isPollingInProgress) {
63
87
  return;
64
88
  }
65
- let statusUrl = '';
89
+ let statusUrl = ''; // Declare at function scope for catch block access
66
90
  try {
67
91
  this.isPollingInProgress = true;
92
+ // Check max attempts before making the request
68
93
  if (attempts >= maxAttempts) {
69
94
  this.stopPolling();
70
95
  if (options === null || options === void 0 ? void 0 : options.onTimeout) {
71
96
  options.onTimeout();
72
97
  }
98
+ // Calculate actual timeout duration
73
99
  const timeoutSeconds = Math.round((maxAttempts * interval) / 1000);
74
100
  const timeoutMessage = timeoutSeconds >= 60
75
101
  ? `${Math.floor(timeoutSeconds / 60)} minute${Math.floor(timeoutSeconds / 60) > 1 ? 's' : ''}`
@@ -83,6 +109,11 @@ export class LinkHandler {
83
109
  reject(new Error(`Authentication timeout after ${timeoutMessage}`));
84
110
  return;
85
111
  }
112
+ // Build public status endpoint URL
113
+ // Use the same priority logic as Desktop strategy:
114
+ // 1. options?.pollingEndpoint (already contains invoke options OR client config from client.ts)
115
+ // 2. Backend-provided status_url from linkData
116
+ // 3. Hardcoded fallback to API server
86
117
  let endpoint = options === null || options === void 0 ? void 0 : options.pollingEndpoint;
87
118
  let endpointSource = 'options';
88
119
  if (!endpoint && linkData.status_url) {
@@ -93,11 +124,14 @@ export class LinkHandler {
93
124
  console.log(' - options?.pollingEndpoint:', options === null || options === void 0 ? void 0 : options.pollingEndpoint);
94
125
  console.log(' - linkData.status_url:', linkData.status_url);
95
126
  console.log(' - selected endpoint:', endpoint, 'from source:', endpointSource);
127
+ // Build the status URL based on endpoint format (same as Desktop)
96
128
  if (endpoint && (endpoint.startsWith('http://') || endpoint.startsWith('https://'))) {
129
+ // Full URL provided
97
130
  if (endpoint.includes('{{session_id}}')) {
98
131
  statusUrl = endpoint.replace('{{session_id}}', sessionKey);
99
132
  }
100
133
  else if (!endpoint.includes(sessionKey)) {
134
+ // If it doesn't already contain the session ID, check if it's a base URL
101
135
  const url = new URL(endpoint);
102
136
  statusUrl = `${url.protocol}//${url.host}/public/public/status/${sessionKey}`;
103
137
  }
@@ -106,34 +140,49 @@ export class LinkHandler {
106
140
  }
107
141
  }
108
142
  else if (endpoint && endpoint !== '') {
143
+ // Relative path provided (e.g. '/api/phone-auth/status')
109
144
  const origin = typeof window !== 'undefined' ? window.location.origin : '';
110
145
  if (endpoint.includes('{{session_id}}')) {
111
146
  statusUrl = origin + endpoint.replace('{{session_id}}', sessionKey);
112
147
  }
113
148
  else {
149
+ // Append session ID to the provided endpoint
114
150
  statusUrl = origin + endpoint + '/' + sessionKey;
115
151
  }
116
152
  }
117
153
  else {
154
+ // No endpoint provided - use hardcoded fallback
118
155
  statusUrl = `https://api.glideidentity.app/public/public/status/${sessionKey}`;
119
156
  endpointSource = 'fallback';
120
157
  }
121
158
  console.log(`[Link Auth] Using ${endpointSource} endpoint: ${statusUrl}`);
159
+ // Poll public status endpoint - no authentication required
122
160
  console.log(`[Link Auth] Polling status (attempt ${attempts}/${maxAttempts}): ${statusUrl}`);
161
+ // Build headers
162
+ const headers = {
163
+ 'Accept': 'application/json'
164
+ };
165
+ // Add developer header if devEnv is set
166
+ if (options === null || options === void 0 ? void 0 : options.devEnv) {
167
+ headers['developer'] = options.devEnv;
168
+ console.log(`[Link Auth] Adding developer header: ${options.devEnv}`);
169
+ }
123
170
  const response = yield fetch(statusUrl, {
124
171
  method: 'GET',
125
- headers: {
126
- 'Accept': 'application/json'
127
- }
172
+ headers
128
173
  });
129
174
  console.log(`[Link Auth] Poll response - Status: ${response.status}, OK: ${response.ok}`);
175
+ // Handle based on HTTP status code
130
176
  if (response.status === 200) {
177
+ // Session is active (pending or completed)
131
178
  const result = yield response.json();
132
179
  console.log('[Link Auth] Poll response data:', JSON.stringify(result, null, 2));
133
180
  if (result.status === 'completed') {
181
+ // Authentication completed successfully
134
182
  console.log('[Link Auth] ✅ Authentication COMPLETED! Session:', sessionKey);
135
183
  console.log('[Link Auth] Full completion result:', JSON.stringify(result, null, 2));
136
184
  this.stopPolling();
185
+ // Authentication completed successfully
137
186
  if (options === null || options === void 0 ? void 0 : options.onStatusUpdate) {
138
187
  options.onStatusUpdate({
139
188
  status: 'authenticated',
@@ -141,7 +190,8 @@ export class LinkHandler {
141
190
  data: result
142
191
  });
143
192
  }
144
- this.pollingReject = undefined;
193
+ // Return the authentication result
194
+ this.pollingReject = undefined; // Clear reject function on success
145
195
  resolve({
146
196
  authenticated: true,
147
197
  credential: result.credential || sessionKey,
@@ -155,8 +205,9 @@ export class LinkHandler {
155
205
  });
156
206
  }
157
207
  else if (result.status === 'pending') {
208
+ // Continue polling
158
209
  console.log('[Link Auth] Status still pending, continuing to poll...');
159
- attempts++;
210
+ attempts++; // Increment attempts after successful poll
160
211
  if (options === null || options === void 0 ? void 0 : options.onStatusUpdate) {
161
212
  options.onStatusUpdate({
162
213
  status: 'pending',
@@ -165,11 +216,13 @@ export class LinkHandler {
165
216
  }
166
217
  }
167
218
  else {
219
+ // Unexpected status value
168
220
  console.log('[Link Auth] ⚠️ Unexpected status value:', result.status, 'Full result:', JSON.stringify(result, null, 2));
169
- attempts++;
221
+ attempts++; // Increment for unexpected status too
170
222
  }
171
223
  }
172
224
  else if (response.status === 410) {
225
+ // Session expired
173
226
  console.log('[Link Auth] ❌ Session expired (410)');
174
227
  this.stopPolling();
175
228
  const errorData = yield response.json().catch(() => ({ message: 'Session expired' }));
@@ -185,6 +238,7 @@ export class LinkHandler {
185
238
  reject(new Error(errorData.message || 'Session expired'));
186
239
  }
187
240
  else if (response.status === 422) {
241
+ // Authentication failed
188
242
  console.log('[Link Auth] ❌ Authentication failed (422)');
189
243
  this.stopPolling();
190
244
  const errorData = yield response.json().catch(() => ({ message: 'Authentication failed' }));
@@ -193,6 +247,7 @@ export class LinkHandler {
193
247
  const errorMsg = isUserCancelled
194
248
  ? 'User cancelled authentication'
195
249
  : (errorData.message || 'Verification failed');
250
+ // Authentication failed
196
251
  if (options === null || options === void 0 ? void 0 : options.onStatusUpdate) {
197
252
  options.onStatusUpdate({
198
253
  status: 'error',
@@ -202,6 +257,7 @@ export class LinkHandler {
202
257
  reject(new Error(errorMsg));
203
258
  }
204
259
  else if (response.status === 404) {
260
+ // Session not found
205
261
  console.log('[Link Auth] ❌ Session not found (404)');
206
262
  this.stopPolling();
207
263
  if (options === null || options === void 0 ? void 0 : options.onStatusUpdate) {
@@ -213,6 +269,7 @@ export class LinkHandler {
213
269
  reject(new Error('Session not found'));
214
270
  }
215
271
  else if (response.status === 400) {
272
+ // Invalid session key
216
273
  console.log('[Link Auth] ❌ Invalid session key (400)');
217
274
  this.stopPolling();
218
275
  const errorData = yield response.json().catch(() => ({ message: 'Invalid session key' }));
@@ -220,8 +277,9 @@ export class LinkHandler {
220
277
  reject(new Error(errorData.message || 'Invalid session key'));
221
278
  }
222
279
  else {
280
+ // Unexpected status - continue polling
223
281
  console.log('[Link Auth] ⚠️ Unexpected HTTP status:', response.status, 'continuing to poll...');
224
- attempts++;
282
+ attempts++; // Increment for unexpected HTTP status
225
283
  try {
226
284
  const body = yield response.text();
227
285
  console.log('[Link Auth] Response body:', body);
@@ -232,8 +290,9 @@ export class LinkHandler {
232
290
  }
233
291
  }
234
292
  catch (error) {
293
+ // Network or other error - continue polling
235
294
  console.error('[Link Auth] 🔴 Polling error:', error.message || error);
236
- attempts++;
295
+ attempts++; // Increment for error case
237
296
  console.error('[Link Auth] Error details:', {
238
297
  name: error.name,
239
298
  message: error.message,
@@ -242,6 +301,7 @@ export class LinkHandler {
242
301
  attempt: attempts,
243
302
  error: error
244
303
  });
304
+ // Check if it's a CORS error (common on mobile)
245
305
  if (error.message && error.message.toLowerCase().includes('failed')) {
246
306
  console.error('[Link Auth] ⚠️ Possible CORS issue. Status URL:', statusUrl);
247
307
  console.error('[Link Auth] Make sure the API endpoint allows CORS from your ngrok domain');
@@ -254,14 +314,20 @@ export class LinkHandler {
254
314
  }
255
315
  }
256
316
  finally {
317
+ // Always clear the polling flag when done
257
318
  this.isPollingInProgress = false;
258
319
  }
259
320
  });
321
+ // Start initial poll immediately
260
322
  poll();
323
+ // Set up constant interval polling (no backoff)
261
324
  this.pollingInterval = setInterval(poll, interval);
262
325
  });
263
326
  });
264
327
  }
328
+ /**
329
+ * Stop polling
330
+ */
265
331
  stopPolling() {
266
332
  console.log('[Link Auth] 🏁 Stopping polling');
267
333
  this.isPollingActive = false;
@@ -271,6 +337,9 @@ export class LinkHandler {
271
337
  this.pollingInterval = undefined;
272
338
  }
273
339
  }
340
+ /**
341
+ * Format response for backend processing
342
+ */
274
343
  formatResponse(response) {
275
344
  if (!response.authenticated || !response.credential) {
276
345
  throw new Error('Authentication not completed');
@@ -281,25 +350,40 @@ export class LinkHandler {
281
350
  type: 'link'
282
351
  };
283
352
  }
353
+ /**
354
+ * Check if link strategy is supported
355
+ * Returns true for mobile devices (iOS and Android)
356
+ */
284
357
  isSupported() {
358
+ // Link strategy is supported on mobile devices
285
359
  const isMobile = /iPhone|iPad|iPod|Android/i.test(navigator.userAgent);
286
360
  return isMobile;
287
361
  }
362
+ /**
363
+ * Clean up resources (stop polling if active)
364
+ */
288
365
  cleanup() {
289
366
  this.stopPolling();
290
367
  this.isCancelled = false;
291
368
  this.onCancel = undefined;
292
369
  this.pollingReject = undefined;
293
370
  }
371
+ /**
372
+ * Check if polling is currently active
373
+ */
294
374
  isPolling() {
295
375
  return this.pollingInterval !== undefined;
296
376
  }
377
+ /**
378
+ * Cancel the ongoing authentication
379
+ */
297
380
  cancel() {
298
381
  var _a;
299
382
  console.log('[Link Auth] Cancelling authentication');
300
383
  this.isCancelled = true;
301
384
  this.stopPolling();
302
385
  (_a = this.onCancel) === null || _a === void 0 ? void 0 : _a.call(this);
386
+ // Immediately reject the polling promise
303
387
  if (this.pollingReject) {
304
388
  this.pollingReject({
305
389
  code: 'USER_DENIED',
@@ -1,9 +1,28 @@
1
+ /**
2
+ * TS-43 Strategy Handler
3
+ * Handles Digital Credentials API authentication for Android/Chromium
4
+ * Properly manages session objects with session_key, nonce, and enc_key
5
+ */
1
6
  import type { StrategyHandler } from './types';
2
7
  import type { PrepareResponse } from '../types';
3
8
  export declare class TS43Handler implements StrategyHandler {
9
+ /**
10
+ * Invoke TS-43 authentication using Digital Credentials API
11
+ * The data structure from backend is already in the correct format for navigator.credentials.get
12
+ */
4
13
  invoke(data: PrepareResponse): Promise<any>;
14
+ /**
15
+ * Format the credential response for backend processing
16
+ * Include the session key so backend can retrieve the full session
17
+ */
5
18
  formatResponse(response: any): any;
19
+ /**
20
+ * Check if Digital Credentials API is supported
21
+ */
6
22
  isSupported(): boolean;
23
+ /**
24
+ * Get browser support information
25
+ */
7
26
  getBrowserSupportInfo(): {
8
27
  supported: boolean;
9
28
  browser: string;
@@ -1,3 +1,8 @@
1
+ /**
2
+ * TS-43 Strategy Handler
3
+ * Handles Digital Credentials API authentication for Android/Chromium
4
+ * Properly manages session objects with session_key, nonce, and enc_key
5
+ */
1
6
  var __awaiter = (this && this.__awaiter) || function (thisArg, _arguments, P, generator) {
2
7
  function adopt(value) { return value instanceof P ? value : new P(function (resolve) { resolve(value); }); }
3
8
  return new (P || (P = Promise))(function (resolve, reject) {
@@ -8,31 +13,43 @@ var __awaiter = (this && this.__awaiter) || function (thisArg, _arguments, P, ge
8
13
  });
9
14
  };
10
15
  export class TS43Handler {
16
+ /**
17
+ * Invoke TS-43 authentication using Digital Credentials API
18
+ * The data structure from backend is already in the correct format for navigator.credentials.get
19
+ */
11
20
  invoke(data) {
12
21
  return __awaiter(this, void 0, void 0, function* () {
22
+ // Validate session structure - only session_key is actually required
13
23
  if (!data.session || !data.session.session_key) {
14
24
  throw new Error('Invalid TS43 session: missing required session_key');
15
25
  }
26
+ // Check if Digital Credentials API is available
16
27
  if (!this.isSupported()) {
17
28
  throw new Error('Digital Credentials API not supported in this browser');
18
29
  }
30
+ // Extract TS43 data from the prepare response
19
31
  const ts43Data = data.data;
32
+ // The data is already in the correct format from backend
33
+ // Just pass it through to navigator.credentials.get
20
34
  const credentialRequest = {
21
35
  digital: {
22
36
  requests: [{
23
- protocol: ts43Data.protocol,
24
- data: ts43Data.data
37
+ protocol: ts43Data.protocol, // e.g., "openid4vp-v1-unsigned"
38
+ data: ts43Data.data // Pass the entire data object as-is
25
39
  }]
26
40
  }
27
41
  };
28
42
  try {
43
+ // @ts-ignore - Digital Credentials API types not yet in TypeScript
29
44
  const credential = yield navigator.credentials.get(credentialRequest);
30
45
  if (!credential) {
31
46
  throw new Error('No credential received from Digital Credentials API');
32
47
  }
48
+ // @ts-ignore - credential.data is not typed yet
33
49
  return credential;
34
50
  }
35
51
  catch (error) {
52
+ // Handle browser-specific errors
36
53
  if (error instanceof Error) {
37
54
  if (error.name === 'NotAllowedError') {
38
55
  throw new Error('User denied the authentication request');
@@ -48,8 +65,13 @@ export class TS43Handler {
48
65
  }
49
66
  });
50
67
  }
68
+ /**
69
+ * Format the credential response for backend processing
70
+ * Include the session key so backend can retrieve the full session
71
+ */
51
72
  formatResponse(response) {
52
73
  var _a;
74
+ // Extract vp_token from the response
53
75
  const vpToken = (_a = response.data) === null || _a === void 0 ? void 0 : _a.vp_token;
54
76
  if (!vpToken) {
55
77
  throw new Error('Invalid TS43 response: missing vp_token');
@@ -59,12 +81,20 @@ export class TS43Handler {
59
81
  type: 'ts43'
60
82
  };
61
83
  }
84
+ /**
85
+ * Check if Digital Credentials API is supported
86
+ */
62
87
  isSupported() {
63
88
  if (typeof window === 'undefined') {
64
89
  return false;
65
90
  }
91
+ // Check for DigitalCredential constructor
92
+ // @ts-ignore - DigitalCredential not yet in TypeScript
66
93
  return 'DigitalCredential' in window;
67
94
  }
95
+ /**
96
+ * Get browser support information
97
+ */
68
98
  getBrowserSupportInfo() {
69
99
  if (typeof window === 'undefined') {
70
100
  return {
@@ -84,6 +114,7 @@ export class TS43Handler {
84
114
  browser: isChrome ? 'Chrome' : isEdge ? 'Edge' : 'Chromium'
85
115
  };
86
116
  }
117
+ // Provide specific guidance based on browser
87
118
  if ((isChrome || isEdge) && isAndroid) {
88
119
  return {
89
120
  supported: false,
@@ -1,5 +1,18 @@
1
+ /**
2
+ * Strategy Handler Interface
3
+ * Defines the contract for authentication strategy implementations
4
+ */
1
5
  export interface StrategyHandler {
6
+ /**
7
+ * Invoke authentication using strategy-specific data
8
+ */
2
9
  invoke(data: any): Promise<any>;
10
+ /**
11
+ * Format response for backend processing
12
+ */
3
13
  formatResponse(response: any): any;
14
+ /**
15
+ * Check if this strategy is supported in the current environment
16
+ */
4
17
  isSupported(): boolean;
5
18
  }
@@ -1 +1,5 @@
1
+ /**
2
+ * Strategy Handler Interface
3
+ * Defines the contract for authentication strategy implementations
4
+ */
1
5
  export {};
@@ -1,15 +1,143 @@
1
+ /**
2
+ * Type Guards and Helper Functions for Phone Authentication
3
+ *
4
+ * These utilities help developers work with the SDK responses in a type-safe way
5
+ * without having to write their own type checking logic.
6
+ */
1
7
  import type { AnyExtendedResponse, DesktopExtendedResponse, LinkExtendedResponse, TS43ExtendedResponse, AuthCredential } from './api-types';
8
+ /**
9
+ * Type guard to check if the result is an ExtendedResponse (extended mode)
10
+ * or a Credential (standard mode).
11
+ *
12
+ * @example
13
+ * ```typescript
14
+ * const result = await invokeSecurePrompt(sdkRequest, { executionMode: 'extended' });
15
+ *
16
+ * if (isExtendedResponse(result)) {
17
+ * // TypeScript knows this is ExtendedResponse
18
+ * console.log(result.strategy);
19
+ * await result.cancel();
20
+ * } else {
21
+ * // TypeScript knows this is a Credential
22
+ * const processedResult = await verifyPhoneNumberCredential(result, session);
23
+ * }
24
+ * ```
25
+ */
2
26
  export declare function isExtendedResponse(result: any): result is AnyExtendedResponse;
27
+ /**
28
+ * Type guard to check if the result is a Credential (standard mode response).
29
+ * A credential is either a string token or an object without ExtendedResponse properties.
30
+ *
31
+ * @example
32
+ * ```typescript
33
+ * if (isCredential(result)) {
34
+ * // Process the credential directly
35
+ * const verified = await verifyPhoneNumberCredential(result, session);
36
+ * }
37
+ * ```
38
+ */
3
39
  export declare function isCredential(result: any): result is string | {
4
40
  [aggregator_id: string]: string | string[];
5
41
  };
42
+ /**
43
+ * Type guard to check if the result is an AuthCredential object.
44
+ *
45
+ * @example
46
+ * ```typescript
47
+ * if (isAuthCredential(result)) {
48
+ * console.log(result.credential);
49
+ * console.log(result.authenticated);
50
+ * }
51
+ * ```
52
+ */
6
53
  export declare function isAuthCredential(result: any): result is AuthCredential;
54
+ /**
55
+ * Type guard to check if an ExtendedResponse is using the Link strategy.
56
+ * Link strategy involves opening an app link (App Clip on iOS, app on Android).
57
+ *
58
+ * @example
59
+ * ```typescript
60
+ * if (isExtendedResponse(result) && isLinkStrategy(result)) {
61
+ * // Re-trigger app opening if needed
62
+ * result.trigger();
63
+ * await result.credential;
64
+ * }
65
+ * ```
66
+ */
7
67
  export declare function isLinkStrategy(result: AnyExtendedResponse): result is LinkExtendedResponse;
68
+ /**
69
+ * Type guard to check if an ExtendedResponse is using the TS43 strategy.
70
+ * TS43 strategy uses the browser's Digital Credentials API.
71
+ *
72
+ * @example
73
+ * ```typescript
74
+ * if (isExtendedResponse(result) && isTS43Strategy(result)) {
75
+ * // Re-trigger credential request if needed
76
+ * await result.trigger();
77
+ * }
78
+ * ```
79
+ */
8
80
  export declare function isTS43Strategy(result: AnyExtendedResponse): result is TS43ExtendedResponse;
81
+ /**
82
+ * Type guard to check if an ExtendedResponse is using the Desktop strategy.
83
+ * Desktop strategy involves QR codes for cross-device authentication.
84
+ *
85
+ * @example
86
+ * ```typescript
87
+ * if (isExtendedResponse(result) && isDesktopStrategy(result)) {
88
+ * // Show custom QR code UI
89
+ * displayQRCode(result.qr_code_data);
90
+ * await result.start_polling();
91
+ * }
92
+ * ```
93
+ */
9
94
  export declare function isDesktopStrategy(result: AnyExtendedResponse): result is DesktopExtendedResponse;
95
+ /**
96
+ * Helper function to safely get the authentication strategy from any result.
97
+ * Returns undefined if the result is not an ExtendedResponse.
98
+ *
99
+ * @example
100
+ * ```typescript
101
+ * const strategy = getStrategy(result);
102
+ * if (strategy === 'link') {
103
+ * // Handle link strategy
104
+ * }
105
+ * ```
106
+ */
10
107
  export declare function getStrategy(result: any): 'link' | 'ts43' | 'desktop' | undefined;
108
+ /**
109
+ * Helper function to determine if a result has polling controls.
110
+ * Link and Desktop strategies have polling controls in extended mode.
111
+ *
112
+ * @example
113
+ * ```typescript
114
+ * if (hasPollingControls(result)) {
115
+ * await result.start_polling();
116
+ * }
117
+ * ```
118
+ */
11
119
  export declare function hasPollingControls(result: any): boolean;
120
+ /**
121
+ * Helper function to determine if a result has a trigger method.
122
+ * Link and TS43 strategies have trigger methods in extended mode.
123
+ *
124
+ * @example
125
+ * ```typescript
126
+ * if (hasTrigger(result)) {
127
+ * result.trigger();
128
+ * }
129
+ * ```
130
+ */
12
131
  export declare function hasTrigger(result: any): boolean;
132
+ /**
133
+ * @deprecated Use isExtendedResponse instead
134
+ */
13
135
  export declare const isHeadlessResult: typeof isExtendedResponse;
136
+ /**
137
+ * @deprecated Use hasPollingControls instead
138
+ */
14
139
  export declare const requiresPolling: typeof hasPollingControls;
140
+ /**
141
+ * @deprecated This function is no longer needed as extended mode handles user actions differently
142
+ */
15
143
  export declare const requiresUserAction: (result: any) => boolean;