@stackframe/stack 2.4.21 → 2.4.22

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 (97) hide show
  1. package/CHANGELOG.md +9 -0
  2. package/dist/components/message-cards/known-error-message-card.d.mts +9 -0
  3. package/dist/components/message-cards/known-error-message-card.d.ts +9 -0
  4. package/dist/components/message-cards/known-error-message-card.js +67 -0
  5. package/dist/components/message-cards/known-error-message-card.js.map +1 -0
  6. package/dist/components/{message-card.d.mts → message-cards/message-card.d.mts} +5 -1
  7. package/dist/components/{message-card.d.ts → message-cards/message-card.d.ts} +5 -1
  8. package/dist/components/{message-card.js → message-cards/message-card.js} +10 -6
  9. package/dist/components/message-cards/message-card.js.map +1 -0
  10. package/dist/components/{redirect-message-card.d.mts → message-cards/predefined-message-card.d.mts} +3 -3
  11. package/dist/components/{redirect-message-card.d.ts → message-cards/predefined-message-card.d.ts} +3 -3
  12. package/dist/components/{redirect-message-card.js → message-cards/predefined-message-card.js} +32 -29
  13. package/dist/components/message-cards/predefined-message-card.js.map +1 -0
  14. package/dist/components/password-reset-inner.js +3 -3
  15. package/dist/components/password-reset-inner.js.map +1 -1
  16. package/dist/components-core/index.d.mts +4 -4
  17. package/dist/components-core/index.d.ts +4 -4
  18. package/dist/components-core-joy/text.d.mts +2 -2
  19. package/dist/components-core-joy/text.d.ts +2 -2
  20. package/dist/components-page/account-settings.js +2 -2
  21. package/dist/components-page/account-settings.js.map +1 -1
  22. package/dist/components-page/auth-page.js +2 -2
  23. package/dist/components-page/auth-page.js.map +1 -1
  24. package/dist/components-page/email-verification.js +3 -3
  25. package/dist/components-page/email-verification.js.map +1 -1
  26. package/dist/components-page/error-page.d.mts +8 -0
  27. package/dist/components-page/error-page.d.ts +8 -0
  28. package/dist/components-page/error-page.js +85 -0
  29. package/dist/components-page/error-page.js.map +1 -0
  30. package/dist/components-page/forgot-password.js +3 -3
  31. package/dist/components-page/forgot-password.js.map +1 -1
  32. package/dist/components-page/magic-link-callback.js +3 -3
  33. package/dist/components-page/magic-link-callback.js.map +1 -1
  34. package/dist/components-page/oauth-callback.js +4 -3
  35. package/dist/components-page/oauth-callback.js.map +1 -1
  36. package/dist/components-page/password-reset.js +1 -1
  37. package/dist/components-page/password-reset.js.map +1 -1
  38. package/dist/components-page/sign-out.js +2 -2
  39. package/dist/components-page/sign-out.js.map +1 -1
  40. package/dist/components-page/stack-handler.js +5 -1
  41. package/dist/components-page/stack-handler.js.map +1 -1
  42. package/dist/esm/components/message-cards/known-error-message-card.js +37 -0
  43. package/dist/esm/components/message-cards/known-error-message-card.js.map +1 -0
  44. package/dist/esm/components/message-cards/message-card.js +21 -0
  45. package/dist/esm/components/message-cards/message-card.js.map +1 -0
  46. package/dist/esm/components/{redirect-message-card.js → message-cards/predefined-message-card.js} +30 -27
  47. package/dist/esm/components/message-cards/predefined-message-card.js.map +1 -0
  48. package/dist/esm/components/password-reset-inner.js +3 -3
  49. package/dist/esm/components/password-reset-inner.js.map +1 -1
  50. package/dist/esm/components-page/account-settings.js +2 -2
  51. package/dist/esm/components-page/account-settings.js.map +1 -1
  52. package/dist/esm/components-page/auth-page.js +2 -2
  53. package/dist/esm/components-page/auth-page.js.map +1 -1
  54. package/dist/esm/components-page/email-verification.js +3 -3
  55. package/dist/esm/components-page/email-verification.js.map +1 -1
  56. package/dist/esm/components-page/error-page.js +55 -0
  57. package/dist/esm/components-page/error-page.js.map +1 -0
  58. package/dist/esm/components-page/forgot-password.js +3 -3
  59. package/dist/esm/components-page/forgot-password.js.map +1 -1
  60. package/dist/esm/components-page/magic-link-callback.js +3 -3
  61. package/dist/esm/components-page/magic-link-callback.js.map +1 -1
  62. package/dist/esm/components-page/oauth-callback.js +4 -3
  63. package/dist/esm/components-page/oauth-callback.js.map +1 -1
  64. package/dist/esm/components-page/password-reset.js +1 -1
  65. package/dist/esm/components-page/password-reset.js.map +1 -1
  66. package/dist/esm/components-page/sign-out.js +1 -1
  67. package/dist/esm/components-page/sign-out.js.map +1 -1
  68. package/dist/esm/components-page/stack-handler.js +5 -1
  69. package/dist/esm/components-page/stack-handler.js.map +1 -1
  70. package/dist/esm/index.js +1 -1
  71. package/dist/esm/index.js.map +1 -1
  72. package/dist/esm/lib/auth.js +30 -14
  73. package/dist/esm/lib/auth.js.map +1 -1
  74. package/dist/esm/lib/stack-app.js +141 -67
  75. package/dist/esm/lib/stack-app.js.map +1 -1
  76. package/dist/index.d.mts +1 -1
  77. package/dist/index.d.ts +1 -1
  78. package/dist/index.js +1 -1
  79. package/dist/index.js.map +1 -1
  80. package/dist/lib/auth.d.mts +13 -3
  81. package/dist/lib/auth.d.ts +13 -3
  82. package/dist/lib/auth.js +31 -14
  83. package/dist/lib/auth.js.map +1 -1
  84. package/dist/lib/stack-app.d.mts +111 -65
  85. package/dist/lib/stack-app.d.ts +111 -65
  86. package/dist/lib/stack-app.js +138 -64
  87. package/dist/lib/stack-app.js.map +1 -1
  88. package/dist/providers/component-provider.d.mts +6 -6
  89. package/dist/providers/component-provider.d.ts +6 -6
  90. package/dist/providers/joy-provider.d.mts +2 -2
  91. package/dist/providers/joy-provider.d.ts +2 -2
  92. package/package.json +3 -3
  93. package/dist/components/message-card.js.map +0 -1
  94. package/dist/components/redirect-message-card.js.map +0 -1
  95. package/dist/esm/components/message-card.js +0 -17
  96. package/dist/esm/components/message-card.js.map +0 -1
  97. package/dist/esm/components/redirect-message-card.js.map +0 -1
@@ -58,8 +58,9 @@ var import_stack_sc = require("@stackframe/stack-sc");
58
58
  var cookie = __toESM(require("cookie"));
59
59
  var import_sessions = require("@stackframe/stack-shared/dist/sessions");
60
60
  var import_use_trigger = require("@stackframe/stack-shared/dist/hooks/use-trigger");
61
+ var import_strings = require("@stackframe/stack-shared/src/utils/strings");
61
62
  var NextNavigation = (0, import_compile_time.scrambleDuringCompileTime)(NextNavigationUnscrambled);
62
- var clientVersion = "js @stackframe/stack@2.4.21";
63
+ var clientVersion = "js @stackframe/stack@2.4.22";
63
64
  function permissionDefinitionScopeToType(scope) {
64
65
  return { "any-team": "team", "specific-team": "team", "global": "global" }[scope.type];
65
66
  }
@@ -80,9 +81,22 @@ function getUrls(partial) {
80
81
  magicLinkCallback: `${handler}/magic-link-callback`,
81
82
  home: "/",
82
83
  accountSettings: `${handler}/account-settings`,
84
+ error: `${handler}/error`,
83
85
  ...(0, import_objects.filterUndefined)(partial)
84
86
  };
85
87
  }
88
+ async function _redirectTo(url, options) {
89
+ if (import_stack_sc.isReactServer) {
90
+ NextNavigation.redirect(url, options?.replace ? NextNavigation.RedirectType.replace : NextNavigation.RedirectType.push);
91
+ } else {
92
+ if (options?.replace) {
93
+ window.location.replace(url);
94
+ } else {
95
+ window.location.assign(url);
96
+ }
97
+ await (0, import_promises.wait)(2e3);
98
+ }
99
+ }
86
100
  function getDefaultProjectId() {
87
101
  return process.env.NEXT_PUBLIC_STACK_PROJECT_ID || (0, import_errors.throwErr)(new Error("Welcome to Stack! It seems that you haven't provided a project ID. Please create a project on the Stack dashboard at https://app.stack-auth.com and put it in the NEXT_PUBLIC_STACK_PROJECT_ID environment variable."));
88
102
  }
@@ -157,6 +171,7 @@ var _StackClientAppImpl = class __StackClientAppImpl {
157
171
  }
158
172
  this._tokenStoreInit = _options.tokenStore;
159
173
  this._urlOptions = _options.urls ?? {};
174
+ this._oauthScopesOnSignIn = _options.oauthScopesOnSignIn ?? {};
160
175
  if (_options.uniqueIdentifier) {
161
176
  this._uniqueIdentifier = _options.uniqueIdentifier;
162
177
  this._initUniqueIdentifier();
@@ -170,6 +185,7 @@ var _StackClientAppImpl = class __StackClientAppImpl {
170
185
  _interface;
171
186
  _tokenStoreInit;
172
187
  _urlOptions;
188
+ _oauthScopesOnSignIn;
173
189
  __DEMO_ENABLE_SLIGHT_FETCH_DELAY = false;
174
190
  _currentUserCache = createCacheBySession(async (session) => {
175
191
  if (this.__DEMO_ENABLE_SLIGHT_FETCH_DELAY) {
@@ -190,6 +206,64 @@ var _StackClientAppImpl = class __StackClientAppImpl {
190
206
  _currentUserTeamsCache = createCacheBySession(async (session) => {
191
207
  return await this._interface.listClientUserTeams(session);
192
208
  });
209
+ _currentUserOAuthConnectionAccessTokensCache = createCacheBySession(
210
+ async (session, [accountId, scope]) => {
211
+ try {
212
+ return await this._interface.getAccessToken(accountId, scope || "", session);
213
+ } catch (err) {
214
+ if (!(err instanceof import_stack_shared.KnownErrors.OAuthConnectionDoesNotHaveRequiredScope || err instanceof import_stack_shared.KnownErrors.OAuthConnectionNotConnectedToUser)) {
215
+ throw err;
216
+ }
217
+ }
218
+ return null;
219
+ }
220
+ );
221
+ _currentUserOAuthConnectionCache = createCacheBySession(
222
+ async (session, [connectionId, scope, redirect]) => {
223
+ const user = await this._currentUserCache.getOrWait([session], "write-only");
224
+ let hasConnection = true;
225
+ if (!user || !user.oauthProviders.find((p) => p === connectionId)) {
226
+ hasConnection = false;
227
+ }
228
+ const token = await this._currentUserOAuthConnectionAccessTokensCache.getOrWait([session, connectionId, scope || ""], "write-only");
229
+ if (!token) {
230
+ hasConnection = false;
231
+ }
232
+ if (!hasConnection && redirect) {
233
+ await (0, import_auth.addNewOAuthProviderOrScope)(
234
+ this._interface,
235
+ {
236
+ provider: connectionId,
237
+ redirectUrl: this.urls.oauthCallback,
238
+ errorRedirectUrl: this.urls.error,
239
+ providerScope: (0, import_strings.mergeScopeStrings)(scope || "", (this._oauthScopesOnSignIn[connectionId] ?? []).join(" "))
240
+ },
241
+ this._getSession()
242
+ );
243
+ return await (0, import_promises.neverResolve)();
244
+ } else if (!hasConnection) {
245
+ return null;
246
+ }
247
+ const app = this;
248
+ return {
249
+ id: connectionId,
250
+ async getAccessToken() {
251
+ const result = await app._currentUserOAuthConnectionAccessTokensCache.getOrWait([session, connectionId, scope || ""], "write-only");
252
+ if (!result) {
253
+ throw new import_errors.StackAssertionError("No access token available");
254
+ }
255
+ return result;
256
+ },
257
+ useAccessToken() {
258
+ const result = useAsyncCache(app._currentUserOAuthConnectionAccessTokensCache, [session, connectionId, scope || ""], "oauthAccount.useAccessToken()");
259
+ if (!result) {
260
+ throw new import_errors.StackAssertionError("No access token available");
261
+ }
262
+ return result;
263
+ }
264
+ };
265
+ }
266
+ );
193
267
  _initUniqueIdentifier() {
194
268
  if (!this._uniqueIdentifier) {
195
269
  throw new import_errors.StackAssertionError("Unique identifier not initialized");
@@ -426,6 +500,14 @@ var _StackClientAppImpl = class __StackClientAppImpl {
426
500
  }
427
501
  _userFromJson(json) {
428
502
  const app = this;
503
+ async function getConnection(id, options) {
504
+ const scopeString = options?.scopes?.join(" ");
505
+ return await app._currentUserOAuthConnectionCache.getOrWait([app._getSession(), id, scopeString || "", options?.or === "redirect"], "write-only");
506
+ }
507
+ function useConnection(id, options) {
508
+ const scopeString = options?.scopes?.join(" ");
509
+ return useAsyncCache(app._currentUserOAuthConnectionCache, [app._useSession(), id, scopeString || "", options?.or === "redirect"], "user.useConnection()");
510
+ }
429
511
  return {
430
512
  projectId: json.projectId,
431
513
  id: json.id,
@@ -439,6 +521,8 @@ var _StackClientAppImpl = class __StackClientAppImpl {
439
521
  hasPassword: json.hasPassword,
440
522
  authWithEmail: json.authWithEmail,
441
523
  oauthProviders: json.oauthProviders,
524
+ getConnection,
525
+ useConnection,
442
526
  async getSelectedTeam() {
443
527
  return await this.getTeam(json.selectedTeamId || "");
444
528
  },
@@ -508,12 +592,9 @@ var _StackClientAppImpl = class __StackClientAppImpl {
508
592
  displayName: json.displayName
509
593
  };
510
594
  }
511
- _currentUserFromJson(json, session) {
512
- if (json === null)
513
- return null;
595
+ _authFromJson(session) {
514
596
  const app = this;
515
- const currentUser = {
516
- ...this._userFromJson(json),
597
+ return {
517
598
  _internalSession: session,
518
599
  currentSession: {
519
600
  async getTokens() {
@@ -524,15 +605,25 @@ var _StackClientAppImpl = class __StackClientAppImpl {
524
605
  };
525
606
  }
526
607
  },
608
+ async getAuthHeaders() {
609
+ return {
610
+ "x-stack-auth": JSON.stringify(await this.getAuthJson())
611
+ };
612
+ },
613
+ async getAuthJson() {
614
+ const tokens = await this.currentSession.getTokens();
615
+ return tokens;
616
+ },
617
+ signOut() {
618
+ return app._signOut(session);
619
+ },
620
+ // TODO these should not actually be on Auth, instead on User
527
621
  async updateSelectedTeam(team) {
528
622
  await app._updateUser({ selectedTeamId: team?.id ?? null }, session);
529
623
  },
530
624
  update(update) {
531
625
  return app._updateUser(update, session);
532
626
  },
533
- signOut() {
534
- return app._signOut(session);
535
- },
536
627
  sendVerificationEmail() {
537
628
  return app._sendVerificationEmail(session);
538
629
  },
@@ -540,6 +631,15 @@ var _StackClientAppImpl = class __StackClientAppImpl {
540
631
  return app._updatePassword(options, session);
541
632
  }
542
633
  };
634
+ }
635
+ _currentUserFromJson(json, session) {
636
+ if (json === null)
637
+ return null;
638
+ const app = this;
639
+ const currentUser = {
640
+ ...this._userFromJson(json),
641
+ ...this._authFromJson(session)
642
+ };
543
643
  if (this._isInternalProject()) {
544
644
  const internalUser = {
545
645
  ...currentUser,
@@ -610,33 +710,12 @@ var _StackClientAppImpl = class __StackClientAppImpl {
610
710
  get urls() {
611
711
  return getUrls(this._urlOptions);
612
712
  }
613
- async getCrossOriginHeaders() {
614
- return {
615
- "x-stack-auth": JSON.stringify(await this.getCrossOriginTokenObject())
616
- };
617
- }
618
- async getCrossOriginTokenObject() {
619
- const user = await this.getUser();
620
- if (!user)
621
- return { accessToken: null, refreshToken: null };
622
- const tokens = await user.currentSession.getTokens();
623
- return tokens;
624
- }
625
713
  async _redirectTo(handlerName, options) {
626
714
  const url = this.urls[handlerName];
627
715
  if (!url) {
628
716
  throw new Error(`No URL for handler name ${handlerName}`);
629
717
  }
630
- if (import_stack_sc.isReactServer) {
631
- NextNavigation.redirect(url, options?.replace ? NextNavigation.RedirectType.replace : NextNavigation.RedirectType.push);
632
- } else {
633
- if (options?.replace) {
634
- window.location.replace(url);
635
- } else {
636
- window.location.assign(url);
637
- }
638
- await (0, import_promises.wait)(2e3);
639
- }
718
+ await _redirectTo(url, options);
640
719
  }
641
720
  async redirectToSignIn() {
642
721
  return await this._redirectTo("signIn");
@@ -677,6 +756,9 @@ var _StackClientAppImpl = class __StackClientAppImpl {
677
756
  async redirectToAccountSettings() {
678
757
  return await this._redirectTo("accountSettings");
679
758
  }
759
+ async redirectToError() {
760
+ return await this._redirectTo("error");
761
+ }
680
762
  async sendForgotPasswordEmail(email) {
681
763
  const redirectUrl = (0, import_url.constructRedirectUrl)(this.urls.passwordReset);
682
764
  const error = await this._interface.sendForgotPasswordEmail(email, redirectUrl);
@@ -756,7 +838,15 @@ var _StackClientAppImpl = class __StackClientAppImpl {
756
838
  }
757
839
  async signInWithOAuth(provider) {
758
840
  this._ensurePersistentTokenStore();
759
- await (0, import_auth.signInWithOAuth)(this._interface, { provider, redirectUrl: this.urls.oauthCallback });
841
+ await (0, import_auth.signInWithOAuth)(
842
+ this._interface,
843
+ {
844
+ provider,
845
+ redirectUrl: this.urls.oauthCallback,
846
+ errorRedirectUrl: this.urls.error,
847
+ providerScope: this._oauthScopesOnSignIn[provider]?.join(" ")
848
+ }
849
+ );
760
850
  }
761
851
  async signInWithCredential(options) {
762
852
  this._ensurePersistentTokenStore();
@@ -803,7 +893,10 @@ var _StackClientAppImpl = class __StackClientAppImpl {
803
893
  const result = await (0, import_auth.callOAuthCallback)(this._interface, this.urls.oauthCallback);
804
894
  if (result) {
805
895
  await this._signInToAccountWithTokens(result);
806
- if (result.newUser) {
896
+ if (result.afterCallbackRedirectUrl) {
897
+ await _redirectTo(result.afterCallbackRedirectUrl, { replace: true });
898
+ return true;
899
+ } else if (result.newUser) {
807
900
  await this.redirectToAfterSignUp({ replace: true });
808
901
  return true;
809
902
  } else {
@@ -883,6 +976,9 @@ var _StackClientAppImpl = class __StackClientAppImpl {
883
976
  return res;
884
977
  }
885
978
  async _refreshUser(session) {
979
+ await this._refreshSession(session);
980
+ }
981
+ async _refreshSession(session) {
886
982
  await this._currentUserCache.refresh([session]);
887
983
  }
888
984
  async _refreshUsers() {
@@ -926,6 +1022,7 @@ var _StackClientAppImpl = class __StackClientAppImpl {
926
1022
  publishableClientKey: this._interface.options.publishableClientKey,
927
1023
  tokenStore: this._tokenStoreInit,
928
1024
  urls: this._urlOptions,
1025
+ oauthScopesOnSignIn: this._oauthScopesOnSignIn,
929
1026
  uniqueIdentifier: this._getUniqueIdentifier()
930
1027
  };
931
1028
  },
@@ -967,7 +1064,8 @@ var _StackServerAppImpl = class extends _StackClientAppImpl {
967
1064
  super("interface" in options ? {
968
1065
  interface: options.interface,
969
1066
  tokenStore: options.tokenStore,
970
- urls: options.urls
1067
+ urls: options.urls,
1068
+ oauthScopesOnSignIn: options.oauthScopesOnSignIn
971
1069
  } : {
972
1070
  interface: new import_stack_shared.StackServerInterface({
973
1071
  baseUrl: options.baseUrl ?? getDefaultBaseUrl(),
@@ -977,7 +1075,8 @@ var _StackServerAppImpl = class extends _StackClientAppImpl {
977
1075
  secretServerKey: options.secretServerKey ?? getDefaultSecretServerKey()
978
1076
  }),
979
1077
  tokenStore: options.tokenStore,
980
- urls: options.urls ?? {}
1078
+ urls: options.urls ?? {},
1079
+ oauthScopesOnSignIn: options.oauthScopesOnSignIn ?? {}
981
1080
  });
982
1081
  }
983
1082
  _serverUserFromJson(json) {
@@ -1073,40 +1172,14 @@ var _StackServerAppImpl = class extends _StackClientAppImpl {
1073
1172
  const nonCurrentServerUser = this._serverUserFromJson(json);
1074
1173
  const currentUser = {
1075
1174
  ...nonCurrentServerUser,
1076
- _internalSession: session,
1077
- currentSession: {
1078
- async getTokens() {
1079
- const tokens = await session.getPotentiallyExpiredTokens();
1080
- return {
1081
- accessToken: tokens?.accessToken.token ?? null,
1082
- refreshToken: tokens?.refreshToken?.token ?? null
1083
- };
1084
- }
1085
- },
1175
+ ...this._authFromJson(session),
1086
1176
  async delete() {
1087
1177
  const res = await nonCurrentServerUser.delete();
1088
1178
  await app._refreshUser(session);
1089
1179
  return res;
1090
1180
  },
1091
- async updateSelectedTeam(team) {
1092
- await this.update({ selectedTeamId: team?.id ?? null });
1093
- },
1094
- async update(update) {
1095
- const res = await nonCurrentServerUser.update(update);
1096
- await app._refreshUser(session);
1097
- return res;
1098
- },
1099
- signOut() {
1100
- return app._signOut(session);
1101
- },
1102
1181
  getClientUser() {
1103
1182
  return app._currentUserFromJson(json, session);
1104
- },
1105
- sendVerificationEmail() {
1106
- return app._sendVerificationEmail(session);
1107
- },
1108
- updatePassword(options) {
1109
- return app._updatePassword(options, session);
1110
1183
  }
1111
1184
  };
1112
1185
  if (this._isInternalProject()) {
@@ -1281,7 +1354,7 @@ var _StackServerAppImpl = class extends _StackClientAppImpl {
1281
1354
  return teams.find((t) => t.id === teamId) ?? null;
1282
1355
  }, [teams, teamId]);
1283
1356
  }
1284
- async _refreshUser(session) {
1357
+ async _refreshSession(session) {
1285
1358
  await Promise.all([
1286
1359
  super._refreshUser(session),
1287
1360
  this._currentServerUserCache.refresh([session])
@@ -1330,7 +1403,8 @@ var _StackAdminAppImpl = class extends _StackServerAppImpl {
1330
1403
  }
1331
1404
  }),
1332
1405
  tokenStore: options.tokenStore,
1333
- urls: options.urls
1406
+ urls: options.urls,
1407
+ oauthScopesOnSignIn: options.oauthScopesOnSignIn
1334
1408
  });
1335
1409
  }
1336
1410
  _createApiKeySetBaseFromJson(data) {