@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.
Files changed (46) hide show
  1. package/dist/esm/lib/cookie.js +50 -15
  2. package/dist/esm/lib/cookie.js.map +1 -1
  3. package/dist/esm/lib/stack-app/apps/implementations/admin-app-impl.js +235 -0
  4. package/dist/esm/lib/stack-app/apps/implementations/admin-app-impl.js.map +1 -1
  5. package/dist/esm/lib/stack-app/apps/implementations/client-app-impl.js +81 -25
  6. package/dist/esm/lib/stack-app/apps/implementations/client-app-impl.js.map +1 -1
  7. package/dist/esm/lib/stack-app/apps/implementations/common.js +2 -1
  8. package/dist/esm/lib/stack-app/apps/implementations/common.js.map +1 -1
  9. package/dist/esm/lib/stack-app/apps/implementations/server-app-impl.js +31 -23
  10. package/dist/esm/lib/stack-app/apps/implementations/server-app-impl.js.map +1 -1
  11. package/dist/esm/lib/stack-app/apps/interfaces/admin-app.js.map +1 -1
  12. package/dist/esm/lib/stack-app/apps/interfaces/client-app.js.map +1 -1
  13. package/dist/esm/lib/stack-app/apps/interfaces/server-app.js.map +1 -1
  14. package/dist/esm/lib/stack-app/common.js.map +1 -1
  15. package/dist/esm/lib/stack-app/index.js.map +1 -1
  16. package/dist/esm/lib/stack-app/projects/index.js +4 -0
  17. package/dist/esm/lib/stack-app/projects/index.js.map +1 -1
  18. package/dist/esm/lib/stack-app/teams/index.js.map +1 -1
  19. package/dist/esm/lib/stack-app/users/index.js +13 -12
  20. package/dist/esm/lib/stack-app/users/index.js.map +1 -1
  21. package/dist/index.d.mts +249 -16
  22. package/dist/index.d.ts +249 -16
  23. package/dist/lib/cookie.js +50 -15
  24. package/dist/lib/cookie.js.map +1 -1
  25. package/dist/lib/stack-app/apps/implementations/admin-app-impl.js +235 -0
  26. package/dist/lib/stack-app/apps/implementations/admin-app-impl.js.map +1 -1
  27. package/dist/lib/stack-app/apps/implementations/client-app-impl.js +79 -23
  28. package/dist/lib/stack-app/apps/implementations/client-app-impl.js.map +1 -1
  29. package/dist/lib/stack-app/apps/implementations/common.js +2 -1
  30. package/dist/lib/stack-app/apps/implementations/common.js.map +1 -1
  31. package/dist/lib/stack-app/apps/implementations/server-app-impl.js +29 -21
  32. package/dist/lib/stack-app/apps/implementations/server-app-impl.js.map +1 -1
  33. package/dist/lib/stack-app/apps/interfaces/admin-app.js.map +1 -1
  34. package/dist/lib/stack-app/apps/interfaces/client-app.js.map +1 -1
  35. package/dist/lib/stack-app/apps/interfaces/server-app.js.map +1 -1
  36. package/dist/lib/stack-app/common.js.map +1 -1
  37. package/dist/lib/stack-app/email/index.js.map +1 -1
  38. package/dist/lib/stack-app/index.js.map +1 -1
  39. package/dist/lib/stack-app/project-configs/index.js.map +1 -1
  40. package/dist/lib/stack-app/projects/index.js +4 -0
  41. package/dist/lib/stack-app/projects/index.js.map +1 -1
  42. package/dist/lib/stack-app/teams/index.js.map +1 -1
  43. package/dist/lib/stack-app/users/index.js +15 -14
  44. package/dist/lib/stack-app/users/index.js.map +1 -1
  45. package/package.json +3 -2
  46. 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 { attachUserDestructureGuard, userUpdateOptionsToCrud } from "../../users/index.js";
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 = { maxAge: 60 * 60 * 24 * 365, domain: targetDomain, noOpIfServerComponent: true };
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) => setOrDeleteCookie(name, null, { noOpIfServerComponent: true })
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
- if (crud?.is_anonymous && options?.or !== "anonymous" && options?.or !== "anonymous-if-exists[deprecated]") {
1386
- crud = null;
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
- await this.redirectToSignIn({ replace: true });
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]);