dexie-cloud-addon 4.4.3 → 4.4.4
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/modern/DexieCloudAPI.d.ts +13 -0
- package/dist/modern/authentication/exchangeOAuthCode.d.ts +2 -0
- package/dist/modern/authentication/interactWithUser.d.ts +1 -1
- package/dist/modern/dexie-cloud-addon.js +175 -75
- 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/errors/PolicyRejectionError.d.ts +23 -0
- package/dist/modern/extend-dexie-interface.d.ts +1 -1
- package/dist/modern/service-worker.js +175 -75
- 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/DXCAlert.d.ts +1 -1
- package/dist/umd/dexie-cloud-addon.js +176 -76
- 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 +176 -76
- 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 +2 -2
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
export type DXCAlert = DXCErrorAlert | DXCWarningAlert | DXCInfoAlert;
|
|
2
2
|
export interface DXCErrorAlert {
|
|
3
3
|
type: 'error';
|
|
4
|
-
messageCode: 'INVALID_OTP' | 'INVALID_EMAIL' | 'LICENSE_LIMIT_REACHED' | 'GENERIC_ERROR';
|
|
4
|
+
messageCode: 'INVALID_OTP' | 'INVALID_EMAIL' | 'LICENSE_LIMIT_REACHED' | 'GENERIC_ERROR' | 'USER_NOT_REGISTERED' | 'USER_NOT_ACCEPTED' | 'NO_SEATS_AVAILABLE' | 'USER_DEACTIVATED' | 'WEBHOOK_ERROR';
|
|
5
5
|
message: string;
|
|
6
6
|
messageParams: {
|
|
7
7
|
[paramName: string]: string;
|
|
@@ -8,7 +8,7 @@
|
|
|
8
8
|
*
|
|
9
9
|
* ==========================================================================
|
|
10
10
|
*
|
|
11
|
-
* Version 4.4.
|
|
11
|
+
* Version 4.4.4, Wed Mar 25 2026
|
|
12
12
|
*
|
|
13
13
|
* https://dexie.org
|
|
14
14
|
*
|
|
@@ -3158,9 +3158,10 @@
|
|
|
3158
3158
|
cancelLabel: null,
|
|
3159
3159
|
});
|
|
3160
3160
|
}
|
|
3161
|
-
function promptForEmail(userInteraction, title, emailHint) {
|
|
3161
|
+
function promptForEmail(userInteraction, title, emailHint, initialAlert) {
|
|
3162
3162
|
return __awaiter(this, void 0, void 0, function* () {
|
|
3163
3163
|
let email = emailHint || '';
|
|
3164
|
+
let firstPrompt = true;
|
|
3164
3165
|
// Regular expression for email validation
|
|
3165
3166
|
// ^[\w-+.]+@([\w-]+\.)+[\w-]{2,10}(\sas\s[\w-+.]+@([\w-]+\.)+[\w-]{2,10})?$
|
|
3166
3167
|
//
|
|
@@ -3183,19 +3184,21 @@
|
|
|
3183
3184
|
// and GLOBAL_WRITE permissions on the database. The email will be checked on the server before
|
|
3184
3185
|
// allowing it and giving out a token for email2, using the OTP sent to email1.
|
|
3185
3186
|
while (!email || !/^[\w-+.]+@([\w-]+\.)+[\w-]{2,10}(\sas\s[\w-+.]+@([\w-]+\.)+[\w-]{2,10})?$/.test(email)) {
|
|
3187
|
+
const alerts = [];
|
|
3188
|
+
if (firstPrompt && initialAlert)
|
|
3189
|
+
alerts.push(initialAlert);
|
|
3190
|
+
if (email)
|
|
3191
|
+
alerts.push({
|
|
3192
|
+
type: 'error',
|
|
3193
|
+
messageCode: 'INVALID_EMAIL',
|
|
3194
|
+
message: 'Please enter a valid email address',
|
|
3195
|
+
messageParams: {},
|
|
3196
|
+
});
|
|
3197
|
+
firstPrompt = false;
|
|
3186
3198
|
email = (yield interactWithUser(userInteraction, {
|
|
3187
3199
|
type: 'email',
|
|
3188
3200
|
title,
|
|
3189
|
-
alerts
|
|
3190
|
-
? [
|
|
3191
|
-
{
|
|
3192
|
-
type: 'error',
|
|
3193
|
-
messageCode: 'INVALID_EMAIL',
|
|
3194
|
-
message: 'Please enter a valid email address',
|
|
3195
|
-
messageParams: {},
|
|
3196
|
-
},
|
|
3197
|
-
]
|
|
3198
|
-
: [],
|
|
3201
|
+
alerts,
|
|
3199
3202
|
fields: {
|
|
3200
3203
|
email: {
|
|
3201
3204
|
type: 'email',
|
|
@@ -3338,6 +3341,29 @@
|
|
|
3338
3341
|
}
|
|
3339
3342
|
}
|
|
3340
3343
|
|
|
3344
|
+
/** Thrown when the server rejects a user due to a policy rule.
|
|
3345
|
+
*
|
|
3346
|
+
* Unlike a generic 403, this error carries a machine-readable `code` so that
|
|
3347
|
+
* the addon can convert it into a DXCUserInteraction challenge rather than
|
|
3348
|
+
* simply throwing.
|
|
3349
|
+
*/
|
|
3350
|
+
class PolicyRejectionError extends Error {
|
|
3351
|
+
constructor(body) {
|
|
3352
|
+
super(body.message);
|
|
3353
|
+
this.code = body.code;
|
|
3354
|
+
}
|
|
3355
|
+
get name() {
|
|
3356
|
+
return 'PolicyRejectionError';
|
|
3357
|
+
}
|
|
3358
|
+
}
|
|
3359
|
+
/** Returns true when a plain fetch Response contains a structured PolicyError body. */
|
|
3360
|
+
function isPolicyErrorBody(value) {
|
|
3361
|
+
return (typeof value === 'object' &&
|
|
3362
|
+
value !== null &&
|
|
3363
|
+
typeof value.code === 'string' &&
|
|
3364
|
+
typeof value.message === 'string');
|
|
3365
|
+
}
|
|
3366
|
+
|
|
3341
3367
|
const SECONDS = 1000;
|
|
3342
3368
|
const MINUTES = 60 * SECONDS;
|
|
3343
3369
|
|
|
@@ -3512,6 +3538,10 @@
|
|
|
3512
3538
|
if (error instanceof OAuthRedirectError || (error === null || error === void 0 ? void 0 : error.name) === 'OAuthRedirectError') {
|
|
3513
3539
|
throw error; // Re-throw without logging
|
|
3514
3540
|
}
|
|
3541
|
+
// Policy rejections have already been shown to the user as a challenge
|
|
3542
|
+
if (error instanceof PolicyRejectionError || (error === null || error === void 0 ? void 0 : error.name) === 'PolicyRejectionError') {
|
|
3543
|
+
throw error;
|
|
3544
|
+
}
|
|
3515
3545
|
if (error instanceof TokenErrorResponseError) {
|
|
3516
3546
|
yield alertUser(userInteraction, error.title, {
|
|
3517
3547
|
type: 'error',
|
|
@@ -3710,13 +3740,8 @@
|
|
|
3710
3740
|
*/
|
|
3711
3741
|
function exchangeOAuthCode(options) {
|
|
3712
3742
|
return __awaiter(this, void 0, void 0, function* () {
|
|
3713
|
-
const { databaseUrl, code, publicKey, scopes = ['ACCESS_DB'] } = options;
|
|
3714
|
-
const tokenRequest = {
|
|
3715
|
-
grant_type: 'authorization_code',
|
|
3716
|
-
code,
|
|
3717
|
-
public_key: publicKey,
|
|
3718
|
-
scopes,
|
|
3719
|
-
};
|
|
3743
|
+
const { databaseUrl, code, publicKey, scopes = ['ACCESS_DB'], intent } = options;
|
|
3744
|
+
const tokenRequest = Object.assign({ grant_type: 'authorization_code', code, public_key: publicKey, scopes }, (intent !== undefined ? { intent } : {}));
|
|
3720
3745
|
try {
|
|
3721
3746
|
const res = yield fetch(`${databaseUrl}/token`, {
|
|
3722
3747
|
method: 'POST',
|
|
@@ -3727,6 +3752,20 @@
|
|
|
3727
3752
|
if (!res.ok) {
|
|
3728
3753
|
// Read body once as text to avoid stream consumption issues
|
|
3729
3754
|
const bodyText = yield res.text().catch(() => res.statusText);
|
|
3755
|
+
// Check for structured policy rejection (403 with JSON body)
|
|
3756
|
+
if (res.status === 403) {
|
|
3757
|
+
try {
|
|
3758
|
+
const body = JSON.parse(bodyText);
|
|
3759
|
+
if (isPolicyErrorBody(body)) {
|
|
3760
|
+
throw new PolicyRejectionError(body);
|
|
3761
|
+
}
|
|
3762
|
+
}
|
|
3763
|
+
catch (e) {
|
|
3764
|
+
if (e instanceof PolicyRejectionError)
|
|
3765
|
+
throw e;
|
|
3766
|
+
// Fall through to generic error
|
|
3767
|
+
}
|
|
3768
|
+
}
|
|
3730
3769
|
if (res.status === 400 || res.status === 401) {
|
|
3731
3770
|
// Try to parse error response as JSON
|
|
3732
3771
|
try {
|
|
@@ -3862,32 +3901,59 @@
|
|
|
3862
3901
|
|
|
3863
3902
|
function otpFetchTokenCallback(db) {
|
|
3864
3903
|
const { userInteraction } = db.cloud;
|
|
3865
|
-
|
|
3866
|
-
|
|
3904
|
+
/**
|
|
3905
|
+
* Core authentication function.
|
|
3906
|
+
*
|
|
3907
|
+
* @param public_key - RSA public key PEM for the session
|
|
3908
|
+
* @param hints - Optional login hints from the caller
|
|
3909
|
+
* @param policyAlert - When set, a previous attempt was rejected by a server
|
|
3910
|
+
* policy rule. The alert is injected into the first
|
|
3911
|
+
* interactive prompt so the user sees why they were
|
|
3912
|
+
* rejected without changing any other flow logic.
|
|
3913
|
+
*/
|
|
3914
|
+
function otpAuthenticate(_a, policyAlert_1) {
|
|
3915
|
+
return __awaiter(this, arguments, void 0, function* ({ public_key, hints }, policyAlert) {
|
|
3867
3916
|
var _b, _c;
|
|
3868
3917
|
let tokenRequest;
|
|
3869
3918
|
const url = (_b = db.cloud.options) === null || _b === void 0 ? void 0 : _b.databaseUrl;
|
|
3870
3919
|
if (!url)
|
|
3871
3920
|
throw new Error(`No database URL given.`);
|
|
3921
|
+
const intent = hints === null || hints === void 0 ? void 0 : hints.intent;
|
|
3922
|
+
// ── Non-interactive paths ──────────────────────────────────────────────
|
|
3923
|
+
// These paths POST directly without prompting the user. If a policyAlert
|
|
3924
|
+
// exists (from a previous rejected attempt), show it with a message-alert
|
|
3925
|
+
// before proceeding so the user understands what happened.
|
|
3872
3926
|
// Handle OAuth code exchange (from redirect/deep link flows)
|
|
3873
3927
|
if ((hints === null || hints === void 0 ? void 0 : hints.oauthCode) && hints.provider) {
|
|
3874
|
-
|
|
3875
|
-
|
|
3876
|
-
|
|
3877
|
-
|
|
3878
|
-
|
|
3879
|
-
|
|
3928
|
+
try {
|
|
3929
|
+
return yield exchangeOAuthCode({
|
|
3930
|
+
databaseUrl: url,
|
|
3931
|
+
code: hints.oauthCode,
|
|
3932
|
+
publicKey: public_key,
|
|
3933
|
+
scopes: ['ACCESS_DB'],
|
|
3934
|
+
intent,
|
|
3935
|
+
});
|
|
3936
|
+
}
|
|
3937
|
+
catch (err) {
|
|
3938
|
+
if (err instanceof PolicyRejectionError) {
|
|
3939
|
+
return yield otpAuthenticate({ public_key, hints: undefined }, toPolicyAlert(err));
|
|
3940
|
+
}
|
|
3941
|
+
throw err;
|
|
3942
|
+
}
|
|
3880
3943
|
}
|
|
3881
|
-
// Handle OAuth provider login via redirect
|
|
3944
|
+
// Handle OAuth provider login via redirect (programmatic, no interaction)
|
|
3882
3945
|
if (hints === null || hints === void 0 ? void 0 : hints.provider) {
|
|
3946
|
+
if (policyAlert) {
|
|
3947
|
+
// A previous OAuth attempt was rejected. Fall through to the
|
|
3948
|
+
// interactive flow — policyAlert will be shown inside the prompt.
|
|
3949
|
+
return yield otpAuthenticate({ public_key, hints: undefined }, policyAlert);
|
|
3950
|
+
}
|
|
3883
3951
|
let resolvedRedirectUri = undefined;
|
|
3884
3952
|
if (hints.redirectPath) {
|
|
3885
|
-
// If redirectPath is absolute, use as is. If relative, resolve against current location
|
|
3886
3953
|
if (/^https?:\/\//i.test(hints.redirectPath)) {
|
|
3887
3954
|
resolvedRedirectUri = hints.redirectPath;
|
|
3888
3955
|
}
|
|
3889
3956
|
else if (typeof window !== 'undefined' && window.location) {
|
|
3890
|
-
// Use URL constructor to resolve relative path
|
|
3891
3957
|
resolvedRedirectUri = new URL(hints.redirectPath, window.location.href).toString();
|
|
3892
3958
|
}
|
|
3893
3959
|
else if (typeof location !== 'undefined' && location.href) {
|
|
@@ -3895,23 +3961,27 @@
|
|
|
3895
3961
|
}
|
|
3896
3962
|
}
|
|
3897
3963
|
initiateOAuthRedirect(db, hints.provider, resolvedRedirectUri);
|
|
3898
|
-
// This function never returns - page navigates away
|
|
3899
3964
|
throw new OAuthRedirectError(hints.provider);
|
|
3900
3965
|
}
|
|
3966
|
+
// ── Interactive paths ──────────────────────────────────────────────────
|
|
3967
|
+
// policyAlert (if set) is injected into the first prompt so the user sees
|
|
3968
|
+
// it alongside the normal auth UI — no separate error screen needed.
|
|
3901
3969
|
if ((hints === null || hints === void 0 ? void 0 : hints.grant_type) === 'demo') {
|
|
3902
|
-
const demo_user = yield promptForEmail(userInteraction, 'Enter a demo user email', (hints === null || hints === void 0 ? void 0 : hints.email) || (hints === null || hints === void 0 ? void 0 : hints.userId));
|
|
3970
|
+
const demo_user = yield promptForEmail(userInteraction, 'Enter a demo user email', (hints === null || hints === void 0 ? void 0 : hints.email) || (hints === null || hints === void 0 ? void 0 : hints.userId), policyAlert);
|
|
3903
3971
|
tokenRequest = {
|
|
3904
3972
|
demo_user,
|
|
3905
3973
|
grant_type: 'demo',
|
|
3906
3974
|
scopes: ['ACCESS_DB'],
|
|
3907
|
-
public_key
|
|
3975
|
+
public_key,
|
|
3908
3976
|
};
|
|
3909
3977
|
}
|
|
3910
3978
|
else if ((hints === null || hints === void 0 ? void 0 : hints.otpId) && hints.otp) {
|
|
3911
|
-
//
|
|
3912
|
-
//
|
|
3913
|
-
|
|
3914
|
-
|
|
3979
|
+
// Magic-link flow: OTP already supplied by the caller (e.g. from email).
|
|
3980
|
+
// No interaction — show alert as a plain message if there is one.
|
|
3981
|
+
if (policyAlert) {
|
|
3982
|
+
yield alertUser(userInteraction, 'Access Denied', policyAlert);
|
|
3983
|
+
return yield otpAuthenticate({ public_key, hints: undefined }, policyAlert);
|
|
3984
|
+
}
|
|
3915
3985
|
tokenRequest = {
|
|
3916
3986
|
grant_type: 'otp',
|
|
3917
3987
|
otp_id: hints.otpId,
|
|
@@ -3921,56 +3991,52 @@
|
|
|
3921
3991
|
};
|
|
3922
3992
|
}
|
|
3923
3993
|
else if ((hints === null || hints === void 0 ? void 0 : hints.grant_type) === 'otp' || (hints === null || hints === void 0 ? void 0 : hints.email)) {
|
|
3924
|
-
//
|
|
3925
|
-
const email = (hints === null || hints === void 0 ? void 0 : hints.email) ||
|
|
3994
|
+
// Caller explicitly requested OTP — skip provider selection.
|
|
3995
|
+
const email = (hints === null || hints === void 0 ? void 0 : hints.email) ||
|
|
3996
|
+
(yield promptForEmail(userInteraction, 'Enter email address', undefined, policyAlert));
|
|
3926
3997
|
if (/@demo.local$/.test(email)) {
|
|
3927
3998
|
tokenRequest = {
|
|
3928
3999
|
demo_user: email,
|
|
3929
4000
|
grant_type: 'demo',
|
|
3930
4001
|
scopes: ['ACCESS_DB'],
|
|
3931
|
-
public_key
|
|
4002
|
+
public_key,
|
|
3932
4003
|
};
|
|
3933
4004
|
}
|
|
3934
4005
|
else {
|
|
3935
|
-
tokenRequest = {
|
|
3936
|
-
email,
|
|
3937
|
-
grant_type: 'otp',
|
|
3938
|
-
scopes: ['ACCESS_DB'],
|
|
3939
|
-
};
|
|
4006
|
+
tokenRequest = Object.assign({ email, grant_type: 'otp', scopes: ['ACCESS_DB'] }, (intent !== undefined ? { intent } : {}));
|
|
3940
4007
|
}
|
|
3941
4008
|
}
|
|
3942
4009
|
else {
|
|
3943
|
-
//
|
|
4010
|
+
// Default path: check for OAuth providers, then fall back to OTP.
|
|
3944
4011
|
const socialAuthEnabled = ((_c = db.cloud.options) === null || _c === void 0 ? void 0 : _c.socialAuth) !== false;
|
|
3945
4012
|
const authProviders = yield fetchAuthProviders(url, socialAuthEnabled);
|
|
3946
|
-
// If we have OAuth providers available, prompt for selection
|
|
3947
4013
|
if (authProviders.providers.length > 0) {
|
|
3948
|
-
const
|
|
4014
|
+
const providerAlerts = policyAlert ? [policyAlert] : [];
|
|
4015
|
+
const selection = yield promptForProvider(userInteraction, authProviders.providers, authProviders.otpEnabled, 'Sign in', providerAlerts);
|
|
3949
4016
|
if (selection.type === 'provider') {
|
|
3950
|
-
// User selected an OAuth provider - initiate redirect
|
|
3951
4017
|
initiateOAuthRedirect(db, selection.provider);
|
|
3952
|
-
// This function never returns - page navigates away
|
|
3953
4018
|
throw new OAuthRedirectError(selection.provider);
|
|
3954
4019
|
}
|
|
3955
|
-
// User chose OTP
|
|
4020
|
+
// User chose OTP — fall through to email prompt (no policyAlert here;
|
|
4021
|
+
// it was already shown in the provider prompt above).
|
|
3956
4022
|
}
|
|
3957
|
-
const email = yield promptForEmail(userInteraction, 'Enter email address', hints === null || hints === void 0 ? void 0 : hints.email
|
|
4023
|
+
const email = yield promptForEmail(userInteraction, 'Enter email address', hints === null || hints === void 0 ? void 0 : hints.email,
|
|
4024
|
+
// Show policyAlert in email prompt only if there were no providers
|
|
4025
|
+
// (otherwise it was already shown in the provider selection above).
|
|
4026
|
+
authProviders.providers.length === 0 ? policyAlert : undefined);
|
|
3958
4027
|
if (/@demo.local$/.test(email)) {
|
|
3959
4028
|
tokenRequest = {
|
|
3960
4029
|
demo_user: email,
|
|
3961
4030
|
grant_type: 'demo',
|
|
3962
4031
|
scopes: ['ACCESS_DB'],
|
|
3963
|
-
public_key
|
|
4032
|
+
public_key,
|
|
3964
4033
|
};
|
|
3965
4034
|
}
|
|
3966
4035
|
else {
|
|
3967
|
-
tokenRequest = {
|
|
3968
|
-
email,
|
|
3969
|
-
grant_type: 'otp',
|
|
3970
|
-
scopes: ['ACCESS_DB'],
|
|
3971
|
-
};
|
|
4036
|
+
tokenRequest = Object.assign({ email, grant_type: 'otp', scopes: ['ACCESS_DB'] }, (intent !== undefined ? { intent } : {}));
|
|
3972
4037
|
}
|
|
3973
4038
|
}
|
|
4039
|
+
// ── POST /token (step 1) ───────────────────────────────────────────────
|
|
3974
4040
|
const res1 = yield fetch(`${url}/token`, {
|
|
3975
4041
|
body: JSON.stringify(tokenRequest),
|
|
3976
4042
|
method: 'post',
|
|
@@ -3978,19 +4044,22 @@
|
|
|
3978
4044
|
mode: 'cors',
|
|
3979
4045
|
});
|
|
3980
4046
|
if (res1.status !== 200) {
|
|
4047
|
+
const alert = yield tryParsePolicyAlert(res1);
|
|
4048
|
+
if (alert) {
|
|
4049
|
+
// Policy rejection — restart the flow with the error injected.
|
|
4050
|
+
return yield otpAuthenticate({ public_key, hints: undefined }, alert);
|
|
4051
|
+
}
|
|
3981
4052
|
const errMsg = yield res1.text();
|
|
3982
|
-
yield alertUser(userInteraction,
|
|
4053
|
+
yield alertUser(userInteraction, 'Token request failed', {
|
|
3983
4054
|
type: 'error',
|
|
3984
4055
|
messageCode: 'GENERIC_ERROR',
|
|
3985
4056
|
message: errMsg,
|
|
3986
|
-
messageParams: {}
|
|
4057
|
+
messageParams: {},
|
|
3987
4058
|
}).catch(() => { });
|
|
3988
4059
|
throw new HttpError(res1, errMsg);
|
|
3989
4060
|
}
|
|
3990
4061
|
const response = yield res1.json();
|
|
3991
4062
|
if (response.type === 'tokens' || response.type === 'error') {
|
|
3992
|
-
// Demo user request can get a "tokens" response right away
|
|
3993
|
-
// Error can also be returned right away.
|
|
3994
4063
|
return response;
|
|
3995
4064
|
}
|
|
3996
4065
|
else if (tokenRequest.grant_type === 'otp' && 'email' in tokenRequest) {
|
|
@@ -3998,6 +4067,7 @@
|
|
|
3998
4067
|
throw new Error(`Unexpected response from ${url}/token`);
|
|
3999
4068
|
const otp = yield promptForOTP(userInteraction, tokenRequest.email);
|
|
4000
4069
|
const tokenRequest2 = Object.assign(Object.assign({}, tokenRequest), { otp: otp || '', otp_id: response.otp_id, public_key });
|
|
4070
|
+
// ── POST /token (step 2: OTP verification) ─────────────────────────
|
|
4001
4071
|
let res2 = yield fetch(`${url}/token`, {
|
|
4002
4072
|
body: JSON.stringify(tokenRequest2),
|
|
4003
4073
|
method: 'post',
|
|
@@ -4010,7 +4080,7 @@
|
|
|
4010
4080
|
type: 'error',
|
|
4011
4081
|
messageCode: 'INVALID_OTP',
|
|
4012
4082
|
message: errorText,
|
|
4013
|
-
messageParams: {}
|
|
4083
|
+
messageParams: {},
|
|
4014
4084
|
});
|
|
4015
4085
|
res2 = yield fetch(`${url}/token`, {
|
|
4016
4086
|
body: JSON.stringify(tokenRequest2),
|
|
@@ -4020,6 +4090,10 @@
|
|
|
4020
4090
|
});
|
|
4021
4091
|
}
|
|
4022
4092
|
if (res2.status !== 200) {
|
|
4093
|
+
const alert = yield tryParsePolicyAlert(res2);
|
|
4094
|
+
if (alert) {
|
|
4095
|
+
return yield otpAuthenticate({ public_key, hints: undefined }, alert);
|
|
4096
|
+
}
|
|
4023
4097
|
const errMsg = yield res2.text();
|
|
4024
4098
|
throw new HttpError(res2, errMsg);
|
|
4025
4099
|
}
|
|
@@ -4030,14 +4104,11 @@
|
|
|
4030
4104
|
throw new Error(`Unexpected response from ${url}/token`);
|
|
4031
4105
|
}
|
|
4032
4106
|
});
|
|
4033
|
-
}
|
|
4107
|
+
}
|
|
4108
|
+
return ({ public_key, hints }) => otpAuthenticate({ public_key, hints });
|
|
4034
4109
|
}
|
|
4035
4110
|
/**
|
|
4036
4111
|
* Initiates OAuth login via full page redirect.
|
|
4037
|
-
*
|
|
4038
|
-
* The page will navigate away to the OAuth provider. After authentication,
|
|
4039
|
-
* the user is redirected back with a dxc-auth query parameter that is
|
|
4040
|
-
* automatically detected by db.cloud.configure().
|
|
4041
4112
|
*/
|
|
4042
4113
|
function initiateOAuthRedirect(db, provider, redirectUriOverride) {
|
|
4043
4114
|
var _a, _b;
|
|
@@ -4047,17 +4118,44 @@
|
|
|
4047
4118
|
const redirectUri = redirectUriOverride ||
|
|
4048
4119
|
((_b = db.cloud.options) === null || _b === void 0 ? void 0 : _b.oauthRedirectUri) ||
|
|
4049
4120
|
(typeof location !== 'undefined' ? location.href : undefined);
|
|
4050
|
-
// CodeRabbit suggested to fail fast here, but the only situation where
|
|
4051
|
-
// redirectUri would be undefined is in non-browser environments, and
|
|
4052
|
-
// in those environments OAuth redirect does not make sense anyway
|
|
4053
|
-
// and will fail fast in startOAuthRedirect().
|
|
4054
|
-
// Start OAuth redirect flow - page navigates away
|
|
4055
4121
|
startOAuthRedirect({
|
|
4056
4122
|
databaseUrl: url,
|
|
4057
4123
|
provider,
|
|
4058
4124
|
redirectUri,
|
|
4059
4125
|
});
|
|
4060
4126
|
}
|
|
4127
|
+
/**
|
|
4128
|
+
* Converts a PolicyRejectionError to a DXCAlert for injection into prompts.
|
|
4129
|
+
*/
|
|
4130
|
+
function toPolicyAlert(err) {
|
|
4131
|
+
return {
|
|
4132
|
+
type: 'error',
|
|
4133
|
+
messageCode: err.code,
|
|
4134
|
+
message: err.message,
|
|
4135
|
+
messageParams: {},
|
|
4136
|
+
};
|
|
4137
|
+
}
|
|
4138
|
+
/**
|
|
4139
|
+
* Tries to parse a failed Response as a structured PolicyError body.
|
|
4140
|
+
* Returns a DXCAlert if it is one, otherwise returns null.
|
|
4141
|
+
* Safe to call: reads body via clone() so the original Response is untouched.
|
|
4142
|
+
*/
|
|
4143
|
+
function tryParsePolicyAlert(res) {
|
|
4144
|
+
return __awaiter(this, void 0, void 0, function* () {
|
|
4145
|
+
if (res.status !== 403)
|
|
4146
|
+
return null;
|
|
4147
|
+
try {
|
|
4148
|
+
const body = yield res.clone().json();
|
|
4149
|
+
if (isPolicyErrorBody(body)) {
|
|
4150
|
+
return toPolicyAlert(new PolicyRejectionError(body));
|
|
4151
|
+
}
|
|
4152
|
+
}
|
|
4153
|
+
catch (_a) {
|
|
4154
|
+
// Not JSON
|
|
4155
|
+
}
|
|
4156
|
+
return null;
|
|
4157
|
+
});
|
|
4158
|
+
}
|
|
4061
4159
|
|
|
4062
4160
|
/** A way to log to console in production without terser stripping out
|
|
4063
4161
|
* it from the release bundle.
|
|
@@ -14359,7 +14457,7 @@
|
|
|
14359
14457
|
*
|
|
14360
14458
|
* ==========================================================================
|
|
14361
14459
|
*
|
|
14362
|
-
* Version 4.4.0,
|
|
14460
|
+
* Version 4.4.0, Wed Mar 25 2026
|
|
14363
14461
|
*
|
|
14364
14462
|
* https://dexie.org
|
|
14365
14463
|
*
|
|
@@ -17006,6 +17104,7 @@
|
|
|
17006
17104
|
return cursor.start(() => {
|
|
17007
17105
|
const rawValue = cursor.value;
|
|
17008
17106
|
if (!rawValue || !hasUnresolvedBlobRefs(rawValue)) {
|
|
17107
|
+
wrappedCursor.value = rawValue;
|
|
17009
17108
|
onNext();
|
|
17010
17109
|
return;
|
|
17011
17110
|
}
|
|
@@ -17014,6 +17113,7 @@
|
|
|
17014
17113
|
onNext();
|
|
17015
17114
|
}, err => {
|
|
17016
17115
|
console.error('Failed to resolve BlobRefs for cursor value:', err);
|
|
17116
|
+
wrappedCursor.value = rawValue;
|
|
17017
17117
|
onNext();
|
|
17018
17118
|
});
|
|
17019
17119
|
});
|
|
@@ -19503,7 +19603,7 @@
|
|
|
19503
19603
|
const downloading$ = createDownloadingState();
|
|
19504
19604
|
dexie.cloud = {
|
|
19505
19605
|
// @ts-ignore
|
|
19506
|
-
version: "4.4.
|
|
19606
|
+
version: "4.4.4",
|
|
19507
19607
|
options: Object.assign({}, DEFAULT_OPTIONS),
|
|
19508
19608
|
schema: null,
|
|
19509
19609
|
get currentUserId() {
|
|
@@ -19930,7 +20030,7 @@
|
|
|
19930
20030
|
}
|
|
19931
20031
|
}
|
|
19932
20032
|
// @ts-ignore
|
|
19933
|
-
dexieCloud.version = "4.4.
|
|
20033
|
+
dexieCloud.version = "4.4.4";
|
|
19934
20034
|
Dexie.Cloud = dexieCloud;
|
|
19935
20035
|
|
|
19936
20036
|
exports.default = dexieCloud;
|