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