@stackframe/js 2.8.54 → 2.8.58
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/dist/esm/lib/cookie.js +50 -15
- package/dist/esm/lib/cookie.js.map +1 -1
- package/dist/esm/lib/stack-app/apps/implementations/admin-app-impl.js +235 -0
- 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.js +81 -25
- package/dist/esm/lib/stack-app/apps/implementations/client-app-impl.js.map +1 -1
- package/dist/esm/lib/stack-app/apps/implementations/common.js +2 -1
- package/dist/esm/lib/stack-app/apps/implementations/common.js.map +1 -1
- package/dist/esm/lib/stack-app/apps/implementations/server-app-impl.js +31 -23
- package/dist/esm/lib/stack-app/apps/implementations/server-app-impl.js.map +1 -1
- package/dist/esm/lib/stack-app/apps/interfaces/admin-app.js.map +1 -1
- package/dist/esm/lib/stack-app/apps/interfaces/client-app.js.map +1 -1
- 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/index.js.map +1 -1
- package/dist/esm/lib/stack-app/projects/index.js +4 -0
- 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/users/index.js +13 -12
- package/dist/esm/lib/stack-app/users/index.js.map +1 -1
- package/dist/index.d.mts +249 -16
- package/dist/index.d.ts +249 -16
- package/dist/lib/cookie.js +50 -15
- package/dist/lib/cookie.js.map +1 -1
- package/dist/lib/stack-app/apps/implementations/admin-app-impl.js +235 -0
- package/dist/lib/stack-app/apps/implementations/admin-app-impl.js.map +1 -1
- package/dist/lib/stack-app/apps/implementations/client-app-impl.js +79 -23
- package/dist/lib/stack-app/apps/implementations/client-app-impl.js.map +1 -1
- package/dist/lib/stack-app/apps/implementations/common.js +2 -1
- package/dist/lib/stack-app/apps/implementations/common.js.map +1 -1
- package/dist/lib/stack-app/apps/implementations/server-app-impl.js +29 -21
- package/dist/lib/stack-app/apps/implementations/server-app-impl.js.map +1 -1
- package/dist/lib/stack-app/apps/interfaces/admin-app.js.map +1 -1
- package/dist/lib/stack-app/apps/interfaces/client-app.js.map +1 -1
- 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/email/index.js.map +1 -1
- package/dist/lib/stack-app/index.js.map +1 -1
- package/dist/lib/stack-app/project-configs/index.js.map +1 -1
- package/dist/lib/stack-app/projects/index.js +4 -0
- 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/users/index.js +15 -14
- package/dist/lib/stack-app/users/index.js.map +1 -1
- package/package.json +3 -2
- package/CHANGELOG.md +0 -2052
|
@@ -5,6 +5,7 @@ import { InternalSession } from "@stackframe/stack-shared/dist/sessions";
|
|
|
5
5
|
import { encodeBase32 } from "@stackframe/stack-shared/dist/utils/bytes";
|
|
6
6
|
import { isBrowserLike } from "@stackframe/stack-shared/dist/utils/env";
|
|
7
7
|
import { StackAssertionError, captureError, throwErr } from "@stackframe/stack-shared/dist/utils/errors";
|
|
8
|
+
import { parseJson } from "@stackframe/stack-shared/dist/utils/json";
|
|
8
9
|
import { DependenciesMap } from "@stackframe/stack-shared/dist/utils/maps";
|
|
9
10
|
import { deepPlainEquals, omit } from "@stackframe/stack-shared/dist/utils/objects";
|
|
10
11
|
import { neverResolve, runAsynchronously, wait } from "@stackframe/stack-shared/dist/utils/promises";
|
|
@@ -16,15 +17,14 @@ import { generateUuid } from "@stackframe/stack-shared/dist/utils/uuids";
|
|
|
16
17
|
import * as cookie from "cookie";
|
|
17
18
|
import { constructRedirectUrl } from "../../../../utils/url.js";
|
|
18
19
|
import { addNewOAuthProviderOrScope, callOAuthCallback, signInWithOAuth } from "../../../auth.js";
|
|
19
|
-
import { createCookieHelper, createPlaceholderCookieHelper, deleteCookieClient, isSecure as isSecureCookieContext, setOrDeleteCookie, setOrDeleteCookieClient } from "../../../cookie.js";
|
|
20
|
+
import { createCookieHelper, createPlaceholderCookieHelper, deleteCookie, deleteCookieClient, isSecure as isSecureCookieContext, setOrDeleteCookie, setOrDeleteCookieClient } from "../../../cookie.js";
|
|
20
21
|
import { apiKeyCreationOptionsToCrud } from "../../api-keys/index.js";
|
|
21
22
|
import { stackAppInternalsSymbol } from "../../common.js";
|
|
22
23
|
import { contactChannelCreateOptionsToCrud, contactChannelUpdateOptionsToCrud } from "../../contact-channels/index.js";
|
|
23
24
|
import { adminProjectCreateOptionsToCrud } from "../../projects/index.js";
|
|
24
25
|
import { teamCreateOptionsToCrud, teamUpdateOptionsToCrud } from "../../teams/index.js";
|
|
25
|
-
import {
|
|
26
|
+
import { userUpdateOptionsToCrud, withUserDestructureGuard } from "../../users/index.js";
|
|
26
27
|
import { clientVersion, createCache, createCacheBySession, createEmptyTokenStore, getBaseUrl, getDefaultExtraRequestHeaders, getDefaultProjectId, getDefaultPublishableClientKey, getUrls, resolveConstructorOptions } from "./common.js";
|
|
27
|
-
import { parseJson } from "@stackframe/stack-shared/dist/utils/json";
|
|
28
28
|
var isReactServer = false;
|
|
29
29
|
var process = globalThis.process ?? { env: {} };
|
|
30
30
|
var allClientApps = /* @__PURE__ */ new Map();
|
|
@@ -449,9 +449,10 @@ var __StackClientAppImplIncomplete = class __StackClientAppImplIncomplete {
|
|
|
449
449
|
return;
|
|
450
450
|
}
|
|
451
451
|
const domain = await this._trustedParentDomainCache.getOrWait([hostname], "read-write");
|
|
452
|
+
const cookieOptions = { maxAge: 60 * 60 * 24 * 365, noOpIfServerComponent: true };
|
|
452
453
|
const setCookie = async (targetDomain, value2) => {
|
|
453
454
|
const name = this._getCustomRefreshCookieName(targetDomain);
|
|
454
|
-
const options = {
|
|
455
|
+
const options = { ...cookieOptions, domain: targetDomain };
|
|
455
456
|
if (context === "browser") {
|
|
456
457
|
setOrDeleteCookieClient(name, value2, options);
|
|
457
458
|
} else {
|
|
@@ -464,7 +465,7 @@ var __StackClientAppImplIncomplete = class __StackClientAppImplIncomplete {
|
|
|
464
465
|
const value = refreshToken && updatedAt ? this._formatRefreshCookieValue(refreshToken, updatedAt) : null;
|
|
465
466
|
await setCookie(domain.data, value);
|
|
466
467
|
const isSecure = await isSecureCookieContext();
|
|
467
|
-
await setOrDeleteCookie(this._getRefreshTokenDefaultCookieNameForSecure(isSecure), null);
|
|
468
|
+
await setOrDeleteCookie(this._getRefreshTokenDefaultCookieNameForSecure(isSecure), null, cookieOptions);
|
|
468
469
|
});
|
|
469
470
|
}
|
|
470
471
|
async _getTrustedParentDomain(currentDomain) {
|
|
@@ -516,7 +517,7 @@ var __StackClientAppImplIncomplete = class __StackClientAppImplIncomplete {
|
|
|
516
517
|
);
|
|
517
518
|
setOrDeleteCookieClient(defaultName, refreshCookieValue, { maxAge: 60 * 60 * 24 * 365, secure });
|
|
518
519
|
setOrDeleteCookieClient(this._accessTokenCookieName, accessTokenPayload, { maxAge: 60 * 60 * 24 });
|
|
519
|
-
cookieNamesToDelete.forEach((name) => deleteCookieClient(name));
|
|
520
|
+
cookieNamesToDelete.forEach((name) => deleteCookieClient(name, {}));
|
|
520
521
|
this._queueCustomRefreshCookieUpdate(refreshToken, updatedAt, "browser");
|
|
521
522
|
hasSucceededInWriting = true;
|
|
522
523
|
} catch (e) {
|
|
@@ -560,7 +561,7 @@ var __StackClientAppImplIncomplete = class __StackClientAppImplIncomplete {
|
|
|
560
561
|
if (cookieNamesToDelete.length > 0) {
|
|
561
562
|
await Promise.all(
|
|
562
563
|
cookieNamesToDelete.map(
|
|
563
|
-
(name) =>
|
|
564
|
+
(name) => deleteCookie(name, { noOpIfServerComponent: true })
|
|
564
565
|
)
|
|
565
566
|
);
|
|
566
567
|
}
|
|
@@ -896,13 +897,21 @@ var __StackClientAppImplIncomplete = class __StackClientAppImplIncomplete {
|
|
|
896
897
|
_internalSession: session,
|
|
897
898
|
currentSession: {
|
|
898
899
|
async getTokens() {
|
|
899
|
-
const tokens = await session.getOrFetchLikelyValidTokens(2e4);
|
|
900
|
+
const tokens = await session.getOrFetchLikelyValidTokens(2e4, 75e3);
|
|
900
901
|
return {
|
|
901
902
|
accessToken: tokens?.accessToken.token ?? null,
|
|
902
903
|
refreshToken: tokens?.refreshToken?.token ?? null
|
|
903
904
|
};
|
|
904
905
|
}
|
|
905
906
|
},
|
|
907
|
+
async getAccessToken() {
|
|
908
|
+
const tokens = await this.currentSession.getTokens();
|
|
909
|
+
return tokens.accessToken;
|
|
910
|
+
},
|
|
911
|
+
async getRefreshToken() {
|
|
912
|
+
const tokens = await this.currentSession.getTokens();
|
|
913
|
+
return tokens.refreshToken;
|
|
914
|
+
},
|
|
906
915
|
async getAuthHeaders() {
|
|
907
916
|
return {
|
|
908
917
|
"x-stack-auth": JSON.stringify(await this.getAuthJson())
|
|
@@ -952,6 +961,8 @@ var __StackClientAppImplIncomplete = class __StackClientAppImplIncomplete {
|
|
|
952
961
|
passkeyAuthEnabled: crud.passkey_auth_enabled,
|
|
953
962
|
isMultiFactorRequired: crud.requires_totp_mfa,
|
|
954
963
|
isAnonymous: crud.is_anonymous,
|
|
964
|
+
isRestricted: crud.is_restricted,
|
|
965
|
+
restrictedReason: crud.restricted_reason,
|
|
955
966
|
toClientJson() {
|
|
956
967
|
return crud;
|
|
957
968
|
}
|
|
@@ -978,7 +989,7 @@ var __StackClientAppImplIncomplete = class __StackClientAppImplIncomplete {
|
|
|
978
989
|
return this.update({ clientMetadata: metadata });
|
|
979
990
|
},
|
|
980
991
|
async setSelectedTeam(team) {
|
|
981
|
-
await this.update({ selectedTeamId: team?.id ?? null });
|
|
992
|
+
await this.update({ selectedTeamId: typeof team === "string" ? team : team?.id ?? null });
|
|
982
993
|
},
|
|
983
994
|
getConnectedAccount,
|
|
984
995
|
async getTeam(teamId) {
|
|
@@ -1183,16 +1194,33 @@ var __StackClientAppImplIncomplete = class __StackClientAppImplIncomplete {
|
|
|
1183
1194
|
const response = Result.orThrow(await this._customProductsCache.getOrWait([session, options.customCustomerId, options.cursor ?? null, options.limit ?? null], "write-only"));
|
|
1184
1195
|
return this._customerProductsFromResponse(response);
|
|
1185
1196
|
}
|
|
1197
|
+
async cancelSubscription(options) {
|
|
1198
|
+
const session = await this._getSession();
|
|
1199
|
+
const user = await this.getUser();
|
|
1200
|
+
if (!user) {
|
|
1201
|
+
throw new KnownErrors.UserAuthenticationRequired();
|
|
1202
|
+
}
|
|
1203
|
+
const customerType = "teamId" in options ? "team" : "user";
|
|
1204
|
+
const customerId = "teamId" in options ? options.teamId : user.id;
|
|
1205
|
+
await this._interface.cancelSubscription({
|
|
1206
|
+
customer_type: customerType,
|
|
1207
|
+
customer_id: customerId,
|
|
1208
|
+
product_id: options.productId
|
|
1209
|
+
}, session);
|
|
1210
|
+
if (customerType === "user") {
|
|
1211
|
+
await this._userProductsCache.invalidateWhere(([cachedSession, userId]) => cachedSession === session && userId === customerId);
|
|
1212
|
+
} else {
|
|
1213
|
+
await this._teamProductsCache.invalidateWhere(([cachedSession, teamId]) => cachedSession === session && teamId === customerId);
|
|
1214
|
+
}
|
|
1215
|
+
}
|
|
1186
1216
|
_currentUserFromCrud(crud, session) {
|
|
1187
|
-
const currentUser = {
|
|
1217
|
+
const currentUser = withUserDestructureGuard({
|
|
1188
1218
|
...this._createBaseUser(crud),
|
|
1189
1219
|
...this._createAuth(session),
|
|
1190
1220
|
...this._createUserExtraFromCurrent(crud, session),
|
|
1191
1221
|
...this._isInternalProject() ? this._createInternalUserExtra(session) : {},
|
|
1192
1222
|
...this._createCustomer(crud.id, "user", session)
|
|
1193
|
-
};
|
|
1194
|
-
attachUserDestructureGuard(currentUser);
|
|
1195
|
-
Object.freeze(currentUser);
|
|
1223
|
+
});
|
|
1196
1224
|
return currentUser;
|
|
1197
1225
|
}
|
|
1198
1226
|
_clientSessionFromCrud(crud) {
|
|
@@ -1265,7 +1293,7 @@ var __StackClientAppImplIncomplete = class __StackClientAppImplIncomplete {
|
|
|
1265
1293
|
const queryParams = new URLSearchParams(window.location.search);
|
|
1266
1294
|
url = queryParams.get("after_auth_return_to") || url;
|
|
1267
1295
|
}
|
|
1268
|
-
} else if (handlerName === "signIn" || handlerName === "signUp") {
|
|
1296
|
+
} else if (handlerName === "signIn" || handlerName === "signUp" || handlerName === "onboarding") {
|
|
1269
1297
|
if (isReactServer || typeof window === "undefined") {
|
|
1270
1298
|
} else {
|
|
1271
1299
|
const currentUrl = new URL(window.location.href);
|
|
@@ -1314,6 +1342,9 @@ var __StackClientAppImplIncomplete = class __StackClientAppImplIncomplete {
|
|
|
1314
1342
|
async redirectToAfterSignUp(options) {
|
|
1315
1343
|
return await this._redirectToHandler("afterSignUp", options);
|
|
1316
1344
|
}
|
|
1345
|
+
async redirectToOnboarding(options) {
|
|
1346
|
+
return await this._redirectToHandler("onboarding", options);
|
|
1347
|
+
}
|
|
1317
1348
|
async redirectToAfterSignOut(options) {
|
|
1318
1349
|
return await this._redirectToHandler("afterSignOut", options);
|
|
1319
1350
|
}
|
|
@@ -1379,16 +1410,22 @@ var __StackClientAppImplIncomplete = class __StackClientAppImplIncomplete {
|
|
|
1379
1410
|
return result;
|
|
1380
1411
|
}
|
|
1381
1412
|
async getUser(options) {
|
|
1413
|
+
if (options?.or === "anonymous" && options.includeRestricted === false) {
|
|
1414
|
+
throw new Error("Cannot use { or: 'anonymous' } with { includeRestricted: false }. Anonymous users implicitly include restricted users.");
|
|
1415
|
+
}
|
|
1382
1416
|
this._ensurePersistentTokenStore(options?.tokenStore);
|
|
1383
1417
|
const session = await this._getSession(options?.tokenStore);
|
|
1384
1418
|
let crud = Result.orThrow(await this._currentUserCache.getOrWait([session], "write-only"));
|
|
1385
|
-
|
|
1386
|
-
|
|
1387
|
-
|
|
1388
|
-
if (crud === null) {
|
|
1419
|
+
const includeAnonymous = options?.or === "anonymous" || options?.or === "anonymous-if-exists[deprecated]";
|
|
1420
|
+
const includeRestricted = options?.includeRestricted === true || includeAnonymous;
|
|
1421
|
+
if (crud === null || crud.is_anonymous && !includeAnonymous || crud.is_restricted && !includeRestricted) {
|
|
1389
1422
|
switch (options?.or) {
|
|
1390
1423
|
case "redirect": {
|
|
1391
|
-
|
|
1424
|
+
if (!crud?.is_anonymous && crud?.is_restricted) {
|
|
1425
|
+
await this.redirectToOnboarding({ replace: true });
|
|
1426
|
+
} else {
|
|
1427
|
+
await this.redirectToSignIn({ replace: true });
|
|
1428
|
+
}
|
|
1392
1429
|
break;
|
|
1393
1430
|
}
|
|
1394
1431
|
case "throw": {
|
|
@@ -1396,7 +1433,7 @@ var __StackClientAppImplIncomplete = class __StackClientAppImplIncomplete {
|
|
|
1396
1433
|
}
|
|
1397
1434
|
case "anonymous": {
|
|
1398
1435
|
const tokens = await this._signUpAnonymously();
|
|
1399
|
-
return await this.getUser({ tokenStore: tokens, or: "anonymous-if-exists[deprecated]" }) ?? throwErr("Something went wrong while signing up anonymously");
|
|
1436
|
+
return await this.getUser({ tokenStore: tokens, or: "anonymous-if-exists[deprecated]", includeRestricted: true }) ?? throwErr("Something went wrong while signing up anonymously");
|
|
1400
1437
|
}
|
|
1401
1438
|
case void 0:
|
|
1402
1439
|
case "anonymous-if-exists[deprecated]":
|
|
@@ -1408,7 +1445,7 @@ var __StackClientAppImplIncomplete = class __StackClientAppImplIncomplete {
|
|
|
1408
1445
|
return crud && this._currentUserFromCrud(crud, session);
|
|
1409
1446
|
}
|
|
1410
1447
|
_getTokenPartialUserFromSession(session, options) {
|
|
1411
|
-
const accessToken = session.getAccessTokenIfNotExpiredYet(0);
|
|
1448
|
+
const accessToken = session.getAccessTokenIfNotExpiredYet(0, null);
|
|
1412
1449
|
if (!accessToken) {
|
|
1413
1450
|
return null;
|
|
1414
1451
|
}
|
|
@@ -1421,7 +1458,9 @@ var __StackClientAppImplIncomplete = class __StackClientAppImplIncomplete {
|
|
|
1421
1458
|
primaryEmail: accessToken.payload.email,
|
|
1422
1459
|
displayName: accessToken.payload.name,
|
|
1423
1460
|
primaryEmailVerified: accessToken.payload.email_verified,
|
|
1424
|
-
isAnonymous
|
|
1461
|
+
isAnonymous,
|
|
1462
|
+
isRestricted: accessToken.payload.is_restricted,
|
|
1463
|
+
restrictedReason: accessToken.payload.restricted_reason
|
|
1425
1464
|
};
|
|
1426
1465
|
}
|
|
1427
1466
|
async _getPartialUserFromConvex(ctx) {
|
|
@@ -1434,7 +1473,9 @@ var __StackClientAppImplIncomplete = class __StackClientAppImplIncomplete {
|
|
|
1434
1473
|
displayName: auth.name ?? null,
|
|
1435
1474
|
primaryEmail: auth.email ?? null,
|
|
1436
1475
|
primaryEmailVerified: auth.email_verified,
|
|
1437
|
-
isAnonymous: auth.is_anonymous
|
|
1476
|
+
isAnonymous: auth.is_anonymous,
|
|
1477
|
+
isRestricted: auth.is_restricted,
|
|
1478
|
+
restrictedReason: auth.restricted_reason ?? null
|
|
1438
1479
|
};
|
|
1439
1480
|
}
|
|
1440
1481
|
async getPartialUser(options) {
|
|
@@ -1456,7 +1497,7 @@ var __StackClientAppImplIncomplete = class __StackClientAppImplIncomplete {
|
|
|
1456
1497
|
return async (args) => {
|
|
1457
1498
|
const session = await this._getSession(options.tokenStore ?? this._tokenStoreInit);
|
|
1458
1499
|
if (!args.forceRefreshToken) {
|
|
1459
|
-
const tokens2 = await session.getOrFetchLikelyValidTokens(2e4);
|
|
1500
|
+
const tokens2 = await session.getOrFetchLikelyValidTokens(2e4, 75e3);
|
|
1460
1501
|
return tokens2?.accessToken.token ?? null;
|
|
1461
1502
|
}
|
|
1462
1503
|
const tokens = await session.fetchNewTokens();
|
|
@@ -1465,7 +1506,7 @@ var __StackClientAppImplIncomplete = class __StackClientAppImplIncomplete {
|
|
|
1465
1506
|
}
|
|
1466
1507
|
async getConvexHttpClientAuth(options) {
|
|
1467
1508
|
const session = await this._getSession(options.tokenStore);
|
|
1468
|
-
const tokens = await session.getOrFetchLikelyValidTokens(2e4);
|
|
1509
|
+
const tokens = await session.getOrFetchLikelyValidTokens(2e4, 75e3);
|
|
1469
1510
|
return tokens?.accessToken.token ?? "";
|
|
1470
1511
|
}
|
|
1471
1512
|
async _updateClientUser(update, session) {
|
|
@@ -1812,6 +1853,20 @@ ${url}`);
|
|
|
1812
1853
|
await user.signOut({ redirectUrl: options?.redirectUrl });
|
|
1813
1854
|
}
|
|
1814
1855
|
}
|
|
1856
|
+
async getAccessToken(options) {
|
|
1857
|
+
const user = await this.getUser({ tokenStore: options?.tokenStore ?? void 0 });
|
|
1858
|
+
if (user) {
|
|
1859
|
+
return await user.getAccessToken();
|
|
1860
|
+
}
|
|
1861
|
+
return null;
|
|
1862
|
+
}
|
|
1863
|
+
async getRefreshToken(options) {
|
|
1864
|
+
const user = await this.getUser({ tokenStore: options?.tokenStore ?? void 0 });
|
|
1865
|
+
if (user) {
|
|
1866
|
+
return await user.getRefreshToken();
|
|
1867
|
+
}
|
|
1868
|
+
return null;
|
|
1869
|
+
}
|
|
1815
1870
|
async getAuthHeaders(options) {
|
|
1816
1871
|
return {
|
|
1817
1872
|
"x-stack-auth": JSON.stringify(await this.getAuthJson(options))
|
|
@@ -1848,6 +1903,7 @@ ${url}`);
|
|
|
1848
1903
|
}
|
|
1849
1904
|
async _refreshUser(session) {
|
|
1850
1905
|
await this._refreshSession(session);
|
|
1906
|
+
session.suggestAccessTokenExpired();
|
|
1851
1907
|
}
|
|
1852
1908
|
async _refreshSession(session) {
|
|
1853
1909
|
await this._currentUserCache.refresh([session]);
|