dexie-cloud-addon 4.3.4 → 4.3.6
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/authentication/handleOAuthCallback.d.ts +0 -4
- package/dist/modern/default-ui/OptionButton.d.ts +0 -4
- package/dist/modern/dexie-cloud-addon.js +69 -119
- 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 +69 -119
- 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 +70 -120
- 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 +70 -120
- 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
|
@@ -8,7 +8,7 @@
|
|
|
8
8
|
*
|
|
9
9
|
* ==========================================================================
|
|
10
10
|
*
|
|
11
|
-
* Version 4.3.
|
|
11
|
+
* Version 4.3.6, Wed Jan 28 2026
|
|
12
12
|
*
|
|
13
13
|
* https://dexie.org
|
|
14
14
|
*
|
|
@@ -2445,73 +2445,19 @@
|
|
|
2445
2445
|
}
|
|
2446
2446
|
}
|
|
2447
2447
|
|
|
2448
|
-
/**
|
|
2449
|
-
const
|
|
2450
|
-
/** Default SVG icons for built-in OAuth providers */
|
|
2451
|
-
const ProviderIcons = {
|
|
2452
|
-
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>`,
|
|
2453
|
-
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>`,
|
|
2454
|
-
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>`,
|
|
2455
|
-
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>`,
|
|
2456
|
-
};
|
|
2457
|
-
/** Email/envelope icon for OTP option */
|
|
2458
|
-
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>`;
|
|
2459
|
-
/**
|
|
2460
|
-
* Fetches SVG content from a URL and caches it.
|
|
2461
|
-
* Returns the SVG string or null if fetch fails.
|
|
2462
|
-
*/
|
|
2463
|
-
function fetchSvgIcon(url) {
|
|
2464
|
-
return __awaiter(this, void 0, void 0, function* () {
|
|
2465
|
-
if (svgCache[url]) {
|
|
2466
|
-
return svgCache[url];
|
|
2467
|
-
}
|
|
2468
|
-
try {
|
|
2469
|
-
const res = yield fetch(url);
|
|
2470
|
-
if (res.ok) {
|
|
2471
|
-
const svg = yield res.text();
|
|
2472
|
-
// Validate it looks like SVG
|
|
2473
|
-
if (svg.includes('<svg')) {
|
|
2474
|
-
svgCache[url] = svg;
|
|
2475
|
-
return svg;
|
|
2476
|
-
}
|
|
2477
|
-
}
|
|
2478
|
-
}
|
|
2479
|
-
catch (_a) {
|
|
2480
|
-
// Silently fail - will show no icon
|
|
2481
|
-
}
|
|
2482
|
-
return null;
|
|
2483
|
-
});
|
|
2484
|
-
}
|
|
2448
|
+
/** Email/envelope icon data URL for OTP option */
|
|
2449
|
+
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>')}`;
|
|
2485
2450
|
/**
|
|
2486
2451
|
* Converts an OAuthProviderInfo to a generic DXCOption.
|
|
2487
|
-
* Fetches SVG icons from URLs if needed.
|
|
2488
2452
|
*/
|
|
2489
2453
|
function providerToOption(provider) {
|
|
2490
|
-
return
|
|
2491
|
-
|
|
2492
|
-
|
|
2493
|
-
|
|
2494
|
-
|
|
2495
|
-
|
|
2496
|
-
|
|
2497
|
-
// If provider has iconUrl pointing to SVG, fetch and inline it
|
|
2498
|
-
else if ((_a = provider.iconUrl) === null || _a === void 0 ? void 0 : _a.toLowerCase().endsWith('.svg')) {
|
|
2499
|
-
const fetched = yield fetchSvgIcon(provider.iconUrl);
|
|
2500
|
-
if (fetched) {
|
|
2501
|
-
iconSvg = fetched;
|
|
2502
|
-
}
|
|
2503
|
-
}
|
|
2504
|
-
return {
|
|
2505
|
-
name: 'provider',
|
|
2506
|
-
value: provider.name,
|
|
2507
|
-
displayName: `Continue with ${provider.displayName}`,
|
|
2508
|
-
iconSvg,
|
|
2509
|
-
// If iconUrl is not SVG, pass it through for img tag rendering
|
|
2510
|
-
iconUrl: (!iconSvg && provider.iconUrl) ? provider.iconUrl : undefined,
|
|
2511
|
-
// Use provider type as style hint for branding
|
|
2512
|
-
styleHint: provider.type,
|
|
2513
|
-
};
|
|
2514
|
-
});
|
|
2454
|
+
return {
|
|
2455
|
+
name: 'provider',
|
|
2456
|
+
value: provider.name,
|
|
2457
|
+
displayName: `Continue with ${provider.displayName}`,
|
|
2458
|
+
iconUrl: provider.iconUrl,
|
|
2459
|
+
styleHint: provider.type,
|
|
2460
|
+
};
|
|
2515
2461
|
}
|
|
2516
2462
|
function interactWithUser(userInteraction, req) {
|
|
2517
2463
|
return new Promise((resolve, reject) => {
|
|
@@ -2662,8 +2608,8 @@
|
|
|
2662
2608
|
*/
|
|
2663
2609
|
function promptForProvider(userInteraction_1, providers_1, otpEnabled_1) {
|
|
2664
2610
|
return __awaiter(this, arguments, void 0, function* (userInteraction, providers, otpEnabled, title = 'Choose login method', alerts = []) {
|
|
2665
|
-
// Convert providers to generic options
|
|
2666
|
-
const providerOptions =
|
|
2611
|
+
// Convert providers to generic options
|
|
2612
|
+
const providerOptions = providers.map(providerToOption);
|
|
2667
2613
|
// Build the options array
|
|
2668
2614
|
const options = [...providerOptions];
|
|
2669
2615
|
// Add OTP option if enabled
|
|
@@ -2672,7 +2618,7 @@
|
|
|
2672
2618
|
name: 'otp',
|
|
2673
2619
|
value: 'email',
|
|
2674
2620
|
displayName: 'Continue with email',
|
|
2675
|
-
|
|
2621
|
+
iconUrl: EmailIcon,
|
|
2676
2622
|
styleHint: 'otp',
|
|
2677
2623
|
});
|
|
2678
2624
|
}
|
|
@@ -13261,7 +13207,7 @@
|
|
|
13261
13207
|
*
|
|
13262
13208
|
* ==========================================================================
|
|
13263
13209
|
*
|
|
13264
|
-
* Version 4.2.2,
|
|
13210
|
+
* Version 4.2.2, Wed Jan 28 2026
|
|
13265
13211
|
*
|
|
13266
13212
|
* https://dexie.org
|
|
13267
13213
|
*
|
|
@@ -14708,10 +14654,12 @@
|
|
|
14708
14654
|
mode: 'cors',
|
|
14709
14655
|
});
|
|
14710
14656
|
if (!res.ok) {
|
|
14657
|
+
// Read body once as text to avoid stream consumption issues
|
|
14658
|
+
const bodyText = yield res.text().catch(() => res.statusText);
|
|
14711
14659
|
if (res.status === 400 || res.status === 401) {
|
|
14712
|
-
// Try to parse error response
|
|
14660
|
+
// Try to parse error response as JSON
|
|
14713
14661
|
try {
|
|
14714
|
-
const errorResponse =
|
|
14662
|
+
const errorResponse = JSON.parse(bodyText);
|
|
14715
14663
|
if (errorResponse.type === 'error') {
|
|
14716
14664
|
// Check for specific error codes
|
|
14717
14665
|
if (errorResponse.messageCode === 'INVALID_OTP') {
|
|
@@ -14728,8 +14676,7 @@
|
|
|
14728
14676
|
// Fall through to generic error
|
|
14729
14677
|
}
|
|
14730
14678
|
}
|
|
14731
|
-
|
|
14732
|
-
throw new OAuthError('provider_error', undefined, `Token exchange failed: ${res.status} ${errorText}`);
|
|
14679
|
+
throw new OAuthError('provider_error', undefined, `Token exchange failed: ${res.status} ${bodyText}`);
|
|
14733
14680
|
}
|
|
14734
14681
|
const response = yield res.json();
|
|
14735
14682
|
if (response.type === 'error') {
|
|
@@ -14835,9 +14782,8 @@
|
|
|
14835
14782
|
* ```
|
|
14836
14783
|
*/
|
|
14837
14784
|
function startOAuthRedirect(options) {
|
|
14838
|
-
|
|
14839
|
-
|
|
14840
|
-
sessionStorage.setItem('dexie-cloud-oauth-provider', options.provider);
|
|
14785
|
+
if (typeof window === 'undefined') {
|
|
14786
|
+
throw new Error('OAuth redirect requires a browser environment');
|
|
14841
14787
|
}
|
|
14842
14788
|
const loginUrl = buildOAuthLoginUrl(options);
|
|
14843
14789
|
window.location.href = loginUrl;
|
|
@@ -14889,6 +14835,25 @@
|
|
|
14889
14835
|
public_key,
|
|
14890
14836
|
};
|
|
14891
14837
|
}
|
|
14838
|
+
else if ((hints === null || hints === void 0 ? void 0 : hints.grant_type) === 'otp' || (hints === null || hints === void 0 ? void 0 : hints.email)) {
|
|
14839
|
+
// User explicitly requested OTP flow - skip provider selection
|
|
14840
|
+
const email = (hints === null || hints === void 0 ? void 0 : hints.email) || (yield promptForEmail(userInteraction, 'Enter email address'));
|
|
14841
|
+
if (/@demo.local$/.test(email)) {
|
|
14842
|
+
tokenRequest = {
|
|
14843
|
+
demo_user: email,
|
|
14844
|
+
grant_type: 'demo',
|
|
14845
|
+
scopes: ['ACCESS_DB'],
|
|
14846
|
+
public_key
|
|
14847
|
+
};
|
|
14848
|
+
}
|
|
14849
|
+
else {
|
|
14850
|
+
tokenRequest = {
|
|
14851
|
+
email,
|
|
14852
|
+
grant_type: 'otp',
|
|
14853
|
+
scopes: ['ACCESS_DB'],
|
|
14854
|
+
};
|
|
14855
|
+
}
|
|
14856
|
+
}
|
|
14892
14857
|
else {
|
|
14893
14858
|
// Check for available auth providers (OAuth + OTP)
|
|
14894
14859
|
const socialAuthEnabled = ((_c = db.cloud.options) === null || _c === void 0 ? void 0 : _c.socialAuth) !== false;
|
|
@@ -14924,7 +14889,8 @@
|
|
|
14924
14889
|
const res1 = yield fetch(`${url}/token`, {
|
|
14925
14890
|
body: JSON.stringify(tokenRequest),
|
|
14926
14891
|
method: 'post',
|
|
14927
|
-
headers: { 'Content-Type': 'application/json'
|
|
14892
|
+
headers: { 'Content-Type': 'application/json' },
|
|
14893
|
+
mode: 'cors',
|
|
14928
14894
|
});
|
|
14929
14895
|
if (res1.status !== 200) {
|
|
14930
14896
|
const errMsg = yield res1.text();
|
|
@@ -14994,7 +14960,11 @@
|
|
|
14994
14960
|
if (!url)
|
|
14995
14961
|
throw new Error(`No database URL given.`);
|
|
14996
14962
|
const redirectUri = ((_b = db.cloud.options) === null || _b === void 0 ? void 0 : _b.oauthRedirectUri) ||
|
|
14997
|
-
(typeof
|
|
14963
|
+
(typeof location !== 'undefined' ? location.href : undefined);
|
|
14964
|
+
// CodeRabbit suggested to fail fast here, but the only situation where
|
|
14965
|
+
// redirectUri would be undefined is in non-browser environments, and
|
|
14966
|
+
// in those environments OAuth redirect does not make sense anyway
|
|
14967
|
+
// and will fail fast in startOAuthRedirect().
|
|
14998
14968
|
// Start OAuth redirect flow - page navigates away
|
|
14999
14969
|
startOAuthRedirect({
|
|
15000
14970
|
databaseUrl: url,
|
|
@@ -17047,13 +17017,13 @@
|
|
|
17047
17017
|
color: "#3c4043"
|
|
17048
17018
|
},
|
|
17049
17019
|
ProviderGitHub: {
|
|
17050
|
-
backgroundColor: "#
|
|
17051
|
-
border: "1px solid #
|
|
17052
|
-
color: "#
|
|
17020
|
+
backgroundColor: "#ffffff",
|
|
17021
|
+
border: "1px solid #dadce0",
|
|
17022
|
+
color: "#181717"
|
|
17053
17023
|
},
|
|
17054
17024
|
ProviderMicrosoft: {
|
|
17055
17025
|
backgroundColor: "#ffffff",
|
|
17056
|
-
border: "1px solid #
|
|
17026
|
+
border: "1px solid #dadce0",
|
|
17057
17027
|
color: "#5e5e5e"
|
|
17058
17028
|
},
|
|
17059
17029
|
ProviderApple: {
|
|
@@ -17062,9 +17032,9 @@
|
|
|
17062
17032
|
color: "#ffffff"
|
|
17063
17033
|
},
|
|
17064
17034
|
ProviderCustom: {
|
|
17065
|
-
backgroundColor: "#
|
|
17066
|
-
border: "1px solid #
|
|
17067
|
-
color: "#
|
|
17035
|
+
backgroundColor: "#ffffff",
|
|
17036
|
+
border: "1px solid #dadce0",
|
|
17037
|
+
color: "#181717"
|
|
17068
17038
|
},
|
|
17069
17039
|
// Divider styles
|
|
17070
17040
|
Divider: {
|
|
@@ -17155,39 +17125,13 @@
|
|
|
17155
17125
|
* Generic button component for selectable options.
|
|
17156
17126
|
* Displays the option's icon and display name.
|
|
17157
17127
|
*
|
|
17158
|
-
* The icon can be:
|
|
17159
|
-
* - Inline SVG (iconSvg) - rendered directly with dangerouslySetInnerHTML
|
|
17160
|
-
* - Image URL (iconUrl) - rendered as an img tag
|
|
17161
|
-
*
|
|
17162
17128
|
* Style is determined by the styleHint property for branding purposes.
|
|
17163
17129
|
*/
|
|
17164
17130
|
function OptionButton({ option, onClick }) {
|
|
17165
|
-
const { displayName, iconUrl,
|
|
17131
|
+
const { displayName, iconUrl, styleHint } = option;
|
|
17166
17132
|
const style = getOptionStyle(styleHint);
|
|
17167
|
-
// Get the text color from the button style for SVG fill processing
|
|
17168
|
-
const textColor = style.color || '#000000';
|
|
17169
|
-
// Process SVG to replace currentColor with actual text color
|
|
17170
|
-
const processedSvg = iconSvg
|
|
17171
|
-
? iconSvg
|
|
17172
|
-
.replace(/fill="currentColor"/gi, `fill="${textColor}"`)
|
|
17173
|
-
.replace(/fill='currentColor'/gi, `fill='${textColor}'`)
|
|
17174
|
-
.replace(/stroke="currentColor"/gi, `stroke="${textColor}"`)
|
|
17175
|
-
.replace(/stroke='currentColor'/gi, `stroke='${textColor}'`)
|
|
17176
|
-
: null;
|
|
17177
|
-
// Render the appropriate icon
|
|
17178
|
-
const renderIcon = () => {
|
|
17179
|
-
// Inline SVG
|
|
17180
|
-
if (processedSvg) {
|
|
17181
|
-
return (_$1("span", { style: Styles.ProviderButtonIcon, "aria-hidden": "true", dangerouslySetInnerHTML: { __html: processedSvg } }));
|
|
17182
|
-
}
|
|
17183
|
-
// Image URL
|
|
17184
|
-
if (iconUrl) {
|
|
17185
|
-
return (_$1("img", { src: iconUrl, alt: "", style: Styles.ProviderButtonIcon, "aria-hidden": "true" }));
|
|
17186
|
-
}
|
|
17187
|
-
return null;
|
|
17188
|
-
};
|
|
17189
17133
|
return (_$1("button", { type: "button", style: style, onClick: onClick, class: `dxc-option-btn${styleHint ? ` dxc-option-${styleHint}` : ''}`, "aria-label": displayName },
|
|
17190
|
-
|
|
17134
|
+
iconUrl && (_$1("img", { src: iconUrl, alt: "", style: Styles.ProviderButtonIcon, "aria-hidden": "true" })),
|
|
17191
17135
|
_$1("span", { style: Styles.ProviderButtonText }, displayName)));
|
|
17192
17136
|
}
|
|
17193
17137
|
/**
|
|
@@ -17974,7 +17918,7 @@
|
|
|
17974
17918
|
const syncComplete = new rxjs.Subject();
|
|
17975
17919
|
dexie.cloud = {
|
|
17976
17920
|
// @ts-ignore
|
|
17977
|
-
version: "4.3.
|
|
17921
|
+
version: "4.3.6",
|
|
17978
17922
|
options: Object.assign({}, DEFAULT_OPTIONS),
|
|
17979
17923
|
schema: null,
|
|
17980
17924
|
get currentUserId() {
|
|
@@ -18244,12 +18188,18 @@
|
|
|
18244
18188
|
pendingOAuthError = null; // Clear pending error
|
|
18245
18189
|
console.debug('[dexie-cloud] Showing OAuth error:', error.message);
|
|
18246
18190
|
// Show alert to user about the OAuth error
|
|
18247
|
-
|
|
18248
|
-
|
|
18249
|
-
|
|
18250
|
-
|
|
18251
|
-
|
|
18252
|
-
|
|
18191
|
+
// Guard so UI errors don't abort initialization
|
|
18192
|
+
try {
|
|
18193
|
+
yield alertUser(db.cloud.userInteraction, 'Authentication Error', {
|
|
18194
|
+
type: 'error',
|
|
18195
|
+
messageCode: 'GENERIC_ERROR',
|
|
18196
|
+
message: error.message,
|
|
18197
|
+
messageParams: { provider: error.provider || 'unknown' }
|
|
18198
|
+
});
|
|
18199
|
+
}
|
|
18200
|
+
catch (uiError) {
|
|
18201
|
+
console.error('[dexie-cloud] Failed to show OAuth error alert:', uiError);
|
|
18202
|
+
}
|
|
18253
18203
|
}
|
|
18254
18204
|
// Process pending OAuth callback if present (from dxc-auth redirect)
|
|
18255
18205
|
if (pendingOAuthCode && !db.cloud.isServiceWorkerDB) {
|
|
@@ -18353,7 +18303,7 @@
|
|
|
18353
18303
|
}
|
|
18354
18304
|
}
|
|
18355
18305
|
// @ts-ignore
|
|
18356
|
-
dexieCloud.version = "4.3.
|
|
18306
|
+
dexieCloud.version = "4.3.6";
|
|
18357
18307
|
Dexie.Cloud = dexieCloud;
|
|
18358
18308
|
|
|
18359
18309
|
// In case the SW lives for a while, let it reuse already opened connections:
|