@hexclave/js 1.0.0 → 1.0.2
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/README.md +7 -23
- package/dist/dev-tool/dev-tool-core.d.ts.map +1 -1
- package/dist/dev-tool/dev-tool-core.js +23 -23
- package/dist/dev-tool/dev-tool-core.js.map +1 -1
- package/dist/dev-tool/index.js +6 -6
- package/dist/dev-tool/index.js.map +1 -1
- package/dist/esm/dev-tool/dev-tool-core.d.ts.map +1 -1
- package/dist/esm/dev-tool/dev-tool-core.js +2 -2
- package/dist/esm/dev-tool/dev-tool-core.js.map +1 -1
- package/dist/esm/dev-tool/index.js.map +1 -1
- package/dist/esm/index.d.ts +1 -1
- package/dist/esm/index.js +1 -2
- package/dist/esm/integrations/convex.js.map +1 -1
- package/dist/esm/lib/auth.js.map +1 -1
- package/dist/esm/lib/auth.test.js.map +1 -1
- package/dist/esm/lib/cookie.js.map +1 -1
- package/dist/esm/lib/stack-app/api-keys/index.js.map +1 -1
- package/dist/esm/lib/stack-app/apps/implementations/admin-app-impl.d.ts +11 -11
- package/dist/esm/lib/stack-app/apps/implementations/admin-app-impl.d.ts.map +1 -1
- package/dist/esm/lib/stack-app/apps/implementations/admin-app-impl.js +3 -1
- package/dist/esm/lib/stack-app/apps/implementations/admin-app-impl.js.map +1 -1
- package/dist/esm/lib/stack-app/apps/implementations/client-app-impl.cross-domain.test.js +67 -1
- package/dist/esm/lib/stack-app/apps/implementations/client-app-impl.cross-domain.test.js.map +1 -1
- package/dist/esm/lib/stack-app/apps/implementations/client-app-impl.d.ts +4 -3
- package/dist/esm/lib/stack-app/apps/implementations/client-app-impl.d.ts.map +1 -1
- package/dist/esm/lib/stack-app/apps/implementations/client-app-impl.js +18 -2
- package/dist/esm/lib/stack-app/apps/implementations/client-app-impl.js.map +1 -1
- package/dist/esm/lib/stack-app/apps/implementations/common.d.ts.map +1 -1
- package/dist/esm/lib/stack-app/apps/implementations/common.js +1 -1
- package/dist/esm/lib/stack-app/apps/implementations/common.js.map +1 -1
- package/dist/esm/lib/stack-app/apps/implementations/event-tracker.js.map +1 -1
- package/dist/esm/lib/stack-app/apps/implementations/event-tracker.test.js.map +1 -1
- package/dist/esm/lib/stack-app/apps/implementations/index.js.map +1 -1
- package/dist/esm/lib/stack-app/apps/implementations/redirect-page-urls.js.map +1 -1
- package/dist/esm/lib/stack-app/apps/implementations/server-app-impl.js.map +1 -1
- package/dist/esm/lib/stack-app/apps/implementations/session-replay.d.ts.map +1 -1
- package/dist/esm/lib/stack-app/apps/implementations/session-replay.js +3 -2
- package/dist/esm/lib/stack-app/apps/implementations/session-replay.js.map +1 -1
- package/dist/esm/lib/stack-app/apps/interfaces/admin-app.d.ts +4 -0
- package/dist/esm/lib/stack-app/apps/interfaces/admin-app.d.ts.map +1 -1
- package/dist/esm/lib/stack-app/apps/interfaces/admin-app.js +1 -0
- package/dist/esm/lib/stack-app/apps/interfaces/admin-app.js.map +1 -1
- package/dist/esm/lib/stack-app/apps/interfaces/client-app.d.ts +5 -0
- package/dist/esm/lib/stack-app/apps/interfaces/client-app.d.ts.map +1 -1
- package/dist/esm/lib/stack-app/apps/interfaces/client-app.js +1 -0
- package/dist/esm/lib/stack-app/apps/interfaces/client-app.js.map +1 -1
- package/dist/esm/lib/stack-app/apps/interfaces/server-app.d.ts +4 -0
- package/dist/esm/lib/stack-app/apps/interfaces/server-app.d.ts.map +1 -1
- package/dist/esm/lib/stack-app/apps/interfaces/server-app.js +1 -0
- package/dist/esm/lib/stack-app/apps/interfaces/server-app.js.map +1 -1
- package/dist/esm/lib/stack-app/common.js.map +1 -1
- package/dist/esm/lib/stack-app/contact-channels/index.js.map +1 -1
- package/dist/esm/lib/stack-app/email-templates/index.js.map +1 -1
- package/dist/esm/lib/stack-app/internal-api-keys/index.js.map +1 -1
- package/dist/esm/lib/stack-app/permissions/index.js.map +1 -1
- package/dist/esm/lib/stack-app/projects/index.js.map +1 -1
- package/dist/esm/lib/stack-app/teams/index.js.map +1 -1
- package/dist/esm/lib/stack-app/url-targets.js.map +1 -1
- package/dist/esm/lib/stack-app/url-targets.test.js +1 -1
- package/dist/esm/lib/stack-app/url-targets.test.js.map +1 -1
- package/dist/esm/lib/stack-app/users/index.js.map +1 -1
- package/dist/esm/utils/url.js.map +1 -1
- package/dist/index.d.ts +1 -1
- package/dist/index.js +3 -4
- package/dist/integrations/convex.js +5 -5
- package/dist/integrations/convex.js.map +1 -1
- package/dist/lib/auth.js +12 -12
- package/dist/lib/auth.js.map +1 -1
- package/dist/lib/auth.test.js +2 -2
- package/dist/lib/auth.test.js.map +1 -1
- package/dist/lib/cookie.js +9 -9
- package/dist/lib/cookie.js.map +1 -1
- package/dist/lib/stack-app/api-keys/index.js +2 -2
- package/dist/lib/stack-app/api-keys/index.js.map +1 -1
- package/dist/lib/stack-app/apps/implementations/admin-app-impl.d.ts +11 -11
- package/dist/lib/stack-app/apps/implementations/admin-app-impl.d.ts.map +1 -1
- package/dist/lib/stack-app/apps/implementations/admin-app-impl.js +38 -36
- package/dist/lib/stack-app/apps/implementations/admin-app-impl.js.map +1 -1
- package/dist/lib/stack-app/apps/implementations/client-app-impl.cross-domain.test.js +66 -0
- package/dist/lib/stack-app/apps/implementations/client-app-impl.cross-domain.test.js.map +1 -1
- package/dist/lib/stack-app/apps/implementations/client-app-impl.d.ts +4 -3
- package/dist/lib/stack-app/apps/implementations/client-app-impl.d.ts.map +1 -1
- package/dist/lib/stack-app/apps/implementations/client-app-impl.js +210 -194
- package/dist/lib/stack-app/apps/implementations/client-app-impl.js.map +1 -1
- package/dist/lib/stack-app/apps/implementations/common.d.ts.map +1 -1
- package/dist/lib/stack-app/apps/implementations/common.js +25 -25
- package/dist/lib/stack-app/apps/implementations/common.js.map +1 -1
- package/dist/lib/stack-app/apps/implementations/event-tracker.js +7 -7
- package/dist/lib/stack-app/apps/implementations/event-tracker.js.map +1 -1
- package/dist/lib/stack-app/apps/implementations/event-tracker.test.js +3 -3
- package/dist/lib/stack-app/apps/implementations/event-tracker.test.js.map +1 -1
- package/dist/lib/stack-app/apps/implementations/index.js +4 -4
- package/dist/lib/stack-app/apps/implementations/index.js.map +1 -1
- package/dist/lib/stack-app/apps/implementations/redirect-page-urls.js +8 -8
- package/dist/lib/stack-app/apps/implementations/redirect-page-urls.js.map +1 -1
- package/dist/lib/stack-app/apps/implementations/server-app-impl.js +59 -59
- package/dist/lib/stack-app/apps/implementations/server-app-impl.js.map +1 -1
- package/dist/lib/stack-app/apps/implementations/session-replay.d.ts.map +1 -1
- package/dist/lib/stack-app/apps/implementations/session-replay.js +13 -12
- package/dist/lib/stack-app/apps/implementations/session-replay.js.map +1 -1
- package/dist/lib/stack-app/apps/interfaces/admin-app.d.ts +4 -0
- package/dist/lib/stack-app/apps/interfaces/admin-app.d.ts.map +1 -1
- package/dist/lib/stack-app/apps/interfaces/admin-app.js +1 -0
- package/dist/lib/stack-app/apps/interfaces/admin-app.js.map +1 -1
- package/dist/lib/stack-app/apps/interfaces/client-app.d.ts +5 -0
- package/dist/lib/stack-app/apps/interfaces/client-app.d.ts.map +1 -1
- package/dist/lib/stack-app/apps/interfaces/client-app.js +1 -0
- package/dist/lib/stack-app/apps/interfaces/client-app.js.map +1 -1
- package/dist/lib/stack-app/apps/interfaces/server-app.d.ts +4 -0
- package/dist/lib/stack-app/apps/interfaces/server-app.d.ts.map +1 -1
- package/dist/lib/stack-app/apps/interfaces/server-app.js +1 -0
- package/dist/lib/stack-app/apps/interfaces/server-app.js.map +1 -1
- package/dist/lib/stack-app/common.js.map +1 -1
- package/dist/lib/stack-app/contact-channels/index.js.map +1 -1
- package/dist/lib/stack-app/email-templates/index.js.map +1 -1
- package/dist/lib/stack-app/internal-api-keys/index.js.map +1 -1
- package/dist/lib/stack-app/permissions/index.js.map +1 -1
- package/dist/lib/stack-app/projects/index.js.map +1 -1
- package/dist/lib/stack-app/teams/index.js.map +1 -1
- package/dist/lib/stack-app/url-targets.js +6 -6
- package/dist/lib/stack-app/url-targets.js.map +1 -1
- package/dist/lib/stack-app/url-targets.test.js +1 -1
- package/dist/lib/stack-app/url-targets.test.js.map +1 -1
- package/dist/lib/stack-app/users/index.js +3 -3
- package/dist/lib/stack-app/users/index.js.map +1 -1
- package/dist/utils/url.js +2 -2
- package/dist/utils/url.js.map +1 -1
- package/package.json +3 -3
- package/dist/esm/internal/deprecation-warning.d.ts +0 -1
- package/dist/esm/internal/deprecation-warning.js +0 -24
- package/dist/esm/internal/deprecation-warning.js.map +0 -1
- package/dist/internal/deprecation-warning.d.ts +0 -1
- package/dist/internal/deprecation-warning.js +0 -24
- package/dist/internal/deprecation-warning.js.map +0 -1
|
@@ -1,25 +1,25 @@
|
|
|
1
1
|
Object.defineProperty(exports, Symbol.toStringTag, { value: 'Module' });
|
|
2
2
|
const require_chunk = require('../../../../chunk-BE-pF4vm.js');
|
|
3
|
-
let
|
|
4
|
-
let
|
|
5
|
-
let
|
|
6
|
-
let
|
|
7
|
-
let
|
|
8
|
-
let
|
|
9
|
-
let
|
|
3
|
+
let _hexclave_shared_dist_utils_promises = require("@hexclave/shared/dist/utils/promises");
|
|
4
|
+
let _hexclave_shared_dist_utils_urls = require("@hexclave/shared/dist/utils/urls");
|
|
5
|
+
let _hexclave_shared_dist_utils_errors = require("@hexclave/shared/dist/utils/errors");
|
|
6
|
+
let _hexclave_shared = require("@hexclave/shared");
|
|
7
|
+
let _hexclave_shared_dist_utils_results = require("@hexclave/shared/dist/utils/results");
|
|
8
|
+
let _hexclave_shared_dist_utils_strings = require("@hexclave/shared/dist/utils/strings");
|
|
9
|
+
let _hexclave_shared_dist_utils_env = require("@hexclave/shared/dist/utils/env");
|
|
10
10
|
let __common_js = require("./common.js");
|
|
11
|
-
let
|
|
12
|
-
let
|
|
13
|
-
let
|
|
11
|
+
let _hexclave_shared_dist_utils_redirect_urls = require("@hexclave/shared/dist/utils/redirect-urls");
|
|
12
|
+
let _hexclave_shared_dist_utils_objects = require("@hexclave/shared/dist/utils/objects");
|
|
13
|
+
let _hexclave_shared_dist_utils_bytes = require("@hexclave/shared/dist/utils/bytes");
|
|
14
14
|
let ______common_js = require("../../common.js");
|
|
15
15
|
let ______projects_index_js = require("../../projects/index.js");
|
|
16
16
|
let _simplewebauthn_browser = require("@simplewebauthn/browser");
|
|
17
|
-
let
|
|
18
|
-
let
|
|
19
|
-
let
|
|
20
|
-
let
|
|
21
|
-
let
|
|
22
|
-
let
|
|
17
|
+
let _hexclave_shared_dist_sessions = require("@hexclave/shared/dist/sessions");
|
|
18
|
+
let _hexclave_shared_dist_utils_json = require("@hexclave/shared/dist/utils/json");
|
|
19
|
+
let _hexclave_shared_dist_utils_maps = require("@hexclave/shared/dist/utils/maps");
|
|
20
|
+
let _hexclave_shared_dist_utils_stores = require("@hexclave/shared/dist/utils/stores");
|
|
21
|
+
let _hexclave_shared_dist_utils_turnstile_flow = require("@hexclave/shared/dist/utils/turnstile-flow");
|
|
22
|
+
let _hexclave_shared_dist_utils_uuids = require("@hexclave/shared/dist/utils/uuids");
|
|
23
23
|
let cookie = require("cookie");
|
|
24
24
|
cookie = require_chunk.__toESM(cookie);
|
|
25
25
|
let ____________utils_url_js = require("../../../../utils/url.js");
|
|
@@ -61,7 +61,7 @@ const STACK_AUTHORIZATION_VALUE_PREFIX = "stackauth_";
|
|
|
61
61
|
const HEXCLAVE_AUTHORIZATION_VALUE_PREFIX = "hexclave_";
|
|
62
62
|
function getAuthorizationHeaderValueFromAuthJson(authJson) {
|
|
63
63
|
if (authJson.accessToken == null && authJson.refreshToken == null) return null;
|
|
64
|
-
return `Bearer ${STACK_AUTHORIZATION_VALUE_PREFIX}${(0,
|
|
64
|
+
return `Bearer ${STACK_AUTHORIZATION_VALUE_PREFIX}${(0, _hexclave_shared_dist_utils_bytes.encodeBase64)(new TextEncoder().encode(JSON.stringify(authJson)))}`;
|
|
65
65
|
}
|
|
66
66
|
function getAuthJsonFromAuthorizationHeaderValue(authorizationHeaderValue) {
|
|
67
67
|
const match = authorizationHeaderValue.match(/^Bearer\s+(.+)$/i);
|
|
@@ -73,7 +73,7 @@ function getAuthJsonFromAuthorizationHeaderValue(authorizationHeaderValue) {
|
|
|
73
73
|
if (encodedAuthJson.length === 0) throw new Error("Invalid Authorization header format. Expected `Bearer stackauth_<base64(getAuthJson())>`.");
|
|
74
74
|
let parsed;
|
|
75
75
|
try {
|
|
76
|
-
const decodedAuthJson = new TextDecoder().decode((0,
|
|
76
|
+
const decodedAuthJson = new TextDecoder().decode((0, _hexclave_shared_dist_utils_bytes.decodeBase64)(encodedAuthJson));
|
|
77
77
|
parsed = JSON.parse(decodedAuthJson);
|
|
78
78
|
} catch (e) {
|
|
79
79
|
throw new Error("Invalid stackauth authorization header.", { cause: e });
|
|
@@ -113,7 +113,7 @@ var _StackClientAppImplIncomplete = class _StackClientAppImplIncomplete {
|
|
|
113
113
|
if (!user || !user.oauth_providers.find((p) => p.id === options.providerId)) hasConnection = false;
|
|
114
114
|
if (!await options.getOrWaitOAuthToken()) hasConnection = false;
|
|
115
115
|
if (!hasConnection && options.redirect) {
|
|
116
|
-
if (!options.session) throw new Error(
|
|
116
|
+
if (!options.session) throw new Error(_hexclave_shared_dist_utils_strings.deindent`
|
|
117
117
|
Cannot add new scopes to a user that is not a CurrentUser. Please ensure that you are calling this function on a CurrentUser object, or remove the 'or: redirect' option.
|
|
118
118
|
|
|
119
119
|
Often, you can solve this by calling this function in the browser instead, or by removing the 'or: redirect' option and dealing with the case where the user doesn't have enough permissions.
|
|
@@ -122,10 +122,10 @@ var _StackClientAppImplIncomplete = class _StackClientAppImplIncomplete {
|
|
|
122
122
|
provider: options.providerId,
|
|
123
123
|
redirectUrl: this._getOAuthCallbackRedirectUri(),
|
|
124
124
|
errorRedirectUrl: this.urls.error,
|
|
125
|
-
providerScope: (0,
|
|
125
|
+
providerScope: (0, _hexclave_shared_dist_utils_strings.mergeScopeStrings)(options.scope || "", (this._oauthScopesOnSignIn[options.providerId] ?? []).join(" "))
|
|
126
126
|
}, options.session);
|
|
127
127
|
await this._redirectTo({ url: location });
|
|
128
|
-
return await (0,
|
|
128
|
+
return await (0, _hexclave_shared_dist_utils_promises.neverResolve)();
|
|
129
129
|
} else if (!hasConnection) return null;
|
|
130
130
|
const providerAccountId = user.oauth_providers.find((p) => p.id === options.providerId)?.account_id ?? "";
|
|
131
131
|
return {
|
|
@@ -134,7 +134,7 @@ var _StackClientAppImplIncomplete = class _StackClientAppImplIncomplete {
|
|
|
134
134
|
providerAccountId,
|
|
135
135
|
async getAccessToken() {
|
|
136
136
|
const result = await options.getOrWaitOAuthToken();
|
|
137
|
-
if (!result) throw new
|
|
137
|
+
if (!result) throw new _hexclave_shared_dist_utils_errors.HexclaveAssertionError(`Failed to retrieve an access token for this connected account (provider: ${options.providerId}). This usually means the OAuth refresh token has been revoked or expired. The user needs to re-authorize by calling \`linkConnectedAccount\` or using \`getOrLinkConnectedAccount\`.`);
|
|
138
138
|
return result;
|
|
139
139
|
}
|
|
140
140
|
};
|
|
@@ -149,7 +149,7 @@ var _StackClientAppImplIncomplete = class _StackClientAppImplIncomplete {
|
|
|
149
149
|
providerAccountId,
|
|
150
150
|
async getAccessToken(options) {
|
|
151
151
|
const scopeString = options?.scopes?.join(" ") ?? "";
|
|
152
|
-
const result =
|
|
152
|
+
const result = _hexclave_shared_dist_utils_results.Result.orThrow(await app._currentUserOAuthConnectionAccessTokensByAccountCache.getOrWait([
|
|
153
153
|
session,
|
|
154
154
|
providerId,
|
|
155
155
|
providerAccountId,
|
|
@@ -157,9 +157,9 @@ var _StackClientAppImplIncomplete = class _StackClientAppImplIncomplete {
|
|
|
157
157
|
], "write-only"));
|
|
158
158
|
if (!result) {
|
|
159
159
|
const scopeDetail = scopeString ? `The requested scopes [${scopeString}] are not available on the existing token.` : "The OAuth refresh token has likely been revoked or expired.";
|
|
160
|
-
return
|
|
160
|
+
return _hexclave_shared_dist_utils_results.Result.error(new _hexclave_shared.KnownErrors.OAuthAccessTokenNotAvailable(providerId, `${scopeDetail} The user needs to re-authorize by calling \`linkConnectedAccount\` or using \`getOrLinkConnectedAccount\`.`));
|
|
161
161
|
}
|
|
162
|
-
return
|
|
162
|
+
return _hexclave_shared_dist_utils_results.Result.ok(result);
|
|
163
163
|
}
|
|
164
164
|
};
|
|
165
165
|
}
|
|
@@ -168,14 +168,14 @@ var _StackClientAppImplIncomplete = class _StackClientAppImplIncomplete {
|
|
|
168
168
|
this._sessionRecorder = null;
|
|
169
169
|
this._eventTracker = null;
|
|
170
170
|
this.__DEMO_ENABLE_SLIGHT_FETCH_DELAY = false;
|
|
171
|
-
this._ownedAdminApps = new
|
|
171
|
+
this._ownedAdminApps = new _hexclave_shared_dist_utils_maps.DependenciesMap();
|
|
172
172
|
this._currentUserCache = (0, __common_js.createCacheBySession)(async (session) => {
|
|
173
|
-
if (this.__DEMO_ENABLE_SLIGHT_FETCH_DELAY) await (0,
|
|
173
|
+
if (this.__DEMO_ENABLE_SLIGHT_FETCH_DELAY) await (0, _hexclave_shared_dist_utils_promises.wait)(2e3);
|
|
174
174
|
if (session.isKnownToBeInvalid()) return null;
|
|
175
175
|
return await this._interface.getClientUserByToken(session);
|
|
176
176
|
});
|
|
177
177
|
this._currentProjectCache = (0, __common_js.createCache)(async () => {
|
|
178
|
-
return
|
|
178
|
+
return _hexclave_shared_dist_utils_results.Result.orThrow(await this._interface.getClientProject());
|
|
179
179
|
});
|
|
180
180
|
this._ownedProjectsCache = (0, __common_js.createCacheBySession)(async (session) => {
|
|
181
181
|
return await this._interface.listProjects(session);
|
|
@@ -196,14 +196,14 @@ var _StackClientAppImplIncomplete = class _StackClientAppImplIncomplete {
|
|
|
196
196
|
try {
|
|
197
197
|
return { accessToken: (await this._interface.createProviderAccessToken(providerId, scope || "", session)).access_token };
|
|
198
198
|
} catch (err) {
|
|
199
|
-
if (!(
|
|
199
|
+
if (!(_hexclave_shared.KnownErrors.OAuthAccessTokenNotAvailable.isInstance(err) || _hexclave_shared.KnownErrors.OAuthConnectionDoesNotHaveRequiredScope.isInstance(err) || _hexclave_shared.KnownErrors.OAuthConnectionNotConnectedToUser.isInstance(err))) throw err;
|
|
200
200
|
}
|
|
201
201
|
return null;
|
|
202
202
|
});
|
|
203
203
|
this._currentUserOAuthConnectionCache = (0, __common_js.createCacheBySession)(async (session, [providerId, scope, redirect]) => {
|
|
204
204
|
return await this._getUserOAuthConnectionCacheFn({
|
|
205
|
-
getUser: async () =>
|
|
206
|
-
getOrWaitOAuthToken: async () =>
|
|
205
|
+
getUser: async () => _hexclave_shared_dist_utils_results.Result.orThrow(await this._currentUserCache.getOrWait([session], "write-only")),
|
|
206
|
+
getOrWaitOAuthToken: async () => _hexclave_shared_dist_utils_results.Result.orThrow(await this._currentUserOAuthConnectionAccessTokensCache.getOrWait([
|
|
207
207
|
session,
|
|
208
208
|
providerId,
|
|
209
209
|
scope || ""
|
|
@@ -221,22 +221,22 @@ var _StackClientAppImplIncomplete = class _StackClientAppImplIncomplete {
|
|
|
221
221
|
try {
|
|
222
222
|
return { accessToken: (await this._interface.createProviderAccessTokenByAccount(providerId, providerAccountId, scope, session)).access_token };
|
|
223
223
|
} catch (err) {
|
|
224
|
-
if (
|
|
224
|
+
if (_hexclave_shared.KnownErrors.OAuthAccessTokenNotAvailable.isInstance(err) || _hexclave_shared.KnownErrors.OAuthConnectionDoesNotHaveRequiredScope.isInstance(err) || _hexclave_shared.KnownErrors.OAuthConnectionNotConnectedToUser.isInstance(err)) return null;
|
|
225
225
|
throw err;
|
|
226
226
|
}
|
|
227
227
|
});
|
|
228
228
|
this._currentUserValidConnectedAccountForProviderCache = (0, __common_js.createCacheBySession)(async (session, [provider, scopeString]) => {
|
|
229
|
-
const matchingAccounts =
|
|
229
|
+
const matchingAccounts = _hexclave_shared_dist_utils_results.Result.orThrow(await this._currentUserConnectedAccountsCache.getOrWait([session], "write-only")).filter((a) => a.provider === provider);
|
|
230
230
|
const scopes = scopeString ? scopeString.split(" ") : void 0;
|
|
231
231
|
for (const account of matchingAccounts) if ((await account.getAccessToken({ scopes })).status === "ok") return account;
|
|
232
232
|
const location = await (0, _________auth_js.getNewOAuthProviderOrScopeUrl)(this._interface, {
|
|
233
233
|
provider,
|
|
234
234
|
redirectUrl: this._getOAuthCallbackRedirectUri(),
|
|
235
235
|
errorRedirectUrl: this.urls.error,
|
|
236
|
-
providerScope: (0,
|
|
236
|
+
providerScope: (0, _hexclave_shared_dist_utils_strings.mergeScopeStrings)(scopeString, (this._oauthScopesOnSignIn[provider] ?? []).join(" "))
|
|
237
237
|
}, session);
|
|
238
238
|
await this._redirectTo({ url: location });
|
|
239
|
-
return await (0,
|
|
239
|
+
return await (0, _hexclave_shared_dist_utils_promises.neverResolve)();
|
|
240
240
|
});
|
|
241
241
|
this._teamMemberProfilesCache = (0, __common_js.createCacheBySession)(async (session, [teamId]) => {
|
|
242
242
|
return await this._interface.listTeamMemberProfiles({ teamId }, session);
|
|
@@ -344,7 +344,7 @@ var _StackClientAppImplIncomplete = class _StackClientAppImplIncomplete {
|
|
|
344
344
|
this._sessionsByTokenStoreAndSessionKey = /* @__PURE__ */ new WeakMap();
|
|
345
345
|
this._botChallengeSiteKeysWarned = false;
|
|
346
346
|
const resolvedOptions = (0, __common_js.resolveConstructorOptions)(options);
|
|
347
|
-
if (!_StackClientAppImplIncomplete.LazyStackAdminAppImpl.value) throw new
|
|
347
|
+
if (!_StackClientAppImplIncomplete.LazyStackAdminAppImpl.value) throw new _hexclave_shared_dist_utils_errors.HexclaveAssertionError("Admin app implementation not initialized. Did you import the _StackClientApp from stack-app/apps/implementations/index.ts? You can't import it directly from ./apps/implementations/client-app-impl.ts as that causes a circular dependency (see the comment at _LazyStackAdminAppImpl for more details).");
|
|
348
348
|
this._options = resolvedOptions;
|
|
349
349
|
this._extraOptions = extraOptions;
|
|
350
350
|
const projectId = resolvedOptions.projectId ?? (0, __common_js.getDefaultProjectId)();
|
|
@@ -353,7 +353,7 @@ var _StackClientAppImplIncomplete = class _StackClientAppImplIncomplete {
|
|
|
353
353
|
if (extraOptions && extraOptions.interface) this._interface = extraOptions.interface;
|
|
354
354
|
else {
|
|
355
355
|
const apiUrls = (0, __common_js.resolveApiUrls)(resolvedOptions.baseUrl);
|
|
356
|
-
this._interface = new
|
|
356
|
+
this._interface = new _hexclave_shared.HexclaveClientInterface({
|
|
357
357
|
getBaseUrl: () => apiUrls()[0],
|
|
358
358
|
getAnalyticsBaseUrl: () => (0, __common_js.getAnalyticsBaseUrl)(apiUrls()[0]),
|
|
359
359
|
getApiUrls: apiUrls,
|
|
@@ -365,11 +365,11 @@ var _StackClientAppImplIncomplete = class _StackClientAppImplIncomplete {
|
|
|
365
365
|
});
|
|
366
366
|
}
|
|
367
367
|
this._tokenStoreInit = resolvedOptions.tokenStore;
|
|
368
|
-
this._redirectMethod = resolvedOptions.redirectMethod || ((0,
|
|
368
|
+
this._redirectMethod = resolvedOptions.redirectMethod || ((0, _hexclave_shared_dist_utils_env.isBrowserLike)() ? "window" : "none");
|
|
369
369
|
this._urlOptions = resolvedOptions.urls ?? {};
|
|
370
370
|
this._oauthScopesOnSignIn = resolvedOptions.oauthScopesOnSignIn ?? {};
|
|
371
|
-
if ((0,
|
|
372
|
-
(0,
|
|
371
|
+
if ((0, _hexclave_shared_dist_utils_env.isBrowserLike)() && (resolvedOptions.tokenStore === "cookie" || resolvedOptions.tokenStore === "nextjs-cookie")) {
|
|
372
|
+
(0, _hexclave_shared_dist_utils_promises.runAsynchronously)(this._trustedParentDomainCache.getOrWait([window.location.hostname], "write-only"));
|
|
373
373
|
this._ensureCrossSubdomainCookieExists();
|
|
374
374
|
}
|
|
375
375
|
if (extraOptions && extraOptions.uniqueIdentifier) {
|
|
@@ -386,7 +386,7 @@ var _StackClientAppImplIncomplete = class _StackClientAppImplIncomplete {
|
|
|
386
386
|
return (await this.getUser({ or: "anonymous" }))._internalSession;
|
|
387
387
|
};
|
|
388
388
|
const analyticsEnabled = this._analyticsOptions?.enabled !== false;
|
|
389
|
-
if (analyticsEnabled && (0,
|
|
389
|
+
if (analyticsEnabled && (0, _hexclave_shared_dist_utils_env.isBrowserLike)() && this._hasPersistentTokenStore() && this._analyticsOptions?.replays?.enabled === true) {
|
|
390
390
|
this._sessionRecorder = new __session_replay_js.SessionRecorder({
|
|
391
391
|
projectId: this.projectId,
|
|
392
392
|
sendBatch: async (body, opts) => {
|
|
@@ -395,7 +395,7 @@ var _StackClientAppImplIncomplete = class _StackClientAppImplIncomplete {
|
|
|
395
395
|
}, this._analyticsOptions.replays);
|
|
396
396
|
this._sessionRecorder.start();
|
|
397
397
|
}
|
|
398
|
-
if (analyticsEnabled && (0,
|
|
398
|
+
if (analyticsEnabled && (0, _hexclave_shared_dist_utils_env.isBrowserLike)() && this._hasPersistentTokenStore()) {
|
|
399
399
|
this._eventTracker = new __event_tracker_js.EventTracker({
|
|
400
400
|
projectId: this.projectId,
|
|
401
401
|
sendBatch: async (body, opts) => {
|
|
@@ -404,17 +404,17 @@ var _StackClientAppImplIncomplete = class _StackClientAppImplIncomplete {
|
|
|
404
404
|
});
|
|
405
405
|
this._eventTracker.start();
|
|
406
406
|
}
|
|
407
|
-
if ((0,
|
|
408
|
-
if ((0,
|
|
407
|
+
if ((0, _hexclave_shared_dist_utils_env.isBrowserLike)() && this._isOAuthCallbackUrlHosted() && this._currentUrlLooksLikeStackOAuthCallback()) this._trackPendingAuthResolution(async () => {
|
|
408
|
+
if ((0, _hexclave_shared_dist_utils_env.isBrowserLike)()) await this.callOAuthCallback({ dontWarnAboutMissingQueryParams: true });
|
|
409
409
|
});
|
|
410
|
-
if ((0,
|
|
410
|
+
if ((0, _hexclave_shared_dist_utils_env.isBrowserLike)()) this._trackPendingAuthResolution(async () => {
|
|
411
411
|
await this._maybeHandleNestedCrossDomainAuth();
|
|
412
412
|
});
|
|
413
|
-
if ((0,
|
|
413
|
+
if ((0, _hexclave_shared_dist_utils_env.isBrowserLike)() && resolvedOptions.devTool !== false) (0, ____________dev_tool_index_js.mountDevTool)(this);
|
|
414
414
|
}
|
|
415
415
|
_initUniqueIdentifier() {
|
|
416
|
-
if (!this._uniqueIdentifier) throw new
|
|
417
|
-
if (allClientApps.has(this._uniqueIdentifier)) throw new
|
|
416
|
+
if (!this._uniqueIdentifier) throw new _hexclave_shared_dist_utils_errors.HexclaveAssertionError("Unique identifier not initialized");
|
|
417
|
+
if (allClientApps.has(this._uniqueIdentifier)) throw new _hexclave_shared_dist_utils_errors.HexclaveAssertionError("A Stack client app with the same unique identifier already exists");
|
|
418
418
|
allClientApps.set(this._uniqueIdentifier, [this._extraOptions?.checkString ?? void 0, this]);
|
|
419
419
|
}
|
|
420
420
|
_trackPendingAuthResolution(callback) {
|
|
@@ -423,11 +423,11 @@ var _StackClientAppImplIncomplete = class _StackClientAppImplIncomplete {
|
|
|
423
423
|
try {
|
|
424
424
|
await callback();
|
|
425
425
|
} catch (error) {
|
|
426
|
-
(0,
|
|
426
|
+
(0, _hexclave_shared_dist_utils_errors.captureError)("pending-auth-resolution-failed", error);
|
|
427
427
|
}
|
|
428
428
|
})();
|
|
429
429
|
this._pendingAuthResolutionPromises.push(promise);
|
|
430
|
-
(0,
|
|
430
|
+
(0, _hexclave_shared_dist_utils_promises.runAsynchronously)(async () => {
|
|
431
431
|
try {
|
|
432
432
|
await promise;
|
|
433
433
|
} finally {
|
|
@@ -457,7 +457,7 @@ var _StackClientAppImplIncomplete = class _StackClientAppImplIncomplete {
|
|
|
457
457
|
}
|
|
458
458
|
_getOAuthCallbackRedirectUri() {
|
|
459
459
|
if (!this._isOAuthCallbackUrlHosted()) return this.urls.oauthCallback;
|
|
460
|
-
if (typeof window === "undefined") throw new
|
|
460
|
+
if (typeof window === "undefined") throw new _hexclave_shared_dist_utils_errors.HexclaveAssertionError("Hosted OAuth callback URLs require a browser environment to use the current URL as the redirect URI");
|
|
461
461
|
const currentUrl = new URL(window.location.href);
|
|
462
462
|
for (const param of oauthCallbackResponseQueryParams) currentUrl.searchParams.delete(param);
|
|
463
463
|
return currentUrl.toString();
|
|
@@ -489,13 +489,13 @@ var _StackClientAppImplIncomplete = class _StackClientAppImplIncomplete {
|
|
|
489
489
|
const state = currentUrl.searchParams.get(nestedCrossDomainAuthQueryParams.state);
|
|
490
490
|
const codeChallenge = currentUrl.searchParams.get(nestedCrossDomainAuthQueryParams.codeChallenge);
|
|
491
491
|
if (redirectUri != null || state != null || codeChallenge != null) {
|
|
492
|
-
if (redirectUri == null || state == null || codeChallenge == null) throw new
|
|
492
|
+
if (redirectUri == null || state == null || codeChallenge == null) throw new _hexclave_shared_dist_utils_errors.HexclaveAssertionError("Nested cross-domain auth callback URL is missing OAuth request parameters", {
|
|
493
493
|
redirectUri,
|
|
494
494
|
state,
|
|
495
495
|
codeChallenge
|
|
496
496
|
});
|
|
497
|
-
if ((currentUrl.searchParams.get(nestedCrossDomainAuthQueryParams.codeChallengeMethod) ?? "S256") !== "S256") throw new
|
|
498
|
-
if ((0,
|
|
497
|
+
if ((currentUrl.searchParams.get(nestedCrossDomainAuthQueryParams.codeChallengeMethod) ?? "S256") !== "S256") throw new _hexclave_shared_dist_utils_errors.HexclaveAssertionError("Nested cross-domain auth only supports S256 PKCE");
|
|
498
|
+
if ((0, _hexclave_shared_dist_utils_urls.isRelative)(redirectUri)) throw new Error("Nested cross-domain auth redirect URI must be absolute.");
|
|
499
499
|
const redirectUriUrl = new URL(redirectUri);
|
|
500
500
|
if (!await this._isTrusted(redirectUriUrl.toString())) throw new Error(`Nested cross-domain auth redirect URI ${redirectUri} is not trusted.`);
|
|
501
501
|
const afterCallbackRedirectUrlString = currentUrl.searchParams.get(nestedCrossDomainAuthQueryParams.afterCallbackRedirectUrl);
|
|
@@ -516,16 +516,29 @@ var _StackClientAppImplIncomplete = class _StackClientAppImplIncomplete {
|
|
|
516
516
|
}
|
|
517
517
|
if (await this._getCurrentRefreshTokenIdIfSignedIn({ awaitPendingAuthResolutions: false }) === refreshTokenId) return false;
|
|
518
518
|
const callbackUrlString = currentUrl.searchParams.get(nestedCrossDomainAuthQueryParams.callbackUrl);
|
|
519
|
-
if (callbackUrlString == null) throw new
|
|
520
|
-
if ((0,
|
|
519
|
+
if (callbackUrlString == null) throw new _hexclave_shared_dist_utils_errors.HexclaveAssertionError("Nested cross-domain auth URL is missing callback URL");
|
|
520
|
+
if ((0, _hexclave_shared_dist_utils_urls.isRelative)(callbackUrlString)) throw new Error("Nested cross-domain auth callback URL must be absolute.");
|
|
521
521
|
const callbackUrl = new URL(callbackUrlString);
|
|
522
522
|
if (!await this._isTrusted(callbackUrl.toString())) throw new Error(`Nested cross-domain auth callback URL ${callbackUrlString} is not trusted.`);
|
|
523
523
|
const afterCallbackRedirectUrl = new URL(currentUrl);
|
|
524
524
|
afterCallbackRedirectUrl.searchParams.delete(nestedCrossDomainAuthQueryParams.refreshTokenId);
|
|
525
525
|
afterCallbackRedirectUrl.searchParams.delete(nestedCrossDomainAuthQueryParams.callbackUrl);
|
|
526
|
-
const { state: newState, codeChallenge: newCodeChallenge } = await this.
|
|
526
|
+
const { state: newState, codeChallenge: newCodeChallenge } = await this._getNestedCrossDomainAuthParamsForRedirect();
|
|
527
|
+
const nestedRedirectUri = new URL(this._getOAuthCallbackRedirectUri(), currentUrl);
|
|
528
|
+
nestedRedirectUri.searchParams.delete(nestedCrossDomainAuthQueryParams.refreshTokenId);
|
|
529
|
+
nestedRedirectUri.searchParams.delete(nestedCrossDomainAuthQueryParams.callbackUrl);
|
|
530
|
+
for (const param of [
|
|
531
|
+
"after_auth_return_to",
|
|
532
|
+
__redirect_page_urls_js.crossDomainAuthQueryParams.marker,
|
|
533
|
+
__redirect_page_urls_js.crossDomainAuthQueryParams.state,
|
|
534
|
+
__redirect_page_urls_js.crossDomainAuthQueryParams.codeChallenge,
|
|
535
|
+
__redirect_page_urls_js.crossDomainAuthQueryParams.afterCallbackRedirectUrl
|
|
536
|
+
]) {
|
|
537
|
+
const value = currentUrl.searchParams.get(param);
|
|
538
|
+
if (value != null && !nestedRedirectUri.searchParams.has(param)) nestedRedirectUri.searchParams.set(param, value);
|
|
539
|
+
}
|
|
527
540
|
callbackUrl.searchParams.set(nestedCrossDomainAuthQueryParams.refreshTokenId, refreshTokenId);
|
|
528
|
-
callbackUrl.searchParams.set(nestedCrossDomainAuthQueryParams.redirectUri,
|
|
541
|
+
callbackUrl.searchParams.set(nestedCrossDomainAuthQueryParams.redirectUri, nestedRedirectUri.toString());
|
|
529
542
|
callbackUrl.searchParams.set(nestedCrossDomainAuthQueryParams.state, newState);
|
|
530
543
|
callbackUrl.searchParams.set(nestedCrossDomainAuthQueryParams.codeChallenge, newCodeChallenge);
|
|
531
544
|
callbackUrl.searchParams.set(nestedCrossDomainAuthQueryParams.codeChallengeMethod, "S256");
|
|
@@ -536,6 +549,9 @@ var _StackClientAppImplIncomplete = class _StackClientAppImplIncomplete {
|
|
|
536
549
|
});
|
|
537
550
|
return true;
|
|
538
551
|
}
|
|
552
|
+
async _getNestedCrossDomainAuthParamsForRedirect() {
|
|
553
|
+
return await (0, _________cookie_js.saveVerifierAndState)();
|
|
554
|
+
}
|
|
539
555
|
/**
|
|
540
556
|
* Cloudflare workers does not allow use of randomness on the global scope (on which the Stack app is probably
|
|
541
557
|
* initialized). For that reason, we generate the unique identifier lazily when it is first needed instead of in the
|
|
@@ -543,7 +559,7 @@ var _StackClientAppImplIncomplete = class _StackClientAppImplIncomplete {
|
|
|
543
559
|
*/
|
|
544
560
|
_getUniqueIdentifier() {
|
|
545
561
|
if (!this._uniqueIdentifier) {
|
|
546
|
-
this._uniqueIdentifier = (0,
|
|
562
|
+
this._uniqueIdentifier = (0, _hexclave_shared_dist_utils_uuids.generateUuid)();
|
|
547
563
|
this._initUniqueIdentifier();
|
|
548
564
|
}
|
|
549
565
|
return this._uniqueIdentifier;
|
|
@@ -555,8 +571,8 @@ var _StackClientAppImplIncomplete = class _StackClientAppImplIncomplete {
|
|
|
555
571
|
});
|
|
556
572
|
}
|
|
557
573
|
_useCheckFeatureSupport(name, options) {
|
|
558
|
-
(0,
|
|
559
|
-
throw new
|
|
574
|
+
(0, _hexclave_shared_dist_utils_promises.runAsynchronously)(this._checkFeatureSupport(name, options));
|
|
575
|
+
throw new _hexclave_shared_dist_utils_errors.HexclaveAssertionError(`${name} is not currently supported. Please reach out to Stack support for more information.`);
|
|
560
576
|
}
|
|
561
577
|
get _legacyRefreshTokenCookieName() {
|
|
562
578
|
return `stack-refresh-${this.projectId}`;
|
|
@@ -568,7 +584,7 @@ var _StackClientAppImplIncomplete = class _StackClientAppImplIncomplete {
|
|
|
568
584
|
return `${secure ? "__Host-" : ""}${this._refreshTokenCookieName}--default`;
|
|
569
585
|
}
|
|
570
586
|
_getCustomRefreshCookieName(domain) {
|
|
571
|
-
const encoded = (0,
|
|
587
|
+
const encoded = (0, _hexclave_shared_dist_utils_bytes.encodeBase32)(new TextEncoder().encode(domain.toLowerCase()));
|
|
572
588
|
return `${this._refreshTokenCookieName}--custom-${encoded}`;
|
|
573
589
|
}
|
|
574
590
|
_getDomainFromCustomRefreshCookieName(name) {
|
|
@@ -576,7 +592,7 @@ var _StackClientAppImplIncomplete = class _StackClientAppImplIncomplete {
|
|
|
576
592
|
const prefix = `${base}--custom-`;
|
|
577
593
|
if (!name.startsWith(prefix)) continue;
|
|
578
594
|
try {
|
|
579
|
-
return new TextDecoder().decode((0,
|
|
595
|
+
return new TextDecoder().decode((0, _hexclave_shared_dist_utils_bytes.decodeBase32)(name.slice(prefix.length)));
|
|
580
596
|
} catch {
|
|
581
597
|
return null;
|
|
582
598
|
}
|
|
@@ -594,7 +610,7 @@ var _StackClientAppImplIncomplete = class _StackClientAppImplIncomplete {
|
|
|
594
610
|
}
|
|
595
611
|
_parseStructuredRefreshCookie(value) {
|
|
596
612
|
if (!value) return null;
|
|
597
|
-
const parsed = (0,
|
|
613
|
+
const parsed = (0, _hexclave_shared_dist_utils_json.parseJson)(value);
|
|
598
614
|
if (parsed.status !== "ok" || typeof parsed.data !== "object" || parsed.data === null) {
|
|
599
615
|
console.warn("Failed to parse structured refresh cookie");
|
|
600
616
|
return null;
|
|
@@ -653,7 +669,7 @@ var _StackClientAppImplIncomplete = class _StackClientAppImplIncomplete {
|
|
|
653
669
|
const accessTokenCookie = cookies[this._accessTokenCookieName] ?? cookies[this._legacyAccessTokenCookieName] ?? null;
|
|
654
670
|
let accessToken = null;
|
|
655
671
|
if (accessTokenCookie && accessTokenCookie.startsWith("[\"")) {
|
|
656
|
-
const parsed = (0,
|
|
672
|
+
const parsed = (0, _hexclave_shared_dist_utils_json.parseJson)(accessTokenCookie);
|
|
657
673
|
if (parsed.status === "ok" && typeof parsed.data === "object" && parsed.data !== null && Array.isArray(parsed.data) && parsed.data.length === 2 && typeof parsed.data[0] === "string" && typeof parsed.data[1] === "string") {
|
|
658
674
|
if (parsed.data[0] === refreshToken) accessToken = parsed.data[1];
|
|
659
675
|
} else console.warn("Access token cookie has invalid format");
|
|
@@ -670,7 +686,7 @@ var _StackClientAppImplIncomplete = class _StackClientAppImplIncomplete {
|
|
|
670
686
|
return `stack-access`;
|
|
671
687
|
}
|
|
672
688
|
_getAllBrowserCookies() {
|
|
673
|
-
if (!(0,
|
|
689
|
+
if (!(0, _hexclave_shared_dist_utils_env.isBrowserLike)()) throw new _hexclave_shared_dist_utils_errors.HexclaveAssertionError("Cannot get browser cookies on the server!");
|
|
674
690
|
return cookie.parseCookie(document.cookie || "");
|
|
675
691
|
}
|
|
676
692
|
_getRefreshTokenCookieNamePatterns() {
|
|
@@ -703,7 +719,7 @@ var _StackClientAppImplIncomplete = class _StackClientAppImplIncomplete {
|
|
|
703
719
|
};
|
|
704
720
|
}
|
|
705
721
|
_ensureCrossSubdomainCookieExists() {
|
|
706
|
-
(0,
|
|
722
|
+
(0, _hexclave_shared_dist_utils_promises.runAsynchronously)(async () => {
|
|
707
723
|
const hostname = window.location.hostname;
|
|
708
724
|
const domain = await this._trustedParentDomainCache.getOrWait([hostname], "read-write");
|
|
709
725
|
if (domain.status === "error" || !domain.data) return;
|
|
@@ -718,11 +734,11 @@ var _StackClientAppImplIncomplete = class _StackClientAppImplIncomplete {
|
|
|
718
734
|
});
|
|
719
735
|
}
|
|
720
736
|
_queueCustomRefreshCookieUpdate(refreshToken, updatedAt, context) {
|
|
721
|
-
(0,
|
|
737
|
+
(0, _hexclave_shared_dist_utils_promises.runAsynchronously)(async () => {
|
|
722
738
|
this._mostRecentQueuedCookieRefreshIndex++;
|
|
723
739
|
const updateIndex = this._mostRecentQueuedCookieRefreshIndex;
|
|
724
740
|
let hostname;
|
|
725
|
-
if ((0,
|
|
741
|
+
if ((0, _hexclave_shared_dist_utils_env.isBrowserLike)()) hostname = window.location.hostname;
|
|
726
742
|
else hostname = await getServerRequestHost();
|
|
727
743
|
if (!hostname) {
|
|
728
744
|
console.warn("No hostname found when queueing custom refresh cookie update");
|
|
@@ -752,7 +768,7 @@ var _StackClientAppImplIncomplete = class _StackClientAppImplIncomplete {
|
|
|
752
768
|
});
|
|
753
769
|
}
|
|
754
770
|
async _getTrustedRedirectConfig() {
|
|
755
|
-
const project =
|
|
771
|
+
const project = _hexclave_shared_dist_utils_results.Result.orThrow(await this._currentProjectCache.getOrWait([], "write-only"));
|
|
756
772
|
return {
|
|
757
773
|
allowLocalhost: project.config.allow_localhost,
|
|
758
774
|
trustedDomains: [...project.config.domains.map((d) => d.domain), new URL((0, ______url_targets_js.getHostedHandlerUrl)({
|
|
@@ -762,10 +778,10 @@ var _StackClientAppImplIncomplete = class _StackClientAppImplIncomplete {
|
|
|
762
778
|
};
|
|
763
779
|
}
|
|
764
780
|
async _getTrustedParentDomain(currentDomain) {
|
|
765
|
-
return (0,
|
|
781
|
+
return (0, _hexclave_shared_dist_utils_redirect_urls.getTrustedParentDomain)(currentDomain, (await this._getTrustedRedirectConfig()).trustedDomains);
|
|
766
782
|
}
|
|
767
783
|
_getBrowserCookieTokenStore() {
|
|
768
|
-
if (!(0,
|
|
784
|
+
if (!(0, _hexclave_shared_dist_utils_env.isBrowserLike)()) throw new Error("Cannot use cookie token store on the server!");
|
|
769
785
|
if (this._storedBrowserCookieTokenStore === null) {
|
|
770
786
|
const getCurrentValue = (old) => {
|
|
771
787
|
const tokens = this._getTokensFromCookies(this._getAllBrowserCookies());
|
|
@@ -774,13 +790,13 @@ var _StackClientAppImplIncomplete = class _StackClientAppImplIncomplete {
|
|
|
774
790
|
accessToken: tokens.accessToken ?? (old?.refreshToken === tokens.refreshToken ? old.accessToken : null)
|
|
775
791
|
};
|
|
776
792
|
};
|
|
777
|
-
this._storedBrowserCookieTokenStore = new
|
|
793
|
+
this._storedBrowserCookieTokenStore = new _hexclave_shared_dist_utils_stores.Store(getCurrentValue(null));
|
|
778
794
|
let hasSucceededInWriting = true;
|
|
779
795
|
setInterval(() => {
|
|
780
796
|
if (hasSucceededInWriting) {
|
|
781
797
|
const oldValue = this._storedBrowserCookieTokenStore.get();
|
|
782
798
|
const currentValue = getCurrentValue(oldValue);
|
|
783
|
-
if (!(0,
|
|
799
|
+
if (!(0, _hexclave_shared_dist_utils_objects.deepPlainEquals)(currentValue, oldValue)) this._storedBrowserCookieTokenStore.set(currentValue);
|
|
784
800
|
}
|
|
785
801
|
}, 100);
|
|
786
802
|
this._storedBrowserCookieTokenStore.onChange((value) => {
|
|
@@ -801,7 +817,7 @@ var _StackClientAppImplIncomplete = class _StackClientAppImplIncomplete {
|
|
|
801
817
|
this._queueCustomRefreshCookieUpdate(refreshToken, updatedAt, "browser");
|
|
802
818
|
hasSucceededInWriting = true;
|
|
803
819
|
} catch (e) {
|
|
804
|
-
if (!(0,
|
|
820
|
+
if (!(0, _hexclave_shared_dist_utils_env.isBrowserLike)()) hasSucceededInWriting = false;
|
|
805
821
|
else throw e;
|
|
806
822
|
}
|
|
807
823
|
});
|
|
@@ -812,11 +828,11 @@ var _StackClientAppImplIncomplete = class _StackClientAppImplIncomplete {
|
|
|
812
828
|
const tokenStoreInit = overrideTokenStoreInit === void 0 ? this._tokenStoreInit : overrideTokenStoreInit;
|
|
813
829
|
switch (tokenStoreInit) {
|
|
814
830
|
case "cookie": return this._getBrowserCookieTokenStore();
|
|
815
|
-
case "nextjs-cookie": if ((0,
|
|
831
|
+
case "nextjs-cookie": if ((0, _hexclave_shared_dist_utils_env.isBrowserLike)()) return this._getBrowserCookieTokenStore();
|
|
816
832
|
else {
|
|
817
|
-
const store = new
|
|
833
|
+
const store = new _hexclave_shared_dist_utils_stores.Store(this._getTokensFromCookies(cookieHelper.getAll()));
|
|
818
834
|
store.onChange((value) => {
|
|
819
|
-
(0,
|
|
835
|
+
(0, _hexclave_shared_dist_utils_promises.runAsynchronously)(async () => {
|
|
820
836
|
const refreshToken = value.refreshToken;
|
|
821
837
|
const secure = await (0, _________cookie_js.isSecure)();
|
|
822
838
|
const defaultName = this._getRefreshTokenDefaultCookieNameForSecure(secure);
|
|
@@ -849,7 +865,7 @@ var _StackClientAppImplIncomplete = class _StackClientAppImplIncomplete {
|
|
|
849
865
|
if (authorizationHeader) {
|
|
850
866
|
const authJson = getAuthJsonFromAuthorizationHeaderValue(authorizationHeader);
|
|
851
867
|
if (authJson != null) {
|
|
852
|
-
const tokenStore = new
|
|
868
|
+
const tokenStore = new _hexclave_shared_dist_utils_stores.Store({
|
|
853
869
|
accessToken: authJson.accessToken,
|
|
854
870
|
refreshToken: authJson.refreshToken
|
|
855
871
|
});
|
|
@@ -874,10 +890,10 @@ var _StackClientAppImplIncomplete = class _StackClientAppImplIncomplete {
|
|
|
874
890
|
}
|
|
875
891
|
const cookieHeader = getHeaderValueFromRequestLikeHeaders(tokenStoreInit.headers, "cookie");
|
|
876
892
|
const parsed = cookie.parseCookie(cookieHeader || "");
|
|
877
|
-
const res = new
|
|
893
|
+
const res = new _hexclave_shared_dist_utils_stores.Store(this._getTokensFromCookies(parsed));
|
|
878
894
|
this._requestTokenStores.set(tokenStoreInit, res);
|
|
879
895
|
return res;
|
|
880
|
-
} else if ("accessToken" in tokenStoreInit || "refreshToken" in tokenStoreInit) return new
|
|
896
|
+
} else if ("accessToken" in tokenStoreInit || "refreshToken" in tokenStoreInit) return new _hexclave_shared_dist_utils_stores.Store({
|
|
881
897
|
refreshToken: tokenStoreInit.refreshToken,
|
|
882
898
|
accessToken: tokenStoreInit.accessToken
|
|
883
899
|
});
|
|
@@ -886,7 +902,7 @@ var _StackClientAppImplIncomplete = class _StackClientAppImplIncomplete {
|
|
|
886
902
|
}
|
|
887
903
|
_getSessionFromTokenStore(tokenStore) {
|
|
888
904
|
const tokenObj = tokenStore.get();
|
|
889
|
-
const sessionKey =
|
|
905
|
+
const sessionKey = _hexclave_shared_dist_sessions.InternalSession.calculateSessionKey(tokenObj);
|
|
890
906
|
const existing = sessionKey ? this._sessionsByTokenStoreAndSessionKey.get(tokenStore)?.get(sessionKey) : null;
|
|
891
907
|
if (existing) return existing;
|
|
892
908
|
const session = this._interface.createSession({
|
|
@@ -917,7 +933,7 @@ var _StackClientAppImplIncomplete = class _StackClientAppImplIncomplete {
|
|
|
917
933
|
return this._getSessionFromTokenStore(tokenStore);
|
|
918
934
|
}
|
|
919
935
|
async _signInToAccountWithTokens(tokens) {
|
|
920
|
-
if (!("accessToken" in tokens) || !("refreshToken" in tokens)) throw new
|
|
936
|
+
if (!("accessToken" in tokens) || !("refreshToken" in tokens)) throw new _hexclave_shared_dist_utils_errors.HexclaveAssertionError("Invalid tokens object; can't sign in with this", { tokens });
|
|
921
937
|
const tokenStore = this._getOrCreateTokenStore(await this._createCookieHelper());
|
|
922
938
|
tokenStore.set(tokens);
|
|
923
939
|
const newSession = this._getSessionFromTokenStore(tokenStore);
|
|
@@ -1057,10 +1073,10 @@ var _StackClientAppImplIncomplete = class _StackClientAppImplIncomplete {
|
|
|
1057
1073
|
await app._teamInvitationsCache.refresh([session, crud.id]);
|
|
1058
1074
|
},
|
|
1059
1075
|
async listUsers() {
|
|
1060
|
-
return
|
|
1076
|
+
return _hexclave_shared_dist_utils_results.Result.orThrow(await app._teamMemberProfilesCache.getOrWait([session, crud.id], "write-only")).map((crud) => app._clientTeamUserFromCrud(crud));
|
|
1061
1077
|
},
|
|
1062
1078
|
async listInvitations() {
|
|
1063
|
-
return
|
|
1079
|
+
return _hexclave_shared_dist_utils_results.Result.orThrow(await app._teamInvitationsCache.getOrWait([session, crud.id], "write-only")).map((crud) => app._clientSentTeamInvitationFromCrud(session, crud));
|
|
1064
1080
|
},
|
|
1065
1081
|
async update(data) {
|
|
1066
1082
|
await app._interface.updateTeam({
|
|
@@ -1074,7 +1090,7 @@ var _StackClientAppImplIncomplete = class _StackClientAppImplIncomplete {
|
|
|
1074
1090
|
await app._currentUserTeamsCache.refresh([session]);
|
|
1075
1091
|
},
|
|
1076
1092
|
async listApiKeys() {
|
|
1077
|
-
return
|
|
1093
|
+
return _hexclave_shared_dist_utils_results.Result.orThrow(await app._teamApiKeysCache.getOrWait([session, crud.id], "write-only")).map((crud) => app._clientApiKeyFromCrud(session, crud));
|
|
1078
1094
|
},
|
|
1079
1095
|
async createApiKey(options) {
|
|
1080
1096
|
const result = await app._interface.createProjectApiKey(await (0, ______api_keys_index_js.apiKeyCreationOptionsToCrud)("team", crud.id, options), session, "client");
|
|
@@ -1134,9 +1150,9 @@ var _StackClientAppImplIncomplete = class _StackClientAppImplIncomplete {
|
|
|
1134
1150
|
allow_connected_accounts: data.allowConnectedAccounts
|
|
1135
1151
|
}, session);
|
|
1136
1152
|
await Promise.all([app._currentUserOAuthProvidersCache.refresh([session]), app._currentUserConnectedAccountsCache.refresh([session])]);
|
|
1137
|
-
return
|
|
1153
|
+
return _hexclave_shared_dist_utils_results.Result.ok(void 0);
|
|
1138
1154
|
} catch (error) {
|
|
1139
|
-
if (
|
|
1155
|
+
if (_hexclave_shared.KnownErrors.OAuthProviderAccountIdAlreadyUsedForSignIn.isInstance(error)) return _hexclave_shared_dist_utils_results.Result.error(error);
|
|
1140
1156
|
throw error;
|
|
1141
1157
|
}
|
|
1142
1158
|
},
|
|
@@ -1270,11 +1286,11 @@ var _StackClientAppImplIncomplete = class _StackClientAppImplIncomplete {
|
|
|
1270
1286
|
const scopeString = options?.scopes?.join(" ") ?? "";
|
|
1271
1287
|
if (typeof idOrAccount === "object" && "provider" in idOrAccount && "providerAccountId" in idOrAccount) {
|
|
1272
1288
|
const { provider, providerAccountId } = idOrAccount;
|
|
1273
|
-
const found =
|
|
1289
|
+
const found = _hexclave_shared_dist_utils_results.Result.orThrow(await app._currentUserConnectedAccountsCache.getOrWait([session], "write-only")).find((a) => a.provider === provider && a.providerAccountId === providerAccountId);
|
|
1274
1290
|
if (!found) return null;
|
|
1275
1291
|
return found;
|
|
1276
1292
|
}
|
|
1277
|
-
return
|
|
1293
|
+
return _hexclave_shared_dist_utils_results.Result.orThrow(await app._currentUserOAuthConnectionCache.getOrWait([
|
|
1278
1294
|
session,
|
|
1279
1295
|
idOrAccount,
|
|
1280
1296
|
scopeString,
|
|
@@ -1299,7 +1315,7 @@ var _StackClientAppImplIncomplete = class _StackClientAppImplIncomplete {
|
|
|
1299
1315
|
},
|
|
1300
1316
|
getConnectedAccount,
|
|
1301
1317
|
async listConnectedAccounts() {
|
|
1302
|
-
return
|
|
1318
|
+
return _hexclave_shared_dist_utils_results.Result.orThrow(await app._currentUserConnectedAccountsCache.getOrWait([session], "write-only"));
|
|
1303
1319
|
},
|
|
1304
1320
|
async linkConnectedAccount(provider, options) {
|
|
1305
1321
|
const scopeString = options?.scopes?.join(" ") ?? "";
|
|
@@ -1307,22 +1323,22 @@ var _StackClientAppImplIncomplete = class _StackClientAppImplIncomplete {
|
|
|
1307
1323
|
provider,
|
|
1308
1324
|
redirectUrl: app._getOAuthCallbackRedirectUri(),
|
|
1309
1325
|
errorRedirectUrl: app.urls.error,
|
|
1310
|
-
providerScope: (0,
|
|
1326
|
+
providerScope: (0, _hexclave_shared_dist_utils_strings.mergeScopeStrings)(scopeString, (app._oauthScopesOnSignIn[provider] ?? []).join(" "))
|
|
1311
1327
|
}, session);
|
|
1312
1328
|
await app._redirectTo({ url: location });
|
|
1313
|
-
return await (0,
|
|
1329
|
+
return await (0, _hexclave_shared_dist_utils_promises.neverResolve)();
|
|
1314
1330
|
},
|
|
1315
1331
|
async getOrLinkConnectedAccount(provider, options) {
|
|
1316
|
-
const matchingAccounts =
|
|
1332
|
+
const matchingAccounts = _hexclave_shared_dist_utils_results.Result.orThrow(await app._currentUserConnectedAccountsCache.getOrWait([session], "write-only")).filter((a) => a.provider === provider);
|
|
1317
1333
|
for (const account of matchingAccounts) if ((await account.getAccessToken({ scopes: options?.scopes })).status === "ok") return account;
|
|
1318
1334
|
await this.linkConnectedAccount(provider, options);
|
|
1319
|
-
return await (0,
|
|
1335
|
+
return await (0, _hexclave_shared_dist_utils_promises.neverResolve)();
|
|
1320
1336
|
},
|
|
1321
1337
|
async getTeam(teamId) {
|
|
1322
1338
|
return (await this.listTeams()).find((t) => t.id === teamId) ?? null;
|
|
1323
1339
|
},
|
|
1324
1340
|
async listTeams() {
|
|
1325
|
-
return
|
|
1341
|
+
return _hexclave_shared_dist_utils_results.Result.orThrow(await app._currentUserTeamsCache.getOrWait([session], "write-only")).map((crud) => app._clientTeamFromCrud(crud, session));
|
|
1326
1342
|
},
|
|
1327
1343
|
async createTeam(data) {
|
|
1328
1344
|
const crud = await app._interface.createClientTeam((0, ______teams_index_js.teamCreateOptionsToCrud)(data, "me"), session);
|
|
@@ -1334,20 +1350,20 @@ var _StackClientAppImplIncomplete = class _StackClientAppImplIncomplete {
|
|
|
1334
1350
|
await app._interface.leaveTeam(team.id, session);
|
|
1335
1351
|
},
|
|
1336
1352
|
async listTeamInvitations() {
|
|
1337
|
-
return
|
|
1353
|
+
return _hexclave_shared_dist_utils_results.Result.orThrow(await app._currentUserTeamInvitationsCache.getOrWait([session], "write-only")).map((crud) => app._clientReceivedTeamInvitationFromCrud(session, crud));
|
|
1338
1354
|
},
|
|
1339
1355
|
async listPermissions(scopeOrOptions, options) {
|
|
1340
1356
|
if (scopeOrOptions && "id" in scopeOrOptions) {
|
|
1341
1357
|
const scope = scopeOrOptions;
|
|
1342
1358
|
const recursive = options?.recursive ?? true;
|
|
1343
|
-
return
|
|
1359
|
+
return _hexclave_shared_dist_utils_results.Result.orThrow(await app._currentUserPermissionsCache.getOrWait([
|
|
1344
1360
|
session,
|
|
1345
1361
|
scope.id,
|
|
1346
1362
|
recursive
|
|
1347
1363
|
], "write-only")).map((crud) => app._clientPermissionFromCrud(crud));
|
|
1348
1364
|
} else {
|
|
1349
1365
|
const recursive = scopeOrOptions?.recursive ?? true;
|
|
1350
|
-
return
|
|
1366
|
+
return _hexclave_shared_dist_utils_results.Result.orThrow(await app._currentUserProjectPermissionsCache.getOrWait([session, recursive], "write-only")).map((crud) => app._clientPermissionFromCrud(crud));
|
|
1351
1367
|
}
|
|
1352
1368
|
},
|
|
1353
1369
|
async getPermission(scopeOrPermissionId, permissionId) {
|
|
@@ -1372,7 +1388,7 @@ var _StackClientAppImplIncomplete = class _StackClientAppImplIncomplete {
|
|
|
1372
1388
|
return await app._updateClientUser(update, session);
|
|
1373
1389
|
},
|
|
1374
1390
|
async sendVerificationEmail(options) {
|
|
1375
|
-
if (!crud.primary_email) throw new
|
|
1391
|
+
if (!crud.primary_email) throw new _hexclave_shared_dist_utils_errors.HexclaveAssertionError("User does not have a primary email");
|
|
1376
1392
|
return await app._interface.sendVerificationEmail(crud.primary_email, options?.callbackUrl ?? (0, ____________utils_url_js.constructRedirectUrl)(app.urls.emailVerification, "callbackUrl"), session);
|
|
1377
1393
|
},
|
|
1378
1394
|
async updatePassword(options) {
|
|
@@ -1387,7 +1403,7 @@ var _StackClientAppImplIncomplete = class _StackClientAppImplIncomplete {
|
|
|
1387
1403
|
},
|
|
1388
1404
|
selectedTeam: crud.selected_team && this._clientTeamFromCrud(crud.selected_team, session),
|
|
1389
1405
|
async getTeamProfile(team) {
|
|
1390
|
-
const result =
|
|
1406
|
+
const result = _hexclave_shared_dist_utils_results.Result.orThrow(await app._currentUserTeamProfileCache.getOrWait([session, team.id], "write-only"));
|
|
1391
1407
|
return app._editableTeamProfileFromCrud(result, session);
|
|
1392
1408
|
},
|
|
1393
1409
|
async delete() {
|
|
@@ -1395,7 +1411,7 @@ var _StackClientAppImplIncomplete = class _StackClientAppImplIncomplete {
|
|
|
1395
1411
|
session.markInvalid();
|
|
1396
1412
|
},
|
|
1397
1413
|
async listContactChannels() {
|
|
1398
|
-
return
|
|
1414
|
+
return _hexclave_shared_dist_utils_results.Result.orThrow(await app._clientContactChannelsCache.getOrWait([session], "write-only")).map((crud) => app._clientContactChannelFromCrud(crud, session));
|
|
1399
1415
|
},
|
|
1400
1416
|
async createContactChannel(data) {
|
|
1401
1417
|
const crud = await app._interface.createClientContactChannel((0, ______contact_channels_index_js.contactChannelCreateOptionsToCrud)("me", data), session);
|
|
@@ -1403,7 +1419,7 @@ var _StackClientAppImplIncomplete = class _StackClientAppImplIncomplete {
|
|
|
1403
1419
|
return app._clientContactChannelFromCrud(crud, session);
|
|
1404
1420
|
},
|
|
1405
1421
|
async listNotificationCategories() {
|
|
1406
|
-
return
|
|
1422
|
+
return _hexclave_shared_dist_utils_results.Result.orThrow(await app._notificationCategoriesCache.getOrWait([session], "write-only")).map((crud) => app._clientNotificationCategoryFromCrud(crud, session));
|
|
1407
1423
|
},
|
|
1408
1424
|
async listApiKeys() {
|
|
1409
1425
|
return (await app._interface.listProjectApiKeys({ user_id: "me" }, session, "client")).map((crud) => app._clientApiKeyFromCrud(session, crud));
|
|
@@ -1414,27 +1430,27 @@ var _StackClientAppImplIncomplete = class _StackClientAppImplIncomplete {
|
|
|
1414
1430
|
return app._clientApiKeyFromCrud(session, result);
|
|
1415
1431
|
},
|
|
1416
1432
|
async listOAuthProviders() {
|
|
1417
|
-
return
|
|
1433
|
+
return _hexclave_shared_dist_utils_results.Result.orThrow(await app._currentUserOAuthProvidersCache.getOrWait([session], "write-only")).map((crud) => app._clientOAuthProviderFromCrud(crud, session));
|
|
1418
1434
|
},
|
|
1419
1435
|
async getOAuthProvider(id) {
|
|
1420
1436
|
return (await this.listOAuthProviders()).find((p) => p.id === id) ?? null;
|
|
1421
1437
|
},
|
|
1422
1438
|
async registerPasskey(options) {
|
|
1423
1439
|
const hostname = (await app._getCurrentUrl())?.hostname;
|
|
1424
|
-
if (!hostname) throw new
|
|
1440
|
+
if (!hostname) throw new _hexclave_shared_dist_utils_errors.HexclaveAssertionError("hostname must be provided if the Stack App does not have a redirect method");
|
|
1425
1441
|
const initiationResult = await app._interface.initiatePasskeyRegistration({}, session);
|
|
1426
|
-
if (initiationResult.status !== "ok") return
|
|
1442
|
+
if (initiationResult.status !== "ok") return _hexclave_shared_dist_utils_results.Result.error(new _hexclave_shared.KnownErrors.PasskeyRegistrationFailed("Failed to get initiation options for passkey registration"));
|
|
1427
1443
|
const { options_json, code } = initiationResult.data;
|
|
1428
|
-
if (options_json.rp.id !== "THIS_VALUE_WILL_BE_REPLACED.example.com") throw new
|
|
1444
|
+
if (options_json.rp.id !== "THIS_VALUE_WILL_BE_REPLACED.example.com") throw new _hexclave_shared_dist_utils_errors.HexclaveAssertionError(`Expected returned RP ID from server to equal sentinel, but found ${options_json.rp.id}`);
|
|
1429
1445
|
options_json.rp.id = hostname;
|
|
1430
1446
|
let attResp;
|
|
1431
1447
|
try {
|
|
1432
1448
|
attResp = await (0, _simplewebauthn_browser.startRegistration)({ optionsJSON: options_json });
|
|
1433
1449
|
} catch (error) {
|
|
1434
|
-
if (error instanceof _simplewebauthn_browser.WebAuthnError) return
|
|
1450
|
+
if (error instanceof _simplewebauthn_browser.WebAuthnError) return _hexclave_shared_dist_utils_results.Result.error(new _hexclave_shared.KnownErrors.PasskeyWebAuthnError(error.message, error.name));
|
|
1435
1451
|
else {
|
|
1436
|
-
(0,
|
|
1437
|
-
return
|
|
1452
|
+
(0, _hexclave_shared_dist_utils_errors.captureError)("passkey-registration-failed", error);
|
|
1453
|
+
return _hexclave_shared_dist_utils_results.Result.error(new _hexclave_shared.KnownErrors.PasskeyRegistrationFailed("Failed to start passkey registration due to unknown error"));
|
|
1438
1454
|
}
|
|
1439
1455
|
}
|
|
1440
1456
|
const registrationResult = await app._interface.registerPasskey({
|
|
@@ -1468,7 +1484,7 @@ var _StackClientAppImplIncomplete = class _StackClientAppImplIncomplete {
|
|
|
1468
1484
|
const customerOptions = type === "user" ? { userId: userIdOrTeamId } : { teamId: userIdOrTeamId };
|
|
1469
1485
|
return {
|
|
1470
1486
|
async getBilling() {
|
|
1471
|
-
const response =
|
|
1487
|
+
const response = _hexclave_shared_dist_utils_results.Result.orThrow(await app._customerBillingCache.getOrWait([
|
|
1472
1488
|
effectiveSession,
|
|
1473
1489
|
type,
|
|
1474
1490
|
userIdOrTeamId
|
|
@@ -1534,17 +1550,17 @@ var _StackClientAppImplIncomplete = class _StackClientAppImplIncomplete {
|
|
|
1534
1550
|
async getItem(options) {
|
|
1535
1551
|
const session = await this._getSession();
|
|
1536
1552
|
let crud;
|
|
1537
|
-
if ("userId" in options) crud =
|
|
1553
|
+
if ("userId" in options) crud = _hexclave_shared_dist_utils_results.Result.orThrow(await this._userItemCache.getOrWait([
|
|
1538
1554
|
session,
|
|
1539
1555
|
options.userId,
|
|
1540
1556
|
options.itemId
|
|
1541
1557
|
], "write-only"));
|
|
1542
|
-
else if ("teamId" in options) crud =
|
|
1558
|
+
else if ("teamId" in options) crud = _hexclave_shared_dist_utils_results.Result.orThrow(await this._teamItemCache.getOrWait([
|
|
1543
1559
|
session,
|
|
1544
1560
|
options.teamId,
|
|
1545
1561
|
options.itemId
|
|
1546
1562
|
], "write-only"));
|
|
1547
|
-
else crud =
|
|
1563
|
+
else crud = _hexclave_shared_dist_utils_results.Result.orThrow(await this._customItemCache.getOrWait([
|
|
1548
1564
|
session,
|
|
1549
1565
|
options.customCustomerId,
|
|
1550
1566
|
options.itemId
|
|
@@ -1554,7 +1570,7 @@ var _StackClientAppImplIncomplete = class _StackClientAppImplIncomplete {
|
|
|
1554
1570
|
async listProducts(options) {
|
|
1555
1571
|
const session = (await this.getUser())?._internalSession ?? await this._getSession();
|
|
1556
1572
|
if ("userId" in options) {
|
|
1557
|
-
const response =
|
|
1573
|
+
const response = _hexclave_shared_dist_utils_results.Result.orThrow(await this._userProductsCache.getOrWait([
|
|
1558
1574
|
session,
|
|
1559
1575
|
options.userId,
|
|
1560
1576
|
options.cursor ?? null,
|
|
@@ -1562,7 +1578,7 @@ var _StackClientAppImplIncomplete = class _StackClientAppImplIncomplete {
|
|
|
1562
1578
|
], "write-only"));
|
|
1563
1579
|
return this._customerProductsFromResponse(response);
|
|
1564
1580
|
} else if ("teamId" in options) {
|
|
1565
|
-
const response =
|
|
1581
|
+
const response = _hexclave_shared_dist_utils_results.Result.orThrow(await this._teamProductsCache.getOrWait([
|
|
1566
1582
|
session,
|
|
1567
1583
|
options.teamId,
|
|
1568
1584
|
options.cursor ?? null,
|
|
@@ -1570,7 +1586,7 @@ var _StackClientAppImplIncomplete = class _StackClientAppImplIncomplete {
|
|
|
1570
1586
|
], "write-only"));
|
|
1571
1587
|
return this._customerProductsFromResponse(response);
|
|
1572
1588
|
}
|
|
1573
|
-
const response =
|
|
1589
|
+
const response = _hexclave_shared_dist_utils_results.Result.orThrow(await this._customProductsCache.getOrWait([
|
|
1574
1590
|
session,
|
|
1575
1591
|
options.customCustomerId,
|
|
1576
1592
|
options.cursor ?? null,
|
|
@@ -1581,7 +1597,7 @@ var _StackClientAppImplIncomplete = class _StackClientAppImplIncomplete {
|
|
|
1581
1597
|
async listInvoices(options) {
|
|
1582
1598
|
const session = await this._getSession();
|
|
1583
1599
|
if ("userId" in options) {
|
|
1584
|
-
const response =
|
|
1600
|
+
const response = _hexclave_shared_dist_utils_results.Result.orThrow(await this._userInvoicesCache.getOrWait([
|
|
1585
1601
|
session,
|
|
1586
1602
|
options.userId,
|
|
1587
1603
|
options.cursor ?? null,
|
|
@@ -1589,7 +1605,7 @@ var _StackClientAppImplIncomplete = class _StackClientAppImplIncomplete {
|
|
|
1589
1605
|
], "write-only"));
|
|
1590
1606
|
return this._customerInvoicesFromResponse(response);
|
|
1591
1607
|
}
|
|
1592
|
-
const response =
|
|
1608
|
+
const response = _hexclave_shared_dist_utils_results.Result.orThrow(await this._teamInvoicesCache.getOrWait([
|
|
1593
1609
|
session,
|
|
1594
1610
|
options.teamId,
|
|
1595
1611
|
options.cursor ?? null,
|
|
@@ -1600,7 +1616,7 @@ var _StackClientAppImplIncomplete = class _StackClientAppImplIncomplete {
|
|
|
1600
1616
|
async cancelSubscription(options) {
|
|
1601
1617
|
const session = await this._getSession();
|
|
1602
1618
|
const user = await this.getUser();
|
|
1603
|
-
if (!user) throw new
|
|
1619
|
+
if (!user) throw new _hexclave_shared.KnownErrors.UserAuthenticationRequired();
|
|
1604
1620
|
const customerType = "teamId" in options ? "team" : "user";
|
|
1605
1621
|
const customerId = "teamId" in options ? options.teamId : user.id;
|
|
1606
1622
|
await this._interface.cancelSubscription({
|
|
@@ -1649,7 +1665,7 @@ var _StackClientAppImplIncomplete = class _StackClientAppImplIncomplete {
|
|
|
1649
1665
|
return __common_js.clientVersion;
|
|
1650
1666
|
}
|
|
1651
1667
|
_getBotChallengeSiteKeys() {
|
|
1652
|
-
if (!(0,
|
|
1668
|
+
if (!(0, _hexclave_shared_dist_utils_env.isBrowserLike)()) return null;
|
|
1653
1669
|
const visibleSiteKey = _________env_js.envVars.NEXT_PUBLIC_STACK_BOT_CHALLENGE_SITE_KEY;
|
|
1654
1670
|
if (!visibleSiteKey) {
|
|
1655
1671
|
if (!this._botChallengeSiteKeysWarned) {
|
|
@@ -1664,23 +1680,23 @@ var _StackClientAppImplIncomplete = class _StackClientAppImplIncomplete {
|
|
|
1664
1680
|
};
|
|
1665
1681
|
}
|
|
1666
1682
|
_getBotChallengeFlowFailure(error) {
|
|
1667
|
-
if (error instanceof
|
|
1683
|
+
if (error instanceof _hexclave_shared_dist_utils_turnstile_flow.BotChallengeUserCancelledError) return {
|
|
1668
1684
|
type: "cancelled",
|
|
1669
|
-
knownError: new
|
|
1685
|
+
knownError: new _hexclave_shared.KnownErrors.BotChallengeFailed("Bot challenge cancelled by user")
|
|
1670
1686
|
};
|
|
1671
|
-
if (error instanceof
|
|
1687
|
+
if (error instanceof _hexclave_shared_dist_utils_turnstile_flow.BotChallengeExecutionFailedError) return {
|
|
1672
1688
|
type: "failed",
|
|
1673
|
-
knownError: new
|
|
1689
|
+
knownError: new _hexclave_shared.KnownErrors.BotChallengeFailed(error.message)
|
|
1674
1690
|
};
|
|
1675
1691
|
return null;
|
|
1676
1692
|
}
|
|
1677
1693
|
_normalizeBotChallengeResult(result) {
|
|
1678
1694
|
if (result.status === "ok") return result;
|
|
1679
|
-
if (
|
|
1680
|
-
(0,
|
|
1681
|
-
return
|
|
1695
|
+
if (_hexclave_shared.KnownErrors.BotChallengeRequired.isInstance(result.error)) {
|
|
1696
|
+
(0, _hexclave_shared_dist_utils_errors.captureError)("bot-challenge-unexpected-after-flow", result.error);
|
|
1697
|
+
return _hexclave_shared_dist_utils_results.Result.error(new _hexclave_shared.KnownErrors.BotChallengeFailed("Unexpected bot challenge after flow completion"));
|
|
1682
1698
|
}
|
|
1683
|
-
return
|
|
1699
|
+
return _hexclave_shared_dist_utils_results.Result.error(result.error);
|
|
1684
1700
|
}
|
|
1685
1701
|
_toInterfaceBotChallengeInput(challenge) {
|
|
1686
1702
|
if (challenge.unavailable) return { phase: "visible" };
|
|
@@ -1693,25 +1709,25 @@ var _StackClientAppImplIncomplete = class _StackClientAppImplIncomplete {
|
|
|
1693
1709
|
const siteKeys = this._getBotChallengeSiteKeys();
|
|
1694
1710
|
let result;
|
|
1695
1711
|
try {
|
|
1696
|
-
if (siteKeys) result = await (0,
|
|
1712
|
+
if (siteKeys) result = await (0, _hexclave_shared_dist_utils_turnstile_flow.withBotChallengeFlow)({
|
|
1697
1713
|
...siteKeys,
|
|
1698
1714
|
action: options.action,
|
|
1699
1715
|
execute: options.execute,
|
|
1700
1716
|
isChallengeRequired: (flowResult) => {
|
|
1701
|
-
return flowResult.status === "error" &&
|
|
1717
|
+
return flowResult.status === "error" && _hexclave_shared.KnownErrors.BotChallengeRequired.isInstance(flowResult.error);
|
|
1702
1718
|
}
|
|
1703
1719
|
});
|
|
1704
1720
|
else result = await options.execute({});
|
|
1705
1721
|
} catch (e) {
|
|
1706
1722
|
const flowFailure = this._getBotChallengeFlowFailure(e);
|
|
1707
|
-
if (flowFailure) return
|
|
1723
|
+
if (flowFailure) return _hexclave_shared_dist_utils_results.Result.error(flowFailure.knownError);
|
|
1708
1724
|
throw e;
|
|
1709
1725
|
}
|
|
1710
1726
|
return this._normalizeBotChallengeResult(result);
|
|
1711
1727
|
}
|
|
1712
1728
|
async _isTrusted(url) {
|
|
1713
|
-
if ((0,
|
|
1714
|
-
const parsedUrl = (0,
|
|
1729
|
+
if ((0, _hexclave_shared_dist_utils_urls.isRelative)(url)) return true;
|
|
1730
|
+
const parsedUrl = (0, _hexclave_shared_dist_utils_urls.createUrlIfValid)(url);
|
|
1715
1731
|
if (parsedUrl == null) return false;
|
|
1716
1732
|
if (typeof window !== "undefined" && window.location.origin === parsedUrl.origin) return true;
|
|
1717
1733
|
if ((0, ______url_targets_js.isHostedHandlerUrlForProject)({
|
|
@@ -1719,7 +1735,7 @@ var _StackClientAppImplIncomplete = class _StackClientAppImplIncomplete {
|
|
|
1719
1735
|
projectId: this.projectId
|
|
1720
1736
|
})) return true;
|
|
1721
1737
|
const trustedRedirectConfig = await this._getTrustedRedirectConfig();
|
|
1722
|
-
return (0,
|
|
1738
|
+
return (0, _hexclave_shared_dist_utils_redirect_urls.validateRedirectUrl)(parsedUrl, {
|
|
1723
1739
|
allowLocalhost: trustedRedirectConfig.allowLocalhost,
|
|
1724
1740
|
trustedDomains: trustedRedirectConfig.trustedDomains
|
|
1725
1741
|
});
|
|
@@ -1729,11 +1745,11 @@ var _StackClientAppImplIncomplete = class _StackClientAppImplIncomplete {
|
|
|
1729
1745
|
}
|
|
1730
1746
|
_prefetchCrossDomainHandoffParamsIfNeeded() {
|
|
1731
1747
|
const canWriteOauthVerifierCookie = this._tokenStoreInit === "cookie" || this._tokenStoreInit === "nextjs-cookie";
|
|
1732
|
-
if (!(0,
|
|
1748
|
+
if (!(0, _hexclave_shared_dist_utils_env.isBrowserLike)() || !canWriteOauthVerifierCookie || this._isPrefetchingCrossDomainHandoffParams || this._getFreshPrefetchedCrossDomainHandoffParams() != null) return;
|
|
1733
1749
|
this._isPrefetchingCrossDomainHandoffParams = true;
|
|
1734
|
-
(0,
|
|
1750
|
+
(0, _hexclave_shared_dist_utils_promises.runAsynchronously)(async () => {
|
|
1735
1751
|
try {
|
|
1736
|
-
if (!(0,
|
|
1752
|
+
if (!(0, _hexclave_shared_dist_utils_env.isBrowserLike)()) return;
|
|
1737
1753
|
const { state, codeChallenge } = await (0, _________cookie_js.saveVerifierAndState)();
|
|
1738
1754
|
this._prefetchedCrossDomainHandoffParams = {
|
|
1739
1755
|
state,
|
|
@@ -1795,10 +1811,10 @@ var _StackClientAppImplIncomplete = class _StackClientAppImplIncomplete {
|
|
|
1795
1811
|
}, session);
|
|
1796
1812
|
if (!response.ok) {
|
|
1797
1813
|
const responseBody = await response.text();
|
|
1798
|
-
throw new
|
|
1814
|
+
throw new _hexclave_shared_dist_utils_errors.HexclaveAssertionError(`Cross-domain authorization endpoint failed: ${response.status} ${responseBody}`);
|
|
1799
1815
|
}
|
|
1800
1816
|
const result = await response.json();
|
|
1801
|
-
if (!("redirect_url" in result) || typeof result.redirect_url !== "string") throw new
|
|
1817
|
+
if (!("redirect_url" in result) || typeof result.redirect_url !== "string") throw new _hexclave_shared_dist_utils_errors.HexclaveAssertionError("Cross-domain authorization endpoint returned an invalid payload", { result });
|
|
1802
1818
|
return result.redirect_url;
|
|
1803
1819
|
}
|
|
1804
1820
|
_getFreshPrefetchedCrossDomainHandoffParams() {
|
|
@@ -1819,7 +1835,7 @@ var _StackClientAppImplIncomplete = class _StackClientAppImplIncomplete {
|
|
|
1819
1835
|
else if (typeof this._redirectMethod === "object" && this._redirectMethod.navigate) this._redirectMethod.navigate(options.url.toString());
|
|
1820
1836
|
else if (options.replace) window.location.replace(options.url);
|
|
1821
1837
|
else window.location.assign(options.url);
|
|
1822
|
-
await (0,
|
|
1838
|
+
await (0, _hexclave_shared_dist_utils_promises.wait)(2e3);
|
|
1823
1839
|
}
|
|
1824
1840
|
async _redirectIfTrusted(url, options) {
|
|
1825
1841
|
if (!await this._isTrusted(url)) throw new Error(`Redirect URL ${url} is not trusted; should be relative.`);
|
|
@@ -1951,8 +1967,8 @@ var _StackClientAppImplIncomplete = class _StackClientAppImplIncomplete {
|
|
|
1951
1967
|
code,
|
|
1952
1968
|
session: await this._getSession()
|
|
1953
1969
|
});
|
|
1954
|
-
if (result.status === "ok") return
|
|
1955
|
-
else return
|
|
1970
|
+
if (result.status === "ok") return _hexclave_shared_dist_utils_results.Result.ok(void 0);
|
|
1971
|
+
else return _hexclave_shared_dist_utils_results.Result.error(result.error);
|
|
1956
1972
|
}
|
|
1957
1973
|
async getTeamInvitationDetails(code) {
|
|
1958
1974
|
const result = await this._interface.acceptTeamInvitation({
|
|
@@ -1960,8 +1976,8 @@ var _StackClientAppImplIncomplete = class _StackClientAppImplIncomplete {
|
|
|
1960
1976
|
code,
|
|
1961
1977
|
session: await this._getSession()
|
|
1962
1978
|
});
|
|
1963
|
-
if (result.status === "ok") return
|
|
1964
|
-
else return
|
|
1979
|
+
if (result.status === "ok") return _hexclave_shared_dist_utils_results.Result.ok({ teamDisplayName: result.data.team_display_name });
|
|
1980
|
+
else return _hexclave_shared_dist_utils_results.Result.error(result.error);
|
|
1965
1981
|
}
|
|
1966
1982
|
async verifyEmail(code) {
|
|
1967
1983
|
const result = await this._interface.verifyEmail(code);
|
|
@@ -1973,7 +1989,7 @@ var _StackClientAppImplIncomplete = class _StackClientAppImplIncomplete {
|
|
|
1973
1989
|
if (options?.or === "anonymous" && options.includeRestricted === false) throw new Error("Cannot use { or: 'anonymous' } with { includeRestricted: false }. Anonymous users implicitly include restricted users.");
|
|
1974
1990
|
this._ensurePersistentTokenStore(options?.tokenStore);
|
|
1975
1991
|
const session = await this._getSession(options?.tokenStore);
|
|
1976
|
-
let crud =
|
|
1992
|
+
let crud = _hexclave_shared_dist_utils_results.Result.orThrow(await this._currentUserCache.getOrWait([session], "write-only"));
|
|
1977
1993
|
const includeAnonymous = options?.or === "anonymous" || options?.or === "anonymous-if-exists[deprecated]";
|
|
1978
1994
|
const includeRestricted = options?.includeRestricted === true || includeAnonymous;
|
|
1979
1995
|
if (crud === null || crud.is_anonymous && !includeAnonymous || crud.is_restricted && !includeRestricted) switch (options?.or) {
|
|
@@ -1988,7 +2004,7 @@ var _StackClientAppImplIncomplete = class _StackClientAppImplIncomplete {
|
|
|
1988
2004
|
tokenStore: tokens,
|
|
1989
2005
|
or: "anonymous-if-exists[deprecated]",
|
|
1990
2006
|
includeRestricted: true
|
|
1991
|
-
}) ?? (0,
|
|
2007
|
+
}) ?? (0, _hexclave_shared_dist_utils_errors.throwErr)("Something went wrong while signing up anonymously");
|
|
1992
2008
|
}
|
|
1993
2009
|
case void 0:
|
|
1994
2010
|
case "anonymous-if-exists[deprecated]":
|
|
@@ -2076,12 +2092,12 @@ var _StackClientAppImplIncomplete = class _StackClientAppImplIncomplete {
|
|
|
2076
2092
|
};
|
|
2077
2093
|
let authorizeResult;
|
|
2078
2094
|
try {
|
|
2079
|
-
if (siteKeys) authorizeResult = await (0,
|
|
2095
|
+
if (siteKeys) authorizeResult = await (0, _hexclave_shared_dist_utils_turnstile_flow.withBotChallengeFlow)({
|
|
2080
2096
|
...siteKeys,
|
|
2081
2097
|
action: "oauth_authenticate",
|
|
2082
2098
|
execute: executeOAuth,
|
|
2083
2099
|
isChallengeRequired: (result) => {
|
|
2084
|
-
return result.status === "error" &&
|
|
2100
|
+
return result.status === "error" && _hexclave_shared.KnownErrors.BotChallengeRequired.isInstance(result.error);
|
|
2085
2101
|
}
|
|
2086
2102
|
});
|
|
2087
2103
|
else authorizeResult = await executeOAuth({});
|
|
@@ -2091,17 +2107,17 @@ var _StackClientAppImplIncomplete = class _StackClientAppImplIncomplete {
|
|
|
2091
2107
|
if (flowFailure?.type === "failed") throw flowFailure.knownError;
|
|
2092
2108
|
throw e;
|
|
2093
2109
|
}
|
|
2094
|
-
const location =
|
|
2110
|
+
const location = _hexclave_shared_dist_utils_results.Result.orThrow(authorizeResult);
|
|
2095
2111
|
await this._redirectTo({ url: location });
|
|
2096
|
-
await (0,
|
|
2112
|
+
await (0, _hexclave_shared_dist_utils_promises.neverResolve)();
|
|
2097
2113
|
}
|
|
2098
2114
|
/**
|
|
2099
2115
|
* Handles MFA verification by redirecting to the OTP page
|
|
2100
2116
|
*/
|
|
2101
2117
|
async _experimentalMfa(error, session) {
|
|
2102
|
-
if (typeof window !== "undefined") window.sessionStorage.setItem("hexclave_mfa_attempt_code", error.details?.attempt_code ?? (0,
|
|
2118
|
+
if (typeof window !== "undefined") window.sessionStorage.setItem("hexclave_mfa_attempt_code", error.details?.attempt_code ?? (0, _hexclave_shared_dist_utils_errors.throwErr)("attempt code missing"));
|
|
2103
2119
|
await this.redirectToMfa();
|
|
2104
|
-
throw new
|
|
2120
|
+
throw new _hexclave_shared_dist_utils_errors.HexclaveAssertionError("we should have redirected in redirectToMfa()");
|
|
2105
2121
|
}
|
|
2106
2122
|
/**
|
|
2107
2123
|
* @deprecated
|
|
@@ -2111,7 +2127,7 @@ var _StackClientAppImplIncomplete = class _StackClientAppImplIncomplete {
|
|
|
2111
2127
|
try {
|
|
2112
2128
|
return await callback();
|
|
2113
2129
|
} catch (e) {
|
|
2114
|
-
if (
|
|
2130
|
+
if (_hexclave_shared.KnownErrors.MultiFactorAuthenticationRequired.isInstance(e)) return _hexclave_shared_dist_utils_results.Result.ok(await this._experimentalMfa(e, await this._getSession(void 0, { awaitPendingAuthResolutions: false })));
|
|
2115
2131
|
throw e;
|
|
2116
2132
|
}
|
|
2117
2133
|
}
|
|
@@ -2124,25 +2140,25 @@ var _StackClientAppImplIncomplete = class _StackClientAppImplIncomplete {
|
|
|
2124
2140
|
return await this._interface.signInWithCredential(options.email, options.password, session);
|
|
2125
2141
|
});
|
|
2126
2142
|
} catch (e) {
|
|
2127
|
-
if (
|
|
2143
|
+
if (_hexclave_shared.KnownErrors.InvalidTotpCode.isInstance(e)) return _hexclave_shared_dist_utils_results.Result.error(e);
|
|
2128
2144
|
throw e;
|
|
2129
2145
|
}
|
|
2130
2146
|
if (result.status === "ok") {
|
|
2131
2147
|
await this._signInToAccountWithTokens(result.data);
|
|
2132
2148
|
if (!options.noRedirect) await this._redirectToHandler("afterSignIn", { replace: true }, { overrideTokenStoreInit: this._getTokenStoreInitForFreshTokens(result.data) });
|
|
2133
|
-
return
|
|
2134
|
-
} else return
|
|
2149
|
+
return _hexclave_shared_dist_utils_results.Result.ok(void 0);
|
|
2150
|
+
} else return _hexclave_shared_dist_utils_results.Result.error(result.error);
|
|
2135
2151
|
}
|
|
2136
2152
|
async signUpWithCredential(options) {
|
|
2137
|
-
if (options.noVerificationCallback && options.verificationCallbackUrl) throw new
|
|
2153
|
+
if (options.noVerificationCallback && options.verificationCallbackUrl) throw new _hexclave_shared_dist_utils_errors.HexclaveAssertionError("verificationCallbackUrl is not allowed when noVerificationCallback is true");
|
|
2138
2154
|
this._ensurePersistentTokenStore();
|
|
2139
2155
|
const session = await this._getSession();
|
|
2140
2156
|
const emailVerificationRedirectUrl = options.noVerificationCallback ? void 0 : options.verificationCallbackUrl ?? (0, ____________utils_url_js.constructRedirectUrl)(this.urls.emailVerification, "verificationCallbackUrl");
|
|
2141
2157
|
const executeSignUp = async (challenge) => {
|
|
2142
2158
|
let result = await this._interface.signUpWithCredential(options.email, options.password, emailVerificationRedirectUrl, session, this._toInterfaceBotChallengeInput(challenge));
|
|
2143
|
-
if (result.status === "error" && result.error instanceof
|
|
2159
|
+
if (result.status === "error" && result.error instanceof _hexclave_shared.KnownErrors.RedirectUrlNotWhitelisted && emailVerificationRedirectUrl !== void 0) {
|
|
2144
2160
|
if (!options.verificationCallbackUrl) {
|
|
2145
|
-
(0,
|
|
2161
|
+
(0, _hexclave_shared_dist_utils_errors.captureError)("signup-verification-url-not-whitelisted", new _hexclave_shared_dist_utils_errors.HexclaveAssertionError("The auto-constructed verification callback URL is not whitelisted; proceeding without email verification", { emailVerificationRedirectUrl }));
|
|
2146
2162
|
result = await this._interface.signUpWithCredential(options.email, options.password, void 0, session, this._toInterfaceBotChallengeInput(challenge));
|
|
2147
2163
|
}
|
|
2148
2164
|
}
|
|
@@ -2156,8 +2172,8 @@ var _StackClientAppImplIncomplete = class _StackClientAppImplIncomplete {
|
|
|
2156
2172
|
if (result.status === "ok") {
|
|
2157
2173
|
await this._signInToAccountWithTokens(result.data);
|
|
2158
2174
|
if (!options.noRedirect) await this._redirectToHandler("afterSignUp", { replace: true }, { overrideTokenStoreInit: this._getTokenStoreInitForFreshTokens(result.data) });
|
|
2159
|
-
return
|
|
2160
|
-
} else return
|
|
2175
|
+
return _hexclave_shared_dist_utils_results.Result.ok(void 0);
|
|
2176
|
+
} else return _hexclave_shared_dist_utils_results.Result.error(result.error);
|
|
2161
2177
|
}
|
|
2162
2178
|
async _signUpAnonymously() {
|
|
2163
2179
|
this._ensurePersistentTokenStore();
|
|
@@ -2166,7 +2182,7 @@ var _StackClientAppImplIncomplete = class _StackClientAppImplIncomplete {
|
|
|
2166
2182
|
const session = await this._getSession();
|
|
2167
2183
|
const result = await this._interface.signUpAnonymously(session);
|
|
2168
2184
|
if (result.status === "ok") await this._signInToAccountWithTokens(result.data);
|
|
2169
|
-
else throw new
|
|
2185
|
+
else throw new _hexclave_shared_dist_utils_errors.HexclaveAssertionError("signUpAnonymously() should never return an error");
|
|
2170
2186
|
this._anonymousSignUpInProgress = null;
|
|
2171
2187
|
return result.data;
|
|
2172
2188
|
})();
|
|
@@ -2181,7 +2197,7 @@ var _StackClientAppImplIncomplete = class _StackClientAppImplIncomplete {
|
|
|
2181
2197
|
return await this._interface.signInWithMagicLink(code, session);
|
|
2182
2198
|
});
|
|
2183
2199
|
} catch (e) {
|
|
2184
|
-
if (
|
|
2200
|
+
if (_hexclave_shared.KnownErrors.InvalidTotpCode.isInstance(e)) return _hexclave_shared_dist_utils_results.Result.error(e);
|
|
2185
2201
|
throw e;
|
|
2186
2202
|
}
|
|
2187
2203
|
if (result.status === "ok") {
|
|
@@ -2194,8 +2210,8 @@ var _StackClientAppImplIncomplete = class _StackClientAppImplIncomplete {
|
|
|
2194
2210
|
awaitPendingAuthResolutions: false,
|
|
2195
2211
|
overrideTokenStoreInit: this._getTokenStoreInitForFreshTokens(result.data)
|
|
2196
2212
|
});
|
|
2197
|
-
return
|
|
2198
|
-
} else return
|
|
2213
|
+
return _hexclave_shared_dist_utils_results.Result.ok(void 0);
|
|
2214
|
+
} else return _hexclave_shared_dist_utils_results.Result.error(result.error);
|
|
2199
2215
|
}
|
|
2200
2216
|
/**
|
|
2201
2217
|
* Initiates a CLI authentication process that allows a command line application
|
|
@@ -2226,7 +2242,7 @@ var _StackClientAppImplIncomplete = class _StackClientAppImplIncomplete {
|
|
|
2226
2242
|
...options.anonRefreshToken != null ? { anon_refresh_token: options.anonRefreshToken } : {}
|
|
2227
2243
|
})
|
|
2228
2244
|
}, null);
|
|
2229
|
-
if (!response.ok) return
|
|
2245
|
+
if (!response.ok) return _hexclave_shared_dist_utils_results.Result.error(new _hexclave_shared.KnownErrors.CliAuthError(`Failed to initiate CLI auth: ${response.status} ${await response.text()}`));
|
|
2230
2246
|
const initResult = await response.json();
|
|
2231
2247
|
const pollingCode = initResult.polling_code;
|
|
2232
2248
|
const loginCode = initResult.login_code;
|
|
@@ -2248,18 +2264,18 @@ var _StackClientAppImplIncomplete = class _StackClientAppImplIncomplete {
|
|
|
2248
2264
|
headers: { "Content-Type": "application/json" },
|
|
2249
2265
|
body: JSON.stringify({ polling_code: pollingCode })
|
|
2250
2266
|
}, null);
|
|
2251
|
-
if (!pollResponse.ok) return
|
|
2267
|
+
if (!pollResponse.ok) return _hexclave_shared_dist_utils_results.Result.error(new _hexclave_shared.KnownErrors.CliAuthError(`Failed to initiate CLI auth: ${pollResponse.status} ${await pollResponse.text()}`));
|
|
2252
2268
|
const pollResult = await pollResponse.json();
|
|
2253
|
-
if (pollResponse.status === 201 && pollResult.status === "success") return
|
|
2269
|
+
if (pollResponse.status === 201 && pollResult.status === "success") return _hexclave_shared_dist_utils_results.Result.ok(pollResult.refresh_token);
|
|
2254
2270
|
if (pollResult.status === "waiting") {
|
|
2255
|
-
await (0,
|
|
2271
|
+
await (0, _hexclave_shared_dist_utils_promises.wait)(options.waitTimeMillis ?? 2e3);
|
|
2256
2272
|
continue;
|
|
2257
2273
|
}
|
|
2258
|
-
if (pollResult.status === "expired") return
|
|
2259
|
-
if (pollResult.status === "used") return
|
|
2260
|
-
return
|
|
2274
|
+
if (pollResult.status === "expired") return _hexclave_shared_dist_utils_results.Result.error(new _hexclave_shared.KnownErrors.CliAuthExpiredError("CLI authentication request expired. Please try again."));
|
|
2275
|
+
if (pollResult.status === "used") return _hexclave_shared_dist_utils_results.Result.error(new _hexclave_shared.KnownErrors.CliAuthUsedError("This authentication token has already been used."));
|
|
2276
|
+
return _hexclave_shared_dist_utils_results.Result.error(new _hexclave_shared.KnownErrors.CliAuthError(`Unexpected status from CLI auth polling: ${pollResult.status}`));
|
|
2261
2277
|
}
|
|
2262
|
-
return
|
|
2278
|
+
return _hexclave_shared_dist_utils_results.Result.error(new _hexclave_shared.KnownErrors.CliAuthError("Timed out waiting for CLI authentication."));
|
|
2263
2279
|
}
|
|
2264
2280
|
async signInWithMfa(totp, code, options) {
|
|
2265
2281
|
this._ensurePersistentTokenStore();
|
|
@@ -2270,16 +2286,16 @@ var _StackClientAppImplIncomplete = class _StackClientAppImplIncomplete {
|
|
|
2270
2286
|
return await this._interface.signInWithMfa(totp, code, session);
|
|
2271
2287
|
});
|
|
2272
2288
|
} catch (e) {
|
|
2273
|
-
if (e instanceof
|
|
2289
|
+
if (e instanceof _hexclave_shared.KnownErrors.InvalidTotpCode) return _hexclave_shared_dist_utils_results.Result.error(e);
|
|
2274
2290
|
throw e;
|
|
2275
2291
|
}
|
|
2276
2292
|
if (result.status === "ok") {
|
|
2277
2293
|
await this._signInToAccountWithTokens(result.data);
|
|
2278
2294
|
if (!options?.noRedirect) if (result.data.newUser) await this._redirectToHandler("afterSignUp", { replace: true }, { overrideTokenStoreInit: this._getTokenStoreInitForFreshTokens(result.data) });
|
|
2279
2295
|
else await this._redirectToHandler("afterSignIn", { replace: true }, { overrideTokenStoreInit: this._getTokenStoreInitForFreshTokens(result.data) });
|
|
2280
|
-
return
|
|
2296
|
+
return _hexclave_shared_dist_utils_results.Result.ok(void 0);
|
|
2281
2297
|
}
|
|
2282
|
-
return
|
|
2298
|
+
return _hexclave_shared_dist_utils_results.Result.error(result.error);
|
|
2283
2299
|
}
|
|
2284
2300
|
async signInWithPasskey() {
|
|
2285
2301
|
this._ensurePersistentTokenStore();
|
|
@@ -2288,9 +2304,9 @@ var _StackClientAppImplIncomplete = class _StackClientAppImplIncomplete {
|
|
|
2288
2304
|
try {
|
|
2289
2305
|
result = await this._catchMfaRequiredError(async () => {
|
|
2290
2306
|
const initiationResult = await this._interface.initiatePasskeyAuthentication({}, session);
|
|
2291
|
-
if (initiationResult.status !== "ok") return
|
|
2307
|
+
if (initiationResult.status !== "ok") return _hexclave_shared_dist_utils_results.Result.error(new _hexclave_shared.KnownErrors.PasskeyAuthenticationFailed("Failed to get initiation options for passkey authentication"));
|
|
2292
2308
|
const { options_json, code } = initiationResult.data;
|
|
2293
|
-
if (options_json.rpId !== "THIS_VALUE_WILL_BE_REPLACED.example.com") throw new
|
|
2309
|
+
if (options_json.rpId !== "THIS_VALUE_WILL_BE_REPLACED.example.com") throw new _hexclave_shared_dist_utils_errors.HexclaveAssertionError(`Expected returned RP ID from server to equal sentinel, but found ${options_json.rpId}`);
|
|
2294
2310
|
options_json.rpId = window.location.hostname;
|
|
2295
2311
|
const authentication_response = await (0, _simplewebauthn_browser.startAuthentication)({ optionsJSON: options_json });
|
|
2296
2312
|
return await this._interface.signInWithPasskey({
|
|
@@ -2299,14 +2315,14 @@ var _StackClientAppImplIncomplete = class _StackClientAppImplIncomplete {
|
|
|
2299
2315
|
}, session);
|
|
2300
2316
|
});
|
|
2301
2317
|
} catch (error) {
|
|
2302
|
-
if (error instanceof _simplewebauthn_browser.WebAuthnError) return
|
|
2303
|
-
else return
|
|
2318
|
+
if (error instanceof _simplewebauthn_browser.WebAuthnError) return _hexclave_shared_dist_utils_results.Result.error(new _hexclave_shared.KnownErrors.PasskeyWebAuthnError(error.message, error.name));
|
|
2319
|
+
else return _hexclave_shared_dist_utils_results.Result.error(new _hexclave_shared.KnownErrors.PasskeyAuthenticationFailed("Failed to sign in with passkey"));
|
|
2304
2320
|
}
|
|
2305
2321
|
if (result.status === "ok") {
|
|
2306
2322
|
await this._signInToAccountWithTokens(result.data);
|
|
2307
2323
|
await this._redirectToHandler("afterSignIn", { replace: true }, { overrideTokenStoreInit: this._getTokenStoreInitForFreshTokens(result.data) });
|
|
2308
|
-
return
|
|
2309
|
-
} else return
|
|
2324
|
+
return _hexclave_shared_dist_utils_results.Result.ok(void 0);
|
|
2325
|
+
} else return _hexclave_shared_dist_utils_results.Result.error(result.error);
|
|
2310
2326
|
}
|
|
2311
2327
|
async callOAuthCallback(options) {
|
|
2312
2328
|
if (typeof window === "undefined") throw new Error("callOAuthCallback can currently only be called in a browser environment");
|
|
@@ -2324,7 +2340,7 @@ var _StackClientAppImplIncomplete = class _StackClientAppImplIncomplete {
|
|
|
2324
2340
|
return await (0, _________auth_js.callOAuthCallback)(this._interface, oauthCallbackRedirectUri, options);
|
|
2325
2341
|
});
|
|
2326
2342
|
} catch (e) {
|
|
2327
|
-
if (
|
|
2343
|
+
if (_hexclave_shared.KnownErrors.InvalidTotpCode.isInstance(e)) {
|
|
2328
2344
|
alert("Invalid TOTP code. Please try signing in again.");
|
|
2329
2345
|
return false;
|
|
2330
2346
|
} else throw e;
|
|
@@ -2357,7 +2373,7 @@ var _StackClientAppImplIncomplete = class _StackClientAppImplIncomplete {
|
|
|
2357
2373
|
async _signOut(session, options) {
|
|
2358
2374
|
this._eventTracker?.clearBuffer();
|
|
2359
2375
|
this._sessionRecorder?.clearBuffer();
|
|
2360
|
-
await
|
|
2376
|
+
await _hexclave_shared_dist_utils_stores.storeLock.withWriteLock(async () => {
|
|
2361
2377
|
await this._interface.signOut(session);
|
|
2362
2378
|
if (options?.redirectUrl) await this._redirectTo({
|
|
2363
2379
|
url: options.redirectUrl,
|
|
@@ -2395,12 +2411,12 @@ var _StackClientAppImplIncomplete = class _StackClientAppImplIncomplete {
|
|
|
2395
2411
|
};
|
|
2396
2412
|
}
|
|
2397
2413
|
async getProject() {
|
|
2398
|
-
const crud =
|
|
2414
|
+
const crud = _hexclave_shared_dist_utils_results.Result.orThrow(await this._currentProjectCache.getOrWait([], "write-only"));
|
|
2399
2415
|
return this._clientProjectFromCrud(crud);
|
|
2400
2416
|
}
|
|
2401
2417
|
async _listOwnedProjects(session) {
|
|
2402
2418
|
this._ensureInternalProject();
|
|
2403
|
-
return
|
|
2419
|
+
return _hexclave_shared_dist_utils_results.Result.orThrow(await this._ownedProjectsCache.getOrWait([session], "write-only")).map((j) => this._getOwnedAdminApp(j.id, session)._adminOwnedProjectFromCrud(j, () => this._refreshOwnedProjects(session)));
|
|
2404
2420
|
}
|
|
2405
2421
|
async _createProject(session, newProject) {
|
|
2406
2422
|
this._ensureInternalProject();
|
|
@@ -2425,17 +2441,17 @@ var _StackClientAppImplIncomplete = class _StackClientAppImplIncomplete {
|
|
|
2425
2441
|
}
|
|
2426
2442
|
static get [______common_js.stackAppInternalsSymbol]() {
|
|
2427
2443
|
return { fromClientJson: (json) => {
|
|
2428
|
-
const providedCheckString = JSON.stringify((0,
|
|
2444
|
+
const providedCheckString = JSON.stringify((0, _hexclave_shared_dist_utils_objects.omit)(json, []));
|
|
2429
2445
|
const existing = allClientApps.get(json.uniqueIdentifier);
|
|
2430
2446
|
if (existing) {
|
|
2431
2447
|
const [existingCheckString, clientApp] = existing;
|
|
2432
|
-
if (existingCheckString !== void 0 && existingCheckString !== providedCheckString) throw new
|
|
2448
|
+
if (existingCheckString !== void 0 && existingCheckString !== providedCheckString) throw new _hexclave_shared_dist_utils_errors.HexclaveAssertionError("The provided app JSON does not match the configuration of the existing client app with the same unique identifier", {
|
|
2433
2449
|
providedObj: json,
|
|
2434
2450
|
existingString: existingCheckString
|
|
2435
2451
|
});
|
|
2436
2452
|
return clientApp;
|
|
2437
2453
|
}
|
|
2438
|
-
const { analytics, ...restJson } = (0,
|
|
2454
|
+
const { analytics, ...restJson } = (0, _hexclave_shared_dist_utils_objects.omit)(json, ["uniqueIdentifier"]);
|
|
2439
2455
|
return new _StackClientAppImplIncomplete({
|
|
2440
2456
|
...restJson,
|
|
2441
2457
|
analytics: (0, __session_replay_js.analyticsOptionsFromJson)(analytics)
|
|
@@ -2448,7 +2464,7 @@ var _StackClientAppImplIncomplete = class _StackClientAppImplIncomplete {
|
|
|
2448
2464
|
get [______common_js.stackAppInternalsSymbol]() {
|
|
2449
2465
|
return {
|
|
2450
2466
|
toClientJson: () => {
|
|
2451
|
-
if (typeof this._redirectMethod !== "string") throw new
|
|
2467
|
+
if (typeof this._redirectMethod !== "string") throw new _hexclave_shared_dist_utils_errors.HexclaveAssertionError("Cannot serialize to JSON from an application with a non-string redirect method");
|
|
2452
2468
|
const publishableClientKey = "publishableClientKey" in this._interface.options ? this._interface.options.publishableClientKey : void 0;
|
|
2453
2469
|
return {
|
|
2454
2470
|
baseUrl: this._options.baseUrl,
|
|
@@ -2465,8 +2481,8 @@ var _StackClientAppImplIncomplete = class _StackClientAppImplIncomplete {
|
|
|
2465
2481
|
};
|
|
2466
2482
|
},
|
|
2467
2483
|
setCurrentUser: (userJsonPromise) => {
|
|
2468
|
-
(0,
|
|
2469
|
-
await this._currentUserCache.forceSetCachedValueAsync([await this._getSession()],
|
|
2484
|
+
(0, _hexclave_shared_dist_utils_promises.runAsynchronously)(async () => {
|
|
2485
|
+
await this._currentUserCache.forceSetCachedValueAsync([await this._getSession()], _hexclave_shared_dist_utils_results.Result.fromPromise(userJsonPromise));
|
|
2470
2486
|
});
|
|
2471
2487
|
},
|
|
2472
2488
|
getConstructorOptions: () => this._options,
|
|
@@ -2482,7 +2498,7 @@ var _StackClientAppImplIncomplete = class _StackClientAppImplIncomplete {
|
|
|
2482
2498
|
sendRequest: async (path, requestOptions, requestType = "client") => {
|
|
2483
2499
|
return await this._interface.sendClientRequest(path, requestOptions, await this._getSession(), requestType);
|
|
2484
2500
|
},
|
|
2485
|
-
getRedirectMethod: () => this._redirectMethod ?? (0,
|
|
2501
|
+
getRedirectMethod: () => this._redirectMethod ?? (0, _hexclave_shared_dist_utils_errors.throwErr)("Redirect method should have been initialized in the Stack client app constructor"),
|
|
2486
2502
|
redirectToUrl: async (url, options) => {
|
|
2487
2503
|
await this._redirectTo({
|
|
2488
2504
|
url,
|