@glideidentity/web-client-sdk 5.1.3 → 6.0.0-beta.2

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 +428 -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 +424 -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 +535 -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 -161
  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 -157
  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
@@ -0,0 +1,177 @@
1
+ "use strict";
2
+ /**
3
+ * Shared polling utility for Link and Desktop strategies.
4
+ * Handles authentication status polling with cancel support.
5
+ */
6
+ Object.defineProperty(exports, "__esModule", { value: true });
7
+ exports.createPollingHandler = createPollingHandler;
8
+ const errors_1 = require("../../core/errors");
9
+ // ============================================================================
10
+ // POLLING HANDLER
11
+ // ============================================================================
12
+ /**
13
+ * Creates a polling handler for authentication status.
14
+ */
15
+ function createPollingHandler(config) {
16
+ const { sessionKey, interval = 2000, maxAttempts = 30, pollingEndpoint, statusUrl, logger, } = config;
17
+ let pollingIntervalId;
18
+ let attempts = 0;
19
+ let isCancelled = false;
20
+ let isPollingActive = false;
21
+ let rejectFn;
22
+ /**
23
+ * Build the status URL.
24
+ * Priority: 1. Client config endpoint > 2. Backend status_url > 3. Prod fallback
25
+ */
26
+ function buildStatusUrl() {
27
+ // Priority 1: Developer-provided endpoint from client config (highest priority)
28
+ // Developer provides base path, we append session key
29
+ // Examples:
30
+ // /api/phone-auth/status → /api/phone-auth/status/{sessionKey}
31
+ // https://myserver.com/polling → https://myserver.com/polling/{sessionKey}
32
+ if (pollingEndpoint) {
33
+ logger?.debug('Using developer config endpoint for polling', { pollingEndpoint });
34
+ return `${pollingEndpoint}/${sessionKey}`;
35
+ }
36
+ // Priority 2: Backend-provided status_url from prepare response
37
+ // This URL already includes the session key - use as-is
38
+ // Example: https://api-dev.glideidentity.app/public/status/ee25b966c9395f0b
39
+ if (statusUrl) {
40
+ logger?.debug('Using backend status_url for polling', { statusUrl });
41
+ return statusUrl;
42
+ }
43
+ // Priority 3: Fallback to prod API - build URL with session key
44
+ logger?.debug('Using prod fallback for status polling');
45
+ return `https://api.glideidentity.app/public/status/${sessionKey}`;
46
+ }
47
+ /**
48
+ * Start polling.
49
+ */
50
+ function start() {
51
+ return new Promise((resolve, reject) => {
52
+ rejectFn = reject;
53
+ isPollingActive = true;
54
+ attempts = 0;
55
+ const poll = async () => {
56
+ if (!isPollingActive || isCancelled) {
57
+ return;
58
+ }
59
+ // Check max attempts
60
+ if (attempts >= maxAttempts) {
61
+ stop();
62
+ logger?.warn('Polling timeout reached', { attempts, maxAttempts });
63
+ resolve({
64
+ status: 'expired',
65
+ message: 'Authentication timeout',
66
+ });
67
+ return;
68
+ }
69
+ try {
70
+ const url = buildStatusUrl();
71
+ logger?.debug('Polling status', { url, attempt: attempts + 1, maxAttempts });
72
+ const response = await fetch(url, {
73
+ method: 'GET',
74
+ headers: { 'Accept': 'application/json' },
75
+ });
76
+ if (response.status === 200) {
77
+ const result = await response.json();
78
+ if (result.status === 'completed') {
79
+ stop();
80
+ logger?.info('Authentication completed');
81
+ resolve({
82
+ status: 'completed',
83
+ credential: result.credential || sessionKey,
84
+ session: result.session || { session_key: sessionKey },
85
+ });
86
+ return;
87
+ }
88
+ // Still pending - continue
89
+ attempts++;
90
+ }
91
+ else if (response.status === 410) {
92
+ // Session expired
93
+ stop();
94
+ const data = await response.json().catch(() => ({}));
95
+ resolve({
96
+ status: 'expired',
97
+ message: data.message || 'Session expired',
98
+ });
99
+ }
100
+ else if (response.status === 422) {
101
+ // Authentication failed
102
+ stop();
103
+ const data = await response.json().catch(() => ({}));
104
+ resolve({
105
+ status: 'error',
106
+ message: data.message || 'Authentication failed',
107
+ });
108
+ }
109
+ else if (response.status === 404) {
110
+ // Session not found
111
+ stop();
112
+ resolve({
113
+ status: 'error',
114
+ message: 'Session not found',
115
+ });
116
+ }
117
+ else {
118
+ // Unexpected status - continue polling
119
+ attempts++;
120
+ }
121
+ }
122
+ catch (error) {
123
+ // Network error - continue polling
124
+ logger?.debug('Polling error, retrying', { error, attempt: attempts + 1 });
125
+ attempts++;
126
+ }
127
+ };
128
+ // Start immediately
129
+ poll();
130
+ // Set up interval
131
+ pollingIntervalId = setInterval(poll, interval);
132
+ });
133
+ }
134
+ /**
135
+ * Stop polling.
136
+ */
137
+ function stop() {
138
+ isPollingActive = false;
139
+ if (pollingIntervalId) {
140
+ clearInterval(pollingIntervalId);
141
+ pollingIntervalId = undefined;
142
+ }
143
+ }
144
+ /**
145
+ * Cancel polling and reject the promise.
146
+ */
147
+ function cancel() {
148
+ logger?.debug('Polling cancelled');
149
+ isCancelled = true;
150
+ stop();
151
+ if (rejectFn) {
152
+ rejectFn((0, errors_1.createAuthError)(errors_1.ERROR_CODES.CANCELLED, 'Authentication cancelled'));
153
+ rejectFn = undefined;
154
+ }
155
+ }
156
+ /**
157
+ * Check if polling is active.
158
+ */
159
+ function isPolling() {
160
+ return pollingIntervalId !== undefined;
161
+ }
162
+ /**
163
+ * Cleanup resources.
164
+ */
165
+ function cleanup() {
166
+ stop();
167
+ isCancelled = false;
168
+ rejectFn = undefined;
169
+ }
170
+ return {
171
+ start,
172
+ stop,
173
+ cancel,
174
+ isPolling,
175
+ cleanup,
176
+ };
177
+ }
@@ -0,0 +1,204 @@
1
+ "use strict";
2
+ /**
3
+ * Error utilities for phone authentication.
4
+ *
5
+ * This file only handles CLIENT-SIDE errors (validation, browser issues, etc.).
6
+ * Server errors from Magic Auth are passed through as-is since they already
7
+ * have proper error codes and messages.
8
+ */
9
+ Object.defineProperty(exports, "__esModule", { value: true });
10
+ exports.ERROR_CODES = void 0;
11
+ exports.isAuthError = isAuthError;
12
+ exports.isClientError = isClientError;
13
+ exports.isRetryableError = isRetryableError;
14
+ exports.getUserMessage = getUserMessage;
15
+ exports.createAuthError = createAuthError;
16
+ exports.createAuthErrorWithContext = createAuthErrorWithContext;
17
+ exports.parseBackendError = parseBackendError;
18
+ exports.serializeError = serializeError;
19
+ // ============================================================================
20
+ // CLIENT-SIDE ERROR CODES
21
+ // ============================================================================
22
+ /**
23
+ * Error codes for client-side errors only.
24
+ * Server errors use their own codes from Magic Auth backend.
25
+ */
26
+ exports.ERROR_CODES = {
27
+ // --- Validation Errors (before sending to server) ---
28
+ INVALID_PHONE_NUMBER: 'INVALID_PHONE_NUMBER',
29
+ INVALID_PLMN: 'INVALID_PLMN',
30
+ MISSING_PARAMETERS: 'MISSING_PARAMETERS',
31
+ // --- Browser/Platform Errors ---
32
+ BROWSER_NOT_SUPPORTED: 'BROWSER_NOT_SUPPORTED',
33
+ UNSUPPORTED_STRATEGY: 'UNSUPPORTED_STRATEGY',
34
+ // --- User Actions ---
35
+ USER_CANCELLED: 'USER_CANCELLED',
36
+ CANCELLED: 'CANCELLED',
37
+ // --- Verification Errors (client-side) ---
38
+ VERIFICATION_FAILED: 'VERIFICATION_FAILED',
39
+ // --- Network/Client Errors ---
40
+ NETWORK_ERROR: 'NETWORK_ERROR',
41
+ TIMEOUT: 'TIMEOUT',
42
+ INVALID_RESPONSE: 'INVALID_RESPONSE',
43
+ };
44
+ // ============================================================================
45
+ // CLIENT-SIDE ERROR MESSAGES
46
+ // ============================================================================
47
+ /**
48
+ * User-facing messages for client-side errors only.
49
+ */
50
+ const CLIENT_ERROR_MESSAGES = {
51
+ [exports.ERROR_CODES.INVALID_PHONE_NUMBER]: 'Please enter a valid phone number in E.164 format (e.g., +14155551234).',
52
+ [exports.ERROR_CODES.INVALID_PLMN]: 'Invalid carrier information provided.',
53
+ [exports.ERROR_CODES.MISSING_PARAMETERS]: 'Required information is missing.',
54
+ [exports.ERROR_CODES.BROWSER_NOT_SUPPORTED]: 'Your browser does not support this authentication method. Please use Chrome or Edge with the Digital Credentials flag enabled.',
55
+ [exports.ERROR_CODES.UNSUPPORTED_STRATEGY]: 'This authentication strategy is not supported.',
56
+ [exports.ERROR_CODES.USER_CANCELLED]: 'Authentication was cancelled.',
57
+ [exports.ERROR_CODES.CANCELLED]: 'Authentication was cancelled.',
58
+ [exports.ERROR_CODES.VERIFICATION_FAILED]: 'Verification failed. Please try again.',
59
+ [exports.ERROR_CODES.NETWORK_ERROR]: 'Network connection failed. Please check your connection and try again.',
60
+ [exports.ERROR_CODES.TIMEOUT]: 'Request timed out. Please try again.',
61
+ [exports.ERROR_CODES.INVALID_RESPONSE]: 'Invalid response received.',
62
+ };
63
+ // ============================================================================
64
+ // ERROR HELPER FUNCTIONS
65
+ // ============================================================================
66
+ /**
67
+ * Type guard to check if an error is an AuthError.
68
+ */
69
+ function isAuthError(error) {
70
+ return (error !== null &&
71
+ typeof error === 'object' &&
72
+ 'code' in error &&
73
+ 'message' in error &&
74
+ typeof error.code === 'string' &&
75
+ typeof error.message === 'string');
76
+ }
77
+ /**
78
+ * Check if error is a client-side error (not from server).
79
+ */
80
+ function isClientError(error) {
81
+ return Object.values(exports.ERROR_CODES).includes(error.code);
82
+ }
83
+ /**
84
+ * Check if error is retryable.
85
+ */
86
+ function isRetryableError(error) {
87
+ return error.code === exports.ERROR_CODES.NETWORK_ERROR || error.code === exports.ERROR_CODES.TIMEOUT;
88
+ }
89
+ /**
90
+ * Get user-friendly message for client-side errors.
91
+ * For server errors, returns the server's message as-is.
92
+ */
93
+ function getUserMessage(error) {
94
+ // For client-side errors, use our messages
95
+ if (isClientError(error)) {
96
+ return CLIENT_ERROR_MESSAGES[error.code] || error.message;
97
+ }
98
+ // For server errors, use the server's message directly
99
+ return error.message;
100
+ }
101
+ /**
102
+ * Create a client-side AuthError.
103
+ *
104
+ * @example
105
+ * ```typescript
106
+ * throw createAuthError('INVALID_PHONE_NUMBER', 'Phone number must start with +');
107
+ * ```
108
+ */
109
+ function createAuthError(code, message, details) {
110
+ const error = new Error(message || CLIENT_ERROR_MESSAGES[code] || code);
111
+ error.code = code;
112
+ error.details = details;
113
+ error.timestamp = new Date().toISOString();
114
+ return error;
115
+ }
116
+ /**
117
+ * Create a client-side AuthError with context.
118
+ */
119
+ function createAuthErrorWithContext(code, context) {
120
+ const error = createAuthError(code, context.message, context.details);
121
+ error.context = {
122
+ step: context.step,
123
+ useCase: context.useCase,
124
+ timestamp: new Date().toISOString(),
125
+ userAgent: typeof navigator !== 'undefined' ? navigator.userAgent : undefined,
126
+ url: typeof window !== 'undefined' ? window.location.href : undefined,
127
+ };
128
+ return error;
129
+ }
130
+ /**
131
+ * Parse error response from backend API.
132
+ * Simply converts the server response to AuthError format without modifying the message.
133
+ */
134
+ function parseBackendError(response) {
135
+ // Server error with code and message - pass through as-is
136
+ if (response && typeof response === 'object' && ('code' in response || 'error' in response)) {
137
+ const resp = response;
138
+ const errorCode = (resp.code || resp.error);
139
+ const errorMessage = resp.message;
140
+ // Create error with server's message directly
141
+ const error = new Error(errorMessage || 'An error occurred');
142
+ error.code = errorCode;
143
+ error.status = resp.status;
144
+ error.requestId = (resp.requestId || resp.request_id);
145
+ error.timestamp = resp.timestamp;
146
+ error.details = resp.details;
147
+ error.traceId = (resp.trace_id || resp.traceId);
148
+ error.spanId = (resp.span_id || resp.spanId);
149
+ error.service = resp.service;
150
+ // Extract retryAfter if present
151
+ if (resp.details && typeof resp.details === 'object' && 'retryAfter' in resp.details) {
152
+ error.retryAfter = resp.details.retryAfter;
153
+ }
154
+ return error;
155
+ }
156
+ // HTTP response without structured error - use status to create generic error
157
+ if (response && typeof response === 'object' && 'status' in response) {
158
+ const resp = response;
159
+ const status = resp.status;
160
+ const error = new Error(resp.message || `Request failed with status ${status}`);
161
+ error.code = `HTTP_${status}`;
162
+ error.status = status;
163
+ return error;
164
+ }
165
+ // Unknown error format
166
+ const error = new Error('An unexpected error occurred');
167
+ error.code = 'UNKNOWN_ERROR';
168
+ return error;
169
+ }
170
+ /**
171
+ * Serialize error for logging (sanitizes sensitive info).
172
+ */
173
+ function serializeError(error) {
174
+ return {
175
+ code: error.code,
176
+ message: error.message,
177
+ status: error.status,
178
+ requestId: error.requestId,
179
+ timestamp: error.timestamp,
180
+ traceId: error.traceId,
181
+ spanId: error.spanId,
182
+ service: error.service,
183
+ retryAfter: error.retryAfter,
184
+ browserError: error.browserError,
185
+ context: error.context,
186
+ details: sanitizeDetails(error.details),
187
+ };
188
+ }
189
+ /**
190
+ * Sanitize error details to remove sensitive information.
191
+ */
192
+ function sanitizeDetails(details) {
193
+ if (!details || typeof details !== 'object') {
194
+ return details;
195
+ }
196
+ const sanitized = JSON.parse(JSON.stringify(details));
197
+ const sensitiveFields = ['carrier', 'phone_number', 'mnc', 'mcc', 'carrier_name'];
198
+ for (const field of sensitiveFields) {
199
+ delete sanitized[field];
200
+ }
201
+ return sanitized;
202
+ }
203
+ // TODO: Test cancel behavior - when cancel() is called, credential promise should reject
204
+ // with error code 'CANCELLED'. Need to verify this works correctly in all scenarios.
@@ -0,0 +1,83 @@
1
+ "use strict";
2
+ /**
3
+ * Glide Phone Authentication - Core Package
4
+ *
5
+ * This package contains:
6
+ * - All TypeScript types (API and SDK types)
7
+ * - Pure validation functions
8
+ * - Type guards for type-safe development
9
+ * - Error codes and utilities
10
+ *
11
+ * ZERO RUNTIME DEPENDENCIES - safe to import anywhere.
12
+ *
13
+ * @example
14
+ * ```typescript
15
+ * // Import from core for types-only usage
16
+ * import {
17
+ * type PrepareRequest,
18
+ * type PrepareResponse,
19
+ * validatePhoneNumber,
20
+ * isDesktopStrategy,
21
+ * ERROR_CODES
22
+ * } from '@glideidentity/web-client-sdk/core';
23
+ * ```
24
+ */
25
+ Object.defineProperty(exports, "__esModule", { value: true });
26
+ exports.serializeError = exports.parseBackendError = exports.createAuthErrorWithContext = exports.createAuthError = exports.getUserMessage = exports.isRetryableError = exports.isClientError = exports.isAuthError = exports.isErrorResponse = exports.isVerifyPhoneNumberResponse = exports.isGetPhoneNumberResponse = exports.getStrategyData = exports.isDesktopData = exports.isLinkData = exports.isTS43Data = exports.isCancellable = exports.isDesktopStrategy = exports.isLinkStrategy = exports.isTS43Strategy = exports.isAuthCredential = exports.isInvokeResult = exports.E164_REGEX = exports.validateSessionKey = exports.validateNonce = exports.validateUseCaseRequirements = exports.validatePlmn = exports.validatePhoneNumber = exports.ERROR_CODES = exports.AUTHENTICATION_STRATEGY = exports.USE_CASE = void 0;
27
+ // ============================================================================
28
+ // CONSTANTS
29
+ // ============================================================================
30
+ var types_1 = require("./types");
31
+ Object.defineProperty(exports, "USE_CASE", { enumerable: true, get: function () { return types_1.USE_CASE; } });
32
+ Object.defineProperty(exports, "AUTHENTICATION_STRATEGY", { enumerable: true, get: function () { return types_1.AUTHENTICATION_STRATEGY; } });
33
+ var errors_1 = require("./errors");
34
+ Object.defineProperty(exports, "ERROR_CODES", { enumerable: true, get: function () { return errors_1.ERROR_CODES; } });
35
+ // ============================================================================
36
+ // VALIDATORS
37
+ // ============================================================================
38
+ var validators_1 = require("./validators");
39
+ Object.defineProperty(exports, "validatePhoneNumber", { enumerable: true, get: function () { return validators_1.validatePhoneNumber; } });
40
+ Object.defineProperty(exports, "validatePlmn", { enumerable: true, get: function () { return validators_1.validatePlmn; } });
41
+ Object.defineProperty(exports, "validateUseCaseRequirements", { enumerable: true, get: function () { return validators_1.validateUseCaseRequirements; } });
42
+ Object.defineProperty(exports, "validateNonce", { enumerable: true, get: function () { return validators_1.validateNonce; } });
43
+ Object.defineProperty(exports, "validateSessionKey", { enumerable: true, get: function () { return validators_1.validateSessionKey; } });
44
+ Object.defineProperty(exports, "E164_REGEX", { enumerable: true, get: function () { return validators_1.E164_REGEX; } });
45
+ // ============================================================================
46
+ // TYPE GUARDS
47
+ // ============================================================================
48
+ var type_guards_1 = require("./type-guards");
49
+ // Invoke result guards
50
+ Object.defineProperty(exports, "isInvokeResult", { enumerable: true, get: function () { return type_guards_1.isInvokeResult; } });
51
+ Object.defineProperty(exports, "isAuthCredential", { enumerable: true, get: function () { return type_guards_1.isAuthCredential; } });
52
+ // Strategy guards
53
+ Object.defineProperty(exports, "isTS43Strategy", { enumerable: true, get: function () { return type_guards_1.isTS43Strategy; } });
54
+ Object.defineProperty(exports, "isLinkStrategy", { enumerable: true, get: function () { return type_guards_1.isLinkStrategy; } });
55
+ Object.defineProperty(exports, "isDesktopStrategy", { enumerable: true, get: function () { return type_guards_1.isDesktopStrategy; } });
56
+ Object.defineProperty(exports, "isCancellable", { enumerable: true, get: function () { return type_guards_1.isCancellable; } });
57
+ // Prepare response guards
58
+ Object.defineProperty(exports, "isTS43Data", { enumerable: true, get: function () { return type_guards_1.isTS43Data; } });
59
+ Object.defineProperty(exports, "isLinkData", { enumerable: true, get: function () { return type_guards_1.isLinkData; } });
60
+ Object.defineProperty(exports, "isDesktopData", { enumerable: true, get: function () { return type_guards_1.isDesktopData; } });
61
+ Object.defineProperty(exports, "getStrategyData", { enumerable: true, get: function () { return type_guards_1.getStrategyData; } });
62
+ // Process response guards
63
+ Object.defineProperty(exports, "isGetPhoneNumberResponse", { enumerable: true, get: function () { return type_guards_1.isGetPhoneNumberResponse; } });
64
+ Object.defineProperty(exports, "isVerifyPhoneNumberResponse", { enumerable: true, get: function () { return type_guards_1.isVerifyPhoneNumberResponse; } });
65
+ // Error response guard
66
+ Object.defineProperty(exports, "isErrorResponse", { enumerable: true, get: function () { return type_guards_1.isErrorResponse; } });
67
+ // ============================================================================
68
+ // ERROR UTILITIES
69
+ // ============================================================================
70
+ var errors_2 = require("./errors");
71
+ // Type guards
72
+ Object.defineProperty(exports, "isAuthError", { enumerable: true, get: function () { return errors_2.isAuthError; } });
73
+ Object.defineProperty(exports, "isClientError", { enumerable: true, get: function () { return errors_2.isClientError; } });
74
+ Object.defineProperty(exports, "isRetryableError", { enumerable: true, get: function () { return errors_2.isRetryableError; } });
75
+ // Message helpers
76
+ Object.defineProperty(exports, "getUserMessage", { enumerable: true, get: function () { return errors_2.getUserMessage; } });
77
+ // Error creation (for client-side errors only)
78
+ Object.defineProperty(exports, "createAuthError", { enumerable: true, get: function () { return errors_2.createAuthError; } });
79
+ Object.defineProperty(exports, "createAuthErrorWithContext", { enumerable: true, get: function () { return errors_2.createAuthErrorWithContext; } });
80
+ // Server error parsing (passes through as-is)
81
+ Object.defineProperty(exports, "parseBackendError", { enumerable: true, get: function () { return errors_2.parseBackendError; } });
82
+ // Logging
83
+ Object.defineProperty(exports, "serializeError", { enumerable: true, get: function () { return errors_2.serializeError; } });
@@ -0,0 +1,196 @@
1
+ "use strict";
2
+ /**
3
+ * Type Guards for Phone Authentication.
4
+ *
5
+ * These utilities help developers work with SDK responses in a type-safe way
6
+ * without having to write their own type checking logic.
7
+ */
8
+ Object.defineProperty(exports, "__esModule", { value: true });
9
+ exports.isInvokeResult = isInvokeResult;
10
+ exports.isAuthCredential = isAuthCredential;
11
+ exports.isTS43Strategy = isTS43Strategy;
12
+ exports.isLinkStrategy = isLinkStrategy;
13
+ exports.isDesktopStrategy = isDesktopStrategy;
14
+ exports.isCancellable = isCancellable;
15
+ exports.isTS43Data = isTS43Data;
16
+ exports.isLinkData = isLinkData;
17
+ exports.isDesktopData = isDesktopData;
18
+ exports.getStrategyData = getStrategyData;
19
+ exports.isGetPhoneNumberResponse = isGetPhoneNumberResponse;
20
+ exports.isVerifyPhoneNumberResponse = isVerifyPhoneNumberResponse;
21
+ exports.isErrorResponse = isErrorResponse;
22
+ const types_1 = require("./types");
23
+ // ============================================================================
24
+ // INVOKE RESULT TYPE GUARDS
25
+ // ============================================================================
26
+ /**
27
+ * Type guard to check if result is an InvokeResult.
28
+ *
29
+ * @example
30
+ * ```typescript
31
+ * const result = await sdk.invokeSecurePrompt(prepared);
32
+ * if (isInvokeResult(result)) {
33
+ * const credential = await result.credential;
34
+ * }
35
+ * ```
36
+ */
37
+ function isInvokeResult(result) {
38
+ return (result !== null &&
39
+ typeof result === 'object' &&
40
+ 'credential' in result &&
41
+ 'strategy' in result &&
42
+ 'session' in result);
43
+ }
44
+ /**
45
+ * Type guard to check if result is an AuthCredential.
46
+ *
47
+ * @example
48
+ * ```typescript
49
+ * const credential = await result.credential;
50
+ * if (isAuthCredential(credential)) {
51
+ * console.log(credential.phone_number);
52
+ * }
53
+ * ```
54
+ */
55
+ function isAuthCredential(result) {
56
+ return (result !== null &&
57
+ typeof result === 'object' &&
58
+ 'credential' in result &&
59
+ 'authenticated' in result &&
60
+ 'session' in result);
61
+ }
62
+ // ============================================================================
63
+ // STRATEGY TYPE GUARDS
64
+ // ============================================================================
65
+ /**
66
+ * Check if result is from TS43 strategy.
67
+ * TS43 uses Android Digital Credentials API.
68
+ *
69
+ * @example
70
+ * ```typescript
71
+ * const result = await sdk.invokeSecurePrompt(prepared);
72
+ * if (isTS43Strategy(result)) {
73
+ * // result.cancel is undefined for TS43
74
+ * // To retry: call invokeSecurePrompt again
75
+ * }
76
+ * ```
77
+ */
78
+ function isTS43Strategy(result) {
79
+ return result.strategy === types_1.AUTHENTICATION_STRATEGY.TS43;
80
+ }
81
+ /**
82
+ * Check if result is from Link strategy.
83
+ * Link strategy uses iOS App Clips or Android App Links.
84
+ *
85
+ * @example
86
+ * ```typescript
87
+ * const result = await sdk.invokeSecurePrompt(prepared);
88
+ * if (isLinkStrategy(result)) {
89
+ * // Can cancel polling
90
+ * result.cancel?.();
91
+ * }
92
+ * ```
93
+ */
94
+ function isLinkStrategy(result) {
95
+ return result.strategy === types_1.AUTHENTICATION_STRATEGY.LINK;
96
+ }
97
+ /**
98
+ * Check if result is from Desktop strategy.
99
+ * Desktop strategy uses QR codes for cross-device auth.
100
+ *
101
+ * @example
102
+ * ```typescript
103
+ * const result = await sdk.invokeSecurePrompt(prepared);
104
+ * if (isDesktopStrategy(result)) {
105
+ * // QR code data is in prepared.data
106
+ * // Can cancel polling
107
+ * result.cancel?.();
108
+ * }
109
+ * ```
110
+ */
111
+ function isDesktopStrategy(result) {
112
+ return result.strategy === types_1.AUTHENTICATION_STRATEGY.DESKTOP;
113
+ }
114
+ /**
115
+ * Check if result has cancel capability.
116
+ * Only Link and Desktop strategies support cancel.
117
+ */
118
+ function isCancellable(result) {
119
+ return result.cancel !== undefined;
120
+ }
121
+ // ============================================================================
122
+ // PREPARE RESPONSE TYPE GUARDS
123
+ // ============================================================================
124
+ /**
125
+ * Check if prepare response data is TS43Data.
126
+ */
127
+ function isTS43Data(data) {
128
+ return (data !== null &&
129
+ typeof data === 'object' &&
130
+ 'protocol' in data &&
131
+ 'data' in data &&
132
+ typeof data.data === 'object' &&
133
+ 'dcql_query' in data.data);
134
+ }
135
+ /**
136
+ * Check if prepare response data is LinkData.
137
+ */
138
+ function isLinkData(data) {
139
+ return (data !== null &&
140
+ typeof data === 'object' &&
141
+ 'url' in data &&
142
+ typeof data.url === 'string');
143
+ }
144
+ /**
145
+ * Check if prepare response data is DesktopData.
146
+ */
147
+ function isDesktopData(data) {
148
+ return (data !== null &&
149
+ typeof data === 'object' &&
150
+ 'data' in data &&
151
+ typeof data.data === 'object');
152
+ }
153
+ /**
154
+ * Get strategy-specific data from PrepareResponse with proper typing.
155
+ *
156
+ * @example
157
+ * ```typescript
158
+ * const prepared = await sdk.prepare(request);
159
+ *
160
+ * if (prepared.authentication_strategy === 'desktop') {
161
+ * const desktopData = getStrategyData(prepared);
162
+ * // Show QR code: desktopData.data.ios_qr_image
163
+ * }
164
+ * ```
165
+ */
166
+ function getStrategyData(prepared) {
167
+ return prepared.data;
168
+ }
169
+ // ============================================================================
170
+ // PROCESS RESPONSE TYPE GUARDS
171
+ // ============================================================================
172
+ /**
173
+ * Check if response is GetPhoneNumberResponse.
174
+ */
175
+ function isGetPhoneNumberResponse(result) {
176
+ return !('verified' in result);
177
+ }
178
+ /**
179
+ * Check if response is VerifyPhoneNumberResponse.
180
+ */
181
+ function isVerifyPhoneNumberResponse(result) {
182
+ return 'verified' in result;
183
+ }
184
+ // ============================================================================
185
+ // ERROR TYPE GUARDS
186
+ // ============================================================================
187
+ // Note: isAuthError is exported from errors.ts to avoid duplication
188
+ /**
189
+ * Check if response is an error response from server.
190
+ */
191
+ function isErrorResponse(response) {
192
+ return (response !== null &&
193
+ typeof response === 'object' &&
194
+ 'code' in response &&
195
+ 'message' in response);
196
+ }
@@ -0,0 +1,25 @@
1
+ "use strict";
2
+ /**
3
+ * Glide Phone Authentication - Core Types
4
+ *
5
+ * This file contains all types for the Phone Auth SDK.
6
+ * Zero runtime dependencies - pure TypeScript types and constants.
7
+ *
8
+ * NAMING CONVENTION:
9
+ * - All types use snake_case to match API communication
10
+ * - This eliminates conversion errors and makes debugging easier
11
+ */
12
+ Object.defineProperty(exports, "__esModule", { value: true });
13
+ exports.AUTHENTICATION_STRATEGY = exports.USE_CASE = void 0;
14
+ // ============================================================================
15
+ // CONSTANTS
16
+ // ============================================================================
17
+ exports.USE_CASE = {
18
+ GET_PHONE_NUMBER: 'GetPhoneNumber',
19
+ VERIFY_PHONE_NUMBER: 'VerifyPhoneNumber'
20
+ };
21
+ exports.AUTHENTICATION_STRATEGY = {
22
+ TS43: 'ts43',
23
+ LINK: 'link',
24
+ DESKTOP: 'desktop'
25
+ };