mnfst 0.5.224 → 0.5.225
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.
|
@@ -70,6 +70,7 @@ async function getAppwriteConfig() {
|
|
|
70
70
|
|
|
71
71
|
const magicEnabled = authMethods.includes("magic");
|
|
72
72
|
const otpEnabled = authMethods.includes("otp");
|
|
73
|
+
const phoneEnabled = authMethods.includes("phone");
|
|
73
74
|
const oauthEnabled = authMethods.includes("oauth");
|
|
74
75
|
|
|
75
76
|
// Teams (presence of teams object enables it)
|
|
@@ -92,7 +93,7 @@ async function getAppwriteConfig() {
|
|
|
92
93
|
: toBool(appwriteConfig.auth.teams.authenticated);
|
|
93
94
|
|
|
94
95
|
// Guest upgrade: preserve the anonymous account + teams on sign-in (magic/oauth;
|
|
95
|
-
// OTP can't convert anonymous accounts). Defaults to guestTeams.
|
|
96
|
+
// email/phone OTP can't convert anonymous accounts). Defaults to guestTeams.
|
|
96
97
|
const guestUpgrade = appwriteConfig.auth?.guestUpgrade !== undefined
|
|
97
98
|
? toBool(appwriteConfig.auth.guestUpgrade)
|
|
98
99
|
: guestTeams;
|
|
@@ -135,6 +136,7 @@ async function getAppwriteConfig() {
|
|
|
135
136
|
anonymous: guestAuto, // back-compat alias
|
|
136
137
|
magic: magicEnabled,
|
|
137
138
|
otp: otpEnabled,
|
|
139
|
+
phone: phoneEnabled,
|
|
138
140
|
oauth: oauthEnabled,
|
|
139
141
|
teams: teamsEnabled,
|
|
140
142
|
permanentTeams: permanentTeams,
|
|
@@ -329,10 +331,10 @@ function initializeAuthStore() {
|
|
|
329
331
|
error: null,
|
|
330
332
|
magicLinkSent: false,
|
|
331
333
|
magicLinkExpired: false,
|
|
332
|
-
otpSent: false, //
|
|
333
|
-
otpExpired: false, //
|
|
334
|
-
otpPhrase: null, // Email OTP: security phrase to display (when enabled)
|
|
335
|
-
_otpUserId: null, //
|
|
334
|
+
otpSent: false, // OTP (email/phone): a code has been sent and is awaiting entry
|
|
335
|
+
otpExpired: false, // OTP (email/phone): the entered code was wrong/expired
|
|
336
|
+
otpPhrase: null, // Email OTP: security phrase to display (when enabled; phone has none)
|
|
337
|
+
_otpUserId: null, // OTP: userId returned by createEmailToken/createPhoneToken, used by verifyOTP
|
|
336
338
|
teams: [], // List of user's teams
|
|
337
339
|
currentTeam: null, // Currently selected/active team
|
|
338
340
|
_teamsPollInterval: null, // Interval ID for teams polling (deprecated, use realtime instead)
|
|
@@ -933,7 +935,7 @@ function initializeAuthStore() {
|
|
|
933
935
|
this.magicLinkSent = false;
|
|
934
936
|
this.magicLinkExpired = false;
|
|
935
937
|
|
|
936
|
-
// Clear
|
|
938
|
+
// Clear OTP flags (email/phone)
|
|
937
939
|
this.otpSent = false;
|
|
938
940
|
this.otpExpired = false;
|
|
939
941
|
this.otpPhrase = null;
|
|
@@ -6294,7 +6296,8 @@ window.ManifestAppwriteAuthMagicLinks = {
|
|
|
6294
6296
|
/* Auth email OTP (one-time passcode) */
|
|
6295
6297
|
|
|
6296
6298
|
// Two-step in-page flow (no redirect): createEmailOTP(email) emails a code + returns
|
|
6297
|
-
// a userId, verifyOTP(code) creates the session.
|
|
6299
|
+
// a userId, verifyOTP(code) creates the session. verifyOTP/submitOTP are shared
|
|
6300
|
+
// with phone OTP (users.phone.js).
|
|
6298
6301
|
// Gotcha: Appwrite can't convert an anonymous guest via OTP — a guest verifying an OTP
|
|
6299
6302
|
// gets a fresh account (guest teams lost). Use magic links for guest upgrade.
|
|
6300
6303
|
|
|
@@ -6364,17 +6367,20 @@ function initializeEmailOTP() {
|
|
|
6364
6367
|
this._appwrite = await config.getAppwriteClient();
|
|
6365
6368
|
}
|
|
6366
6369
|
if (!this._appwrite) {
|
|
6367
|
-
|
|
6370
|
+
this.error = 'Appwrite not configured';
|
|
6371
|
+
return { success: false, error: this.error };
|
|
6368
6372
|
}
|
|
6369
6373
|
|
|
6370
6374
|
// Don't allow OTP request if already signed in (non-anonymous)
|
|
6371
6375
|
if (this.isAuthenticated && !this.isAnonymous) {
|
|
6372
|
-
|
|
6376
|
+
this.error = 'Already signed in. Please logout first.';
|
|
6377
|
+
return { success: false, error: this.error };
|
|
6373
6378
|
}
|
|
6374
6379
|
|
|
6375
6380
|
const appwriteConfig = await config.getAppwriteConfig();
|
|
6376
6381
|
if (appwriteConfig && !appwriteConfig.otp) {
|
|
6377
|
-
|
|
6382
|
+
this.error = 'Email OTP authentication is not enabled';
|
|
6383
|
+
return { success: false, error: this.error };
|
|
6378
6384
|
}
|
|
6379
6385
|
|
|
6380
6386
|
// OTP can't convert a guest — warn so lost guest teams aren't a surprise.
|
|
@@ -6384,10 +6390,8 @@ function initializeEmailOTP() {
|
|
|
6384
6390
|
|
|
6385
6391
|
const account = this._appwrite.account;
|
|
6386
6392
|
if (typeof account.createEmailToken !== 'function') {
|
|
6387
|
-
|
|
6388
|
-
|
|
6389
|
-
error: 'Email OTP method not available. Please ensure you are using a recent Appwrite SDK.'
|
|
6390
|
-
};
|
|
6393
|
+
this.error = 'Email OTP method not available. Please ensure you are using a recent Appwrite SDK.';
|
|
6394
|
+
return { success: false, error: this.error };
|
|
6391
6395
|
}
|
|
6392
6396
|
|
|
6393
6397
|
this.inProgress = true;
|
|
@@ -6433,7 +6437,8 @@ function initializeEmailOTP() {
|
|
|
6433
6437
|
const { email, inputEl, dataObj } = resolveEmailInput(emailInputOrRef);
|
|
6434
6438
|
|
|
6435
6439
|
if (!email || !email.trim()) {
|
|
6436
|
-
|
|
6440
|
+
this.error = 'Email is required';
|
|
6441
|
+
return { success: false, error: this.error };
|
|
6437
6442
|
}
|
|
6438
6443
|
|
|
6439
6444
|
const result = await this.createEmailOTP(email.trim(), options);
|
|
@@ -6607,6 +6612,197 @@ window.ManifestAppwriteAuthEmailOTP = {
|
|
|
6607
6612
|
};
|
|
6608
6613
|
|
|
6609
6614
|
|
|
6615
|
+
/* Auth phone OTP (SMS one-time passcode) */
|
|
6616
|
+
|
|
6617
|
+
// Two-step in-page flow (no redirect): createPhoneOTP(phone) texts a code + returns
|
|
6618
|
+
// a userId, then the shared verifyOTP(code)/submitOTP() (users.otp.js) creates the
|
|
6619
|
+
// session. Phone numbers must be E.164 (+ country code).
|
|
6620
|
+
// Gotcha: like email OTP, Appwrite can't convert an anonymous guest via phone OTP —
|
|
6621
|
+
// a guest verifying a code gets a fresh account. Use magic links for guest upgrade.
|
|
6622
|
+
|
|
6623
|
+
function initializePhoneOTP() {
|
|
6624
|
+
if (typeof Alpine === 'undefined') {
|
|
6625
|
+
return;
|
|
6626
|
+
}
|
|
6627
|
+
|
|
6628
|
+
const config = window.ManifestAppwriteAuthConfig;
|
|
6629
|
+
if (!config) {
|
|
6630
|
+
return;
|
|
6631
|
+
}
|
|
6632
|
+
|
|
6633
|
+
// Resolve a phone from an input/selector/{ phone } object/string, or auto-find
|
|
6634
|
+
// the nearest tel input. Returns { phone, inputEl, dataObj }.
|
|
6635
|
+
function resolvePhoneInput(phoneInputOrRef) {
|
|
6636
|
+
let phone = null;
|
|
6637
|
+
let inputEl = null;
|
|
6638
|
+
let dataObj = null;
|
|
6639
|
+
|
|
6640
|
+
if (phoneInputOrRef === undefined || phoneInputOrRef === null) {
|
|
6641
|
+
let eventTarget = (typeof window !== 'undefined' && window.event) ? window.event.target : null;
|
|
6642
|
+
if (eventTarget) {
|
|
6643
|
+
const form = eventTarget.closest('form');
|
|
6644
|
+
const scope = form || eventTarget.parentElement;
|
|
6645
|
+
if (scope) {
|
|
6646
|
+
inputEl = scope.querySelector('input[type="tel"]');
|
|
6647
|
+
if (inputEl) phone = inputEl.value;
|
|
6648
|
+
}
|
|
6649
|
+
}
|
|
6650
|
+
if (!inputEl) {
|
|
6651
|
+
inputEl = document.querySelector('input[type="tel"]');
|
|
6652
|
+
if (inputEl) phone = inputEl.value;
|
|
6653
|
+
}
|
|
6654
|
+
} else if (typeof phoneInputOrRef === 'string') {
|
|
6655
|
+
try {
|
|
6656
|
+
const element = document.querySelector(phoneInputOrRef);
|
|
6657
|
+
if (element && element.tagName === 'INPUT' && element.type === 'tel') {
|
|
6658
|
+
inputEl = element;
|
|
6659
|
+
phone = element.value;
|
|
6660
|
+
} else {
|
|
6661
|
+
phone = phoneInputOrRef; // Treat as a direct phone string
|
|
6662
|
+
}
|
|
6663
|
+
} catch (e) {
|
|
6664
|
+
phone = phoneInputOrRef; // Invalid selector -> treat as phone string
|
|
6665
|
+
}
|
|
6666
|
+
} else if (phoneInputOrRef && typeof phoneInputOrRef === 'object') {
|
|
6667
|
+
if (phoneInputOrRef.tagName === 'INPUT' || phoneInputOrRef.matches?.('input[type="tel"]')) {
|
|
6668
|
+
inputEl = phoneInputOrRef;
|
|
6669
|
+
phone = inputEl.value;
|
|
6670
|
+
} else if ('phone' in phoneInputOrRef) {
|
|
6671
|
+
phone = phoneInputOrRef.phone;
|
|
6672
|
+
dataObj = phoneInputOrRef;
|
|
6673
|
+
}
|
|
6674
|
+
}
|
|
6675
|
+
|
|
6676
|
+
return { phone, inputEl, dataObj };
|
|
6677
|
+
}
|
|
6678
|
+
|
|
6679
|
+
const waitForStore = () => {
|
|
6680
|
+
const store = Alpine.store('auth');
|
|
6681
|
+
if (store && !store.createPhoneOTP) {
|
|
6682
|
+
// Step 1: text a passcode. Verification reuses verifyOTP/submitOTP.
|
|
6683
|
+
store.createPhoneOTP = async function (phone) {
|
|
6684
|
+
if (!this._appwrite) {
|
|
6685
|
+
this._appwrite = await config.getAppwriteClient();
|
|
6686
|
+
}
|
|
6687
|
+
if (!this._appwrite) {
|
|
6688
|
+
this.error = 'Appwrite not configured';
|
|
6689
|
+
return { success: false, error: this.error };
|
|
6690
|
+
}
|
|
6691
|
+
|
|
6692
|
+
// Don't allow OTP request if already signed in (non-anonymous)
|
|
6693
|
+
if (this.isAuthenticated && !this.isAnonymous) {
|
|
6694
|
+
this.error = 'Already signed in. Please logout first.';
|
|
6695
|
+
return { success: false, error: this.error };
|
|
6696
|
+
}
|
|
6697
|
+
|
|
6698
|
+
const appwriteConfig = await config.getAppwriteConfig();
|
|
6699
|
+
if (appwriteConfig && !appwriteConfig.phone) {
|
|
6700
|
+
this.error = 'Phone OTP authentication is not enabled';
|
|
6701
|
+
return { success: false, error: this.error };
|
|
6702
|
+
}
|
|
6703
|
+
|
|
6704
|
+
// Normalize to E.164: strip separators, require the country code.
|
|
6705
|
+
const normalized = String(phone).replace(/[\s().-]/g, '');
|
|
6706
|
+
if (!/^\+\d{6,15}$/.test(normalized)) {
|
|
6707
|
+
this.error = 'Phone number must be in international format, e.g. +14155550123';
|
|
6708
|
+
return { success: false, error: this.error };
|
|
6709
|
+
}
|
|
6710
|
+
|
|
6711
|
+
// Phone OTP can't convert a guest — warn so lost guest teams aren't a surprise.
|
|
6712
|
+
if (this.isAnonymous && appwriteConfig?.guestUpgrade) {
|
|
6713
|
+
console.warn('[Manifest Appwrite Auth] Phone OTP cannot upgrade a guest account (Appwrite limitation); the guest session and any guest-created teams will be replaced. Use magic links for guest upgrade.');
|
|
6714
|
+
}
|
|
6715
|
+
|
|
6716
|
+
const account = this._appwrite.account;
|
|
6717
|
+
if (typeof account.createPhoneToken !== 'function') {
|
|
6718
|
+
this.error = 'Phone OTP method not available. Please ensure you are using a recent Appwrite SDK.';
|
|
6719
|
+
return { success: false, error: this.error };
|
|
6720
|
+
}
|
|
6721
|
+
|
|
6722
|
+
this.inProgress = true;
|
|
6723
|
+
this.error = null;
|
|
6724
|
+
this.otpExpired = false;
|
|
6725
|
+
|
|
6726
|
+
try {
|
|
6727
|
+
const uniqueId = (window.Appwrite?.ID?.unique) ? window.Appwrite.ID.unique() : 'unique()';
|
|
6728
|
+
const token = await account.createPhoneToken(uniqueId, normalized);
|
|
6729
|
+
|
|
6730
|
+
// Stash the userId Appwrite assigned; verifyOTP needs it to complete login.
|
|
6731
|
+
this._otpUserId = token.userId;
|
|
6732
|
+
this.otpPhrase = null; // phone tokens have no security phrase
|
|
6733
|
+
this.otpSent = true;
|
|
6734
|
+
this.otpExpired = false;
|
|
6735
|
+
this.error = null;
|
|
6736
|
+
|
|
6737
|
+
window.dispatchEvent(new CustomEvent('manifest:auth:otp-sent', {
|
|
6738
|
+
detail: { phone: normalized }
|
|
6739
|
+
}));
|
|
6740
|
+
|
|
6741
|
+
return { success: true, message: 'OTP sent by SMS' };
|
|
6742
|
+
} catch (error) {
|
|
6743
|
+
// Appwrite returns 501 when phone auth/SMS isn't set up — surface an
|
|
6744
|
+
// actionable message rather than the raw error.
|
|
6745
|
+
const code = error.code || error.statusCode;
|
|
6746
|
+
const notEnabled = code === 501 || /not implemented/i.test(error.message || '');
|
|
6747
|
+
this.error = notEnabled
|
|
6748
|
+
? 'Phone OTP is not enabled for this Appwrite project. Enable Phone under Auth → Settings and configure an SMS provider under Messaging.'
|
|
6749
|
+
: error.message;
|
|
6750
|
+
this.otpSent = false;
|
|
6751
|
+
this.otpExpired = false;
|
|
6752
|
+
return { success: false, error: this.error };
|
|
6753
|
+
} finally {
|
|
6754
|
+
this.inProgress = false;
|
|
6755
|
+
}
|
|
6756
|
+
};
|
|
6757
|
+
|
|
6758
|
+
// Convenience: resolve the phone from an input/selector/object/string and send.
|
|
6759
|
+
// Clears the phone input on success (mirrors sendEmailOTP).
|
|
6760
|
+
store.sendPhoneOTP = async function (phoneInputOrRef) {
|
|
6761
|
+
const { phone, inputEl, dataObj } = resolvePhoneInput(phoneInputOrRef);
|
|
6762
|
+
|
|
6763
|
+
if (!phone || !String(phone).trim()) {
|
|
6764
|
+
this.error = 'Phone number is required';
|
|
6765
|
+
return { success: false, error: this.error };
|
|
6766
|
+
}
|
|
6767
|
+
|
|
6768
|
+
const result = await this.createPhoneOTP(String(phone).trim());
|
|
6769
|
+
|
|
6770
|
+
if (result.success) {
|
|
6771
|
+
Promise.resolve().then(() => {
|
|
6772
|
+
if (inputEl) {
|
|
6773
|
+
inputEl.value = '';
|
|
6774
|
+
inputEl.dispatchEvent(new Event('input', { bubbles: true }));
|
|
6775
|
+
} else if (dataObj) {
|
|
6776
|
+
dataObj.phone = '';
|
|
6777
|
+
}
|
|
6778
|
+
});
|
|
6779
|
+
}
|
|
6780
|
+
|
|
6781
|
+
return result;
|
|
6782
|
+
};
|
|
6783
|
+
} else if (!store) {
|
|
6784
|
+
setTimeout(waitForStore, 50);
|
|
6785
|
+
}
|
|
6786
|
+
};
|
|
6787
|
+
|
|
6788
|
+
setTimeout(waitForStore, 100);
|
|
6789
|
+
}
|
|
6790
|
+
|
|
6791
|
+
// Initialize when Alpine is ready
|
|
6792
|
+
document.addEventListener('alpine:init', () => {
|
|
6793
|
+
try {
|
|
6794
|
+
initializePhoneOTP();
|
|
6795
|
+
} catch (error) {
|
|
6796
|
+
// Failed to initialize phone OTP
|
|
6797
|
+
}
|
|
6798
|
+
});
|
|
6799
|
+
|
|
6800
|
+
// Export phone OTP interface
|
|
6801
|
+
window.ManifestAppwriteAuthPhoneOTP = {
|
|
6802
|
+
initialize: initializePhoneOTP
|
|
6803
|
+
};
|
|
6804
|
+
|
|
6805
|
+
|
|
6610
6806
|
/* Auth OAuth */
|
|
6611
6807
|
|
|
6612
6808
|
// Add OAuth methods to auth store
|
package/lib/manifest.data.js
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
|
-
"manifest.appwrite.auth.js": "sha384-
|
|
3
|
-
"manifest.appwrite.data.js": "sha384-
|
|
2
|
+
"manifest.appwrite.auth.js": "sha384-eJ46LQV0lAoY48Zy1J8iecrK9azn/407FdeXz9+dwsuAJESUugOzlEBdTCw+i3m5",
|
|
3
|
+
"manifest.appwrite.data.js": "sha384-uWy++AIY+DZbiEm+Qhkqxc6OJ3E0NSzx5Mq+8TCaAAI+cCV6PSbrS84JRjYV2jNF",
|
|
4
4
|
"manifest.appwrite.presences.js": "sha384-JyVDWFT69b7Svq8J8p9tNWe2v9PZNQBY5UyhtOl1vnuHFAX0CRQ3MA9SiKq5wzNh",
|
|
5
5
|
"manifest.bindings.js": "sha384-lPtMf8Ykaic9gNVZKq8Scia1881ZeMAyxer3WCIkUNwwrgzGBWto1OXADUwjvORF",
|
|
6
6
|
"manifest.charts.js": "sha384-gEAv/98+29RbhvNkiNWTNyBPbLTFr2Ld15wLu29FLCL57j1cwGChRrL9Pfk7dBtT",
|
|
@@ -11,7 +11,7 @@
|
|
|
11
11
|
"manifest.combobox.js": "sha384-MILTkrgsTzsYUjGo4ZuADqV85Xs4GmfB4xexfe9vbJMIoQTZ42W4zs+DTaVSPEsx",
|
|
12
12
|
"manifest.components.js": "sha384-4bc3HgPvF9DHMiOG08w+nWXI7Hho01RuAPAUL9xyLxOiS2igeZpulCVcvr5aT9v6",
|
|
13
13
|
"manifest.computed.js": "sha384-GYML/e81gQfN+iDbqhPUgny8bINCyL+SrbTofoGk4hlCnLLjv51mCv42JMqq+ku5",
|
|
14
|
-
"manifest.data.js": "sha384-
|
|
14
|
+
"manifest.data.js": "sha384-YljhDHjZ6BCU7qjoeecMvG1mgC7FwR7vw1EWBAyd6ZcMAlc3nmiztv3swRckN320",
|
|
15
15
|
"manifest.datepicker.js": "sha384-XnbeURni2X91ozVzatQcSjYYIS4MoW12dBRJnYAGBr0nCQ624heH5s+xtQSpLZX6",
|
|
16
16
|
"manifest.defer.js": "sha384-WcCf8YQ1bKIXCLSZ24a0bJwepbYntYc8TzQM50hklo5VMIH8AtzDnwl6WU4prRv1",
|
|
17
17
|
"manifest.device.js": "sha384-g+txmrEszYtuOvRelTp/c1wSNR2AtllVI9rx5NPPD7DzhVUnMNughonZykv2xlBW",
|
|
@@ -28,7 +28,7 @@
|
|
|
28
28
|
"manifest.slides.js": "sha384-3uRTkyK9XPLmnxI2+igZlpi4EyPlU/7IHj5j3BZJJ2KN455vXyk99fiXV3feO/XY",
|
|
29
29
|
"manifest.status.js": "sha384-MBO345ab7H6Uq1X2dZLt4Ge1Gcra+Z2qYApvlAeIV8CJhDDJrz2FPXpp+Kcp8zcM",
|
|
30
30
|
"manifest.svg.js": "sha384-qr/8H9+2cIhSXNbRWRtIdrDlTOxKlNJqwEefHvCYoiBNW/kKhPTFa109Orv/EBnb",
|
|
31
|
-
"manifest.sw.js": "sha384-
|
|
31
|
+
"manifest.sw.js": "sha384-hEYCjpYM1VHGJLc/RnSyUsmhBx/XrGhxCA31U6kW/TpFadcUZ0Uz96Rqm0uFbr+I",
|
|
32
32
|
"manifest.tabs.js": "sha384-OIIcyaQnGS0eNYk4zgAFEDboNYect7THvUd9D0V6nqCeDOxQcoiqLrBEmmWVTTet",
|
|
33
33
|
"manifest.tailwind.js": "sha384-r/Jvqb+Piz21jUts10BbVAJoKkShOdJRVFpywyi4HPIi/OfOJq5CtPyWAPbdkMgt",
|
|
34
34
|
"manifest.text.edit.js": "sha384-RzOvLQE8GbmI6gntAwiotDewYT/08OHcd7sJ5hLon8e8u1Xbq1D7VfEGuaRVd2CE",
|
package/lib/manifest.sw.js
CHANGED
|
@@ -16,7 +16,7 @@
|
|
|
16
16
|
|
|
17
17
|
// Build stamps the published version here; unstamped (dev) falls back to the
|
|
18
18
|
// registration URL's `v`, then 'dev'.
|
|
19
|
-
const BUILD_VERSION = '0.5.
|
|
19
|
+
const BUILD_VERSION = '0.5.225';
|
|
20
20
|
const CACHE_PREFIX = 'mnfst-sw:';
|
|
21
21
|
const META_CACHE = CACHE_PREFIX + 'meta';
|
|
22
22
|
// Sized to hold a full precache.json warm-up (PRECACHE_MAX_ENTRIES server-side)
|