@proveanything/smartlinks-auth-ui 0.1.31 → 0.1.34

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.
@@ -1,4 +1,6 @@
1
1
  import React from 'react';
2
2
  import type { SmartlinksAuthUIProps } from '../types';
3
+ declare const signOutGoogleNative: () => Promise<void>;
4
+ export { signOutGoogleNative };
3
5
  export declare const SmartlinksAuthUI: React.FC<SmartlinksAuthUIProps>;
4
6
  //# sourceMappingURL=SmartlinksAuthUI.d.ts.map
@@ -1 +1 @@
1
- {"version":3,"file":"SmartlinksAuthUI.d.ts","sourceRoot":"","sources":["../../src/components/SmartlinksAuthUI.tsx"],"names":[],"mappings":"AAAA,OAAO,KAAuC,MAAM,OAAO,CAAC;AAW5D,OAAO,KAAK,EAAE,qBAAqB,EAAuD,MAAM,UAAU,CAAC;AA4I3G,eAAO,MAAM,gBAAgB,EAAE,KAAK,CAAC,EAAE,CAAC,qBAAqB,CA6zC5D,CAAC"}
1
+ {"version":3,"file":"SmartlinksAuthUI.d.ts","sourceRoot":"","sources":["../../src/components/SmartlinksAuthUI.tsx"],"names":[],"mappings":"AAAA,OAAO,KAAuC,MAAM,OAAO,CAAC;AAW5D,OAAO,KAAK,EAAE,qBAAqB,EAAuD,MAAM,UAAU,CAAC;AAgI3G,QAAA,MAAM,mBAAmB,QAAa,OAAO,CAAC,IAAI,CAgDjD,CAAC;AA0FF,OAAO,EAAE,mBAAmB,EAAE,CAAC;AA8B/B,eAAO,MAAM,gBAAgB,EAAE,KAAK,CAAC,EAAE,CAAC,qBAAqB,CAw3C5D,CAAC"}
@@ -1 +1 @@
1
- {"version":3,"file":"AuthContext.d.ts","sourceRoot":"","sources":["../../src/context/AuthContext.tsx"],"names":[],"mappings":"AAAA,OAAO,KAA8E,MAAM,OAAO,CAAC;AAGnG,OAAO,KAAK,EAAE,eAAe,EAAE,MAAM,2BAA2B,CAAC;AAGjE,OAAO,KAAK,EAAE,QAAQ,EAAE,uBAAuB,EAAE,iBAAiB,EAAE,MAAM,UAAU,CAAC;AAErF,UAAU,gBAAgB;IACxB,IAAI,EAAE,QAAQ,GAAG,IAAI,CAAC;IACtB,KAAK,EAAE,MAAM,GAAG,IAAI,CAAC;IACrB,WAAW,EAAE,MAAM,CAAC,MAAM,EAAE,GAAG,CAAC,GAAG,IAAI,CAAC;IACxC,WAAW,EAAE,MAAM,CAAC,MAAM,EAAE,GAAG,CAAC,GAAG,IAAI,CAAC;IACxC,eAAe,EAAE,OAAO,CAAC;IACzB,UAAU,EAAE,OAAO,CAAC;IACpB,SAAS,EAAE,OAAO,CAAC;IACnB,QAAQ,EAAE,OAAO,CAAC;IAClB,SAAS,EAAE,OAAO,CAAC;IAGnB,OAAO,EAAE,eAAe,GAAG,IAAI,CAAC;IAChC,SAAS,EAAE,MAAM,GAAG,IAAI,CAAC;IACzB,UAAU,EAAE,CAAC,YAAY,CAAC,EAAE,OAAO,KAAK,OAAO,CAAC,eAAe,GAAG,IAAI,CAAC,CAAC;IACxE,yBAAyB,EAAE,CAAC,YAAY,EAAE,MAAM,CAAC,MAAM,EAAE,GAAG,CAAC,KAAK,OAAO,CAAC,eAAe,CAAC,CAAC;IAG3F,KAAK,EAAE,CAAC,KAAK,EAAE,MAAM,EAAE,IAAI,EAAE,QAAQ,EAAE,WAAW,CAAC,EAAE,MAAM,CAAC,MAAM,EAAE,GAAG,CAAC,EAAE,SAAS,CAAC,EAAE,OAAO,EAAE,SAAS,CAAC,EAAE,MAAM,KAAK,OAAO,CAAC,IAAI,CAAC,CAAC;IACpI,MAAM,EAAE,MAAM,OAAO,CAAC,IAAI,CAAC,CAAC;IAC5B,QAAQ,EAAE,MAAM,OAAO,CAAC,MAAM,GAAG,IAAI,CAAC,CAAC;IACvC,YAAY,EAAE,MAAM,OAAO,CAAC;QAAE,KAAK,EAAE,MAAM,CAAC;QAAC,SAAS,EAAE,MAAM,CAAC;QAAC,SAAS,EAAE,MAAM,CAAA;KAAE,GAAG,IAAI,CAAC,CAAC;IAC5F,YAAY,EAAE,MAAM,OAAO,CAAC,MAAM,CAAC,CAAC;IACpC,UAAU,EAAE,CAAC,YAAY,CAAC,EAAE,OAAO,KAAK,OAAO,CAAC,MAAM,CAAC,MAAM,EAAE,GAAG,CAAC,CAAC,CAAC;IACrE,cAAc,EAAE,MAAM,OAAO,CAAC,MAAM,CAAC,MAAM,EAAE,GAAG,CAAC,CAAC,CAAC;IACnD,iBAAiB,EAAE,MAAM,OAAO,CAAC,IAAI,CAAC,CAAC;IACvC,iBAAiB,EAAE,CAAC,QAAQ,EAAE,uBAAuB,KAAK,MAAM,IAAI,CAAC;IACrE,iBAAiB,EAAE,MAAM,OAAO,CAAC,OAAO,CAAC,CAAC;CAC3C;AAID,eAAO,MAAM,YAAY,EAAE,KAAK,CAAC,EAAE,CAAC,iBAAiB,CAg2BpD,CAAC;AAEF,eAAO,MAAM,OAAO,QAAO,gBAM1B,CAAC"}
1
+ {"version":3,"file":"AuthContext.d.ts","sourceRoot":"","sources":["../../src/context/AuthContext.tsx"],"names":[],"mappings":"AAAA,OAAO,KAA8E,MAAM,OAAO,CAAC;AAGnG,OAAO,KAAK,EAAE,eAAe,EAAE,MAAM,2BAA2B,CAAC;AAGjE,OAAO,KAAK,EAAE,QAAQ,EAAE,uBAAuB,EAAE,iBAAiB,EAAE,MAAM,UAAU,CAAC;AAErF,UAAU,gBAAgB;IACxB,IAAI,EAAE,QAAQ,GAAG,IAAI,CAAC;IACtB,KAAK,EAAE,MAAM,GAAG,IAAI,CAAC;IACrB,WAAW,EAAE,MAAM,CAAC,MAAM,EAAE,GAAG,CAAC,GAAG,IAAI,CAAC;IACxC,WAAW,EAAE,MAAM,CAAC,MAAM,EAAE,GAAG,CAAC,GAAG,IAAI,CAAC;IACxC,eAAe,EAAE,OAAO,CAAC;IACzB,UAAU,EAAE,OAAO,CAAC;IACpB,SAAS,EAAE,OAAO,CAAC;IACnB,QAAQ,EAAE,OAAO,CAAC;IAClB,SAAS,EAAE,OAAO,CAAC;IAGnB,OAAO,EAAE,eAAe,GAAG,IAAI,CAAC;IAChC,SAAS,EAAE,MAAM,GAAG,IAAI,CAAC;IACzB,UAAU,EAAE,CAAC,YAAY,CAAC,EAAE,OAAO,KAAK,OAAO,CAAC,eAAe,GAAG,IAAI,CAAC,CAAC;IACxE,yBAAyB,EAAE,CAAC,YAAY,EAAE,MAAM,CAAC,MAAM,EAAE,GAAG,CAAC,KAAK,OAAO,CAAC,eAAe,CAAC,CAAC;IAG3F,KAAK,EAAE,CAAC,KAAK,EAAE,MAAM,EAAE,IAAI,EAAE,QAAQ,EAAE,WAAW,CAAC,EAAE,MAAM,CAAC,MAAM,EAAE,GAAG,CAAC,EAAE,SAAS,CAAC,EAAE,OAAO,EAAE,SAAS,CAAC,EAAE,MAAM,KAAK,OAAO,CAAC,IAAI,CAAC,CAAC;IACpI,MAAM,EAAE,MAAM,OAAO,CAAC,IAAI,CAAC,CAAC;IAC5B,QAAQ,EAAE,MAAM,OAAO,CAAC,MAAM,GAAG,IAAI,CAAC,CAAC;IACvC,YAAY,EAAE,MAAM,OAAO,CAAC;QAAE,KAAK,EAAE,MAAM,CAAC;QAAC,SAAS,EAAE,MAAM,CAAC;QAAC,SAAS,EAAE,MAAM,CAAA;KAAE,GAAG,IAAI,CAAC,CAAC;IAC5F,YAAY,EAAE,MAAM,OAAO,CAAC,MAAM,CAAC,CAAC;IACpC,UAAU,EAAE,CAAC,YAAY,CAAC,EAAE,OAAO,KAAK,OAAO,CAAC,MAAM,CAAC,MAAM,EAAE,GAAG,CAAC,CAAC,CAAC;IACrE,cAAc,EAAE,MAAM,OAAO,CAAC,MAAM,CAAC,MAAM,EAAE,GAAG,CAAC,CAAC,CAAC;IACnD,iBAAiB,EAAE,MAAM,OAAO,CAAC,IAAI,CAAC,CAAC;IACvC,iBAAiB,EAAE,CAAC,QAAQ,EAAE,uBAAuB,KAAK,MAAM,IAAI,CAAC;IACrE,iBAAiB,EAAE,MAAM,OAAO,CAAC,OAAO,CAAC,CAAC;CAC3C;AAID,eAAO,MAAM,YAAY,EAAE,KAAK,CAAC,EAAE,CAAC,iBAAiB,CA62BpD,CAAC;AAEF,eAAO,MAAM,OAAO,QAAO,gBAM1B,CAAC"}
package/dist/index.esm.js CHANGED
@@ -11851,6 +11851,19 @@ collectionId, enableContactSync, enableInteractionTracking, interactionAppId, in
11851
11851
  const currentUser = user;
11852
11852
  const currentContactId = contactId;
11853
11853
  try {
11854
+ // Clear Google Sign-In session on native side (fire-and-forget with timeout)
11855
+ // This ensures the next login shows the account picker instead of auto-signing in
11856
+ console.log('[AuthContext] Checking for native Google sign-out...');
11857
+ try {
11858
+ // Dynamic import to avoid circular dependency
11859
+ const { signOutGoogleNative } = await Promise.resolve().then(function () { return SmartlinksAuthUI$1; });
11860
+ await signOutGoogleNative();
11861
+ console.log('[AuthContext] Native Google sign-out completed');
11862
+ }
11863
+ catch (err) {
11864
+ // signOutGoogleNative is fire-and-forget, errors are expected if no native bridge
11865
+ console.log('[AuthContext] Native Google sign-out skipped or failed (non-blocking):', err);
11866
+ }
11854
11867
  // Only clear persistent storage in standalone mode
11855
11868
  if (!proxyMode) {
11856
11869
  await tokenStorage.clearAll();
@@ -12138,6 +12151,9 @@ const useAuth = () => {
12138
12151
  return context;
12139
12152
  };
12140
12153
 
12154
+ // VERSION: Update this when making changes to help identify which version is running
12155
+ const AUTH_UI_VERSION = '34';
12156
+ const LOG_PREFIX = `[SmartlinksAuthUI:v${AUTH_UI_VERSION}]`;
12141
12157
  // Helper to calculate expiration from AuthResponse
12142
12158
  const getExpirationFromResponse = (response) => {
12143
12159
  if (response.expiresAt)
@@ -12192,51 +12208,152 @@ const loadGoogleIdentityServices = () => {
12192
12208
  // Helper to detect WebView environments (Android/iOS)
12193
12209
  const detectWebView = () => {
12194
12210
  const ua = navigator.userAgent;
12195
- console.log('[SmartlinksAuthUI] 🔍 detectWebView checking UA:', ua);
12211
+ console.log(`${LOG_PREFIX} 🔍 detectWebView checking UA:`, ua);
12196
12212
  // Android WebView detection
12197
12213
  if (/Android/i.test(ua)) {
12198
- console.log('[SmartlinksAuthUI] 🔍 Android device detected');
12214
+ console.log(`${LOG_PREFIX} 🔍 Android device detected`);
12199
12215
  // Modern Android WebViews include "wv" in UA string
12200
12216
  if (/\bwv\b/i.test(ua)) {
12201
- console.log('[SmartlinksAuthUI] ✅ Android WebView detected (wv in UA)');
12217
+ console.log(`${LOG_PREFIX} ✅ Android WebView detected (wv in UA)`);
12202
12218
  return true;
12203
12219
  }
12204
12220
  // Check for legacy Android bridge
12205
12221
  if (typeof window.Android !== 'undefined') {
12206
- console.log('[SmartlinksAuthUI] ✅ Android WebView detected (Android bridge exists)');
12222
+ console.log(`${LOG_PREFIX} ✅ Android WebView detected (Android bridge exists)`);
12207
12223
  return true;
12208
12224
  }
12209
- console.log('[SmartlinksAuthUI] ❌ Android but not WebView');
12225
+ console.log(`${LOG_PREFIX} ❌ Android but not WebView`);
12210
12226
  }
12211
12227
  // iOS WKWebView detection
12212
12228
  if (/iPhone|iPad|iPod/i.test(ua)) {
12213
- console.log('[SmartlinksAuthUI] 🔍 iOS device detected');
12229
+ console.log(`${LOG_PREFIX} 🔍 iOS device detected`);
12214
12230
  const hasWebKitHandlers = !!window.webkit?.messageHandlers;
12215
12231
  const isSafari = !!window.safari;
12216
- console.log('[SmartlinksAuthUI] 🔍 iOS check:', { hasWebKitHandlers, isSafari });
12232
+ console.log(`${LOG_PREFIX} 🔍 iOS check:`, { hasWebKitHandlers, isSafari });
12217
12233
  // WKWebView has webkit handlers but no safari object
12218
12234
  if (hasWebKitHandlers && !isSafari) {
12219
- console.log('[SmartlinksAuthUI] ✅ iOS WKWebView detected');
12235
+ console.log(`${LOG_PREFIX} ✅ iOS WKWebView detected`);
12220
12236
  return true;
12221
12237
  }
12222
- console.log('[SmartlinksAuthUI] ❌ iOS but not WKWebView (likely Safari)');
12238
+ console.log(`${LOG_PREFIX} ❌ iOS but not WKWebView (likely Safari)`);
12223
12239
  }
12224
- console.log('[SmartlinksAuthUI] ❌ Not a WebView environment');
12240
+ console.log(`${LOG_PREFIX} ❌ Not a WebView environment`);
12225
12241
  return false;
12226
12242
  };
12227
- // Helper to detect native bridge for Google Sign-In delegation
12228
- // Android apps can expose SmartlinksNative.signInWithGoogle() to handle OAuth natively
12229
12243
  const getNativeBridge = () => {
12230
- console.log('[SmartlinksAuthUI] 🔍 getNativeBridge checking for SmartlinksNative...');
12231
- console.log('[SmartlinksAuthUI] 🔍 window.SmartlinksNative:', window.SmartlinksNative);
12244
+ console.log(`${LOG_PREFIX} 🔍 getNativeBridge checking for SmartlinksNative...`);
12245
+ console.log(`${LOG_PREFIX} 🔍 window.SmartlinksNative:`, window.SmartlinksNative);
12232
12246
  const native = window.SmartlinksNative;
12233
12247
  if (native?.signInWithGoogle) {
12234
- console.log('[SmartlinksAuthUI] ✅ Native bridge found! SmartlinksNative.signInWithGoogle is available');
12248
+ console.log(`${LOG_PREFIX} ✅ Native bridge found!`, {
12249
+ signInWithGoogle: !!native.signInWithGoogle,
12250
+ signOutGoogle: !!native.signOutGoogle,
12251
+ checkGoogleSignIn: !!native.checkGoogleSignIn,
12252
+ });
12235
12253
  return native;
12236
12254
  }
12237
- console.log('[SmartlinksAuthUI] ❌ No native bridge found (SmartlinksNative.signInWithGoogle not available)');
12255
+ console.log(`${LOG_PREFIX} ❌ No native bridge found (SmartlinksNative.signInWithGoogle not available)`);
12238
12256
  return null;
12239
12257
  };
12258
+ // Sign out from Google on the native side (clears cached Google account)
12259
+ // This is fire-and-forget with a timeout - gracefully degrades if not supported
12260
+ const signOutGoogleNative = async () => {
12261
+ const nativeBridge = getNativeBridge();
12262
+ if (!nativeBridge?.signOutGoogle) {
12263
+ console.log(`${LOG_PREFIX} 🚪 signOutGoogleNative: no native bridge or signOutGoogle not available`);
12264
+ return;
12265
+ }
12266
+ // Store reference to the method (TypeScript now knows it's defined)
12267
+ const signOutMethod = nativeBridge.signOutGoogle;
12268
+ const callbackId = `google_signout_${Date.now()}`;
12269
+ console.log(`${LOG_PREFIX} 🚪 Initiating native Google sign-out, callbackId:`, callbackId);
12270
+ return new Promise((resolve) => {
12271
+ // Timeout after 3 seconds - don't block logout on native response
12272
+ const timeout = setTimeout(() => {
12273
+ console.log(`${LOG_PREFIX} 🚪 Native sign-out timed out (continuing anyway)`);
12274
+ resolve();
12275
+ }, 3000);
12276
+ // Store original callback to restore later
12277
+ const originalCallback = window.smartlinksNativeCallback;
12278
+ window.smartlinksNativeCallback = (result) => {
12279
+ if (result.callbackId === callbackId) {
12280
+ clearTimeout(timeout);
12281
+ console.log(`${LOG_PREFIX} 🚪 Native Google sign-out result:`, result);
12282
+ // Restore original callback
12283
+ window.smartlinksNativeCallback = originalCallback;
12284
+ resolve();
12285
+ }
12286
+ else if (originalCallback) {
12287
+ // Pass through to original callback for other messages
12288
+ originalCallback(result);
12289
+ }
12290
+ };
12291
+ const payload = JSON.stringify({
12292
+ type: 'GOOGLE_SIGN_OUT',
12293
+ callbackId,
12294
+ });
12295
+ console.log(`${LOG_PREFIX} 🚪 Calling nativeBridge.signOutGoogle with payload:`, payload);
12296
+ signOutMethod(payload);
12297
+ });
12298
+ };
12299
+ const checkSilentGoogleSignIn = async (clientId, googleClientId) => {
12300
+ const nativeBridge = getNativeBridge();
12301
+ if (!nativeBridge?.checkGoogleSignIn) {
12302
+ console.log(`${LOG_PREFIX} 🔇 checkSilentGoogleSignIn: no native bridge or checkGoogleSignIn not available`);
12303
+ return null;
12304
+ }
12305
+ // Store reference to the method (TypeScript now knows it's defined)
12306
+ const checkMethod = nativeBridge.checkGoogleSignIn;
12307
+ const callbackId = `google_check_${Date.now()}`;
12308
+ console.log(`${LOG_PREFIX} 🔇 Checking for silent Google sign-in, callbackId:`, callbackId);
12309
+ return new Promise((resolve) => {
12310
+ // Timeout after 5 seconds
12311
+ const timeout = setTimeout(() => {
12312
+ console.log(`${LOG_PREFIX} 🔇 Silent sign-in check timed out`);
12313
+ resolve(null);
12314
+ }, 5000);
12315
+ // Store original callback to restore later
12316
+ const originalCallback = window.smartlinksNativeCallback;
12317
+ window.smartlinksNativeCallback = (result) => {
12318
+ if (result.callbackId === callbackId) {
12319
+ clearTimeout(timeout);
12320
+ console.log(`${LOG_PREFIX} 🔇 Silent sign-in check result:`, {
12321
+ success: result.success,
12322
+ isSignedIn: result.isSignedIn,
12323
+ hasIdToken: !!result.idToken,
12324
+ email: result.email,
12325
+ });
12326
+ // Restore original callback
12327
+ window.smartlinksNativeCallback = originalCallback;
12328
+ if (result.success) {
12329
+ resolve({
12330
+ isSignedIn: result.isSignedIn || false,
12331
+ idToken: result.idToken,
12332
+ email: result.email,
12333
+ name: result.name,
12334
+ picture: result.picture,
12335
+ });
12336
+ }
12337
+ else {
12338
+ resolve(null);
12339
+ }
12340
+ }
12341
+ else if (originalCallback) {
12342
+ // Pass through to original callback for other messages
12343
+ originalCallback(result);
12344
+ }
12345
+ };
12346
+ const payload = JSON.stringify({
12347
+ type: 'GOOGLE_CHECK_SIGN_IN',
12348
+ clientId,
12349
+ googleClientId,
12350
+ serverClientId: googleClientId, // Alias for Android SDK
12351
+ callbackId,
12352
+ });
12353
+ console.log(`${LOG_PREFIX} 🔇 Calling nativeBridge.checkGoogleSignIn with payload:`, payload);
12354
+ checkMethod(payload);
12355
+ });
12356
+ };
12240
12357
  // Helper to convert generic SDK errors to user-friendly messages
12241
12358
  const getFriendlyErrorMessage = (errorMessage) => {
12242
12359
  // Check for common HTTP status codes in the error message
@@ -12264,7 +12381,7 @@ const getFriendlyErrorMessage = (errorMessage) => {
12264
12381
  // Return original message if no pattern matches
12265
12382
  return errorMessage;
12266
12383
  };
12267
- const SmartlinksAuthUI = ({ apiEndpoint, clientId, clientName, accountData, onAuthSuccess, onAuthError, enabledProviders = ['email', 'google', 'phone'], initialMode = 'login', redirectUrl, theme = 'auto', className, customization, skipConfigFetch = false, minimal = false, logger, proxyMode = false, collectionId, disableConfigCache = false, }) => {
12384
+ const SmartlinksAuthUI = ({ apiEndpoint, clientId, clientName, accountData, onAuthSuccess, onAuthError, enabledProviders = ['email', 'google', 'phone'], initialMode = 'login', redirectUrl, theme = 'auto', className, customization, skipConfigFetch = false, minimal = false, logger, proxyMode = false, collectionId, disableConfigCache = false, enableSilentGoogleSignIn = false, }) => {
12268
12385
  const [mode, setMode] = useState(initialMode);
12269
12386
  const [loading, setLoading] = useState(false);
12270
12387
  const [error, setError] = useState();
@@ -12282,6 +12399,7 @@ const SmartlinksAuthUI = ({ apiEndpoint, clientId, clientName, accountData, onAu
12282
12399
  const [showEmailForm, setShowEmailForm] = useState(false); // Track if email form should be shown when emailDisplayMode is 'button'
12283
12400
  const [sdkReady, setSdkReady] = useState(false); // Track SDK initialization state
12284
12401
  const [contactSchema, setContactSchema] = useState(null); // Schema for registration fields
12402
+ const [silentSignInChecked, setSilentSignInChecked] = useState(false); // Track if silent sign-in has been checked
12285
12403
  const log = useMemo(() => createLoggerWrapper(logger), [logger]);
12286
12404
  const api = new AuthAPI(apiEndpoint, clientId, clientName, logger);
12287
12405
  const auth = useAuth();
@@ -12301,7 +12419,7 @@ const SmartlinksAuthUI = ({ apiEndpoint, clientId, clientName, accountData, onAu
12301
12419
  // Reinitialize Smartlinks SDK when apiEndpoint or proxyMode changes
12302
12420
  // IMPORTANT: Preserve bearer token during reinitialization
12303
12421
  useEffect(() => {
12304
- console.log('[SmartlinksAuthUI] 🔧 SDK INIT useEffect triggered', {
12422
+ console.log(`${LOG_PREFIX} 🔧 SDK INIT useEffect triggered`, {
12305
12423
  apiEndpoint,
12306
12424
  proxyMode,
12307
12425
  hasLogger: !!logger,
@@ -12311,7 +12429,7 @@ const SmartlinksAuthUI = ({ apiEndpoint, clientId, clientName, accountData, onAu
12311
12429
  setSdkReady(false); // Mark SDK as not ready during reinitialization
12312
12430
  const reinitializeWithToken = async () => {
12313
12431
  if (apiEndpoint) {
12314
- console.log('[SmartlinksAuthUI] 🔧 Reinitializing SDK with:', {
12432
+ console.log(`${LOG_PREFIX} 🔧 Reinitializing SDK with:`, {
12315
12433
  baseURL: apiEndpoint,
12316
12434
  proxyMode: proxyMode,
12317
12435
  ngrokSkipBrowserWarning: true
@@ -12325,7 +12443,7 @@ const SmartlinksAuthUI = ({ apiEndpoint, clientId, clientName, accountData, onAu
12325
12443
  ngrokSkipBrowserWarning: true,
12326
12444
  logger: logger, // Pass logger to SDK for verbose SDK logging
12327
12445
  });
12328
- console.log('[SmartlinksAuthUI] ✅ SDK reinitialized, proxyMode:', proxyMode);
12446
+ console.log(`${LOG_PREFIX} ✅ SDK reinitialized, proxyMode:`, proxyMode);
12329
12447
  log.log('SDK reinitialized successfully');
12330
12448
  // Restore bearer token after reinitialization using auth.verifyToken (standalone mode only)
12331
12449
  if (currentToken && !proxyMode) {
@@ -12334,17 +12452,17 @@ const SmartlinksAuthUI = ({ apiEndpoint, clientId, clientName, accountData, onAu
12334
12452
  });
12335
12453
  }
12336
12454
  // Mark SDK as ready
12337
- console.log('[SmartlinksAuthUI] ✅ Setting sdkReady=true (with apiEndpoint)');
12455
+ console.log(`${LOG_PREFIX} ✅ Setting sdkReady=true (with apiEndpoint)`);
12338
12456
  setSdkReady(true);
12339
12457
  }
12340
12458
  else if (proxyMode) {
12341
12459
  // In proxy mode without custom endpoint, SDK should already be initialized by parent
12342
- console.log('[SmartlinksAuthUI] ⚠️ Proxy mode WITHOUT apiEndpoint - expecting SDK already initialized by parent');
12460
+ console.log(`${LOG_PREFIX} ⚠️ Proxy mode WITHOUT apiEndpoint - expecting SDK already initialized by parent`);
12343
12461
  log.log('Proxy mode without apiEndpoint, SDK already initialized by parent');
12344
12462
  setSdkReady(true);
12345
12463
  }
12346
12464
  else {
12347
- console.log('[SmartlinksAuthUI] ℹ️ No apiEndpoint, no proxyMode - SDK already initialized by App');
12465
+ console.log(`${LOG_PREFIX} ℹ️ No apiEndpoint, no proxyMode - SDK already initialized by App`);
12348
12466
  log.log('No apiEndpoint, SDK already initialized by App');
12349
12467
  // SDK was initialized by App component, mark as ready
12350
12468
  setSdkReady(true);
@@ -12363,7 +12481,7 @@ const SmartlinksAuthUI = ({ apiEndpoint, clientId, clientName, accountData, onAu
12363
12481
  };
12364
12482
  // Fetch UI configuration
12365
12483
  useEffect(() => {
12366
- console.log('[SmartlinksAuthUI] 📋 CONFIG FETCH useEffect triggered', {
12484
+ console.log(`${LOG_PREFIX} 📋 CONFIG FETCH useEffect triggered`, {
12367
12485
  skipConfigFetch,
12368
12486
  clientId,
12369
12487
  apiEndpoint,
@@ -12381,12 +12499,12 @@ const SmartlinksAuthUI = ({ apiEndpoint, clientId, clientName, accountData, onAu
12381
12499
  });
12382
12500
  // Wait for SDK to be ready before fetching config
12383
12501
  if (!sdkReady) {
12384
- console.log('[SmartlinksAuthUI] ⏳ SDK not ready yet, waiting before config fetch...');
12502
+ console.log(`${LOG_PREFIX} ⏳ SDK not ready yet, waiting before config fetch...`);
12385
12503
  log.log('SDK not ready yet, waiting...');
12386
12504
  return;
12387
12505
  }
12388
12506
  if (skipConfigFetch) {
12389
- console.log('[SmartlinksAuthUI] ⏭️ Skipping config fetch - skipConfigFetch is true');
12507
+ console.log(`${LOG_PREFIX} ⏭️ Skipping config fetch - skipConfigFetch is true`);
12390
12508
  log.log('Skipping config fetch - skipConfigFetch is true');
12391
12509
  setConfig(customization || {});
12392
12510
  return;
@@ -12394,7 +12512,7 @@ const SmartlinksAuthUI = ({ apiEndpoint, clientId, clientName, accountData, onAu
12394
12512
  const fetchConfig = async () => {
12395
12513
  // If no clientId provided, use default config immediately without API call
12396
12514
  if (!clientId) {
12397
- console.log('[SmartlinksAuthUI] ⚠️ No clientId provided, using default config');
12515
+ console.log(`${LOG_PREFIX} ⚠️ No clientId provided, using default config`);
12398
12516
  log.log('No clientId provided, using default config');
12399
12517
  const defaultConfig = {
12400
12518
  ...DEFAULT_AUTH_CONFIG,
@@ -12414,13 +12532,13 @@ const SmartlinksAuthUI = ({ apiEndpoint, clientId, clientName, accountData, onAu
12414
12532
  const age = Date.now() - timestamp;
12415
12533
  // Use cache if less than 1 hour old
12416
12534
  if (age < 3600000) {
12417
- console.log('[SmartlinksAuthUI] 📦 Using cached config (age:', Math.round(age / 1000), 'seconds)');
12535
+ console.log(`${LOG_PREFIX} 📦 Using cached config (age:`, Math.round(age / 1000), 'seconds)');
12418
12536
  setConfig({ ...cachedConfig, ...customization });
12419
12537
  setConfigLoading(false);
12420
12538
  // Fetch in background to update cache
12421
- console.log('[SmartlinksAuthUI] 🔄 Background refresh of config via SDK...');
12539
+ console.log(`${LOG_PREFIX} 🔄 Background refresh of config via SDK...`);
12422
12540
  api.fetchConfig().then(freshConfig => {
12423
- console.log('[SmartlinksAuthUI] ✅ Background config refresh complete');
12541
+ console.log(`${LOG_PREFIX} ✅ Background config refresh complete`);
12424
12542
  localStorage.setItem(cacheKey, JSON.stringify({
12425
12543
  config: freshConfig,
12426
12544
  timestamp: Date.now()
@@ -12428,20 +12546,20 @@ const SmartlinksAuthUI = ({ apiEndpoint, clientId, clientName, accountData, onAu
12428
12546
  // Update config if it changed
12429
12547
  setConfig({ ...freshConfig, ...customization });
12430
12548
  }).catch(err => {
12431
- console.log('[SmartlinksAuthUI] ❌ Background config refresh failed:', err);
12549
+ console.log(`${LOG_PREFIX} ❌ Background config refresh failed:`, err);
12432
12550
  });
12433
12551
  return;
12434
12552
  }
12435
12553
  }
12436
12554
  }
12437
12555
  else {
12438
- console.log('[SmartlinksAuthUI] ⚠️ Config caching disabled, fetching fresh config');
12556
+ console.log(`${LOG_PREFIX} ⚠️ Config caching disabled, fetching fresh config`);
12439
12557
  }
12440
12558
  // Fetch from API
12441
- console.log('[SmartlinksAuthUI] 🌐 Fetching config via SDK for clientId:', clientId, 'proxyMode:', proxyMode);
12559
+ console.log(`${LOG_PREFIX} 🌐 Fetching config via SDK for clientId:`, clientId, 'proxyMode:', proxyMode);
12442
12560
  log.log('Fetching config from API for clientId:', clientId);
12443
12561
  const fetchedConfig = await api.fetchConfig();
12444
- console.log('[SmartlinksAuthUI] ✅ Config fetched successfully:', fetchedConfig);
12562
+ console.log(`${LOG_PREFIX} ✅ Config fetched successfully:`, fetchedConfig);
12445
12563
  log.log('Received config:', fetchedConfig);
12446
12564
  // Merge with customization props (props take precedence)
12447
12565
  const mergedConfig = { ...fetchedConfig, ...customization };
@@ -12455,7 +12573,7 @@ const SmartlinksAuthUI = ({ apiEndpoint, clientId, clientName, accountData, onAu
12455
12573
  }
12456
12574
  }
12457
12575
  catch (err) {
12458
- console.log('[SmartlinksAuthUI] ❌ Config fetch failed:', err);
12576
+ console.log(`${LOG_PREFIX} ❌ Config fetch failed:`, err);
12459
12577
  log.error('Failed to fetch config:', err);
12460
12578
  setConfig(customization || {});
12461
12579
  }
@@ -12471,18 +12589,62 @@ const SmartlinksAuthUI = ({ apiEndpoint, clientId, clientName, accountData, onAu
12471
12589
  return;
12472
12590
  const fetchSchema = async () => {
12473
12591
  try {
12474
- console.log('[SmartlinksAuthUI] 📋 Fetching contact schema for collection:', collectionId);
12592
+ console.log(`${LOG_PREFIX} 📋 Fetching contact schema for collection:`, collectionId);
12475
12593
  const schema = await smartlinks.contact.publicGetSchema(collectionId);
12476
- console.log('[SmartlinksAuthUI] ✅ Schema loaded:', schema);
12594
+ console.log(`${LOG_PREFIX} ✅ Schema loaded:`, schema);
12477
12595
  setContactSchema(schema);
12478
12596
  }
12479
12597
  catch (err) {
12480
- console.warn('[SmartlinksAuthUI] ⚠️ Failed to fetch schema (non-fatal):', err);
12598
+ console.warn(`${LOG_PREFIX} ⚠️ Failed to fetch schema (non-fatal):`, err);
12481
12599
  // Non-fatal - registration will work without schema fields
12482
12600
  }
12483
12601
  };
12484
12602
  fetchSchema();
12485
12603
  }, [collectionId, sdkReady]);
12604
+ // Silent Google Sign-In check on mount (for native Android apps)
12605
+ // When enabled, checks if user is already signed in via Google on the native side
12606
+ useEffect(() => {
12607
+ if (!enableSilentGoogleSignIn || silentSignInChecked || !sdkReady || auth.isAuthenticated) {
12608
+ return;
12609
+ }
12610
+ const googleClientId = config?.googleClientId || DEFAULT_GOOGLE_CLIENT_ID;
12611
+ const performSilentSignIn = async () => {
12612
+ console.log(`${LOG_PREFIX} 🔇 Silent Google Sign-In check enabled, checking native session...`);
12613
+ try {
12614
+ const result = await checkSilentGoogleSignIn(clientId, googleClientId);
12615
+ setSilentSignInChecked(true);
12616
+ if (result?.isSignedIn && result.idToken) {
12617
+ console.log(`${LOG_PREFIX} 🔇 Silent sign-in found existing Google session, authenticating...`);
12618
+ setLoading(true);
12619
+ try {
12620
+ const authResponse = await api.loginWithGoogle(result.idToken);
12621
+ if (authResponse.token) {
12622
+ console.log(`${LOG_PREFIX} 🔇 Silent sign-in successful!`);
12623
+ auth.login(authResponse.token, authResponse.user, authResponse.accountData, false, getExpirationFromResponse(authResponse));
12624
+ setAuthSuccess(true);
12625
+ setSuccessMessage('Signed in automatically with Google!');
12626
+ onAuthSuccess(authResponse.token, authResponse.user, authResponse.accountData);
12627
+ }
12628
+ }
12629
+ catch (err) {
12630
+ console.warn(`${LOG_PREFIX} 🔇 Silent sign-in backend auth failed:`, err);
12631
+ // Don't show error - user can still log in manually
12632
+ }
12633
+ finally {
12634
+ setLoading(false);
12635
+ }
12636
+ }
12637
+ else {
12638
+ console.log(`${LOG_PREFIX} 🔇 No existing Google session found`);
12639
+ }
12640
+ }
12641
+ catch (err) {
12642
+ console.warn(`${LOG_PREFIX} 🔇 Silent sign-in check failed:`, err);
12643
+ setSilentSignInChecked(true);
12644
+ }
12645
+ };
12646
+ performSilentSignIn();
12647
+ }, [enableSilentGoogleSignIn, silentSignInChecked, sdkReady, auth.isAuthenticated, clientId, config?.googleClientId, api, auth, onAuthSuccess]);
12486
12648
  // Reset showEmailForm when mode changes away from login/register
12487
12649
  useEffect(() => {
12488
12650
  if (mode !== 'login' && mode !== 'register') {
@@ -12814,19 +12976,19 @@ const SmartlinksAuthUI = ({ apiEndpoint, clientId, clientName, accountData, onAu
12814
12976
  }
12815
12977
  };
12816
12978
  const handleGoogleLogin = async () => {
12817
- console.log('[SmartlinksAuthUI] 🚀 handleGoogleLogin called');
12979
+ console.log(`${LOG_PREFIX} 🚀 handleGoogleLogin called`);
12818
12980
  // Use custom client ID from config, or fall back to default Smartlinks client ID
12819
12981
  const googleClientId = config?.googleClientId || DEFAULT_GOOGLE_CLIENT_ID;
12820
12982
  // Determine OAuth flow: default to 'oneTap' for better UX, but allow 'popup' for iframe compatibility
12821
12983
  const configuredFlow = config?.googleOAuthFlow || 'oneTap';
12822
12984
  // Check for native bridge and WebView environment
12823
- console.log('[SmartlinksAuthUI] 🔍 Checking environment...');
12985
+ console.log(`${LOG_PREFIX} 🔍 Checking environment...`);
12824
12986
  const isWebView = detectWebView();
12825
12987
  const nativeBridge = getNativeBridge();
12826
12988
  // For oneTap, automatically use redirect flow in WebView environments (if no native bridge)
12827
12989
  const oauthFlow = (configuredFlow === 'oneTap' && isWebView && !nativeBridge) ? 'redirect' : configuredFlow;
12828
12990
  // Log Google Auth configuration for debugging
12829
- console.log('[SmartlinksAuthUI] 📋 Google Auth configuration:', {
12991
+ console.log(`${LOG_PREFIX} 📋 Google Auth configuration:`, {
12830
12992
  googleClientId,
12831
12993
  configuredFlow,
12832
12994
  effectiveFlow: oauthFlow,
@@ -12853,14 +13015,14 @@ const SmartlinksAuthUI = ({ apiEndpoint, clientId, clientName, accountData, onAu
12853
13015
  try {
12854
13016
  // Priority 1: Use native bridge if available (for WebView environments)
12855
13017
  if (nativeBridge) {
12856
- console.log('[SmartlinksAuthUI] 🌉 NATIVE BRIDGE PATH - Using native bridge for Google Sign-In');
13018
+ console.log(`${LOG_PREFIX} 🌉 NATIVE BRIDGE PATH - Using native bridge for Google Sign-In`);
12857
13019
  log.log('Using native bridge for Google Sign-In');
12858
13020
  const callbackId = `google_auth_${Date.now()}`;
12859
- console.log('[SmartlinksAuthUI] 🔑 Generated callbackId:', callbackId);
13021
+ console.log(`${LOG_PREFIX} 🔑 Generated callbackId:`, callbackId);
12860
13022
  // Set up callback for native response
12861
- console.log('[SmartlinksAuthUI] 📡 Registering window.smartlinksNativeCallback...');
13023
+ console.log(`${LOG_PREFIX} 📡 Registering window.smartlinksNativeCallback...`);
12862
13024
  window.smartlinksNativeCallback = async (result) => {
12863
- console.log('[SmartlinksAuthUI] 📨 smartlinksNativeCallback INVOKED with:', {
13025
+ console.log(`${LOG_PREFIX} 📨 smartlinksNativeCallback INVOKED with:`, {
12864
13026
  callbackId: result.callbackId,
12865
13027
  success: result.success,
12866
13028
  hasIdToken: !!result.idToken,
@@ -12872,11 +13034,11 @@ const SmartlinksAuthUI = ({ apiEndpoint, clientId, clientName, accountData, onAu
12872
13034
  });
12873
13035
  // Ignore stale callbacks
12874
13036
  if (result.callbackId !== callbackId) {
12875
- console.log('[SmartlinksAuthUI] ⚠️ Ignoring stale callback. Expected:', callbackId, 'Got:', result.callbackId);
13037
+ console.log(`${LOG_PREFIX} ⚠️ Ignoring stale callback. Expected:`, callbackId, 'Got:', result.callbackId);
12876
13038
  log.log('Ignoring stale native callback:', result.callbackId);
12877
13039
  return;
12878
13040
  }
12879
- console.log('[SmartlinksAuthUI] ✅ Callback ID matches, processing result...');
13041
+ console.log(`${LOG_PREFIX} ✅ Callback ID matches, processing result...`);
12880
13042
  log.log('Native callback received:', {
12881
13043
  success: result.success,
12882
13044
  hasIdToken: !!result.idToken,
@@ -12886,70 +13048,79 @@ const SmartlinksAuthUI = ({ apiEndpoint, clientId, clientName, accountData, onAu
12886
13048
  });
12887
13049
  try {
12888
13050
  if (result.success && result.idToken) {
12889
- console.log('[SmartlinksAuthUI] 🔐 Success! Calling api.loginWithGoogle with idToken...');
13051
+ console.log(`${LOG_PREFIX} 🔐 Success! Calling api.loginWithGoogle with idToken...`);
12890
13052
  // Process through existing Google auth flow
12891
13053
  const authResponse = await api.loginWithGoogle(result.idToken);
12892
- console.log('[SmartlinksAuthUI] 📦 api.loginWithGoogle response:', {
13054
+ console.log(`${LOG_PREFIX} 📦 api.loginWithGoogle response:`, {
12893
13055
  hasToken: !!authResponse.token,
12894
13056
  hasUser: !!authResponse.user,
12895
13057
  isNewUser: authResponse.isNewUser,
12896
13058
  });
12897
13059
  if (authResponse.token) {
12898
- console.log('[SmartlinksAuthUI] 🎉 Login successful! Calling auth.login and onAuthSuccess...');
13060
+ console.log(`${LOG_PREFIX} 🎉 Login successful! Calling auth.login and onAuthSuccess...`);
12899
13061
  auth.login(authResponse.token, authResponse.user, authResponse.accountData, authResponse.isNewUser, getExpirationFromResponse(authResponse));
12900
13062
  setAuthSuccess(true);
12901
13063
  setSuccessMessage('Google login successful!');
12902
13064
  onAuthSuccess(authResponse.token, authResponse.user, authResponse.accountData);
12903
13065
  }
12904
13066
  else {
12905
- console.log('[SmartlinksAuthUI] ❌ No token in authResponse');
13067
+ console.log(`${LOG_PREFIX} ❌ No token in authResponse`);
12906
13068
  throw new Error('Authentication failed - no token received');
12907
13069
  }
12908
13070
  }
12909
13071
  else {
12910
13072
  // Handle error from native
12911
- console.log('[SmartlinksAuthUI] ❌ Native returned error:', result.error, result.errorCode);
13073
+ console.log(`${LOG_PREFIX} ❌ Native returned error:`, result.error, result.errorCode);
12912
13074
  const errorMessage = result.error || 'Google Sign-In failed';
12913
13075
  setError(errorMessage);
12914
13076
  onAuthError?.(new Error(errorMessage));
12915
13077
  }
12916
13078
  }
12917
13079
  catch (err) {
12918
- console.log('[SmartlinksAuthUI] 💥 Exception in callback handler:', err);
13080
+ console.log(`${LOG_PREFIX} 💥 Exception in callback handler:`, err);
12919
13081
  const errorMessage = err instanceof Error ? err.message : 'Google login failed';
12920
13082
  setError(errorMessage);
12921
13083
  onAuthError?.(err instanceof Error ? err : new Error(errorMessage));
12922
13084
  }
12923
13085
  finally {
12924
- console.log('[SmartlinksAuthUI] 🏁 Callback processing complete, setting loading=false');
13086
+ console.log(`${LOG_PREFIX} 🏁 Callback processing complete, setting loading=false`);
12925
13087
  setLoading(false);
12926
13088
  }
12927
13089
  };
12928
- console.log('[SmartlinksAuthUI] ✅ window.smartlinksNativeCallback registered');
13090
+ console.log(`${LOG_PREFIX} ✅ window.smartlinksNativeCallback registered`);
12929
13091
  // Invoke native sign-in
12930
- const payload = JSON.stringify({
13092
+ // Pass comprehensive payload for Android to configure Google Sign-In correctly
13093
+ const payloadObj = {
12931
13094
  type: 'GOOGLE_SIGN_IN',
12932
- clientId,
12933
- googleClientId,
13095
+ clientId, // Smartlinks Auth Kit client ID
13096
+ googleClientId, // Web/Server Client ID - use this for requestIdToken()
13097
+ serverClientId: googleClientId, // Explicit alias - Android should use this for GoogleSignInOptions.requestIdToken()
12934
13098
  callbackId,
12935
- });
12936
- console.log('[SmartlinksAuthUI] 📤 Calling nativeBridge.signInWithGoogle with payload:', payload);
12937
- log.log('Invoking native signInWithGoogle with payload:', payload);
13099
+ // Additional context that might help Android configuration
13100
+ scopes: ['email', 'profile'], // Requested OAuth scopes
13101
+ requestIdToken: true, // We need an ID token for backend verification
13102
+ requestServerAuthCode: false, // We don't need server auth code
13103
+ };
13104
+ const payload = JSON.stringify(payloadObj);
13105
+ console.log(`${LOG_PREFIX} 📤 Calling nativeBridge.signInWithGoogle with payload object:`, payloadObj);
13106
+ console.log(`${LOG_PREFIX} 📤 Payload JSON string:`, payload);
13107
+ log.log('Invoking native signInWithGoogle with payload:', payloadObj);
12938
13108
  nativeBridge.signInWithGoogle(payload);
12939
- console.log('[SmartlinksAuthUI] ✅ nativeBridge.signInWithGoogle called successfully');
12940
- console.log('[SmartlinksAuthUI] ⏳ Waiting for native callback...');
13109
+ console.log(`${LOG_PREFIX} ✅ nativeBridge.signInWithGoogle called successfully`);
13110
+ console.log(`${LOG_PREFIX} ⏳ Waiting for native callback...`);
13111
+ console.log(`${LOG_PREFIX} 💡 Android should use serverClientId for GoogleSignInOptions.Builder().requestIdToken(serverClientId)`);
12941
13112
  // Don't set loading to false - waiting for native callback
12942
13113
  return;
12943
13114
  }
12944
13115
  // Priority 2: If WebView but no native bridge, show helpful error
12945
13116
  if (isWebView) {
12946
- console.log('[SmartlinksAuthUI] ⚠️ WebView detected but NO native bridge - showing error');
13117
+ console.log(`${LOG_PREFIX} ⚠️ WebView detected but NO native bridge - showing error`);
12947
13118
  log.log('WebView detected but no native bridge available');
12948
13119
  setError('Google Sign-In is not available in this app. Please use email or phone login instead.');
12949
13120
  setLoading(false);
12950
13121
  return;
12951
13122
  }
12952
- console.log('[SmartlinksAuthUI] 🌐 WEB PATH - Using web-based OAuth flow:', oauthFlow);
13123
+ console.log(`${LOG_PREFIX} 🌐 WEB PATH - Using web-based OAuth flow:`, oauthFlow);
12953
13124
  // Priority 3: Web-based flows (redirect, popup, oneTap)
12954
13125
  // Dynamically load Google Identity Services if not already loaded
12955
13126
  await loadGoogleIdentityServices();
@@ -13326,6 +13497,12 @@ const SmartlinksAuthUI = ({ apiEndpoint, clientId, clientName, accountData, onAu
13326
13497
  })() })) })) : null }));
13327
13498
  };
13328
13499
 
13500
+ var SmartlinksAuthUI$1 = /*#__PURE__*/Object.freeze({
13501
+ __proto__: null,
13502
+ SmartlinksAuthUI: SmartlinksAuthUI,
13503
+ signOutGoogleNative: signOutGoogleNative
13504
+ });
13505
+
13329
13506
  const AccountManagement = ({ apiEndpoint, clientId, collectionId, onError, className = '', customization = {}, }) => {
13330
13507
  const auth = useAuth();
13331
13508
  const [loading, setLoading] = useState(false);