@stackframe/stack 2.4.23 → 2.4.25

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 (36) hide show
  1. package/CHANGELOG.md +18 -0
  2. package/dist/components/magic-link-sign-in.js +1 -1
  3. package/dist/components/magic-link-sign-in.js.map +1 -1
  4. package/dist/components/selected-team-switcher.d.mts +8 -0
  5. package/dist/components/selected-team-switcher.d.ts +8 -0
  6. package/dist/components/selected-team-switcher.js +75 -0
  7. package/dist/components/selected-team-switcher.js.map +1 -0
  8. package/dist/components-page/stack-handler.js +1 -1
  9. package/dist/components-page/stack-handler.js.map +1 -1
  10. package/dist/esm/components/magic-link-sign-in.js +1 -1
  11. package/dist/esm/components/magic-link-sign-in.js.map +1 -1
  12. package/dist/esm/components/selected-team-switcher.js +63 -0
  13. package/dist/esm/components/selected-team-switcher.js.map +1 -0
  14. package/dist/esm/components-page/stack-handler.js +1 -1
  15. package/dist/esm/components-page/stack-handler.js.map +1 -1
  16. package/dist/esm/index.js +22 -16
  17. package/dist/esm/index.js.map +1 -1
  18. package/dist/esm/lib/hooks.js.map +1 -1
  19. package/dist/esm/lib/stack-app.js +285 -282
  20. package/dist/esm/lib/stack-app.js.map +1 -1
  21. package/dist/esm/providers/stack-provider.js +1 -1
  22. package/dist/esm/providers/stack-provider.js.map +1 -1
  23. package/dist/index.d.mts +1 -0
  24. package/dist/index.d.ts +1 -0
  25. package/dist/index.js +5 -0
  26. package/dist/index.js.map +1 -1
  27. package/dist/lib/hooks.d.mts +3 -3
  28. package/dist/lib/hooks.d.ts +3 -3
  29. package/dist/lib/hooks.js.map +1 -1
  30. package/dist/lib/stack-app.d.mts +100 -81
  31. package/dist/lib/stack-app.d.ts +100 -81
  32. package/dist/lib/stack-app.js +283 -280
  33. package/dist/lib/stack-app.js.map +1 -1
  34. package/dist/providers/stack-provider.js +1 -1
  35. package/dist/providers/stack-provider.js.map +1 -1
  36. package/package.json +3 -3
@@ -60,7 +60,7 @@ var import_sessions = require("@stackframe/stack-shared/dist/sessions");
60
60
  var import_use_trigger = require("@stackframe/stack-shared/dist/hooks/use-trigger");
61
61
  var import_strings = require("@stackframe/stack-shared/dist/utils/strings");
62
62
  var NextNavigation = (0, import_compile_time.scrambleDuringCompileTime)(NextNavigationUnscrambled);
63
- var clientVersion = "js @stackframe/stack@2.4.23";
63
+ var clientVersion = "js @stackframe/stack@2.4.25";
64
64
  function permissionDefinitionScopeToType(scope) {
65
65
  return { "any-team": "team", "specific-team": "team", "global": "global" }[scope.type];
66
66
  }
@@ -238,7 +238,7 @@ var _StackClientAppImpl = class __StackClientAppImpl {
238
238
  errorRedirectUrl: this.urls.error,
239
239
  providerScope: (0, import_strings.mergeScopeStrings)(scope || "", (this._oauthScopesOnSignIn[connectionId] ?? []).join(" "))
240
240
  },
241
- this._getSession()
241
+ session
242
242
  );
243
243
  return await (0, import_promises.neverResolve)();
244
244
  } else if (!hasConnection) {
@@ -284,12 +284,28 @@ var _StackClientAppImpl = class __StackClientAppImpl {
284
284
  }
285
285
  return this._uniqueIdentifier;
286
286
  }
287
+ async _checkFeatureSupport(featureName, options) {
288
+ return await this._interface.checkFeatureSupport({ ...options, featureName });
289
+ }
290
+ _useCheckFeatureSupport(featureName, options) {
291
+ (0, import_promises.runAsynchronously)(this._checkFeatureSupport(featureName, options));
292
+ throw new import_errors.StackAssertionError(`${featureName} is not currently supported. Please reach out to Stack support for more information.`);
293
+ }
287
294
  _memoryTokenStore = createEmptyTokenStore();
288
295
  _requestTokenStores = /* @__PURE__ */ new WeakMap();
289
296
  _storedCookieTokenStore = null;
290
297
  get _refreshTokenCookieName() {
291
298
  return `stack-refresh-${this.projectId}`;
292
299
  }
300
+ _getTokensFromCookies(cookies) {
301
+ const refreshToken = cookies.refreshTokenCookie;
302
+ const accessTokenObject = cookies.accessTokenCookie?.startsWith('["') ? JSON.parse(cookies.accessTokenCookie) : null;
303
+ const accessToken = accessTokenObject && refreshToken === accessTokenObject[0] ? accessTokenObject[1] : null;
304
+ return {
305
+ refreshToken,
306
+ accessToken
307
+ };
308
+ }
293
309
  get _accessTokenCookieName() {
294
310
  return `stack-access`;
295
311
  }
@@ -298,14 +314,17 @@ var _StackClientAppImpl = class __StackClientAppImpl {
298
314
  throw new Error("Cannot use cookie token store on the server!");
299
315
  }
300
316
  if (this._storedCookieTokenStore === null) {
301
- const getCurrentValue = (old) => ({
302
- refreshToken: (0, import_cookie.getCookie)(this._refreshTokenCookieName) ?? (0, import_cookie.getCookie)("stack-refresh"),
303
- // keep old cookie name for backwards-compatibility
304
- // if there is an access token in memory already, don't update the access token based on cookies (access token
305
- // cookies may be set by another project on the same domain)
306
- // see the comment in _accessTokenCookieName for more information
307
- accessToken: old === null ? (0, import_cookie.getCookie)(this._accessTokenCookieName) : old.accessToken
308
- });
317
+ const getCurrentValue = (old) => {
318
+ const tokens = this._getTokensFromCookies({
319
+ refreshTokenCookie: (0, import_cookie.getCookie)(this._refreshTokenCookieName) ?? (0, import_cookie.getCookie)("stack-refresh"),
320
+ // keep old cookie name for backwards-compatibility
321
+ accessTokenCookie: (0, import_cookie.getCookie)(this._accessTokenCookieName)
322
+ });
323
+ return {
324
+ refreshToken: tokens.refreshToken,
325
+ accessToken: tokens.accessToken ?? (old?.refreshToken === tokens.refreshToken ? old.accessToken : null)
326
+ };
327
+ };
309
328
  this._storedCookieTokenStore = new import_stores.Store(getCurrentValue(null));
310
329
  let hasSucceededInWriting = true;
311
330
  setInterval(() => {
@@ -320,7 +339,8 @@ var _StackClientAppImpl = class __StackClientAppImpl {
320
339
  this._storedCookieTokenStore.onChange((value) => {
321
340
  try {
322
341
  (0, import_cookie.setOrDeleteCookie)(this._refreshTokenCookieName, value.refreshToken, { maxAge: 60 * 60 * 24 * 365 });
323
- (0, import_cookie.setOrDeleteCookie)(this._accessTokenCookieName, value.accessToken, { maxAge: 60 * 60 * 24 });
342
+ (0, import_cookie.setOrDeleteCookie)(this._accessTokenCookieName, value.accessToken ? JSON.stringify([value.refreshToken, value.accessToken]) : null, { maxAge: 60 * 60 * 24 });
343
+ (0, import_cookie.deleteCookie)("stack-refresh");
324
344
  hasSucceededInWriting = true;
325
345
  } catch (e) {
326
346
  if (!(0, import_env.isBrowserLike)()) {
@@ -343,15 +363,16 @@ var _StackClientAppImpl = class __StackClientAppImpl {
343
363
  if ((0, import_env.isBrowserLike)()) {
344
364
  return this._getCookieTokenStore();
345
365
  } else {
346
- const store = new import_stores.Store({
347
- refreshToken: (0, import_cookie.getCookie)(this._refreshTokenCookieName) ?? (0, import_cookie.getCookie)("stack-refresh"),
366
+ const tokens = this._getTokensFromCookies({
367
+ refreshTokenCookie: (0, import_cookie.getCookie)(this._refreshTokenCookieName) ?? (0, import_cookie.getCookie)("stack-refresh"),
348
368
  // keep old cookie name for backwards-compatibility
349
- accessToken: (0, import_cookie.getCookie)(this._accessTokenCookieName)
369
+ accessTokenCookie: (0, import_cookie.getCookie)(this._accessTokenCookieName)
350
370
  });
371
+ const store = new import_stores.Store(tokens);
351
372
  store.onChange((value) => {
352
373
  try {
353
374
  (0, import_cookie.setOrDeleteCookie)(this._refreshTokenCookieName, value.refreshToken, { maxAge: 60 * 60 * 24 * 365 });
354
- (0, import_cookie.setOrDeleteCookie)(this._accessTokenCookieName, value.accessToken, { maxAge: 60 * 60 * 24 });
375
+ (0, import_cookie.setOrDeleteCookie)(this._accessTokenCookieName, value.accessToken ? JSON.stringify([value.refreshToken, value.accessToken]) : null, { maxAge: 60 * 60 * 24 });
355
376
  } catch (e) {
356
377
  }
357
378
  });
@@ -447,7 +468,9 @@ var _StackClientAppImpl = class __StackClientAppImpl {
447
468
  _useSession(overrideTokenStoreInit) {
448
469
  const tokenStore = this._getOrCreateTokenStore(overrideTokenStoreInit);
449
470
  const subscribe = (0, import_react.useCallback)((cb) => {
450
- const { unsubscribe } = tokenStore.onChange(() => cb());
471
+ const { unsubscribe } = tokenStore.onChange(() => {
472
+ cb();
473
+ });
451
474
  return unsubscribe;
452
475
  }, [tokenStore]);
453
476
  const getSnapshot = (0, import_react.useCallback)(() => this._getSessionFromTokenStore(tokenStore), [tokenStore]);
@@ -498,16 +521,43 @@ var _StackClientAppImpl = class __StackClientAppImpl {
498
521
  }
499
522
  };
500
523
  }
501
- _userFromJson(json) {
524
+ _teamMemberFromJson(json) {
525
+ if (json === null)
526
+ return null;
527
+ return {
528
+ teamId: json.teamId,
529
+ userId: json.userId,
530
+ displayName: json.displayName
531
+ };
532
+ }
533
+ _createAuth(session) {
502
534
  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
- }
535
+ return {
536
+ _internalSession: session,
537
+ currentSession: {
538
+ async getTokens() {
539
+ const tokens = await session.getPotentiallyExpiredTokens();
540
+ return {
541
+ accessToken: tokens?.accessToken.token ?? null,
542
+ refreshToken: tokens?.refreshToken?.token ?? null
543
+ };
544
+ }
545
+ },
546
+ async getAuthHeaders() {
547
+ return {
548
+ "x-stack-auth": JSON.stringify(await this.getAuthJson())
549
+ };
550
+ },
551
+ async getAuthJson() {
552
+ const tokens = await this.currentSession.getTokens();
553
+ return tokens;
554
+ },
555
+ signOut() {
556
+ return app._signOut(session);
557
+ }
558
+ };
559
+ }
560
+ _createBaseUser(json) {
511
561
  return {
512
562
  projectId: json.projectId,
513
563
  id: json.id,
@@ -517,18 +567,52 @@ var _StackClientAppImpl = class __StackClientAppImpl {
517
567
  profileImageUrl: json.profileImageUrl,
518
568
  signedUpAt: new Date(json.signedUpAtMillis),
519
569
  clientMetadata: json.clientMetadata,
520
- authMethod: json.authMethod,
521
570
  hasPassword: json.hasPassword,
522
571
  authWithEmail: json.authWithEmail,
523
572
  oauthProviders: json.oauthProviders,
524
- getConnection,
525
- useConnection,
526
- async getSelectedTeam() {
527
- return await this.getTeam(json.selectedTeamId || "");
573
+ selectedTeam: json.selectedTeam && this._teamFromJson(json.selectedTeam),
574
+ toClientJson() {
575
+ return (0, import_objects.pick)(json, [
576
+ "projectId",
577
+ "id",
578
+ "displayName",
579
+ "primaryEmail",
580
+ "primaryEmailVerified",
581
+ "profileImageUrl",
582
+ "signedUpAtMillis",
583
+ "clientMetadata",
584
+ "hasPassword",
585
+ "authMethod",
586
+ "authWithEmail",
587
+ "selectedTeamId",
588
+ "selectedTeam",
589
+ "oauthProviders"
590
+ ]);
591
+ }
592
+ };
593
+ }
594
+ _createUserExtra(json, session) {
595
+ const app = this;
596
+ async function getConnectedAccount(id, options) {
597
+ const scopeString = options?.scopes?.join(" ");
598
+ return await app._currentUserOAuthConnectionCache.getOrWait([session, id, scopeString || "", options?.or === "redirect"], "write-only");
599
+ }
600
+ function useConnectedAccount(id, options) {
601
+ const scopeString = options?.scopes?.join(" ");
602
+ return useAsyncCache(app._currentUserOAuthConnectionCache, [session, id, scopeString || "", options?.or === "redirect"], "user.useConnectedAccount()");
603
+ }
604
+ return {
605
+ setDisplayName(displayName) {
606
+ return this.update({ displayName });
607
+ },
608
+ setClientMetadata(metadata) {
609
+ return this.update({ clientMetadata: metadata });
528
610
  },
529
- useSelectedTeam() {
530
- return this.useTeam(json.selectedTeamId || "");
611
+ async setSelectedTeam(team) {
612
+ await this.update({ selectedTeamId: team?.id ?? null });
531
613
  },
614
+ getConnectedAccount,
615
+ useConnectedAccount,
532
616
  async getTeam(teamId) {
533
617
  const teams = await this.listTeams();
534
618
  return teams.find((t) => t.id === teamId) ?? null;
@@ -539,32 +623,20 @@ var _StackClientAppImpl = class __StackClientAppImpl {
539
623
  return teams.find((t) => t.id === teamId) ?? null;
540
624
  }, [teams, teamId]);
541
625
  },
542
- onTeamChange(teamId, callback) {
543
- return this.onTeamsChange((teams) => {
544
- const team = teams.find((t) => t.id === teamId) ?? null;
545
- callback(team);
546
- });
547
- },
548
626
  async listTeams() {
549
- const teams = await app._currentUserTeamsCache.getOrWait([app._getSession()], "write-only");
627
+ const teams = await app._currentUserTeamsCache.getOrWait([session], "write-only");
550
628
  return teams.map((json2) => app._teamFromJson(json2));
551
629
  },
552
630
  useTeams() {
553
- const session = app._useSession();
554
631
  const teams = useAsyncCache(app._currentUserTeamsCache, [session], "user.useTeams()");
555
632
  return (0, import_react.useMemo)(() => teams.map((json2) => app._teamFromJson(json2)), [teams]);
556
633
  },
557
- onTeamsChange(callback) {
558
- return app._currentUserTeamsCache.onChange([app._getSession()], (value, oldValue) => {
559
- callback(value.map((json2) => app._teamFromJson(json2)), oldValue?.map((json2) => app._teamFromJson(json2)));
560
- });
561
- },
562
634
  async listPermissions(scope, options) {
563
- const permissions = await app._currentUserPermissionsCache.getOrWait([app._getSession(), scope.id, "team", !!options?.direct], "write-only");
635
+ const permissions = await app._currentUserPermissionsCache.getOrWait([session, scope.id, "team", !!options?.direct], "write-only");
564
636
  return permissions.map((json2) => app._permissionFromJson(json2));
565
637
  },
566
638
  usePermissions(scope, options) {
567
- const permissions = useAsyncCache(app._currentUserPermissionsCache, [app._getSession(), scope.id, "team", !!options?.direct], "user.usePermissions()");
639
+ const permissions = useAsyncCache(app._currentUserPermissionsCache, [session, scope.id, "team", !!options?.direct], "user.usePermissions()");
568
640
  return (0, import_react.useMemo)(() => permissions.map((json2) => app._permissionFromJson(json2)), [permissions]);
569
641
  },
570
642
  usePermission(scope, permissionId) {
@@ -578,49 +650,6 @@ var _StackClientAppImpl = class __StackClientAppImpl {
578
650
  async hasPermission(scope, permissionId) {
579
651
  return await this.getPermission(scope, permissionId) !== null;
580
652
  },
581
- toJson() {
582
- return json;
583
- }
584
- };
585
- }
586
- _teamMemberFromJson(json) {
587
- if (json === null)
588
- return null;
589
- return {
590
- teamId: json.teamId,
591
- userId: json.userId,
592
- displayName: json.displayName
593
- };
594
- }
595
- _authFromJson(session) {
596
- const app = this;
597
- return {
598
- _internalSession: session,
599
- currentSession: {
600
- async getTokens() {
601
- const tokens = await session.getPotentiallyExpiredTokens();
602
- return {
603
- accessToken: tokens?.accessToken.token ?? null,
604
- refreshToken: tokens?.refreshToken?.token ?? null
605
- };
606
- }
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
621
- async updateSelectedTeam(team) {
622
- await app._updateUser({ selectedTeamId: team?.id ?? null }, session);
623
- },
624
653
  update(update) {
625
654
  return app._updateUser(update, session);
626
655
  },
@@ -632,36 +661,30 @@ var _StackClientAppImpl = class __StackClientAppImpl {
632
661
  }
633
662
  };
634
663
  }
635
- _currentUserFromJson(json, session) {
636
- if (json === null)
637
- return null;
664
+ _createInternalUserExtra(session) {
638
665
  const app = this;
666
+ this._ensureInternalProject();
667
+ return {
668
+ createProject(newProject) {
669
+ return app._createProject(session, newProject);
670
+ },
671
+ listOwnedProjects() {
672
+ return app._listOwnedProjects(session);
673
+ },
674
+ useOwnedProjects() {
675
+ return app._useOwnedProjects(session);
676
+ }
677
+ };
678
+ }
679
+ _createCurrentUser(json, session) {
639
680
  const currentUser = {
640
- ...this._userFromJson(json),
641
- ...this._authFromJson(session)
681
+ ...this._createBaseUser(json),
682
+ ...this._createAuth(session),
683
+ ...this._createUserExtra(json, session),
684
+ ...this._isInternalProject() ? this._createInternalUserExtra(session) : {}
642
685
  };
643
- if (this._isInternalProject()) {
644
- const internalUser = {
645
- ...currentUser,
646
- createProject(newProject) {
647
- return app._createProject(newProject);
648
- },
649
- listOwnedProjects() {
650
- return app._listOwnedProjects();
651
- },
652
- useOwnedProjects() {
653
- return app._useOwnedProjects();
654
- },
655
- onOwnedProjectsChange(callback) {
656
- return app._onOwnedProjectsChange(callback);
657
- }
658
- };
659
- Object.freeze(internalUser);
660
- return internalUser;
661
- } else {
662
- Object.freeze(currentUser);
663
- return currentUser;
664
- }
686
+ Object.freeze(currentUser);
687
+ return currentUser;
665
688
  }
666
689
  _projectAdminFromJson(data, adminInterface, onRefresh) {
667
690
  if (data.id !== adminInterface.projectId) {
@@ -797,12 +820,12 @@ var _StackClientAppImpl = class __StackClientAppImpl {
797
820
  }
798
821
  }
799
822
  }
800
- return this._currentUserFromJson(userJson, session);
823
+ return userJson && this._createCurrentUser(userJson, session);
801
824
  }
802
825
  useUser(options) {
803
826
  this._ensurePersistentTokenStore(options?.tokenStore);
804
827
  const router = NextNavigation.useRouter();
805
- const session = this._getSession(options?.tokenStore);
828
+ const session = this._useSession(options?.tokenStore);
806
829
  const userJson = useAsyncCache(this._currentUserCache, [session], "useUser()");
807
830
  const triggerRedirectToSignIn = (0, import_use_trigger.useTrigger)(() => router.replace(this.urls.signIn));
808
831
  if (userJson === null) {
@@ -821,16 +844,9 @@ var _StackClientAppImpl = class __StackClientAppImpl {
821
844
  }
822
845
  }
823
846
  return (0, import_react.useMemo)(() => {
824
- return this._currentUserFromJson(userJson, session);
847
+ return userJson && this._createCurrentUser(userJson, session);
825
848
  }, [userJson, session, options?.or]);
826
849
  }
827
- onUserChange(callback) {
828
- this._ensurePersistentTokenStore();
829
- const session = this._getSession();
830
- return this._currentUserCache.onChange([session], (userJson) => {
831
- callback(this._currentUserFromJson(userJson, session));
832
- });
833
- }
834
850
  async _updateUser(update, session) {
835
851
  const res = await this._interface.setClientUserCustomizableData(update, session);
836
852
  await this._refreshUser(session);
@@ -929,12 +945,8 @@ var _StackClientAppImpl = class __StackClientAppImpl {
929
945
  useProject() {
930
946
  return useAsyncCache(this._currentProjectCache, [], "useProject()");
931
947
  }
932
- onProjectChange(callback) {
933
- return this._currentProjectCache.onChange([], callback);
934
- }
935
- async _listOwnedProjects() {
948
+ async _listOwnedProjects(session) {
936
949
  this._ensureInternalProject();
937
- const session = this._getSession();
938
950
  const json = await this._ownedProjectsCache.getOrWait([session], "write-only");
939
951
  return json.map((j) => this._projectAdminFromJson(
940
952
  j,
@@ -942,9 +954,8 @@ var _StackClientAppImpl = class __StackClientAppImpl {
942
954
  () => this._refreshOwnedProjects(session)
943
955
  ));
944
956
  }
945
- _useOwnedProjects() {
957
+ _useOwnedProjects(session) {
946
958
  this._ensureInternalProject();
947
- const session = this._getSession();
948
959
  const json = useAsyncCache(this._ownedProjectsCache, [session], "useOwnedProjects()");
949
960
  return (0, import_react.useMemo)(() => json.map((j) => this._projectAdminFromJson(
950
961
  j,
@@ -952,20 +963,8 @@ var _StackClientAppImpl = class __StackClientAppImpl {
952
963
  () => this._refreshOwnedProjects(session)
953
964
  )), [json]);
954
965
  }
955
- _onOwnedProjectsChange(callback) {
966
+ async _createProject(session, newProject) {
956
967
  this._ensureInternalProject();
957
- const session = this._getSession();
958
- return this._ownedProjectsCache.onChange([session], (projects) => {
959
- callback(projects.map((j) => this._projectAdminFromJson(
960
- j,
961
- this._createAdminInterface(j.id, session),
962
- () => this._refreshOwnedProjects(session)
963
- )));
964
- });
965
- }
966
- async _createProject(newProject) {
967
- this._ensureInternalProject();
968
- const session = this._getSession();
969
968
  const json = await this._interface.createProject(newProject, session);
970
969
  const res = this._projectAdminFromJson(
971
970
  json,
@@ -1079,37 +1078,45 @@ var _StackServerAppImpl = class extends _StackClientAppImpl {
1079
1078
  oauthScopesOnSignIn: options.oauthScopesOnSignIn ?? {}
1080
1079
  });
1081
1080
  }
1082
- _serverUserFromJson(json) {
1083
- if (json === null)
1084
- return null;
1081
+ _createBaseUser(json) {
1082
+ return {
1083
+ ...super._createBaseUser(json),
1084
+ ..."serverMetadata" in json ? {
1085
+ serverMetadata: json.serverMetadata,
1086
+ toServerJson() {
1087
+ return {
1088
+ ...this.toClientJson(),
1089
+ ...(0, import_objects.pick)(json, [
1090
+ "serverMetadata"
1091
+ ])
1092
+ };
1093
+ }
1094
+ } : {}
1095
+ };
1096
+ }
1097
+ _createUserExtra(json) {
1085
1098
  const app = this;
1086
1099
  return {
1087
- ...this._userFromJson(json),
1088
- serverMetadata: json.serverMetadata,
1089
- async delete() {
1090
- const res = await app._interface.deleteServerUser(this.id);
1091
- await app._refreshUsers();
1092
- return res;
1100
+ async setDisplayName(displayName) {
1101
+ return await this.update({ displayName });
1093
1102
  },
1094
- async update(update) {
1095
- const res = await app._interface.setServerUserCustomizableData(this.id, update);
1096
- await app._refreshUsers();
1097
- return res;
1103
+ async setClientMetadata(metadata) {
1104
+ return await this.update({ clientMetadata: metadata });
1098
1105
  },
1099
- getClientUser() {
1100
- return app._userFromJson(json);
1106
+ async setServerMetadata(metadata) {
1107
+ return await this.update({ serverMetadata: metadata });
1101
1108
  },
1102
- async grantPermission(scope, permissionId) {
1103
- await app._interface.grantTeamUserPermission(scope.id, json.id, permissionId, "team");
1104
- for (const direct of [true, false]) {
1105
- await app._serverTeamUserPermissionsCache.refresh([scope.id, json.id, "team", direct]);
1106
- }
1109
+ async setSelectedTeam(team) {
1110
+ return await this.update({ selectedTeamId: team?.id ?? null });
1107
1111
  },
1108
- async revokePermission(scope, permissionId) {
1109
- await app._interface.revokeTeamUserPermission(scope.id, json.id, permissionId, "team");
1110
- for (const direct of [true, false]) {
1111
- await app._serverTeamUserPermissionsCache.refresh([scope.id, json.id, "team", direct]);
1112
- }
1112
+ async setPrimaryEmail(email, options) {
1113
+ return await this.update({ primaryEmail: email });
1114
+ },
1115
+ getConnectedAccount: async () => {
1116
+ return await app._checkFeatureSupport("getConnectedAccount() on ServerUser", {});
1117
+ },
1118
+ useConnectedAccount: () => {
1119
+ return app._useCheckFeatureSupport("useConnectedAccount() on ServerUser", {});
1113
1120
  },
1114
1121
  async getTeam(teamId) {
1115
1122
  const teams = await this.listTeams();
@@ -1121,24 +1128,13 @@ var _StackServerAppImpl = class extends _StackClientAppImpl {
1121
1128
  return teams.find((t) => t.id === teamId) ?? null;
1122
1129
  }, [teams, teamId]);
1123
1130
  },
1124
- onTeamChange(teamId, callback) {
1125
- return this.onTeamsChange((teams) => {
1126
- const team = teams.find((t) => t.id === teamId) ?? null;
1127
- callback(team);
1128
- });
1129
- },
1130
1131
  async listTeams() {
1131
- const teams = await app._serverTeamsCache.getOrWait([app._getSession()], "write-only");
1132
- return teams.map((json2) => app._serverTeamFromJson(json2));
1132
+ const teams = await app.listTeams();
1133
+ const withMembers = await Promise.all(teams.map(async (t) => [t, await t.listMembers()]));
1134
+ return withMembers.filter(([_, members]) => members.find((m) => m.userId === json.id)).map(([t]) => t);
1133
1135
  },
1134
1136
  useTeams() {
1135
- const teams = useAsyncCache(app._serverTeamsCache, [app._getSession()], "user.useTeams()");
1136
- return (0, import_react.useMemo)(() => teams.map((json2) => app._serverTeamFromJson(json2)), [teams]);
1137
- },
1138
- onTeamsChange(callback) {
1139
- return app._serverTeamsCache.onChange([app._getSession()], (value, oldValue) => {
1140
- callback(value.map((json2) => app._serverTeamFromJson(json2)), oldValue?.map((json2) => app._serverTeamFromJson(json2)));
1141
- });
1137
+ return app._useCheckFeatureSupport("useTeams() on ServerUser", {});
1142
1138
  },
1143
1139
  async listPermissions(scope, options) {
1144
1140
  const permissions = await app._serverTeamUserPermissionsCache.getOrWait([scope.id, json.id, "team", !!options?.direct], "write-only");
@@ -1148,62 +1144,62 @@ var _StackServerAppImpl = class extends _StackClientAppImpl {
1148
1144
  const permissions = useAsyncCache(app._serverTeamUserPermissionsCache, [scope.id, json.id, "team", !!options?.direct], "user.usePermissions()");
1149
1145
  return (0, import_react.useMemo)(() => permissions.map((json2) => app._serverPermissionFromJson(json2)), [permissions]);
1150
1146
  },
1151
- usePermission(scope, permissionId) {
1152
- const permissions = this.usePermissions(scope);
1153
- return (0, import_react.useMemo)(() => permissions.find((p) => p.id === permissionId) ?? null, [permissions, permissionId]);
1154
- },
1155
1147
  async getPermission(scope, permissionId) {
1156
1148
  const permissions = await this.listPermissions(scope);
1157
1149
  return permissions.find((p) => p.id === permissionId) ?? null;
1158
1150
  },
1151
+ usePermission(scope, permissionId) {
1152
+ const permissions = this.usePermissions(scope);
1153
+ return (0, import_react.useMemo)(() => permissions.find((p) => p.id === permissionId) ?? null, [permissions, permissionId]);
1154
+ },
1159
1155
  async hasPermission(scope, permissionId) {
1160
- const permissions = await this.listPermissions(scope);
1161
- return permissions.some((p) => p.id === permissionId);
1156
+ return await this.getPermission(scope, permissionId) !== null;
1162
1157
  },
1163
- toJson() {
1164
- return json;
1158
+ async grantPermission(scope, permissionId) {
1159
+ await app._interface.grantTeamUserPermission(scope.id, json.id, permissionId, "team");
1160
+ for (const direct of [true, false]) {
1161
+ await app._serverTeamUserPermissionsCache.refresh([scope.id, json.id, "team", direct]);
1162
+ }
1163
+ },
1164
+ async revokePermission(scope, permissionId) {
1165
+ await app._interface.revokeTeamUserPermission(scope.id, json.id, permissionId, "team");
1166
+ for (const direct of [true, false]) {
1167
+ await app._serverTeamUserPermissionsCache.refresh([scope.id, json.id, "team", direct]);
1168
+ }
1169
+ },
1170
+ async delete() {
1171
+ const res = await app._interface.deleteServerUser(json.id);
1172
+ await app._refreshUsers();
1173
+ return res;
1174
+ },
1175
+ async update(update) {
1176
+ const res = await app._interface.setServerUserCustomizableData(json.id, update);
1177
+ await app._refreshUsers();
1178
+ return res;
1179
+ },
1180
+ async sendVerificationEmail() {
1181
+ return await app._checkFeatureSupport("sendVerificationEmail() on ServerUser", {});
1182
+ },
1183
+ async updatePassword(options) {
1184
+ return await app._checkFeatureSupport("updatePassword() on ServerUser", {});
1165
1185
  }
1166
1186
  };
1167
1187
  }
1168
- _currentServerUserFromJson(json, session) {
1169
- if (json === null)
1170
- return null;
1188
+ _createUser(json) {
1189
+ return {
1190
+ ...this._createBaseUser(json),
1191
+ ...this._createUserExtra(json)
1192
+ };
1193
+ }
1194
+ _createCurrentUser(json, session) {
1171
1195
  const app = this;
1172
- const nonCurrentServerUser = this._serverUserFromJson(json);
1173
1196
  const currentUser = {
1174
- ...nonCurrentServerUser,
1175
- ...this._authFromJson(session),
1176
- async delete() {
1177
- const res = await nonCurrentServerUser.delete();
1178
- await app._refreshUser(session);
1179
- return res;
1180
- },
1181
- getClientUser() {
1182
- return app._currentUserFromJson(json, session);
1183
- }
1197
+ ...this._createUser(json),
1198
+ ...this._createAuth(session),
1199
+ ...this._isInternalProject() ? this._createInternalUserExtra(session) : {}
1184
1200
  };
1185
- if (this._isInternalProject()) {
1186
- const internalUser = {
1187
- ...currentUser,
1188
- createProject(newProject) {
1189
- return app._createProject(newProject);
1190
- },
1191
- listOwnedProjects() {
1192
- return app._listOwnedProjects();
1193
- },
1194
- useOwnedProjects() {
1195
- return app._useOwnedProjects();
1196
- },
1197
- onOwnedProjectsChange(callback) {
1198
- return app._onOwnedProjectsChange(callback);
1199
- }
1200
- };
1201
- Object.freeze(internalUser);
1202
- return internalUser;
1203
- } else {
1204
- Object.freeze(currentUser);
1205
- return currentUser;
1206
- }
1201
+ Object.freeze(currentUser);
1202
+ return currentUser;
1207
1203
  }
1208
1204
  _serverTeamMemberFromJson(json) {
1209
1205
  if (json === null)
@@ -1211,12 +1207,7 @@ var _StackServerAppImpl = class extends _StackClientAppImpl {
1211
1207
  const app = this;
1212
1208
  return {
1213
1209
  ...app._teamMemberFromJson(json),
1214
- async getUser() {
1215
- const user = app._serverUserFromJson(await app._serverUserCache.getOrWait([json.userId], "write-only"));
1216
- if (!user)
1217
- throw new Error(`User ${json.userId} not found`);
1218
- return user;
1219
- }
1210
+ user: app._createUser(json.user)
1220
1211
  };
1221
1212
  }
1222
1213
  _serverTeamFromJson(json) {
@@ -1259,49 +1250,75 @@ var _StackServerAppImpl = class extends _StackClientAppImpl {
1259
1250
  }
1260
1251
  };
1261
1252
  }
1262
- async getServerUser() {
1263
- this._ensurePersistentTokenStore();
1264
- const session = this._getSession();
1253
+ async getUser(options) {
1254
+ this._ensurePersistentTokenStore(options?.tokenStore);
1255
+ const session = this._getSession(options?.tokenStore);
1265
1256
  const userJson = await this._currentServerUserCache.getOrWait([session], "write-only");
1266
- return this._currentServerUserFromJson(userJson, session);
1257
+ if (userJson === null) {
1258
+ switch (options?.or) {
1259
+ case "redirect": {
1260
+ await this.redirectToSignIn();
1261
+ break;
1262
+ }
1263
+ case "throw": {
1264
+ throw new Error("User is not signed in but getUser was called with { or: 'throw' }");
1265
+ }
1266
+ default: {
1267
+ return null;
1268
+ }
1269
+ }
1270
+ }
1271
+ return userJson && this._createCurrentUser(userJson, session);
1272
+ }
1273
+ async getServerUser() {
1274
+ console.warn("stackServerApp.getServerUser is deprecated; use stackServerApp.getUser instead");
1275
+ return await this.getUser();
1267
1276
  }
1268
1277
  async getServerUserById(userId) {
1269
1278
  const json = await this._serverUserCache.getOrWait([userId], "write-only");
1270
- return this._serverUserFromJson(json);
1279
+ return json && this._createUser(json);
1271
1280
  }
1272
- useServerUser(options) {
1273
- this._ensurePersistentTokenStore();
1274
- const session = this._getSession();
1275
- const userJson = useAsyncCache(this._currentServerUserCache, [session], "useServerUser()");
1276
- return (0, import_react.useMemo)(() => {
1277
- if (options?.required && userJson === null) {
1278
- (0, import_react.use)(this.redirectToSignIn());
1281
+ useUser(options) {
1282
+ this._ensurePersistentTokenStore(options?.tokenStore);
1283
+ const router = NextNavigation.useRouter();
1284
+ const session = this._getSession(options?.tokenStore);
1285
+ const userJson = useAsyncCache(this._currentServerUserCache, [session], "useUser()");
1286
+ const triggerRedirectToSignIn = (0, import_use_trigger.useTrigger)(() => router.replace(this.urls.signIn));
1287
+ if (userJson === null) {
1288
+ switch (options?.or) {
1289
+ case "redirect": {
1290
+ triggerRedirectToSignIn();
1291
+ (0, import_react3.suspend)();
1292
+ throw new import_errors.StackAssertionError("suspend should never return");
1293
+ }
1294
+ case "throw": {
1295
+ throw new Error("User is not signed in but useUser was called with { or: 'throw' }");
1296
+ }
1297
+ case void 0:
1298
+ case "return-null": {
1299
+ }
1279
1300
  }
1280
- return this._currentServerUserFromJson(userJson, session);
1281
- }, [userJson, session, options?.required]);
1301
+ }
1302
+ return (0, import_react.useMemo)(() => {
1303
+ return userJson && this._createCurrentUser(userJson, session);
1304
+ }, [userJson, session, options?.or]);
1282
1305
  }
1283
- onServerUserChange(callback) {
1284
- this._ensurePersistentTokenStore();
1285
- const session = this._getSession();
1286
- return this._currentServerUserCache.onChange([session], (userJson) => {
1287
- callback(this._currentServerUserFromJson(userJson, session));
1288
- });
1306
+ useUserById(userId) {
1307
+ const json = useAsyncCache(this._serverUserCache, [userId], "useUserById()");
1308
+ return (0, import_react.useMemo)(() => {
1309
+ return json && this._createUser(json);
1310
+ }, [json]);
1289
1311
  }
1290
- async listServerUsers() {
1312
+ async listUsers() {
1291
1313
  const json = await this._serverUsersCache.getOrWait([], "write-only");
1292
- return json.map((j) => this._serverUserFromJson(j));
1314
+ return json.map((j) => this._createUser(j));
1293
1315
  }
1294
- useServerUsers() {
1316
+ useUsers() {
1295
1317
  const json = useAsyncCache(this._serverUsersCache, [], "useServerUsers()");
1296
1318
  return (0, import_react.useMemo)(() => {
1297
- return json.map((j) => this._serverUserFromJson(j));
1319
+ return json.map((j) => this._createUser(j));
1298
1320
  }, [json]);
1299
1321
  }
1300
- onServerUsersChange(callback) {
1301
- return this._serverUsersCache.onChange([], (users) => {
1302
- callback(users.map((j) => this._serverUserFromJson(j)));
1303
- });
1304
- }
1305
1322
  async listPermissionDefinitions() {
1306
1323
  return await this._serverTeamPermissionDefinitionsCache.getOrWait([], "write-only");
1307
1324
  }
@@ -1463,15 +1480,6 @@ var _StackAdminAppImpl = class extends _StackServerAppImpl {
1463
1480
  () => this._refreshProject()
1464
1481
  ), [json]);
1465
1482
  }
1466
- onProjectAdminChange(callback) {
1467
- return this._adminProjectCache.onChange([], (project) => {
1468
- callback(this._projectAdminFromJson(
1469
- project,
1470
- this._interface,
1471
- () => this._refreshProject()
1472
- ));
1473
- });
1474
- }
1475
1483
  async listApiKeySets() {
1476
1484
  const json = await this._apiKeySetsCache.getOrWait([], "write-only");
1477
1485
  return json.map((j) => this._createApiKeySetFromJson(j));
@@ -1482,11 +1490,6 @@ var _StackAdminAppImpl = class extends _StackServerAppImpl {
1482
1490
  return json.map((j) => this._createApiKeySetFromJson(j));
1483
1491
  }, [json]);
1484
1492
  }
1485
- onApiKeySetsChange(callback) {
1486
- return this._apiKeySetsCache.onChange([], (apiKeySets) => {
1487
- callback(apiKeySets.map((j) => this._createApiKeySetFromJson(j)));
1488
- });
1489
- }
1490
1493
  async createApiKeySet(options) {
1491
1494
  const json = await this._interface.createApiKeySet(options);
1492
1495
  await this._refreshApiKeySets();