@proveanything/smartlinks-auth-ui 0.1.8 → 0.1.9
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/dist/api.d.ts +3 -2
- package/dist/api.d.ts.map +1 -1
- package/dist/components/SmartlinksAuthUI.d.ts.map +1 -1
- package/dist/index.d.ts +1 -0
- package/dist/index.d.ts.map +1 -1
- package/dist/index.esm.js +61 -24
- package/dist/index.esm.js.map +1 -1
- package/dist/index.js +61 -24
- package/dist/index.js.map +1 -1
- package/dist/types.d.ts +14 -0
- package/dist/types.d.ts.map +1 -1
- package/dist/utils/logger.d.ts +14 -0
- package/dist/utils/logger.d.ts.map +1 -0
- package/package.json +2 -2
package/dist/index.js
CHANGED
|
@@ -10610,16 +10610,51 @@ const MagicLinkForm = ({ onSubmit, onCancel, loading = false, error, }) => {
|
|
|
10610
10610
|
return (jsxRuntime.jsxs("form", { onSubmit: handleSubmit, className: "auth-form", children: [jsxRuntime.jsxs("div", { className: "auth-form-group", children: [jsxRuntime.jsx("label", { htmlFor: "magic-link-email", className: "auth-label", children: "Email Address" }), jsxRuntime.jsx("input", { id: "magic-link-email", type: "email", value: email, onChange: (e) => setEmail(e.target.value), className: "auth-input", placeholder: "you@example.com", required: true, disabled: loading })] }), error && (jsxRuntime.jsx("div", { className: "auth-error-message", children: error })), jsxRuntime.jsx("button", { type: "submit", className: "auth-button auth-button-primary", disabled: loading || !email, children: loading ? (jsxRuntime.jsxs(jsxRuntime.Fragment, { children: [jsxRuntime.jsx("span", { className: "auth-spinner" }), "Sending..."] })) : ('Send Magic Link') }), jsxRuntime.jsx("button", { type: "button", onClick: onCancel, className: "auth-button auth-button-secondary", disabled: loading, children: "Cancel" })] }));
|
|
10611
10611
|
};
|
|
10612
10612
|
|
|
10613
|
+
/**
|
|
10614
|
+
* Creates a normalized logger wrapper that works with different logger types
|
|
10615
|
+
* - If no logger provided, returns no-op logger (silent)
|
|
10616
|
+
* - If function logger, wraps it with level prefixes
|
|
10617
|
+
* - If console-like object, wraps methods with prefixes
|
|
10618
|
+
*/
|
|
10619
|
+
function createLoggerWrapper(logger) {
|
|
10620
|
+
if (!logger) {
|
|
10621
|
+
// No-op logger when not provided
|
|
10622
|
+
return {
|
|
10623
|
+
log: () => { },
|
|
10624
|
+
warn: () => { },
|
|
10625
|
+
error: () => { },
|
|
10626
|
+
debug: () => { },
|
|
10627
|
+
};
|
|
10628
|
+
}
|
|
10629
|
+
if (typeof logger === 'function') {
|
|
10630
|
+
// Function logger - call it for all levels
|
|
10631
|
+
return {
|
|
10632
|
+
log: (...args) => logger('[Auth]', ...args),
|
|
10633
|
+
warn: (...args) => logger('[Auth WARN]', ...args),
|
|
10634
|
+
error: (...args) => logger('[Auth ERROR]', ...args),
|
|
10635
|
+
debug: (...args) => logger('[Auth DEBUG]', ...args),
|
|
10636
|
+
};
|
|
10637
|
+
}
|
|
10638
|
+
// Console-like object logger
|
|
10639
|
+
return {
|
|
10640
|
+
log: logger.log ? (...args) => logger.log('[Auth]', ...args) : () => { },
|
|
10641
|
+
warn: logger.warn ? (...args) => logger.warn('[Auth WARN]', ...args) : () => { },
|
|
10642
|
+
error: logger.error ? (...args) => logger.error('[Auth ERROR]', ...args) : () => { },
|
|
10643
|
+
debug: logger.debug ? (...args) => logger.debug('[Auth DEBUG]', ...args) : () => { },
|
|
10644
|
+
};
|
|
10645
|
+
}
|
|
10646
|
+
|
|
10613
10647
|
/**
|
|
10614
10648
|
* AuthAPI - Thin wrapper around Smartlinks SDK authKit namespace
|
|
10615
10649
|
* All authentication operations now use the global Smartlinks SDK
|
|
10616
10650
|
*/
|
|
10617
10651
|
class AuthAPI {
|
|
10618
|
-
constructor(_apiEndpoint, clientId, clientName) {
|
|
10652
|
+
constructor(_apiEndpoint, clientId, clientName, logger) {
|
|
10619
10653
|
// apiEndpoint is kept for backward compatibility but not used
|
|
10620
10654
|
// Smartlinks SDK is pre-configured globally
|
|
10621
10655
|
this.clientId = clientId;
|
|
10622
10656
|
this.clientName = clientName;
|
|
10657
|
+
this.log = createLoggerWrapper(logger);
|
|
10623
10658
|
}
|
|
10624
10659
|
async login(email, password) {
|
|
10625
10660
|
return smartlinks__namespace.authKit.login(this.clientId, email, password);
|
|
@@ -10674,15 +10709,15 @@ class AuthAPI {
|
|
|
10674
10709
|
});
|
|
10675
10710
|
}
|
|
10676
10711
|
async fetchConfig() {
|
|
10677
|
-
|
|
10712
|
+
this.log.log('fetchConfig called with clientId:', this.clientId);
|
|
10678
10713
|
try {
|
|
10679
|
-
|
|
10714
|
+
this.log.log('Calling smartlinks.authKit.load...');
|
|
10680
10715
|
const result = await smartlinks__namespace.authKit.load(this.clientId);
|
|
10681
|
-
|
|
10716
|
+
this.log.log('smartlinks.authKit.load returned:', result);
|
|
10682
10717
|
return result;
|
|
10683
10718
|
}
|
|
10684
10719
|
catch (error) {
|
|
10685
|
-
|
|
10720
|
+
this.log.warn('Failed to fetch UI config, using defaults:', error);
|
|
10686
10721
|
return {
|
|
10687
10722
|
branding: {
|
|
10688
10723
|
title: 'Smartlinks Auth',
|
|
@@ -11479,7 +11514,7 @@ const loadGoogleIdentityServices = () => {
|
|
|
11479
11514
|
document.head.appendChild(script);
|
|
11480
11515
|
});
|
|
11481
11516
|
};
|
|
11482
|
-
const SmartlinksAuthUI = ({ apiEndpoint, clientId, clientName, accountData, onAuthSuccess, onAuthError, enabledProviders = ['email', 'google', 'phone'], initialMode = 'login', redirectUrl, theme = 'auto', className, customization, skipConfigFetch = false, minimal = false, }) => {
|
|
11517
|
+
const SmartlinksAuthUI = ({ apiEndpoint, clientId, clientName, accountData, onAuthSuccess, onAuthError, enabledProviders = ['email', 'google', 'phone'], initialMode = 'login', redirectUrl, theme = 'auto', className, customization, skipConfigFetch = false, minimal = false, logger, }) => {
|
|
11483
11518
|
const [mode, setMode] = React.useState(initialMode);
|
|
11484
11519
|
const [loading, setLoading] = React.useState(false);
|
|
11485
11520
|
const [error, setError] = React.useState();
|
|
@@ -11495,7 +11530,8 @@ const SmartlinksAuthUI = ({ apiEndpoint, clientId, clientName, accountData, onAu
|
|
|
11495
11530
|
const [config, setConfig] = React.useState(null);
|
|
11496
11531
|
const [configLoading, setConfigLoading] = React.useState(!skipConfigFetch);
|
|
11497
11532
|
const [showEmailForm, setShowEmailForm] = React.useState(false); // Track if email form should be shown when emailDisplayMode is 'button'
|
|
11498
|
-
const
|
|
11533
|
+
const log = React.useMemo(() => createLoggerWrapper(logger), [logger]);
|
|
11534
|
+
const api = new AuthAPI(apiEndpoint, clientId, clientName, logger);
|
|
11499
11535
|
const auth = useAuth();
|
|
11500
11536
|
// Dark mode detection and theme management
|
|
11501
11537
|
React.useEffect(() => {
|
|
@@ -11513,30 +11549,31 @@ const SmartlinksAuthUI = ({ apiEndpoint, clientId, clientName, accountData, onAu
|
|
|
11513
11549
|
// Reinitialize Smartlinks SDK when apiEndpoint changes (for test/dev scenarios)
|
|
11514
11550
|
// IMPORTANT: Preserve bearer token during reinitialization
|
|
11515
11551
|
React.useEffect(() => {
|
|
11516
|
-
|
|
11552
|
+
log.log('SDK reinitialize useEffect triggered', { apiEndpoint });
|
|
11517
11553
|
const reinitializeWithToken = async () => {
|
|
11518
11554
|
if (apiEndpoint) {
|
|
11519
|
-
|
|
11555
|
+
log.log('Reinitializing SDK with baseURL:', apiEndpoint);
|
|
11520
11556
|
// Get current token before reinitializing
|
|
11521
11557
|
const currentToken = await auth.getToken();
|
|
11522
11558
|
smartlinks__namespace.initializeApi({
|
|
11523
11559
|
baseURL: apiEndpoint,
|
|
11524
11560
|
proxyMode: false, // Direct API calls when custom endpoint is provided
|
|
11525
11561
|
ngrokSkipBrowserWarning: true,
|
|
11562
|
+
logger: logger, // Pass logger to SDK for verbose SDK logging
|
|
11526
11563
|
});
|
|
11527
11564
|
// Restore bearer token after reinitialization using auth.verifyToken
|
|
11528
11565
|
if (currentToken) {
|
|
11529
11566
|
smartlinks__namespace.auth.verifyToken(currentToken).catch(err => {
|
|
11530
|
-
|
|
11567
|
+
log.warn('Failed to restore bearer token after reinit:', err);
|
|
11531
11568
|
});
|
|
11532
11569
|
}
|
|
11533
11570
|
}
|
|
11534
11571
|
else {
|
|
11535
|
-
|
|
11572
|
+
log.log('No apiEndpoint, skipping SDK reinitialize');
|
|
11536
11573
|
}
|
|
11537
11574
|
};
|
|
11538
11575
|
reinitializeWithToken();
|
|
11539
|
-
}, [apiEndpoint, auth]);
|
|
11576
|
+
}, [apiEndpoint, auth, logger, log]);
|
|
11540
11577
|
// Get the effective redirect URL (use prop or default to current page)
|
|
11541
11578
|
const getRedirectUrl = () => {
|
|
11542
11579
|
if (redirectUrl)
|
|
@@ -11548,7 +11585,7 @@ const SmartlinksAuthUI = ({ apiEndpoint, clientId, clientName, accountData, onAu
|
|
|
11548
11585
|
};
|
|
11549
11586
|
// Fetch UI configuration
|
|
11550
11587
|
React.useEffect(() => {
|
|
11551
|
-
|
|
11588
|
+
log.log('Config fetch useEffect triggered', {
|
|
11552
11589
|
skipConfigFetch,
|
|
11553
11590
|
clientId,
|
|
11554
11591
|
clientIdType: typeof clientId,
|
|
@@ -11556,14 +11593,14 @@ const SmartlinksAuthUI = ({ apiEndpoint, clientId, clientName, accountData, onAu
|
|
|
11556
11593
|
apiEndpoint
|
|
11557
11594
|
});
|
|
11558
11595
|
if (skipConfigFetch) {
|
|
11559
|
-
|
|
11596
|
+
log.log('Skipping config fetch - skipConfigFetch is true');
|
|
11560
11597
|
setConfig(customization || {});
|
|
11561
11598
|
return;
|
|
11562
11599
|
}
|
|
11563
11600
|
const fetchConfig = async () => {
|
|
11564
11601
|
// If no clientId provided, use default config immediately without API call
|
|
11565
11602
|
if (!clientId) {
|
|
11566
|
-
|
|
11603
|
+
log.log('No clientId provided, using default config');
|
|
11567
11604
|
const defaultConfig = {
|
|
11568
11605
|
...DEFAULT_AUTH_CONFIG,
|
|
11569
11606
|
enabledProviders: enabledProviders || ['email', 'google', 'phone']
|
|
@@ -11594,9 +11631,9 @@ const SmartlinksAuthUI = ({ apiEndpoint, clientId, clientName, accountData, onAu
|
|
|
11594
11631
|
}
|
|
11595
11632
|
}
|
|
11596
11633
|
// Fetch from API
|
|
11597
|
-
|
|
11634
|
+
log.log('Fetching config from API for clientId:', clientId);
|
|
11598
11635
|
const fetchedConfig = await api.fetchConfig();
|
|
11599
|
-
|
|
11636
|
+
log.log('Received config:', fetchedConfig);
|
|
11600
11637
|
// Merge with customization props (props take precedence)
|
|
11601
11638
|
const mergedConfig = { ...fetchedConfig, ...customization };
|
|
11602
11639
|
setConfig(mergedConfig);
|
|
@@ -11607,7 +11644,7 @@ const SmartlinksAuthUI = ({ apiEndpoint, clientId, clientName, accountData, onAu
|
|
|
11607
11644
|
}));
|
|
11608
11645
|
}
|
|
11609
11646
|
catch (err) {
|
|
11610
|
-
|
|
11647
|
+
log.error('Failed to fetch config:', err);
|
|
11611
11648
|
setConfig(customization || {});
|
|
11612
11649
|
}
|
|
11613
11650
|
finally {
|
|
@@ -11615,7 +11652,7 @@ const SmartlinksAuthUI = ({ apiEndpoint, clientId, clientName, accountData, onAu
|
|
|
11615
11652
|
}
|
|
11616
11653
|
};
|
|
11617
11654
|
fetchConfig();
|
|
11618
|
-
}, [apiEndpoint, clientId, customization, skipConfigFetch]);
|
|
11655
|
+
}, [apiEndpoint, clientId, customization, skipConfigFetch, log]);
|
|
11619
11656
|
// Reset showEmailForm when mode changes away from login/register
|
|
11620
11657
|
React.useEffect(() => {
|
|
11621
11658
|
if (mode !== 'login' && mode !== 'register') {
|
|
@@ -11640,7 +11677,7 @@ const SmartlinksAuthUI = ({ apiEndpoint, clientId, clientName, accountData, onAu
|
|
|
11640
11677
|
const params = getUrlParams();
|
|
11641
11678
|
const urlMode = params.get('mode');
|
|
11642
11679
|
const token = params.get('token');
|
|
11643
|
-
|
|
11680
|
+
log.log('URL params detected:', { urlMode, token, hash: window.location.hash, search: window.location.search });
|
|
11644
11681
|
if (urlMode && token) {
|
|
11645
11682
|
handleURLBasedAuth(urlMode, token);
|
|
11646
11683
|
}
|
|
@@ -11650,7 +11687,7 @@ const SmartlinksAuthUI = ({ apiEndpoint, clientId, clientName, accountData, onAu
|
|
|
11650
11687
|
setError(undefined);
|
|
11651
11688
|
try {
|
|
11652
11689
|
if (urlMode === 'verifyEmail') {
|
|
11653
|
-
|
|
11690
|
+
log.log('Verifying email with token:', token);
|
|
11654
11691
|
const response = await api.verifyEmailWithToken(token);
|
|
11655
11692
|
// Get email verification mode from response or config
|
|
11656
11693
|
const verificationMode = response.emailVerificationMode || config?.emailVerification?.mode || 'verify-then-auto-login';
|
|
@@ -11685,7 +11722,7 @@ const SmartlinksAuthUI = ({ apiEndpoint, clientId, clientName, accountData, onAu
|
|
|
11685
11722
|
}
|
|
11686
11723
|
}
|
|
11687
11724
|
else if (urlMode === 'resetPassword') {
|
|
11688
|
-
|
|
11725
|
+
log.log('Verifying reset token:', token);
|
|
11689
11726
|
// Verify token is valid, then show password reset form
|
|
11690
11727
|
await api.verifyResetToken(token);
|
|
11691
11728
|
setResetToken(token); // Store token for use in password reset
|
|
@@ -11695,7 +11732,7 @@ const SmartlinksAuthUI = ({ apiEndpoint, clientId, clientName, accountData, onAu
|
|
|
11695
11732
|
window.history.replaceState({}, document.title, cleanUrl);
|
|
11696
11733
|
}
|
|
11697
11734
|
else if (urlMode === 'magicLink') {
|
|
11698
|
-
|
|
11735
|
+
log.log('Verifying magic link token:', token);
|
|
11699
11736
|
const response = await api.verifyMagicLink(token);
|
|
11700
11737
|
// Auto-login with magic link if token is provided
|
|
11701
11738
|
if (response.token) {
|
|
@@ -11719,7 +11756,7 @@ const SmartlinksAuthUI = ({ apiEndpoint, clientId, clientName, accountData, onAu
|
|
|
11719
11756
|
}
|
|
11720
11757
|
}
|
|
11721
11758
|
catch (err) {
|
|
11722
|
-
|
|
11759
|
+
log.error('URL-based auth error:', err);
|
|
11723
11760
|
const errorMessage = err instanceof Error ? err.message : 'An error occurred';
|
|
11724
11761
|
// If it's an email verification error (expired/invalid token), show resend option
|
|
11725
11762
|
if (urlMode === 'verifyEmail') {
|