@proveanything/smartlinks-auth-ui 0.5.5 → 0.5.7
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 +7 -1
- package/dist/api.d.ts.map +1 -1
- package/dist/components/AccountManagement.d.ts.map +1 -1
- package/dist/components/SmartlinksAuthUI.d.ts.map +1 -1
- package/dist/index.esm.js +78 -37
- package/dist/index.esm.js.map +1 -1
- package/dist/index.js +78 -37
- package/dist/index.js.map +1 -1
- package/package.json +5 -5
package/dist/index.js
CHANGED
|
@@ -11513,15 +11513,18 @@ class AuthAPI {
|
|
|
11513
11513
|
return smartlinks__namespace.authKit.verifyMagicLink(this.clientId, token);
|
|
11514
11514
|
}
|
|
11515
11515
|
// ============= WhatsApp =============
|
|
11516
|
-
async sendWhatsApp(redirectUrl, phoneNumber, reply, prefillMessage) {
|
|
11516
|
+
async sendWhatsApp(redirectUrl, phoneNumber, reply, prefillMessage, contactData) {
|
|
11517
11517
|
// phoneNumber is optional — backend extracts it from the inbound WhatsApp webhook.
|
|
11518
11518
|
// `reply`, when provided, is sent back to the user via WhatsApp on successful verification.
|
|
11519
11519
|
// `prefillMessage` customizes the message body pre-filled in the wa.me link.
|
|
11520
|
+
// `contactData` is upserted onto the contact when the backend creates/links it,
|
|
11521
|
+
// so the returned session.user is fully formed (name, email, custom fields, etc.).
|
|
11520
11522
|
return smartlinks__namespace.authKit.sendWhatsApp(this.clientId, {
|
|
11521
11523
|
phoneNumber: phoneNumber ?? '',
|
|
11522
11524
|
redirectUrl,
|
|
11523
11525
|
...(reply ? { reply } : {}),
|
|
11524
11526
|
...(prefillMessage ? { prefillMessage } : {}),
|
|
11527
|
+
...(contactData ? { contactData } : {}),
|
|
11525
11528
|
});
|
|
11526
11529
|
}
|
|
11527
11530
|
async exchangeWhatsAppSession(token, sessionKey) {
|
|
@@ -14291,8 +14294,17 @@ const SmartlinksAuthUI = ({ apiEndpoint, clientId, clientName, accountData, onAu
|
|
|
14291
14294
|
});
|
|
14292
14295
|
// Resolve outbound prefill message: per-call prop wins, then AuthKit default.
|
|
14293
14296
|
const prefillMessage = whatsappPrefillMessage ?? config?.whatsappPrefillMessage;
|
|
14294
|
-
|
|
14295
|
-
|
|
14297
|
+
// Pass collected signup details as contactData so the backend creates the
|
|
14298
|
+
// contact with name/customFields already attached and returns a fully
|
|
14299
|
+
// formed session.user — no follow-up updateProfile call needed.
|
|
14300
|
+
const trimmedName = displayName?.trim() || undefined;
|
|
14301
|
+
const contactData = trimmedName ? { name: trimmedName } : undefined;
|
|
14302
|
+
const result = await api.sendWhatsApp(getRedirectUrl(), undefined, reply, prefillMessage, contactData);
|
|
14303
|
+
whatsappSendRef.current = {
|
|
14304
|
+
token: result.token,
|
|
14305
|
+
sessionKey: result.sessionKey,
|
|
14306
|
+
displayName: trimmedName,
|
|
14307
|
+
};
|
|
14296
14308
|
return result;
|
|
14297
14309
|
}
|
|
14298
14310
|
catch (err) {
|
|
@@ -14311,9 +14323,9 @@ const SmartlinksAuthUI = ({ apiEndpoint, clientId, clientName, accountData, onAu
|
|
|
14311
14323
|
const target = status.redirectUrl || getRedirectUrl();
|
|
14312
14324
|
setAuthSuccess(true);
|
|
14313
14325
|
setSuccessMessage('WhatsApp verified! Signing you in…');
|
|
14314
|
-
// Exchange the verified WhatsApp proof for a real Auth Kit session token
|
|
14315
|
-
//
|
|
14316
|
-
//
|
|
14326
|
+
// Exchange the verified WhatsApp proof for a real Auth Kit session token.
|
|
14327
|
+
// The backend has already created/updated the contact using contactData
|
|
14328
|
+
// sent at sendWhatsApp time, so session.user is fully formed.
|
|
14317
14329
|
const send = whatsappSendRef.current;
|
|
14318
14330
|
if (send?.sessionKey) {
|
|
14319
14331
|
try {
|
|
@@ -14365,7 +14377,7 @@ const SmartlinksAuthUI = ({ apiEndpoint, clientId, clientName, accountData, onAu
|
|
|
14365
14377
|
? 'hsl(var(--muted-foreground, 215 15% 45%))'
|
|
14366
14378
|
: (resolvedTheme === 'dark' ? '#94a3b8' : '#6B7280'),
|
|
14367
14379
|
fontSize: '0.875rem'
|
|
14368
|
-
}, children: successMessage })] })) : mode === 'magic-link' ? (jsxRuntime.jsx(MagicLinkForm, { onSubmit: handleMagicLink, onCancel: () => setMode('login'), loading: loading, error: error, collectName: config?.collectNameOnPasswordlessSignup })) : mode === 'whatsapp' ? (jsxRuntime.jsx(WhatsAppAuthForm, { onSend: handleWhatsAppSend, onPollStatus: handleWhatsAppPoll, onVerified: handleWhatsAppVerified, onBack: () => setMode('login'), loading: loading, error: error, collectName: config?.collectNameOnPasswordlessSignup })) : mode === 'phone' ? (jsxRuntime.jsx(PhoneAuthForm, { onSubmit: handlePhoneAuth, onBack: () => setMode('login'), loading: loading, error: error, collectName: config?.collectNameOnPasswordlessSignup })) : mode === 'reset-password' ? (jsxRuntime.jsx(PasswordResetForm, { onSubmit: handlePasswordReset, onBack: () => {
|
|
14380
|
+
}, children: successMessage })] })) : mode === 'magic-link' ? (jsxRuntime.jsx(MagicLinkForm, { onSubmit: handleMagicLink, onCancel: () => setMode('login'), loading: loading, error: error, collectName: config?.collectNameOnPasswordlessSignup })) : mode === 'whatsapp' ? (jsxRuntime.jsx(WhatsAppAuthForm, { onSend: handleWhatsAppSend, onPollStatus: handleWhatsAppPoll, onVerified: handleWhatsAppVerified, onBack: () => setMode('login'), loading: loading, error: error, collectName: config?.collectNameOnPasswordlessSignup ?? true })) : mode === 'phone' ? (jsxRuntime.jsx(PhoneAuthForm, { onSubmit: handlePhoneAuth, onBack: () => setMode('login'), loading: loading, error: error, collectName: config?.collectNameOnPasswordlessSignup })) : mode === 'reset-password' ? (jsxRuntime.jsx(PasswordResetForm, { onSubmit: handlePasswordReset, onBack: () => {
|
|
14369
14381
|
setMode('login');
|
|
14370
14382
|
setResetSuccess(false);
|
|
14371
14383
|
setResetToken(undefined); // Clear token when going back
|
|
@@ -14656,6 +14668,32 @@ const AccountManagement = ({ apiEndpoint, clientId, collectionId, onError, class
|
|
|
14656
14668
|
const [profile, setProfile] = React.useState(null);
|
|
14657
14669
|
const [error, setError] = React.useState();
|
|
14658
14670
|
const [success, setSuccess] = React.useState();
|
|
14671
|
+
const [resolvedClientId, setResolvedClientId] = React.useState(clientId);
|
|
14672
|
+
// Keep prop in sync
|
|
14673
|
+
React.useEffect(() => {
|
|
14674
|
+
if (clientId)
|
|
14675
|
+
setResolvedClientId(clientId);
|
|
14676
|
+
}, [clientId]);
|
|
14677
|
+
// If no clientId was provided, try to resolve the collection's default Auth Kit.
|
|
14678
|
+
// This supports "portal mode" where the host app only knows the collectionId.
|
|
14679
|
+
React.useEffect(() => {
|
|
14680
|
+
if (clientId || !collectionId)
|
|
14681
|
+
return;
|
|
14682
|
+
let cancelled = false;
|
|
14683
|
+
(async () => {
|
|
14684
|
+
try {
|
|
14685
|
+
const collection = await smartlinks__namespace.collection.get(collectionId);
|
|
14686
|
+
const defaultId = collection?.defaultAuthKitId;
|
|
14687
|
+
if (!cancelled && defaultId)
|
|
14688
|
+
setResolvedClientId(defaultId);
|
|
14689
|
+
}
|
|
14690
|
+
catch {
|
|
14691
|
+
// Non-fatal — handlers will surface a friendly error if still missing
|
|
14692
|
+
}
|
|
14693
|
+
})();
|
|
14694
|
+
return () => { cancelled = true; };
|
|
14695
|
+
}, [clientId, collectionId]);
|
|
14696
|
+
const NO_CLIENT_ID_MSG = 'This account section is not connected to an Auth Kit yet. Pass a clientId prop, or set a default Auth Kit on the collection in the admin console.';
|
|
14659
14697
|
// Schema state — now uses SDK type directly
|
|
14660
14698
|
const [schema, setSchema] = React.useState(null);
|
|
14661
14699
|
const [schemaLoading, setSchemaLoading] = React.useState(false);
|
|
@@ -14727,26 +14765,29 @@ const AccountManagement = ({ apiEndpoint, clientId, collectionId, onError, class
|
|
|
14727
14765
|
setLoading(true);
|
|
14728
14766
|
setError(undefined);
|
|
14729
14767
|
try {
|
|
14768
|
+
// Pull contact first so we can fall back to fields the auth user object
|
|
14769
|
+
// may not carry (e.g. WhatsApp phone numbers, displayName, email).
|
|
14770
|
+
let contactData = auth.contact;
|
|
14771
|
+
if (collectionId && !contactData) {
|
|
14772
|
+
try {
|
|
14773
|
+
contactData = (await auth.getContact?.()) || null;
|
|
14774
|
+
}
|
|
14775
|
+
catch { /* non-fatal */ }
|
|
14776
|
+
}
|
|
14777
|
+
const contactAny = contactData;
|
|
14730
14778
|
const profileData = {
|
|
14731
14779
|
uid: auth.user?.uid || '',
|
|
14732
|
-
email: auth.user?.email,
|
|
14733
|
-
displayName: auth.user?.displayName,
|
|
14734
|
-
phoneNumber: auth.user?.phoneNumber,
|
|
14780
|
+
email: auth.user?.email || contactAny?.email,
|
|
14781
|
+
displayName: auth.user?.displayName || contactAny?.displayName || contactAny?.name,
|
|
14782
|
+
phoneNumber: auth.user?.phoneNumber || contactAny?.phone || contactAny?.phoneNumber,
|
|
14735
14783
|
photoURL: auth.user?.photoURL,
|
|
14736
14784
|
emailVerified: true,
|
|
14737
14785
|
accountData: auth.accountData || {},
|
|
14738
14786
|
};
|
|
14739
14787
|
setProfile(profileData);
|
|
14740
14788
|
setDisplayName(profileData.displayName || '');
|
|
14741
|
-
|
|
14742
|
-
|
|
14743
|
-
setCustomFieldValues(auth.contact.customFields || {});
|
|
14744
|
-
}
|
|
14745
|
-
else if (collectionId) {
|
|
14746
|
-
const contact = await auth.getContact?.();
|
|
14747
|
-
if (contact?.customFields) {
|
|
14748
|
-
setCustomFieldValues(contact.customFields);
|
|
14749
|
-
}
|
|
14789
|
+
if (collectionId && contactData?.customFields) {
|
|
14790
|
+
setCustomFieldValues(contactData.customFields);
|
|
14750
14791
|
}
|
|
14751
14792
|
}
|
|
14752
14793
|
catch (err) {
|
|
@@ -14778,15 +14819,15 @@ const AccountManagement = ({ apiEndpoint, clientId, collectionId, onError, class
|
|
|
14778
14819
|
const editableCustomFields = getEditableFields(schema, customFieldValues).filter(f => !['email', 'displayName', 'phone', 'phoneNumber'].includes(f.key));
|
|
14779
14820
|
const handleUpdateProfile = async (e) => {
|
|
14780
14821
|
e.preventDefault();
|
|
14781
|
-
if (!
|
|
14782
|
-
setError(
|
|
14822
|
+
if (!resolvedClientId) {
|
|
14823
|
+
setError(NO_CLIENT_ID_MSG);
|
|
14783
14824
|
return;
|
|
14784
14825
|
}
|
|
14785
14826
|
setLoading(true);
|
|
14786
14827
|
setError(undefined);
|
|
14787
14828
|
setSuccess(undefined);
|
|
14788
14829
|
try {
|
|
14789
|
-
await smartlinks__namespace.authKit.updateProfile(
|
|
14830
|
+
await smartlinks__namespace.authKit.updateProfile(resolvedClientId, { displayName });
|
|
14790
14831
|
setSuccess('Profile updated successfully!');
|
|
14791
14832
|
setEditingSection(null);
|
|
14792
14833
|
if (profile) {
|
|
@@ -14825,8 +14866,8 @@ const AccountManagement = ({ apiEndpoint, clientId, collectionId, onError, class
|
|
|
14825
14866
|
};
|
|
14826
14867
|
const handleChangeEmail = async (e) => {
|
|
14827
14868
|
e.preventDefault();
|
|
14828
|
-
if (!
|
|
14829
|
-
setError(
|
|
14869
|
+
if (!resolvedClientId) {
|
|
14870
|
+
setError(NO_CLIENT_ID_MSG);
|
|
14830
14871
|
return;
|
|
14831
14872
|
}
|
|
14832
14873
|
setLoading(true);
|
|
@@ -14834,7 +14875,7 @@ const AccountManagement = ({ apiEndpoint, clientId, collectionId, onError, class
|
|
|
14834
14875
|
setSuccess(undefined);
|
|
14835
14876
|
try {
|
|
14836
14877
|
const redirectUrl = window.location.href;
|
|
14837
|
-
await smartlinks__namespace.authKit.changeEmail(
|
|
14878
|
+
await smartlinks__namespace.authKit.changeEmail(resolvedClientId, newEmail, emailPassword, redirectUrl);
|
|
14838
14879
|
setSuccess('Email change requested. Please check your new email for verification.');
|
|
14839
14880
|
setEditingSection(null);
|
|
14840
14881
|
setNewEmail('');
|
|
@@ -14850,8 +14891,8 @@ const AccountManagement = ({ apiEndpoint, clientId, collectionId, onError, class
|
|
|
14850
14891
|
};
|
|
14851
14892
|
const handleChangePassword = async (e) => {
|
|
14852
14893
|
e.preventDefault();
|
|
14853
|
-
if (!
|
|
14854
|
-
setError(
|
|
14894
|
+
if (!resolvedClientId) {
|
|
14895
|
+
setError(NO_CLIENT_ID_MSG);
|
|
14855
14896
|
return;
|
|
14856
14897
|
}
|
|
14857
14898
|
if (newPassword !== confirmPassword) {
|
|
@@ -14866,7 +14907,7 @@ const AccountManagement = ({ apiEndpoint, clientId, collectionId, onError, class
|
|
|
14866
14907
|
setError(undefined);
|
|
14867
14908
|
setSuccess(undefined);
|
|
14868
14909
|
try {
|
|
14869
|
-
await smartlinks__namespace.authKit.changePassword(
|
|
14910
|
+
await smartlinks__namespace.authKit.changePassword(resolvedClientId, currentPassword, newPassword);
|
|
14870
14911
|
setSuccess('Password changed successfully!');
|
|
14871
14912
|
setEditingSection(null);
|
|
14872
14913
|
setCurrentPassword('');
|
|
@@ -14882,14 +14923,14 @@ const AccountManagement = ({ apiEndpoint, clientId, collectionId, onError, class
|
|
|
14882
14923
|
}
|
|
14883
14924
|
};
|
|
14884
14925
|
const handleSendPhoneCode = async () => {
|
|
14885
|
-
if (!
|
|
14886
|
-
setError(
|
|
14926
|
+
if (!resolvedClientId) {
|
|
14927
|
+
setError(NO_CLIENT_ID_MSG);
|
|
14887
14928
|
return;
|
|
14888
14929
|
}
|
|
14889
14930
|
setLoading(true);
|
|
14890
14931
|
setError(undefined);
|
|
14891
14932
|
try {
|
|
14892
|
-
await smartlinks__namespace.authKit.sendPhoneCode(
|
|
14933
|
+
await smartlinks__namespace.authKit.sendPhoneCode(resolvedClientId, newPhone);
|
|
14893
14934
|
setPhoneCodeSent(true);
|
|
14894
14935
|
setSuccess('Verification code sent to your phone');
|
|
14895
14936
|
}
|
|
@@ -14903,15 +14944,15 @@ const AccountManagement = ({ apiEndpoint, clientId, collectionId, onError, class
|
|
|
14903
14944
|
};
|
|
14904
14945
|
const handleUpdatePhone = async (e) => {
|
|
14905
14946
|
e.preventDefault();
|
|
14906
|
-
if (!
|
|
14907
|
-
setError(
|
|
14947
|
+
if (!resolvedClientId) {
|
|
14948
|
+
setError(NO_CLIENT_ID_MSG);
|
|
14908
14949
|
return;
|
|
14909
14950
|
}
|
|
14910
14951
|
setLoading(true);
|
|
14911
14952
|
setError(undefined);
|
|
14912
14953
|
setSuccess(undefined);
|
|
14913
14954
|
try {
|
|
14914
|
-
await smartlinks__namespace.authKit.updatePhone(
|
|
14955
|
+
await smartlinks__namespace.authKit.updatePhone(resolvedClientId, newPhone, phoneCode);
|
|
14915
14956
|
setSuccess('Phone number updated successfully!');
|
|
14916
14957
|
setEditingSection(null);
|
|
14917
14958
|
setNewPhone('');
|
|
@@ -14928,8 +14969,8 @@ const AccountManagement = ({ apiEndpoint, clientId, collectionId, onError, class
|
|
|
14928
14969
|
}
|
|
14929
14970
|
};
|
|
14930
14971
|
const handleDeleteAccount = async () => {
|
|
14931
|
-
if (!
|
|
14932
|
-
setError(
|
|
14972
|
+
if (!resolvedClientId) {
|
|
14973
|
+
setError(NO_CLIENT_ID_MSG);
|
|
14933
14974
|
return;
|
|
14934
14975
|
}
|
|
14935
14976
|
if (deleteConfirmText !== 'DELETE') {
|
|
@@ -14943,7 +14984,7 @@ const AccountManagement = ({ apiEndpoint, clientId, collectionId, onError, class
|
|
|
14943
14984
|
setLoading(true);
|
|
14944
14985
|
setError(undefined);
|
|
14945
14986
|
try {
|
|
14946
|
-
await smartlinks__namespace.authKit.deleteAccount(
|
|
14987
|
+
await smartlinks__namespace.authKit.deleteAccount(resolvedClientId, deletePassword, deleteConfirmText);
|
|
14947
14988
|
setSuccess('Account deleted successfully');
|
|
14948
14989
|
await auth.logout();
|
|
14949
14990
|
}
|