@glideidentity/web-client-sdk 5.0.1 → 5.1.1-beta.1
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/README.md +8 -108
- package/dist/adapters/angular/index.js +1 -0
- package/dist/adapters/angular/phone-auth.service.d.ts +18 -0
- package/dist/adapters/angular/phone-auth.service.js +26 -0
- package/dist/adapters/react/index.js +3 -0
- package/dist/adapters/react/useClient.js +1 -0
- package/dist/adapters/react/usePhoneAuth.js +16 -1
- package/dist/adapters/vanilla/client.js +1 -0
- package/dist/adapters/vanilla/index.js +1 -0
- package/dist/adapters/vanilla/phone-auth.js +31 -0
- package/dist/adapters/vue/index.js +4 -0
- package/dist/adapters/vue/useClient.js +5 -0
- package/dist/adapters/vue/usePhoneAuth.js +20 -1
- package/dist/browser/web-client-sdk.min.js +1 -2
- package/dist/browser.js +6 -0
- package/dist/core/client.js +12 -0
- package/dist/core/logger.js +81 -1
- package/dist/core/phone-auth/api-types.d.ts +1 -4
- package/dist/core/phone-auth/api-types.js +83 -0
- package/dist/core/phone-auth/client.js +374 -38
- package/dist/core/phone-auth/error-utils.js +83 -1
- package/dist/core/phone-auth/index.d.ts +1 -1
- package/dist/core/phone-auth/index.js +2 -2
- package/dist/core/phone-auth/status-types.d.ts +78 -0
- package/dist/core/phone-auth/status-types.js +17 -0
- package/dist/core/phone-auth/strategies/desktop.d.ts +2 -0
- package/dist/core/phone-auth/strategies/desktop.js +136 -13
- package/dist/core/phone-auth/strategies/index.d.ts +4 -0
- package/dist/core/phone-auth/strategies/index.js +4 -0
- package/dist/core/phone-auth/strategies/link.d.ts +2 -0
- package/dist/core/phone-auth/strategies/link.js +97 -13
- package/dist/core/phone-auth/strategies/ts43.d.ts +19 -0
- package/dist/core/phone-auth/strategies/ts43.js +33 -2
- package/dist/core/phone-auth/strategies/types.js +4 -0
- package/dist/core/phone-auth/type-guards.js +131 -0
- package/dist/core/phone-auth/types.d.ts +5 -0
- package/dist/core/phone-auth/types.js +32 -0
- package/dist/core/phone-auth/ui/mobile-debug-console.js +28 -2
- package/dist/core/phone-auth/ui/modal.d.ts +55 -33
- package/dist/core/phone-auth/ui/modal.js +422 -889
- package/dist/core/phone-auth/validation-utils.d.ts +0 -9
- package/dist/core/phone-auth/validation-utils.js +34 -25
- package/dist/core/version.js +2 -1
- package/dist/esm/adapters/angular/index.js +1 -0
- package/dist/esm/adapters/angular/phone-auth.service.d.ts +18 -0
- package/dist/esm/adapters/angular/phone-auth.service.js +26 -0
- package/dist/esm/adapters/react/index.js +3 -0
- package/dist/esm/adapters/react/useClient.js +1 -0
- package/dist/esm/adapters/react/usePhoneAuth.js +16 -1
- package/dist/esm/adapters/vanilla/client.js +1 -0
- package/dist/esm/adapters/vanilla/index.js +1 -0
- package/dist/esm/adapters/vanilla/phone-auth.d.ts +24 -0
- package/dist/esm/adapters/vanilla/phone-auth.js +31 -0
- package/dist/esm/adapters/vue/index.js +4 -0
- package/dist/esm/adapters/vue/useClient.js +5 -0
- package/dist/esm/adapters/vue/usePhoneAuth.js +20 -1
- package/dist/esm/browser.js +6 -0
- package/dist/esm/core/client.d.ts +10 -0
- package/dist/esm/core/client.js +12 -0
- package/dist/esm/core/logger.d.ts +53 -0
- package/dist/esm/core/logger.js +81 -1
- package/dist/esm/core/phone-auth/api-types.d.ts +313 -1
- package/dist/esm/core/phone-auth/api-types.js +83 -0
- package/dist/esm/core/phone-auth/client.d.ts +144 -0
- package/dist/esm/core/phone-auth/client.js +375 -39
- package/dist/esm/core/phone-auth/error-utils.d.ts +29 -0
- package/dist/esm/core/phone-auth/error-utils.js +83 -1
- package/dist/esm/core/phone-auth/index.d.ts +1 -1
- package/dist/esm/core/phone-auth/index.js +4 -2
- package/dist/esm/core/phone-auth/status-types.d.ts +78 -0
- package/dist/esm/core/phone-auth/status-types.js +17 -0
- package/dist/esm/core/phone-auth/strategies/desktop.d.ts +65 -0
- package/dist/esm/core/phone-auth/strategies/desktop.js +136 -13
- package/dist/esm/core/phone-auth/strategies/index.d.ts +4 -0
- package/dist/esm/core/phone-auth/strategies/index.js +4 -0
- package/dist/esm/core/phone-auth/strategies/link.d.ts +50 -0
- package/dist/esm/core/phone-auth/strategies/link.js +97 -13
- package/dist/esm/core/phone-auth/strategies/ts43.d.ts +19 -0
- package/dist/esm/core/phone-auth/strategies/ts43.js +33 -2
- package/dist/esm/core/phone-auth/strategies/types.d.ts +13 -0
- package/dist/esm/core/phone-auth/strategies/types.js +4 -0
- package/dist/esm/core/phone-auth/type-guards.d.ts +128 -0
- package/dist/esm/core/phone-auth/type-guards.js +131 -0
- package/dist/esm/core/phone-auth/types.d.ts +113 -0
- package/dist/esm/core/phone-auth/types.js +32 -0
- package/dist/esm/core/phone-auth/ui/mobile-debug-console.d.ts +4 -0
- package/dist/esm/core/phone-auth/ui/mobile-debug-console.js +28 -2
- package/dist/esm/core/phone-auth/ui/modal.d.ts +68 -27
- package/dist/esm/core/phone-auth/ui/modal.js +422 -889
- package/dist/esm/core/phone-auth/validation-utils.d.ts +26 -4
- package/dist/esm/core/phone-auth/validation-utils.js +34 -24
- package/dist/esm/core/types.d.ts +35 -0
- package/dist/esm/core/version.js +2 -1
- package/dist/esm/index.js +9 -1
- package/dist/index.js +7 -0
- package/package.json +1 -1
- package/dist/browser/web-client-sdk.min.js.LICENSE.txt +0 -1
|
@@ -42,12 +42,3 @@ export declare function createValidationError(code: PhoneAuthErrorCode, message:
|
|
|
42
42
|
code: PhoneAuthErrorCode;
|
|
43
43
|
field?: string;
|
|
44
44
|
};
|
|
45
|
-
/**
|
|
46
|
-
* Validates nonce format
|
|
47
|
-
* @param nonce - Nonce string to validate
|
|
48
|
-
* @returns Validation result
|
|
49
|
-
*/
|
|
50
|
-
export declare function validateNonce(nonce: string): {
|
|
51
|
-
valid: boolean;
|
|
52
|
-
error?: string;
|
|
53
|
-
};
|
|
@@ -1,15 +1,23 @@
|
|
|
1
1
|
"use strict";
|
|
2
|
+
/**
|
|
3
|
+
* Validation utilities for phone authentication
|
|
4
|
+
*/
|
|
2
5
|
Object.defineProperty(exports, "__esModule", { value: true });
|
|
3
6
|
exports.validatePhoneNumber = validatePhoneNumber;
|
|
4
7
|
exports.validatePlmn = validatePlmn;
|
|
5
8
|
exports.validateUseCaseRequirements = validateUseCaseRequirements;
|
|
6
9
|
exports.createValidationError = createValidationError;
|
|
7
|
-
exports.validateNonce = validateNonce;
|
|
8
10
|
const api_types_1 = require("./api-types");
|
|
11
|
+
/**
|
|
12
|
+
* Validates E.164 phone number format
|
|
13
|
+
* @param phoneNumber - Phone number to validate
|
|
14
|
+
* @returns Validation result with error if invalid
|
|
15
|
+
*/
|
|
9
16
|
function validatePhoneNumber(phoneNumber) {
|
|
10
17
|
if (!phoneNumber) {
|
|
11
|
-
return { valid: true };
|
|
18
|
+
return { valid: true }; // Phone number is optional for GetPhoneNumber
|
|
12
19
|
}
|
|
20
|
+
// E.164 format validation - strict, no cleaning
|
|
13
21
|
const e164Regex = /^\+[1-9]\d{1,14}$/;
|
|
14
22
|
if (!phoneNumber.startsWith('+')) {
|
|
15
23
|
return {
|
|
@@ -29,6 +37,7 @@ function validatePhoneNumber(phoneNumber) {
|
|
|
29
37
|
error: 'Phone number too long for E.164 format (maximum 15 digits after +)'
|
|
30
38
|
};
|
|
31
39
|
}
|
|
40
|
+
// Check for any invalid characters (spaces, dashes, parentheses, etc.)
|
|
32
41
|
if (!/^\+\d+$/.test(phoneNumber)) {
|
|
33
42
|
return {
|
|
34
43
|
valid: false,
|
|
@@ -43,26 +52,42 @@ function validatePhoneNumber(phoneNumber) {
|
|
|
43
52
|
}
|
|
44
53
|
return { valid: true };
|
|
45
54
|
}
|
|
55
|
+
/**
|
|
56
|
+
* Validates PLMN (MCC/MNC) values
|
|
57
|
+
* @param plmn - PLMN object with MCC and MNC
|
|
58
|
+
* @returns Validation result
|
|
59
|
+
*/
|
|
46
60
|
function validatePlmn(plmn) {
|
|
47
61
|
if (!plmn) {
|
|
48
|
-
return { valid: true };
|
|
62
|
+
return { valid: true }; // PLMN is optional
|
|
49
63
|
}
|
|
50
64
|
const { mcc, mnc } = plmn;
|
|
65
|
+
// MCC validation (3 digits) - no range check for telco labs
|
|
51
66
|
if (!mcc || !/^\d{3}$/.test(mcc)) {
|
|
52
67
|
return {
|
|
53
68
|
valid: false,
|
|
54
69
|
error: 'MCC must be exactly 3 digits'
|
|
55
70
|
};
|
|
56
71
|
}
|
|
72
|
+
// MNC validation (2 or 3 digits)
|
|
57
73
|
if (!mnc || !/^\d{2,3}$/.test(mnc)) {
|
|
58
74
|
return {
|
|
59
75
|
valid: false,
|
|
60
76
|
error: 'MNC must be 2 or 3 digits'
|
|
61
77
|
};
|
|
62
78
|
}
|
|
79
|
+
// No range validation - allowing unofficial MCCs for telco labs
|
|
63
80
|
return { valid: true };
|
|
64
81
|
}
|
|
82
|
+
/**
|
|
83
|
+
* Validates use case and phone number combination
|
|
84
|
+
* @param useCase - The use case
|
|
85
|
+
* @param phoneNumber - The phone number (required for VerifyPhoneNumber)
|
|
86
|
+
* @param hasParentSessionId - Whether parent_session_id is provided (allows skipping normal validation)
|
|
87
|
+
* @returns Validation result
|
|
88
|
+
*/
|
|
65
89
|
function validateUseCaseRequirements(useCase, phoneNumber, hasParentSessionId) {
|
|
90
|
+
// VerifyPhoneNumber requires a phone number (unless parent_session_id is provided)
|
|
66
91
|
if (useCase === api_types_1.USE_CASE.VERIFY_PHONE_NUMBER && !phoneNumber && !hasParentSessionId) {
|
|
67
92
|
return {
|
|
68
93
|
valid: false,
|
|
@@ -71,6 +96,12 @@ function validateUseCaseRequirements(useCase, phoneNumber, hasParentSessionId) {
|
|
|
71
96
|
}
|
|
72
97
|
return { valid: true };
|
|
73
98
|
}
|
|
99
|
+
/**
|
|
100
|
+
* Creates a validation error
|
|
101
|
+
* @param code - Error code
|
|
102
|
+
* @param message - Error message
|
|
103
|
+
* @param field - Field that failed validation
|
|
104
|
+
*/
|
|
74
105
|
function createValidationError(code, message, field) {
|
|
75
106
|
const error = new Error(message);
|
|
76
107
|
error.code = code;
|
|
@@ -79,25 +110,3 @@ function createValidationError(code, message, field) {
|
|
|
79
110
|
}
|
|
80
111
|
return error;
|
|
81
112
|
}
|
|
82
|
-
function validateNonce(nonce) {
|
|
83
|
-
const base64urlRegex = /^[A-Za-z0-9_-]+$/;
|
|
84
|
-
if (!nonce || nonce.length === 0) {
|
|
85
|
-
return {
|
|
86
|
-
valid: false,
|
|
87
|
-
error: 'Nonce is required'
|
|
88
|
-
};
|
|
89
|
-
}
|
|
90
|
-
if (!base64urlRegex.test(nonce)) {
|
|
91
|
-
return {
|
|
92
|
-
valid: false,
|
|
93
|
-
error: 'Nonce must be base64url encoded'
|
|
94
|
-
};
|
|
95
|
-
}
|
|
96
|
-
if (nonce.length < 32 || nonce.length > 128) {
|
|
97
|
-
return {
|
|
98
|
-
valid: false,
|
|
99
|
-
error: 'Nonce must be between 32 and 128 characters'
|
|
100
|
-
};
|
|
101
|
-
}
|
|
102
|
-
return { valid: true };
|
|
103
|
-
}
|
package/dist/core/version.js
CHANGED
|
@@ -1,3 +1,4 @@
|
|
|
1
1
|
export { ClientService } from './client.service';
|
|
2
2
|
export { PhoneAuthService } from './phone-auth.service';
|
|
3
|
+
// Export error utilities
|
|
3
4
|
export { PhoneAuthErrorCode, isPhoneAuthError, isUserError, getUserMessage, isErrorCode, getRetryDelay, isRetryableError, serializeError, createErrorBreadcrumb } from '../../core/phone-auth';
|
|
@@ -11,10 +11,28 @@ export declare class PhoneAuthService {
|
|
|
11
11
|
result$: Observable<PhoneAuthResult | null>;
|
|
12
12
|
currentStep$: Observable<AuthStep>;
|
|
13
13
|
constructor();
|
|
14
|
+
/**
|
|
15
|
+
* Configure the phone auth client
|
|
16
|
+
*/
|
|
14
17
|
configure(config: AuthConfig): void;
|
|
18
|
+
/**
|
|
19
|
+
* Check if browser supports secure phone authentication
|
|
20
|
+
*/
|
|
15
21
|
isSupported(): boolean;
|
|
22
|
+
/**
|
|
23
|
+
* Verify phone number
|
|
24
|
+
*/
|
|
16
25
|
verify(options: PhoneAuthOptions): Promise<PhoneAuthResult>;
|
|
26
|
+
/**
|
|
27
|
+
* Get phone number
|
|
28
|
+
*/
|
|
17
29
|
getPhoneNumber(options?: Omit<PhoneAuthOptions, 'use_case' | 'phone_number'>): Promise<PhoneAuthResult>;
|
|
30
|
+
/**
|
|
31
|
+
* Verify specific phone number
|
|
32
|
+
*/
|
|
18
33
|
verifyPhoneNumber(phoneNumber: string, options?: Omit<PhoneAuthOptions, 'use_case' | 'phone_number'>): Promise<PhoneAuthResult>;
|
|
34
|
+
/**
|
|
35
|
+
* Reset state
|
|
36
|
+
*/
|
|
19
37
|
reset(): void;
|
|
20
38
|
}
|
|
@@ -21,22 +21,33 @@ import { PhoneAuthClient } from '../../core/phone-auth';
|
|
|
21
21
|
import { BehaviorSubject } from 'rxjs';
|
|
22
22
|
let PhoneAuthService = class PhoneAuthService {
|
|
23
23
|
constructor() {
|
|
24
|
+
// State subjects
|
|
24
25
|
this.isLoadingSubject = new BehaviorSubject(false);
|
|
25
26
|
this.errorSubject = new BehaviorSubject(null);
|
|
26
27
|
this.resultSubject = new BehaviorSubject(null);
|
|
27
28
|
this.currentStepSubject = new BehaviorSubject('idle');
|
|
29
|
+
// Public observables
|
|
28
30
|
this.isLoading$ = this.isLoadingSubject.asObservable();
|
|
29
31
|
this.error$ = this.errorSubject.asObservable();
|
|
30
32
|
this.result$ = this.resultSubject.asObservable();
|
|
31
33
|
this.currentStep$ = this.currentStepSubject.asObservable();
|
|
32
34
|
this.client = new PhoneAuthClient();
|
|
33
35
|
}
|
|
36
|
+
/**
|
|
37
|
+
* Configure the phone auth client
|
|
38
|
+
*/
|
|
34
39
|
configure(config) {
|
|
35
40
|
this.client = new PhoneAuthClient(config);
|
|
36
41
|
}
|
|
42
|
+
/**
|
|
43
|
+
* Check if browser supports secure phone authentication
|
|
44
|
+
*/
|
|
37
45
|
isSupported() {
|
|
38
46
|
return this.client.isSupported();
|
|
39
47
|
}
|
|
48
|
+
/**
|
|
49
|
+
* Verify phone number
|
|
50
|
+
*/
|
|
40
51
|
verify(options) {
|
|
41
52
|
return __awaiter(this, void 0, void 0, function* () {
|
|
42
53
|
this.isLoadingSubject.next(true);
|
|
@@ -44,14 +55,19 @@ let PhoneAuthService = class PhoneAuthService {
|
|
|
44
55
|
this.resultSubject.next(null);
|
|
45
56
|
this.currentStepSubject.next('requesting');
|
|
46
57
|
try {
|
|
58
|
+
// Step 1: Prepare request
|
|
47
59
|
const preparedRequest = yield this.client.preparePhoneRequest(options);
|
|
60
|
+
// Step 2: Show authenticating state
|
|
48
61
|
this.currentStepSubject.next('authenticating');
|
|
49
62
|
const credentialResponse = yield this.client.invokeSecurePrompt(preparedRequest);
|
|
63
|
+
// Step 3: Process response through appropriate endpoint
|
|
50
64
|
this.currentStepSubject.next('processing');
|
|
65
|
+
// Cast to credential type - adapters never use headless mode
|
|
51
66
|
const credential = credentialResponse;
|
|
52
67
|
const processedResult = options.use_case === 'GetPhoneNumber'
|
|
53
68
|
? yield this.client.getPhoneNumber(credential, preparedRequest.session)
|
|
54
69
|
: yield this.client.verifyPhoneNumber(credential, preparedRequest.session);
|
|
70
|
+
// Create final result
|
|
55
71
|
const isVerifyResponse = 'verified' in processedResult;
|
|
56
72
|
const result = processedResult;
|
|
57
73
|
this.resultSubject.next(result);
|
|
@@ -59,6 +75,7 @@ let PhoneAuthService = class PhoneAuthService {
|
|
|
59
75
|
return result;
|
|
60
76
|
}
|
|
61
77
|
catch (error) {
|
|
78
|
+
// Enhance error with context
|
|
62
79
|
const authError = error;
|
|
63
80
|
const enhancedError = Object.assign(Object.assign({}, authError), { context: authError.context || {
|
|
64
81
|
useCase: options.use_case,
|
|
@@ -75,16 +92,25 @@ let PhoneAuthService = class PhoneAuthService {
|
|
|
75
92
|
}
|
|
76
93
|
});
|
|
77
94
|
}
|
|
95
|
+
/**
|
|
96
|
+
* Get phone number
|
|
97
|
+
*/
|
|
78
98
|
getPhoneNumber(options) {
|
|
79
99
|
return __awaiter(this, void 0, void 0, function* () {
|
|
80
100
|
return this.verify(Object.assign({ use_case: 'GetPhoneNumber' }, options));
|
|
81
101
|
});
|
|
82
102
|
}
|
|
103
|
+
/**
|
|
104
|
+
* Verify specific phone number
|
|
105
|
+
*/
|
|
83
106
|
verifyPhoneNumber(phoneNumber, options) {
|
|
84
107
|
return __awaiter(this, void 0, void 0, function* () {
|
|
85
108
|
return this.verify(Object.assign({ use_case: 'VerifyPhoneNumber', phone_number: phoneNumber }, options));
|
|
86
109
|
});
|
|
87
110
|
}
|
|
111
|
+
/**
|
|
112
|
+
* Reset state
|
|
113
|
+
*/
|
|
88
114
|
reset() {
|
|
89
115
|
this.isLoadingSubject.next(false);
|
|
90
116
|
this.errorSubject.next(null);
|
|
@@ -1,5 +1,8 @@
|
|
|
1
1
|
export { usePhoneAuth } from './usePhoneAuth';
|
|
2
2
|
export { useClient } from './useClient';
|
|
3
|
+
// Export error utilities
|
|
3
4
|
export { PhoneAuthErrorCode, isPhoneAuthError, isUserError, getUserMessage, isErrorCode, getRetryDelay, isRetryableError, serializeError, createErrorBreadcrumb } from '../../core/phone-auth';
|
|
5
|
+
// Export constants for use case and strategy
|
|
4
6
|
export { USE_CASE as UseCase, AUTHENTICATION_STRATEGY as AuthenticationStrategy, BrowserError, BrowserErrorCode, BrowserName } from '../../core/phone-auth/types';
|
|
7
|
+
// Export the PhoneAuthClient class for direct use
|
|
5
8
|
export { PhoneAuthClient } from '../../core/phone-auth';
|
|
@@ -27,6 +27,7 @@ export function useClient(config) {
|
|
|
27
27
|
};
|
|
28
28
|
}, []);
|
|
29
29
|
const authenticate = (authUrl, options) => __awaiter(this, void 0, void 0, function* () {
|
|
30
|
+
// Legacy authentication removed - use setToken directly
|
|
30
31
|
const error = new Error('authenticate method is deprecated. Use client.setToken() directly.');
|
|
31
32
|
setError(error);
|
|
32
33
|
setLoading(false);
|
|
@@ -15,8 +15,13 @@ export function usePhoneAuth(config = {}) {
|
|
|
15
15
|
const [result, setResult] = useState(null);
|
|
16
16
|
const [currentStep, setCurrentStep] = useState('idle');
|
|
17
17
|
const lastRequestRef = useRef(null);
|
|
18
|
-
|
|
18
|
+
// Create client instance with callbacks
|
|
19
|
+
const client = useMemo(() => new PhoneAuthClient(Object.assign(Object.assign({}, config), {
|
|
20
|
+
// Pass through callbacks if provided
|
|
21
|
+
onCrossDeviceDetected: config.onCrossDeviceDetected, onRetryAttempt: config.onRetryAttempt })), [JSON.stringify(config)]);
|
|
22
|
+
// Check browser support
|
|
19
23
|
const isSupported = useMemo(() => client.isSupported(), [client]);
|
|
24
|
+
// Verify method with silent retry support
|
|
20
25
|
const verify = useCallback((options) => __awaiter(this, void 0, void 0, function* () {
|
|
21
26
|
setIsLoading(true);
|
|
22
27
|
setError(null);
|
|
@@ -24,12 +29,14 @@ export function usePhoneAuth(config = {}) {
|
|
|
24
29
|
setCurrentStep('requesting');
|
|
25
30
|
lastRequestRef.current = options;
|
|
26
31
|
try {
|
|
32
|
+
// Use the client's verify method which includes retry logic
|
|
27
33
|
const verificationResult = yield client.verify(options);
|
|
28
34
|
setResult(verificationResult);
|
|
29
35
|
setCurrentStep('complete');
|
|
30
36
|
return verificationResult;
|
|
31
37
|
}
|
|
32
38
|
catch (err) {
|
|
39
|
+
// Error is only set after all retries are exhausted
|
|
33
40
|
const authError = err;
|
|
34
41
|
setError(authError);
|
|
35
42
|
setCurrentStep('idle');
|
|
@@ -39,39 +46,47 @@ export function usePhoneAuth(config = {}) {
|
|
|
39
46
|
setIsLoading(false);
|
|
40
47
|
}
|
|
41
48
|
}), [client]);
|
|
49
|
+
// Manual retry method
|
|
42
50
|
const retryLastRequest = useCallback(() => __awaiter(this, void 0, void 0, function* () {
|
|
43
51
|
if (!lastRequestRef.current) {
|
|
44
52
|
throw new Error('No previous request to retry');
|
|
45
53
|
}
|
|
46
54
|
return verify(lastRequestRef.current);
|
|
47
55
|
}), [verify]);
|
|
56
|
+
// Convenience methods
|
|
48
57
|
const getPhoneNumber = useCallback((options) => verify(Object.assign({ use_case: 'GetPhoneNumber' }, options)), [verify]);
|
|
49
58
|
const verifyPhoneNumber = useCallback((phoneNumber, options) => verify(Object.assign({ use_case: 'VerifyPhoneNumber', phone_number: phoneNumber }, options)), [verify]);
|
|
59
|
+
// Reset state
|
|
50
60
|
const reset = useCallback(() => {
|
|
51
61
|
setIsLoading(false);
|
|
52
62
|
setError(null);
|
|
53
63
|
setResult(null);
|
|
54
64
|
setCurrentStep('idle');
|
|
55
65
|
}, []);
|
|
66
|
+
// Expose granular methods directly from client for better discoverability
|
|
56
67
|
const preparePhoneRequest = useCallback((options) => client.preparePhoneRequest(options), [client]);
|
|
57
68
|
const invokeSecurePrompt = useCallback((prepareResponse) => client.invokeSecurePrompt(prepareResponse), [client]);
|
|
58
69
|
const getPhoneNumberCredential = useCallback((credentialResponse, session) => client.getPhoneNumber(credentialResponse, session), [client]);
|
|
59
70
|
const verifyPhoneNumberCredential = useCallback((credentialResponse, session) => client.verifyPhoneNumber(credentialResponse, session), [client]);
|
|
60
71
|
return {
|
|
72
|
+
// State
|
|
61
73
|
isLoading,
|
|
62
74
|
error,
|
|
63
75
|
result,
|
|
64
76
|
currentStep,
|
|
65
77
|
isSupported,
|
|
78
|
+
// High-level methods
|
|
66
79
|
verify,
|
|
67
80
|
getPhoneNumber,
|
|
68
81
|
verifyPhoneNumber,
|
|
69
82
|
retryLastRequest,
|
|
70
83
|
reset,
|
|
84
|
+
// Granular methods (directly exposed for better discoverability)
|
|
71
85
|
preparePhoneRequest,
|
|
72
86
|
invokeSecurePrompt,
|
|
73
87
|
getPhoneNumberCredential,
|
|
74
88
|
verifyPhoneNumberCredential,
|
|
89
|
+
// Client instance (still available for advanced usage)
|
|
75
90
|
client
|
|
76
91
|
};
|
|
77
92
|
}
|
|
@@ -14,6 +14,7 @@ export class VanillaClient {
|
|
|
14
14
|
}
|
|
15
15
|
authenticate(authUrl, options) {
|
|
16
16
|
return __awaiter(this, void 0, void 0, function* () {
|
|
17
|
+
// Legacy authentication removed - use setToken directly
|
|
17
18
|
throw new Error('authenticate method is deprecated. Use client.setToken() directly.');
|
|
18
19
|
});
|
|
19
20
|
}
|
|
@@ -1,3 +1,4 @@
|
|
|
1
1
|
export { VanillaClient as ClientManager } from './client';
|
|
2
2
|
export { PhoneAuthManager } from './phone-auth';
|
|
3
|
+
// Export error utilities
|
|
3
4
|
export { PhoneAuthErrorCode, isPhoneAuthError, isUserError, getUserMessage, isErrorCode, getRetryDelay, isRetryableError, serializeError, createErrorBreadcrumb } from '../../core/phone-auth';
|
|
@@ -11,12 +11,36 @@ export declare class PhoneAuthManager {
|
|
|
11
11
|
private state;
|
|
12
12
|
private listeners;
|
|
13
13
|
constructor(config?: AuthConfig);
|
|
14
|
+
/**
|
|
15
|
+
* Get current state
|
|
16
|
+
*/
|
|
14
17
|
getState(): PhoneAuthState;
|
|
18
|
+
/**
|
|
19
|
+
* Subscribe to state changes
|
|
20
|
+
*/
|
|
15
21
|
subscribe(listener: (state: PhoneAuthState) => void): () => void;
|
|
22
|
+
/**
|
|
23
|
+
* Update state and notify listeners
|
|
24
|
+
*/
|
|
16
25
|
private updateState;
|
|
26
|
+
/**
|
|
27
|
+
* Verify phone number
|
|
28
|
+
*/
|
|
17
29
|
verify(options: PhoneAuthOptions): Promise<PhoneAuthResult>;
|
|
30
|
+
/**
|
|
31
|
+
* Get phone number
|
|
32
|
+
*/
|
|
18
33
|
getPhoneNumber(options?: Omit<PhoneAuthOptions, 'use_case' | 'phone_number'>): Promise<PhoneAuthResult>;
|
|
34
|
+
/**
|
|
35
|
+
* Verify specific phone number
|
|
36
|
+
*/
|
|
19
37
|
verifyPhoneNumber(phoneNumber: string, options?: Omit<PhoneAuthOptions, 'use_case' | 'phone_number'>): Promise<PhoneAuthResult>;
|
|
38
|
+
/**
|
|
39
|
+
* Reset state
|
|
40
|
+
*/
|
|
20
41
|
reset(): void;
|
|
42
|
+
/**
|
|
43
|
+
* Check if browser supports secure phone authentication
|
|
44
|
+
*/
|
|
21
45
|
isSupported(): boolean;
|
|
22
46
|
}
|
|
@@ -20,11 +20,18 @@ export class PhoneAuthManager {
|
|
|
20
20
|
isSupported: this.client.isSupported()
|
|
21
21
|
};
|
|
22
22
|
}
|
|
23
|
+
/**
|
|
24
|
+
* Get current state
|
|
25
|
+
*/
|
|
23
26
|
getState() {
|
|
24
27
|
return Object.assign({}, this.state);
|
|
25
28
|
}
|
|
29
|
+
/**
|
|
30
|
+
* Subscribe to state changes
|
|
31
|
+
*/
|
|
26
32
|
subscribe(listener) {
|
|
27
33
|
this.listeners.push(listener);
|
|
34
|
+
// Return unsubscribe function
|
|
28
35
|
return () => {
|
|
29
36
|
const index = this.listeners.indexOf(listener);
|
|
30
37
|
if (index !== -1) {
|
|
@@ -32,10 +39,16 @@ export class PhoneAuthManager {
|
|
|
32
39
|
}
|
|
33
40
|
};
|
|
34
41
|
}
|
|
42
|
+
/**
|
|
43
|
+
* Update state and notify listeners
|
|
44
|
+
*/
|
|
35
45
|
updateState(updates) {
|
|
36
46
|
this.state = Object.assign(Object.assign({}, this.state), updates);
|
|
37
47
|
this.listeners.forEach(listener => listener(this.getState()));
|
|
38
48
|
}
|
|
49
|
+
/**
|
|
50
|
+
* Verify phone number
|
|
51
|
+
*/
|
|
39
52
|
verify(options) {
|
|
40
53
|
return __awaiter(this, void 0, void 0, function* () {
|
|
41
54
|
this.updateState({
|
|
@@ -45,14 +58,19 @@ export class PhoneAuthManager {
|
|
|
45
58
|
currentStep: 'requesting'
|
|
46
59
|
});
|
|
47
60
|
try {
|
|
61
|
+
// Step 1: Prepare request
|
|
48
62
|
const preparedRequest = yield this.client.preparePhoneRequest(options);
|
|
63
|
+
// Step 2: Show authenticating state
|
|
49
64
|
this.updateState({ currentStep: 'authenticating' });
|
|
50
65
|
const credentialResponse = yield this.client.invokeSecurePrompt(preparedRequest);
|
|
66
|
+
// Step 3: Process response through appropriate endpoint
|
|
51
67
|
this.updateState({ currentStep: 'processing' });
|
|
68
|
+
// Cast to credential type - adapters never use headless mode
|
|
52
69
|
const credential = credentialResponse;
|
|
53
70
|
const processedResult = options.use_case === 'GetPhoneNumber'
|
|
54
71
|
? yield this.client.getPhoneNumber(credential, preparedRequest.session)
|
|
55
72
|
: yield this.client.verifyPhoneNumber(credential, preparedRequest.session);
|
|
73
|
+
// Create final result
|
|
56
74
|
const isVerifyResponse = 'verified' in processedResult;
|
|
57
75
|
const result = processedResult;
|
|
58
76
|
this.updateState({
|
|
@@ -63,6 +81,7 @@ export class PhoneAuthManager {
|
|
|
63
81
|
return result;
|
|
64
82
|
}
|
|
65
83
|
catch (error) {
|
|
84
|
+
// Enhance error with context
|
|
66
85
|
const authError = error;
|
|
67
86
|
const enhancedError = Object.assign(Object.assign({}, authError), { context: authError.context || {
|
|
68
87
|
useCase: options.use_case,
|
|
@@ -79,16 +98,25 @@ export class PhoneAuthManager {
|
|
|
79
98
|
}
|
|
80
99
|
});
|
|
81
100
|
}
|
|
101
|
+
/**
|
|
102
|
+
* Get phone number
|
|
103
|
+
*/
|
|
82
104
|
getPhoneNumber(options) {
|
|
83
105
|
return __awaiter(this, void 0, void 0, function* () {
|
|
84
106
|
return this.verify(Object.assign({ use_case: 'GetPhoneNumber' }, options));
|
|
85
107
|
});
|
|
86
108
|
}
|
|
109
|
+
/**
|
|
110
|
+
* Verify specific phone number
|
|
111
|
+
*/
|
|
87
112
|
verifyPhoneNumber(phoneNumber, options) {
|
|
88
113
|
return __awaiter(this, void 0, void 0, function* () {
|
|
89
114
|
return this.verify(Object.assign({ use_case: 'VerifyPhoneNumber', phone_number: phoneNumber }, options));
|
|
90
115
|
});
|
|
91
116
|
}
|
|
117
|
+
/**
|
|
118
|
+
* Reset state
|
|
119
|
+
*/
|
|
92
120
|
reset() {
|
|
93
121
|
this.updateState({
|
|
94
122
|
isLoading: false,
|
|
@@ -97,6 +125,9 @@ export class PhoneAuthManager {
|
|
|
97
125
|
currentStep: 'idle'
|
|
98
126
|
});
|
|
99
127
|
}
|
|
128
|
+
/**
|
|
129
|
+
* Check if browser supports secure phone authentication
|
|
130
|
+
*/
|
|
100
131
|
isSupported() {
|
|
101
132
|
return this.state.isSupported;
|
|
102
133
|
}
|
|
@@ -2,6 +2,10 @@ export { usePhoneAuth } from './usePhoneAuth';
|
|
|
2
2
|
export { useClient } from './useClient';
|
|
3
3
|
export { SDKClient } from '../../core/client';
|
|
4
4
|
export { PhoneAuthClient } from '../../core/phone-auth';
|
|
5
|
+
// API response types are already exported via core/phone-auth/types
|
|
6
|
+
// Export error utilities
|
|
5
7
|
export { PhoneAuthErrorCode, isPhoneAuthError, isUserError, getUserMessage, isErrorCode, getRetryDelay, isRetryableError, serializeError, createErrorBreadcrumb } from '../../core/phone-auth';
|
|
8
|
+
// Export constants for use case and strategy
|
|
6
9
|
export { USE_CASE as UseCase, AUTHENTICATION_STRATEGY as AuthenticationStrategy, BrowserError, BrowserErrorCode, BrowserName } from '../../core/phone-auth/types';
|
|
10
|
+
// Export API constants from api-types
|
|
7
11
|
export { USE_CASE, ERROR_CODE, ERROR_MESSAGES, ERROR_STATUS_CODES } from '../../core/phone-auth/api-types';
|
|
@@ -40,14 +40,17 @@ export function useClient(config) {
|
|
|
40
40
|
const authenticate = (authUrl) => __awaiter(this, void 0, void 0, function* () {
|
|
41
41
|
loading.value = true;
|
|
42
42
|
error.value = null;
|
|
43
|
+
// Clean up previous authentication if exists
|
|
43
44
|
if (cleanup) {
|
|
44
45
|
cleanup();
|
|
45
46
|
cleanup = null;
|
|
46
47
|
}
|
|
48
|
+
// Legacy authentication removed - use setToken directly
|
|
47
49
|
error.value = new Error('authenticate method is deprecated. Use client.setToken() directly.');
|
|
48
50
|
loading.value = false;
|
|
49
51
|
throw error.value;
|
|
50
52
|
});
|
|
53
|
+
// Cleanup on component unmount
|
|
51
54
|
onUnmounted(() => {
|
|
52
55
|
if (cleanup) {
|
|
53
56
|
cleanup();
|
|
@@ -100,6 +103,7 @@ export function useClient(config) {
|
|
|
100
103
|
loading.value = false;
|
|
101
104
|
}
|
|
102
105
|
});
|
|
106
|
+
// Low-level methods for advanced control
|
|
103
107
|
const preparePhoneRequest = (options) => __awaiter(this, void 0, void 0, function* () {
|
|
104
108
|
return client.value.phoneAuth.preparePhoneRequest(options);
|
|
105
109
|
});
|
|
@@ -113,6 +117,7 @@ export function useClient(config) {
|
|
|
113
117
|
isSupported,
|
|
114
118
|
getPhoneNumber,
|
|
115
119
|
verifyPhoneNumber,
|
|
120
|
+
// Low-level API for advanced usage
|
|
116
121
|
preparePhoneRequest,
|
|
117
122
|
invokeSecurePrompt
|
|
118
123
|
};
|
|
@@ -10,31 +10,43 @@ var __awaiter = (this && this.__awaiter) || function (thisArg, _arguments, P, ge
|
|
|
10
10
|
import { ref, computed, readonly } from 'vue';
|
|
11
11
|
import { PhoneAuthClient } from '../../core/phone-auth';
|
|
12
12
|
export function usePhoneAuth(config = {}) {
|
|
13
|
+
// State management
|
|
13
14
|
const isLoading = ref(false);
|
|
14
15
|
const error = ref(null);
|
|
15
16
|
const result = ref(null);
|
|
16
17
|
const currentStep = ref('idle');
|
|
17
|
-
|
|
18
|
+
// Create client instance with callbacks
|
|
19
|
+
const client = new PhoneAuthClient(Object.assign(Object.assign({}, config), {
|
|
20
|
+
// Callbacks are now properly typed through AuthConfig
|
|
21
|
+
onCrossDeviceDetected: config.onCrossDeviceDetected, onRetryAttempt: config.onRetryAttempt }));
|
|
22
|
+
// Check browser support
|
|
18
23
|
const isSupported = computed(() => client.isSupported());
|
|
24
|
+
// Verify method - internal wrapper that converts to API format
|
|
19
25
|
const verify = (options) => __awaiter(this, void 0, void 0, function* () {
|
|
20
26
|
isLoading.value = true;
|
|
21
27
|
error.value = null;
|
|
22
28
|
result.value = null;
|
|
23
29
|
currentStep.value = 'requesting';
|
|
24
30
|
try {
|
|
31
|
+
// Step 1: Prepare the request
|
|
25
32
|
const preparedRequest = yield client.preparePhoneRequest(options);
|
|
33
|
+
// Step 2: User authentication
|
|
26
34
|
currentStep.value = 'authenticating';
|
|
27
35
|
const credentialResponse = yield client.invokeSecurePrompt(preparedRequest);
|
|
36
|
+
// Step 3: Process the response through appropriate endpoint
|
|
28
37
|
currentStep.value = 'processing';
|
|
38
|
+
// Cast to credential type - adapters never use headless mode
|
|
29
39
|
const credential = credentialResponse;
|
|
30
40
|
const verificationResult = options.use_case === 'GetPhoneNumber'
|
|
31
41
|
? yield client.getPhoneNumber(credential, preparedRequest.session)
|
|
32
42
|
: yield client.verifyPhoneNumber(credential, preparedRequest.session);
|
|
43
|
+
// Use the result directly - it's already the correct type
|
|
33
44
|
result.value = verificationResult;
|
|
34
45
|
currentStep.value = 'complete';
|
|
35
46
|
return result.value;
|
|
36
47
|
}
|
|
37
48
|
catch (err) {
|
|
49
|
+
// Enhance error with context if it's an AuthError
|
|
38
50
|
const authError = err;
|
|
39
51
|
const enhancedError = Object.assign(Object.assign({}, authError), { context: authError.context || {
|
|
40
52
|
useCase: options.use_case,
|
|
@@ -50,32 +62,39 @@ export function usePhoneAuth(config = {}) {
|
|
|
50
62
|
isLoading.value = false;
|
|
51
63
|
}
|
|
52
64
|
});
|
|
65
|
+
// Convenience methods
|
|
53
66
|
const getPhoneNumber = (options) => verify(Object.assign({ use_case: 'GetPhoneNumber' }, options));
|
|
54
67
|
const verifyPhoneNumber = (phoneNumber, options) => verify(Object.assign({ use_case: 'VerifyPhoneNumber', phone_number: phoneNumber }, options));
|
|
68
|
+
// Reset state
|
|
55
69
|
const reset = () => {
|
|
56
70
|
isLoading.value = false;
|
|
57
71
|
error.value = null;
|
|
58
72
|
result.value = null;
|
|
59
73
|
currentStep.value = 'idle';
|
|
60
74
|
};
|
|
75
|
+
// Expose granular methods directly from client for better discoverability
|
|
61
76
|
const preparePhoneRequest = client.preparePhoneRequest.bind(client);
|
|
62
77
|
const invokeSecurePrompt = client.invokeSecurePrompt.bind(client);
|
|
63
78
|
const getPhoneNumberCredential = client.getPhoneNumber.bind(client);
|
|
64
79
|
const verifyPhoneNumberCredential = client.verifyPhoneNumber.bind(client);
|
|
65
80
|
return {
|
|
81
|
+
// State (readonly)
|
|
66
82
|
isLoading: readonly(isLoading),
|
|
67
83
|
error: readonly(error),
|
|
68
84
|
result: readonly(result),
|
|
69
85
|
currentStep: readonly(currentStep),
|
|
70
86
|
isSupported: readonly(isSupported),
|
|
87
|
+
// High-level methods
|
|
71
88
|
verify,
|
|
72
89
|
getPhoneNumber,
|
|
73
90
|
verifyPhoneNumber,
|
|
74
91
|
reset,
|
|
92
|
+
// Granular methods (directly exposed for better discoverability)
|
|
75
93
|
preparePhoneRequest,
|
|
76
94
|
invokeSecurePrompt,
|
|
77
95
|
getPhoneNumberCredential,
|
|
78
96
|
verifyPhoneNumberCredential,
|
|
97
|
+
// Client instance (still available for advanced usage)
|
|
79
98
|
client
|
|
80
99
|
};
|
|
81
100
|
}
|
package/dist/esm/browser.js
CHANGED
|
@@ -1,5 +1,11 @@
|
|
|
1
|
+
// Browser-specific entry point for vanilla JavaScript usage
|
|
2
|
+
// This excludes framework-specific adapters that require Angular/React/Vue
|
|
3
|
+
// Phone Authentication - Core client
|
|
1
4
|
export { PhoneAuthClient } from './core/phone-auth';
|
|
5
|
+
// Phone Auth Error Utilities
|
|
2
6
|
export { PhoneAuthErrorCode, isPhoneAuthError, isUserError, getUserMessage, isErrorCode, getRetryDelay, isRetryableError, serializeError, createErrorBreadcrumb } from './core/phone-auth';
|
|
7
|
+
// Export constants for use case and strategy
|
|
3
8
|
export { USE_CASE as UseCase, AUTHENTICATION_STRATEGY as AuthenticationStrategy, BrowserError, BrowserErrorCode, BrowserName } from './core/phone-auth/types';
|
|
9
|
+
// Vanilla adapters ONLY (no framework dependencies)
|
|
4
10
|
export { VanillaClient as ClientManager } from './adapters/vanilla/client';
|
|
5
11
|
export { PhoneAuthManager } from './adapters/vanilla/phone-auth';
|
|
@@ -6,7 +6,17 @@ export declare class SDKClient {
|
|
|
6
6
|
private token?;
|
|
7
7
|
phoneAuth: PhoneAuthClient;
|
|
8
8
|
constructor(config: ClientConfig);
|
|
9
|
+
/**
|
|
10
|
+
* Set authentication token for API requests
|
|
11
|
+
*/
|
|
9
12
|
setToken(token: string): void;
|
|
13
|
+
/**
|
|
14
|
+
* Clear authentication token
|
|
15
|
+
*/
|
|
10
16
|
clearToken(): void;
|
|
17
|
+
/**
|
|
18
|
+
* Make a GET request to the API
|
|
19
|
+
* Note: Requires baseURL to be set in the config
|
|
20
|
+
*/
|
|
11
21
|
get<T = any>(path: string, options?: RequestOptions): Promise<ClientResponse<T>>;
|
|
12
22
|
}
|