dexie-cloud-addon 4.3.5 → 4.3.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/TODO-SOCIALAUTH.md +1 -1
- package/dist/modern/DexieCloudAPI.d.ts +2 -0
- package/dist/modern/authentication/handleOAuthCallback.d.ts +0 -4
- package/dist/modern/default-ui/OptionButton.d.ts +0 -4
- package/dist/modern/dexie-cloud-addon.js +68 -122
- package/dist/modern/dexie-cloud-addon.js.map +1 -1
- package/dist/modern/dexie-cloud-addon.min.js +1 -1
- package/dist/modern/dexie-cloud-addon.min.js.map +1 -1
- package/dist/modern/service-worker.js +68 -122
- package/dist/modern/service-worker.js.map +1 -1
- package/dist/modern/service-worker.min.js +1 -1
- package/dist/modern/service-worker.min.js.map +1 -1
- package/dist/modern/types/DXCUserInteraction.d.ts +1 -3
- package/dist/umd/dexie-cloud-addon.js +69 -123
- package/dist/umd/dexie-cloud-addon.js.map +1 -1
- package/dist/umd/dexie-cloud-addon.min.js +1 -1
- package/dist/umd/dexie-cloud-addon.min.js.map +1 -1
- package/dist/umd/service-worker.js +69 -123
- package/dist/umd/service-worker.js.map +1 -1
- package/dist/umd/service-worker.min.js +1 -1
- package/dist/umd/service-worker.min.js.map +1 -1
- package/package.json +1 -1
package/TODO-SOCIALAUTH.md
CHANGED
|
@@ -9,7 +9,7 @@ This feature adds support for OAuth 2.0 social login providers (Google, GitHub,
|
|
|
9
9
|
### Related Files
|
|
10
10
|
|
|
11
11
|
- **Detailed flow diagram**: [oauth_flow.md](oauth_flow.md) - Sequence diagrams and detailed protocol description
|
|
12
|
-
- **Server implementation**:
|
|
12
|
+
- **Server implementation**: See `dexie-cloud-server` repository
|
|
13
13
|
- `src/api/oauth/registerOAuthEndpoints.ts` - OAuth endpoints
|
|
14
14
|
- `src/api/oauth/oauth-helpers.ts` - Provider exchange logic
|
|
15
15
|
- `src/api/registerTokenEndpoint.ts` - Token endpoint (authorization_code grant)
|
|
@@ -21,6 +21,8 @@ export interface LoginHints {
|
|
|
21
21
|
provider?: string;
|
|
22
22
|
/** Dexie Cloud authorization code received from OAuth callback */
|
|
23
23
|
oauthCode?: string;
|
|
24
|
+
/** Optional redirect path (relative or absolute) to use for OAuth redirect URI. */
|
|
25
|
+
redirectPath?: string;
|
|
24
26
|
}
|
|
25
27
|
export interface DexieCloudAPI {
|
|
26
28
|
version: string;
|
|
@@ -26,10 +26,6 @@ export declare function parseOAuthCallback(url?: string): OAuthCallbackParams |
|
|
|
26
26
|
* @returns true if valid, false otherwise
|
|
27
27
|
*/
|
|
28
28
|
export declare function validateOAuthState(receivedState: string): boolean;
|
|
29
|
-
/**
|
|
30
|
-
* Gets the OAuth provider from sessionStorage (for redirect flows).
|
|
31
|
-
*/
|
|
32
|
-
export declare function getStoredOAuthProvider(): string | null;
|
|
33
29
|
/**
|
|
34
30
|
* Cleans up the dxc-auth query parameter from the URL.
|
|
35
31
|
* Call this after successfully handling the callback to clean up the browser URL.
|
|
@@ -8,10 +8,6 @@ export interface OptionButtonProps {
|
|
|
8
8
|
* Generic button component for selectable options.
|
|
9
9
|
* Displays the option's icon and display name.
|
|
10
10
|
*
|
|
11
|
-
* The icon can be:
|
|
12
|
-
* - Inline SVG (iconSvg) - rendered directly with dangerouslySetInnerHTML
|
|
13
|
-
* - Image URL (iconUrl) - rendered as an img tag
|
|
14
|
-
*
|
|
15
11
|
* Style is determined by the styleHint property for branding purposes.
|
|
16
12
|
*/
|
|
17
13
|
export declare function OptionButton({ option, onClick }: OptionButtonProps): h.JSX.Element;
|
|
@@ -8,7 +8,7 @@
|
|
|
8
8
|
*
|
|
9
9
|
* ==========================================================================
|
|
10
10
|
*
|
|
11
|
-
* Version 4.3.
|
|
11
|
+
* Version 4.3.7, Wed Jan 28 2026
|
|
12
12
|
*
|
|
13
13
|
* https://dexie.org
|
|
14
14
|
*
|
|
@@ -761,73 +761,19 @@ class TokenErrorResponseError extends Error {
|
|
|
761
761
|
}
|
|
762
762
|
}
|
|
763
763
|
|
|
764
|
-
/**
|
|
765
|
-
const
|
|
766
|
-
/** Default SVG icons for built-in OAuth providers */
|
|
767
|
-
const ProviderIcons = {
|
|
768
|
-
google: `<svg viewBox="0 0 24 24" width="20" height="20"><path fill="#4285F4" d="M22.56 12.25c0-.78-.07-1.53-.2-2.25H12v4.26h5.92c-.26 1.37-1.04 2.53-2.21 3.31v2.77h3.57c2.08-1.92 3.28-4.74 3.28-8.09z"/><path fill="#34A853" d="M12 23c2.97 0 5.46-.98 7.28-2.66l-3.57-2.77c-.98.66-2.23 1.06-3.71 1.06-2.86 0-5.29-1.93-6.16-4.53H2.18v2.84C3.99 20.53 7.7 23 12 23z"/><path fill="#FBBC05" d="M5.84 14.09c-.22-.66-.35-1.36-.35-2.09s.13-1.43.35-2.09V7.07H2.18C1.43 8.55 1 10.22 1 12s.43 3.45 1.18 4.93l2.85-2.22.81-.62z"/><path fill="#EA4335" d="M12 5.38c1.62 0 3.06.56 4.21 1.64l3.15-3.15C17.45 2.09 14.97 1 12 1 7.7 1 3.99 3.47 2.18 7.07l3.66 2.84c.87-2.6 3.3-4.53 6.16-4.53z"/></svg>`,
|
|
769
|
-
github: `<svg viewBox="0 0 24 24" width="20" height="20" fill="currentColor"><path d="M12 0C5.37 0 0 5.37 0 12c0 5.31 3.435 9.795 8.205 11.385.6.105.825-.255.825-.57 0-.285-.015-1.23-.015-2.235-3.015.555-3.795-.735-4.035-1.41-.135-.345-.72-1.41-1.23-1.695-.42-.225-1.02-.78-.015-.795.945-.015 1.62.87 1.845 1.23 1.08 1.815 2.805 1.305 3.495.99.105-.78.42-1.305.765-1.605-2.67-.3-5.46-1.335-5.46-5.925 0-1.305.465-2.385 1.23-3.225-.12-.3-.54-1.53.12-3.18 0 0 1.005-.315 3.3 1.23.96-.27 1.98-.405 3-.405s2.04.135 3 .405c2.295-1.56 3.3-1.23 3.3-1.23.66 1.65.24 2.88.12 3.18.765.84 1.23 1.905 1.23 3.225 0 4.605-2.805 5.625-5.475 5.925.435.375.81 1.095.81 2.22 0 1.605-.015 2.895-.015 3.3 0 .315.225.69.825.57A12.02 12.02 0 0024 12c0-6.63-5.37-12-12-12z"/></svg>`,
|
|
770
|
-
microsoft: `<svg viewBox="0 0 24 24" width="20" height="20"><rect fill="#F25022" x="1" y="1" width="10" height="10"/><rect fill="#00A4EF" x="1" y="13" width="10" height="10"/><rect fill="#7FBA00" x="13" y="1" width="10" height="10"/><rect fill="#FFB900" x="13" y="13" width="10" height="10"/></svg>`,
|
|
771
|
-
apple: `<svg viewBox="0 0 24 24" width="20" height="20" fill="currentColor"><path d="M18.71 19.5c-.83 1.24-1.71 2.45-3.05 2.47-1.34.03-1.77-.79-3.29-.79-1.53 0-2 .77-3.27.82-1.31.05-2.3-1.32-3.14-2.53C4.25 17 2.94 12.45 4.7 9.39c.87-1.52 2.43-2.48 4.12-2.51 1.28-.02 2.5.87 3.29.87.78 0 2.26-1.07 3.81-.91.65.03 2.47.26 3.64 1.98-.09.06-2.17 1.28-2.15 3.81.03 3.02 2.65 4.03 2.68 4.04-.03.07-.42 1.44-1.38 2.83M13 3.5c.73-.83 1.94-1.46 2.94-1.5.13 1.17-.34 2.35-1.04 3.19-.69.85-1.83 1.51-2.95 1.42-.15-1.15.41-2.35 1.05-3.11z"/></svg>`,
|
|
772
|
-
};
|
|
773
|
-
/** Email/envelope icon for OTP option */
|
|
774
|
-
const EmailIcon = `<svg viewBox="0 0 24 24" width="20" height="20" fill="none" stroke="currentColor" stroke-width="2"><rect x="2" y="4" width="20" height="16" rx="2"/><path d="M22 6L12 13 2 6"/></svg>`;
|
|
775
|
-
/**
|
|
776
|
-
* Fetches SVG content from a URL and caches it.
|
|
777
|
-
* Returns the SVG string or null if fetch fails.
|
|
778
|
-
*/
|
|
779
|
-
function fetchSvgIcon(url) {
|
|
780
|
-
return __awaiter(this, void 0, void 0, function* () {
|
|
781
|
-
if (svgCache[url]) {
|
|
782
|
-
return svgCache[url];
|
|
783
|
-
}
|
|
784
|
-
try {
|
|
785
|
-
const res = yield fetch(url);
|
|
786
|
-
if (res.ok) {
|
|
787
|
-
const svg = yield res.text();
|
|
788
|
-
// Validate it looks like SVG
|
|
789
|
-
if (svg.includes('<svg')) {
|
|
790
|
-
svgCache[url] = svg;
|
|
791
|
-
return svg;
|
|
792
|
-
}
|
|
793
|
-
}
|
|
794
|
-
}
|
|
795
|
-
catch (_a) {
|
|
796
|
-
// Silently fail - will show no icon
|
|
797
|
-
}
|
|
798
|
-
return null;
|
|
799
|
-
});
|
|
800
|
-
}
|
|
764
|
+
/** Email/envelope icon data URL for OTP option */
|
|
765
|
+
const EmailIcon = `data:image/svg+xml;base64,${btoa('<svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 24 24" width="20" height="20" fill="none" stroke="#666666" stroke-width="2"><rect x="2" y="4" width="20" height="16" rx="2"/><path d="M22 6L12 13 2 6"/></svg>')}`;
|
|
801
766
|
/**
|
|
802
767
|
* Converts an OAuthProviderInfo to a generic DXCOption.
|
|
803
|
-
* Fetches SVG icons from URLs if needed.
|
|
804
768
|
*/
|
|
805
769
|
function providerToOption(provider) {
|
|
806
|
-
return
|
|
807
|
-
|
|
808
|
-
|
|
809
|
-
|
|
810
|
-
|
|
811
|
-
|
|
812
|
-
|
|
813
|
-
// If provider has iconUrl pointing to SVG, fetch and inline it
|
|
814
|
-
else if ((_a = provider.iconUrl) === null || _a === void 0 ? void 0 : _a.toLowerCase().endsWith('.svg')) {
|
|
815
|
-
const fetched = yield fetchSvgIcon(provider.iconUrl);
|
|
816
|
-
if (fetched) {
|
|
817
|
-
iconSvg = fetched;
|
|
818
|
-
}
|
|
819
|
-
}
|
|
820
|
-
return {
|
|
821
|
-
name: 'provider',
|
|
822
|
-
value: provider.name,
|
|
823
|
-
displayName: `Continue with ${provider.displayName}`,
|
|
824
|
-
iconSvg,
|
|
825
|
-
// If iconUrl is not SVG, pass it through for img tag rendering
|
|
826
|
-
iconUrl: (!iconSvg && provider.iconUrl) ? provider.iconUrl : undefined,
|
|
827
|
-
// Use provider type as style hint for branding
|
|
828
|
-
styleHint: provider.type,
|
|
829
|
-
};
|
|
830
|
-
});
|
|
770
|
+
return {
|
|
771
|
+
name: 'provider',
|
|
772
|
+
value: provider.name,
|
|
773
|
+
displayName: `Continue with ${provider.displayName}`,
|
|
774
|
+
iconUrl: provider.iconUrl,
|
|
775
|
+
styleHint: provider.type,
|
|
776
|
+
};
|
|
831
777
|
}
|
|
832
778
|
function interactWithUser(userInteraction, req) {
|
|
833
779
|
return new Promise((resolve, reject) => {
|
|
@@ -978,8 +924,8 @@ function confirmLogout(userInteraction, currentUserId, numUnsyncedChanges) {
|
|
|
978
924
|
*/
|
|
979
925
|
function promptForProvider(userInteraction_1, providers_1, otpEnabled_1) {
|
|
980
926
|
return __awaiter(this, arguments, void 0, function* (userInteraction, providers, otpEnabled, title = 'Choose login method', alerts = []) {
|
|
981
|
-
// Convert providers to generic options
|
|
982
|
-
const providerOptions =
|
|
927
|
+
// Convert providers to generic options
|
|
928
|
+
const providerOptions = providers.map(providerToOption);
|
|
983
929
|
// Build the options array
|
|
984
930
|
const options = [...providerOptions];
|
|
985
931
|
// Add OTP option if enabled
|
|
@@ -988,7 +934,7 @@ function promptForProvider(userInteraction_1, providers_1, otpEnabled_1) {
|
|
|
988
934
|
name: 'otp',
|
|
989
935
|
value: 'email',
|
|
990
936
|
displayName: 'Continue with email',
|
|
991
|
-
|
|
937
|
+
iconUrl: EmailIcon,
|
|
992
938
|
styleHint: 'otp',
|
|
993
939
|
});
|
|
994
940
|
}
|
|
@@ -1416,10 +1362,12 @@ function exchangeOAuthCode(options) {
|
|
|
1416
1362
|
mode: 'cors',
|
|
1417
1363
|
});
|
|
1418
1364
|
if (!res.ok) {
|
|
1365
|
+
// Read body once as text to avoid stream consumption issues
|
|
1366
|
+
const bodyText = yield res.text().catch(() => res.statusText);
|
|
1419
1367
|
if (res.status === 400 || res.status === 401) {
|
|
1420
|
-
// Try to parse error response
|
|
1368
|
+
// Try to parse error response as JSON
|
|
1421
1369
|
try {
|
|
1422
|
-
const errorResponse =
|
|
1370
|
+
const errorResponse = JSON.parse(bodyText);
|
|
1423
1371
|
if (errorResponse.type === 'error') {
|
|
1424
1372
|
// Check for specific error codes
|
|
1425
1373
|
if (errorResponse.messageCode === 'INVALID_OTP') {
|
|
@@ -1436,8 +1384,7 @@ function exchangeOAuthCode(options) {
|
|
|
1436
1384
|
// Fall through to generic error
|
|
1437
1385
|
}
|
|
1438
1386
|
}
|
|
1439
|
-
|
|
1440
|
-
throw new OAuthError('provider_error', undefined, `Token exchange failed: ${res.status} ${errorText}`);
|
|
1387
|
+
throw new OAuthError('provider_error', undefined, `Token exchange failed: ${res.status} ${bodyText}`);
|
|
1441
1388
|
}
|
|
1442
1389
|
const response = yield res.json();
|
|
1443
1390
|
if (response.type === 'error') {
|
|
@@ -1543,9 +1490,8 @@ function buildOAuthLoginUrl(options) {
|
|
|
1543
1490
|
* ```
|
|
1544
1491
|
*/
|
|
1545
1492
|
function startOAuthRedirect(options) {
|
|
1546
|
-
|
|
1547
|
-
|
|
1548
|
-
sessionStorage.setItem('dexie-cloud-oauth-provider', options.provider);
|
|
1493
|
+
if (typeof window === 'undefined') {
|
|
1494
|
+
throw new Error('OAuth redirect requires a browser environment');
|
|
1549
1495
|
}
|
|
1550
1496
|
const loginUrl = buildOAuthLoginUrl(options);
|
|
1551
1497
|
window.location.href = loginUrl;
|
|
@@ -1571,7 +1517,21 @@ function otpFetchTokenCallback(db) {
|
|
|
1571
1517
|
}
|
|
1572
1518
|
// Handle OAuth provider login via redirect
|
|
1573
1519
|
if (hints === null || hints === void 0 ? void 0 : hints.provider) {
|
|
1574
|
-
|
|
1520
|
+
let resolvedRedirectUri = undefined;
|
|
1521
|
+
if (hints.redirectPath) {
|
|
1522
|
+
// If redirectPath is absolute, use as is. If relative, resolve against current location
|
|
1523
|
+
if (/^https?:\/\//i.test(hints.redirectPath)) {
|
|
1524
|
+
resolvedRedirectUri = hints.redirectPath;
|
|
1525
|
+
}
|
|
1526
|
+
else if (typeof window !== 'undefined' && window.location) {
|
|
1527
|
+
// Use URL constructor to resolve relative path
|
|
1528
|
+
resolvedRedirectUri = new URL(hints.redirectPath, window.location.href).toString();
|
|
1529
|
+
}
|
|
1530
|
+
else if (typeof location !== 'undefined' && location.href) {
|
|
1531
|
+
resolvedRedirectUri = new URL(hints.redirectPath, location.href).toString();
|
|
1532
|
+
}
|
|
1533
|
+
}
|
|
1534
|
+
initiateOAuthRedirect(db, hints.provider, resolvedRedirectUri);
|
|
1575
1535
|
// This function never returns - page navigates away
|
|
1576
1536
|
throw new OAuthRedirectError(hints.provider);
|
|
1577
1537
|
}
|
|
@@ -1651,7 +1611,8 @@ function otpFetchTokenCallback(db) {
|
|
|
1651
1611
|
const res1 = yield fetch(`${url}/token`, {
|
|
1652
1612
|
body: JSON.stringify(tokenRequest),
|
|
1653
1613
|
method: 'post',
|
|
1654
|
-
headers: { 'Content-Type': 'application/json'
|
|
1614
|
+
headers: { 'Content-Type': 'application/json' },
|
|
1615
|
+
mode: 'cors',
|
|
1655
1616
|
});
|
|
1656
1617
|
if (res1.status !== 200) {
|
|
1657
1618
|
const errMsg = yield res1.text();
|
|
@@ -1715,13 +1676,18 @@ function otpFetchTokenCallback(db) {
|
|
|
1715
1676
|
* the user is redirected back with a dxc-auth query parameter that is
|
|
1716
1677
|
* automatically detected by db.cloud.configure().
|
|
1717
1678
|
*/
|
|
1718
|
-
function initiateOAuthRedirect(db, provider) {
|
|
1679
|
+
function initiateOAuthRedirect(db, provider, redirectUriOverride) {
|
|
1719
1680
|
var _a, _b;
|
|
1720
1681
|
const url = (_a = db.cloud.options) === null || _a === void 0 ? void 0 : _a.databaseUrl;
|
|
1721
1682
|
if (!url)
|
|
1722
1683
|
throw new Error(`No database URL given.`);
|
|
1723
|
-
const redirectUri =
|
|
1724
|
-
(
|
|
1684
|
+
const redirectUri = redirectUriOverride ||
|
|
1685
|
+
((_b = db.cloud.options) === null || _b === void 0 ? void 0 : _b.oauthRedirectUri) ||
|
|
1686
|
+
(typeof location !== 'undefined' ? location.href : undefined);
|
|
1687
|
+
// CodeRabbit suggested to fail fast here, but the only situation where
|
|
1688
|
+
// redirectUri would be undefined is in non-browser environments, and
|
|
1689
|
+
// in those environments OAuth redirect does not make sense anyway
|
|
1690
|
+
// and will fail fast in startOAuthRedirect().
|
|
1725
1691
|
// Start OAuth redirect flow - page navigates away
|
|
1726
1692
|
startOAuthRedirect({
|
|
1727
1693
|
databaseUrl: url,
|
|
@@ -5836,13 +5802,13 @@ const Styles = {
|
|
|
5836
5802
|
color: "#3c4043"
|
|
5837
5803
|
},
|
|
5838
5804
|
ProviderGitHub: {
|
|
5839
|
-
backgroundColor: "#
|
|
5840
|
-
border: "1px solid #
|
|
5841
|
-
color: "#
|
|
5805
|
+
backgroundColor: "#ffffff",
|
|
5806
|
+
border: "1px solid #dadce0",
|
|
5807
|
+
color: "#181717"
|
|
5842
5808
|
},
|
|
5843
5809
|
ProviderMicrosoft: {
|
|
5844
5810
|
backgroundColor: "#ffffff",
|
|
5845
|
-
border: "1px solid #
|
|
5811
|
+
border: "1px solid #dadce0",
|
|
5846
5812
|
color: "#5e5e5e"
|
|
5847
5813
|
},
|
|
5848
5814
|
ProviderApple: {
|
|
@@ -5851,9 +5817,9 @@ const Styles = {
|
|
|
5851
5817
|
color: "#ffffff"
|
|
5852
5818
|
},
|
|
5853
5819
|
ProviderCustom: {
|
|
5854
|
-
backgroundColor: "#
|
|
5855
|
-
border: "1px solid #
|
|
5856
|
-
color: "#
|
|
5820
|
+
backgroundColor: "#ffffff",
|
|
5821
|
+
border: "1px solid #dadce0",
|
|
5822
|
+
color: "#181717"
|
|
5857
5823
|
},
|
|
5858
5824
|
// Divider styles
|
|
5859
5825
|
Divider: {
|
|
@@ -5944,39 +5910,13 @@ function getOptionStyle(styleHint) {
|
|
|
5944
5910
|
* Generic button component for selectable options.
|
|
5945
5911
|
* Displays the option's icon and display name.
|
|
5946
5912
|
*
|
|
5947
|
-
* The icon can be:
|
|
5948
|
-
* - Inline SVG (iconSvg) - rendered directly with dangerouslySetInnerHTML
|
|
5949
|
-
* - Image URL (iconUrl) - rendered as an img tag
|
|
5950
|
-
*
|
|
5951
5913
|
* Style is determined by the styleHint property for branding purposes.
|
|
5952
5914
|
*/
|
|
5953
5915
|
function OptionButton({ option, onClick }) {
|
|
5954
|
-
const { displayName, iconUrl,
|
|
5916
|
+
const { displayName, iconUrl, styleHint } = option;
|
|
5955
5917
|
const style = getOptionStyle(styleHint);
|
|
5956
|
-
// Get the text color from the button style for SVG fill processing
|
|
5957
|
-
const textColor = style.color || '#000000';
|
|
5958
|
-
// Process SVG to replace currentColor with actual text color
|
|
5959
|
-
const processedSvg = iconSvg
|
|
5960
|
-
? iconSvg
|
|
5961
|
-
.replace(/fill="currentColor"/gi, `fill="${textColor}"`)
|
|
5962
|
-
.replace(/fill='currentColor'/gi, `fill='${textColor}'`)
|
|
5963
|
-
.replace(/stroke="currentColor"/gi, `stroke="${textColor}"`)
|
|
5964
|
-
.replace(/stroke='currentColor'/gi, `stroke='${textColor}'`)
|
|
5965
|
-
: null;
|
|
5966
|
-
// Render the appropriate icon
|
|
5967
|
-
const renderIcon = () => {
|
|
5968
|
-
// Inline SVG
|
|
5969
|
-
if (processedSvg) {
|
|
5970
|
-
return (_$1("span", { style: Styles.ProviderButtonIcon, "aria-hidden": "true", dangerouslySetInnerHTML: { __html: processedSvg } }));
|
|
5971
|
-
}
|
|
5972
|
-
// Image URL
|
|
5973
|
-
if (iconUrl) {
|
|
5974
|
-
return (_$1("img", { src: iconUrl, alt: "", style: Styles.ProviderButtonIcon, "aria-hidden": "true" }));
|
|
5975
|
-
}
|
|
5976
|
-
return null;
|
|
5977
|
-
};
|
|
5978
5918
|
return (_$1("button", { type: "button", style: style, onClick: onClick, class: `dxc-option-btn${styleHint ? ` dxc-option-${styleHint}` : ''}`, "aria-label": displayName },
|
|
5979
|
-
|
|
5919
|
+
iconUrl && (_$1("img", { src: iconUrl, alt: "", style: Styles.ProviderButtonIcon, "aria-hidden": "true" })),
|
|
5980
5920
|
_$1("span", { style: Styles.ProviderButtonText }, displayName)));
|
|
5981
5921
|
}
|
|
5982
5922
|
/**
|
|
@@ -6934,7 +6874,7 @@ function dexieCloud(dexie) {
|
|
|
6934
6874
|
const syncComplete = new Subject();
|
|
6935
6875
|
dexie.cloud = {
|
|
6936
6876
|
// @ts-ignore
|
|
6937
|
-
version: "4.3.
|
|
6877
|
+
version: "4.3.7",
|
|
6938
6878
|
options: Object.assign({}, DEFAULT_OPTIONS),
|
|
6939
6879
|
schema: null,
|
|
6940
6880
|
get currentUserId() {
|
|
@@ -7204,12 +7144,18 @@ function dexieCloud(dexie) {
|
|
|
7204
7144
|
pendingOAuthError = null; // Clear pending error
|
|
7205
7145
|
console.debug('[dexie-cloud] Showing OAuth error:', error.message);
|
|
7206
7146
|
// Show alert to user about the OAuth error
|
|
7207
|
-
|
|
7208
|
-
|
|
7209
|
-
|
|
7210
|
-
|
|
7211
|
-
|
|
7212
|
-
|
|
7147
|
+
// Guard so UI errors don't abort initialization
|
|
7148
|
+
try {
|
|
7149
|
+
yield alertUser(db.cloud.userInteraction, 'Authentication Error', {
|
|
7150
|
+
type: 'error',
|
|
7151
|
+
messageCode: 'GENERIC_ERROR',
|
|
7152
|
+
message: error.message,
|
|
7153
|
+
messageParams: { provider: error.provider || 'unknown' }
|
|
7154
|
+
});
|
|
7155
|
+
}
|
|
7156
|
+
catch (uiError) {
|
|
7157
|
+
console.error('[dexie-cloud] Failed to show OAuth error alert:', uiError);
|
|
7158
|
+
}
|
|
7213
7159
|
}
|
|
7214
7160
|
// Process pending OAuth callback if present (from dxc-auth redirect)
|
|
7215
7161
|
if (pendingOAuthCode && !db.cloud.isServiceWorkerDB) {
|
|
@@ -7313,7 +7259,7 @@ function dexieCloud(dexie) {
|
|
|
7313
7259
|
}
|
|
7314
7260
|
}
|
|
7315
7261
|
// @ts-ignore
|
|
7316
|
-
dexieCloud.version = "4.3.
|
|
7262
|
+
dexieCloud.version = "4.3.7";
|
|
7317
7263
|
Dexie.Cloud = dexieCloud;
|
|
7318
7264
|
|
|
7319
7265
|
export { dexieCloud as default, defineYDocTrigger, dexieCloud, getTiedObjectId, getTiedRealmId, resolveText };
|