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