@stackframe/stack 2.6.12 → 2.6.16

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 (38) hide show
  1. package/CHANGELOG.md +39 -0
  2. package/dist/components/passkey-button.d.mts +7 -0
  3. package/dist/components/passkey-button.d.ts +7 -0
  4. package/dist/components/passkey-button.js +58 -0
  5. package/dist/components/passkey-button.js.map +1 -0
  6. package/dist/components-page/account-settings.js +58 -1
  7. package/dist/components-page/account-settings.js.map +1 -1
  8. package/dist/components-page/auth-page.d.mts +1 -0
  9. package/dist/components-page/auth-page.d.ts +1 -0
  10. package/dist/components-page/auth-page.js +5 -1
  11. package/dist/components-page/auth-page.js.map +1 -1
  12. package/dist/esm/components/passkey-button.js +34 -0
  13. package/dist/esm/components/passkey-button.js.map +1 -0
  14. package/dist/esm/components-page/account-settings.js +58 -1
  15. package/dist/esm/components-page/account-settings.js.map +1 -1
  16. package/dist/esm/components-page/auth-page.js +5 -1
  17. package/dist/esm/components-page/auth-page.js.map +1 -1
  18. package/dist/esm/generated/global-css.js +1 -1
  19. package/dist/esm/generated/global-css.js.map +1 -1
  20. package/dist/esm/generated/quetzal-translations.js +2244 -2124
  21. package/dist/esm/generated/quetzal-translations.js.map +1 -1
  22. package/dist/esm/lib/stack-app.js +81 -16
  23. package/dist/esm/lib/stack-app.js.map +1 -1
  24. package/dist/generated/global-css.d.mts +1 -1
  25. package/dist/generated/global-css.d.ts +1 -1
  26. package/dist/generated/global-css.js +1 -1
  27. package/dist/generated/global-css.js.map +1 -1
  28. package/dist/generated/quetzal-translations.d.mts +2 -2
  29. package/dist/generated/quetzal-translations.d.ts +2 -2
  30. package/dist/generated/quetzal-translations.js +2244 -2124
  31. package/dist/generated/quetzal-translations.js.map +1 -1
  32. package/dist/index.d.mts +1 -1
  33. package/dist/index.d.ts +1 -1
  34. package/dist/lib/stack-app.d.mts +31 -6
  35. package/dist/lib/stack-app.d.ts +31 -6
  36. package/dist/lib/stack-app.js +81 -16
  37. package/dist/lib/stack-app.js.map +1 -1
  38. package/package.json +5 -4
@@ -1,4 +1,5 @@
1
1
  // src/lib/stack-app.ts
2
+ import { WebAuthnError, startAuthentication, startRegistration } from "@simplewebauthn/browser";
2
3
  import { isReactServer } from "@stackframe/stack-sc";
3
4
  import { KnownErrors, StackAdminInterface, StackClientInterface, StackServerInterface } from "@stackframe/stack-shared";
4
5
  import { getProductionModeErrors } from "@stackframe/stack-shared/dist/helpers/production-mode";
@@ -24,7 +25,7 @@ import { constructRedirectUrl } from "../utils/url";
24
25
  import { addNewOAuthProviderOrScope, callOAuthCallback, signInWithOAuth } from "./auth";
25
26
  import { deleteCookie, getCookie, setOrDeleteCookie } from "./cookie";
26
27
  var NextNavigation = scrambleDuringCompileTime(NextNavigationUnscrambled);
27
- var clientVersion = "js @stackframe/stack@2.6.12";
28
+ var clientVersion = "js @stackframe/stack@2.6.16";
28
29
  function getUrls(partial) {
29
30
  const handler = partial.handler ?? "/handler";
30
31
  const home = partial.home ?? "/";
@@ -503,6 +504,7 @@ var _StackClientAppImpl = class __StackClientAppImpl {
503
504
  signUpEnabled: crud.config.sign_up_enabled,
504
505
  credentialEnabled: crud.config.credential_enabled,
505
506
  magicLinkEnabled: crud.config.magic_link_enabled,
507
+ passkeyEnabled: crud.config.passkey_enabled,
506
508
  clientTeamCreationEnabled: crud.config.client_team_creation_enabled,
507
509
  clientUserDeletionEnabled: crud.config.client_user_deletion_enabled,
508
510
  oauthProviders: crud.config.enabled_oauth_providers.map((p) => ({
@@ -534,7 +536,7 @@ var _StackClientAppImpl = class __StackClientAppImpl {
534
536
  clientMetadata: crud.client_metadata,
535
537
  clientReadOnlyMetadata: crud.client_read_only_metadata,
536
538
  async inviteUser(options) {
537
- return await app._interface.sendTeamInvitation({
539
+ await app._interface.sendTeamInvitation({
538
540
  teamId: crud.id,
539
541
  email: options.email,
540
542
  session: app._getSession(),
@@ -565,7 +567,7 @@ var _StackClientAppImpl = class __StackClientAppImpl {
565
567
  isPrimary: crud.is_primary,
566
568
  usedForAuth: crud.used_for_auth,
567
569
  async sendVerificationEmail() {
568
- return await app._interface.sendCurrentUserContactChannelVerificationEmail(crud.id, constructRedirectUrl(app.urls.emailVerification), app._getSession());
570
+ await app._interface.sendCurrentUserContactChannelVerificationEmail(crud.id, constructRedirectUrl(app.urls.emailVerification), app._getSession());
569
571
  },
570
572
  async update(data) {
571
573
  await app._interface.updateClientContactChannel(crud.id, contactChannelUpdateOptionsToCrud(data), app._getSession());
@@ -599,6 +601,31 @@ var _StackClientAppImpl = class __StackClientAppImpl {
599
601
  const tokens = await this.currentSession.getTokens();
600
602
  return tokens;
601
603
  },
604
+ async registerPasskey() {
605
+ const initiationResult = await app._interface.initiatePasskeyRegistration({}, session);
606
+ if (initiationResult.status !== "ok") {
607
+ return Result.error(new KnownErrors.PasskeyRegistrationFailed("Failed to get initiation options for passkey registration"));
608
+ }
609
+ const { options_json, code } = initiationResult.data;
610
+ if (options_json.rp.id !== "THIS_VALUE_WILL_BE_REPLACED.example.com") {
611
+ throw new StackAssertionError(`Expected returned RP ID from server to equal sentinel, but found ${options_json.rp.id}`);
612
+ }
613
+ options_json.rp.id = window.location.hostname;
614
+ let attResp;
615
+ try {
616
+ attResp = await startRegistration({ optionsJSON: options_json });
617
+ debugger;
618
+ } catch (error) {
619
+ if (error instanceof WebAuthnError) {
620
+ return Result.error(new KnownErrors.PasskeyWebAuthnError(error.message, error.name));
621
+ } else {
622
+ return Result.error(new KnownErrors.PasskeyRegistrationFailed("Failed to start passkey registration"));
623
+ }
624
+ }
625
+ const registrationResult = await app._interface.registerPasskey({ credential: attResp, code }, session);
626
+ await app._refreshUser(session);
627
+ return registrationResult;
628
+ },
602
629
  signOut() {
603
630
  return app._signOut(session);
604
631
  }
@@ -621,6 +648,7 @@ var _StackClientAppImpl = class __StackClientAppImpl {
621
648
  emailAuthEnabled: crud.auth_with_email,
622
649
  otpAuthEnabled: crud.otp_auth_enabled,
623
650
  oauthProviders: crud.oauth_providers,
651
+ passkeyAuthEnabled: crud.passkey_auth_enabled,
624
652
  selectedTeam: crud.selected_team && this._clientTeamFromCrud(crud.selected_team),
625
653
  isMultiFactorRequired: crud.requires_totp_mfa,
626
654
  toClientJson() {
@@ -1107,6 +1135,38 @@ var _StackClientAppImpl = class __StackClientAppImpl {
1107
1135
  return Result.error(result.error);
1108
1136
  }
1109
1137
  }
1138
+ async signInWithPasskey() {
1139
+ this._ensurePersistentTokenStore();
1140
+ let result;
1141
+ try {
1142
+ result = await this._catchMfaRequiredError(async () => {
1143
+ const initiationResult = await this._interface.initiatePasskeyAuthentication({}, this._getSession());
1144
+ if (initiationResult.status !== "ok") {
1145
+ return Result.error(new KnownErrors.PasskeyAuthenticationFailed("Failed to get initiation options for passkey authentication"));
1146
+ }
1147
+ const { options_json, code } = initiationResult.data;
1148
+ if (options_json.rpId !== "THIS_VALUE_WILL_BE_REPLACED.example.com") {
1149
+ throw new StackAssertionError(`Expected returned RP ID from server to equal sentinel, but found ${options_json.rpId}`);
1150
+ }
1151
+ options_json.rpId = window.location.hostname;
1152
+ const authentication_response = await startAuthentication({ optionsJSON: options_json });
1153
+ return await this._interface.signInWithPasskey({ authentication_response, code });
1154
+ });
1155
+ } catch (error) {
1156
+ if (error instanceof WebAuthnError) {
1157
+ return Result.error(new KnownErrors.PasskeyWebAuthnError(error.message, error.name));
1158
+ } else {
1159
+ return Result.error(new KnownErrors.PasskeyAuthenticationFailed("Failed to sign in with passkey"));
1160
+ }
1161
+ }
1162
+ if (result.status === "ok") {
1163
+ await this._signInToAccountWithTokens(result.data);
1164
+ await this.redirectToAfterSignIn({ replace: true });
1165
+ return Result.ok(void 0);
1166
+ } else {
1167
+ return Result.error(result.error);
1168
+ }
1169
+ }
1110
1170
  async callOAuthCallback() {
1111
1171
  this._ensurePersistentTokenStore();
1112
1172
  let result;
@@ -1263,8 +1323,8 @@ var _StackServerAppImpl = class extends _StackClientAppImpl {
1263
1323
  this._currentServerUserCache = createCacheBySession(async (session) => {
1264
1324
  return await this._interface.getServerUserByToken(session);
1265
1325
  });
1266
- this._serverUsersCache = createCache(async () => {
1267
- return await this._interface.listServerUsers();
1326
+ this._serverUsersCache = createCache(async ([cursor, limit, orderBy, desc, query]) => {
1327
+ return await this._interface.listServerUsers({ cursor, limit, orderBy, desc, query });
1268
1328
  });
1269
1329
  this._serverUserCache = createCache(async ([userId]) => {
1270
1330
  const user = await this._interface.getServerUserById(userId);
@@ -1339,7 +1399,7 @@ var _StackServerAppImpl = class extends _StackClientAppImpl {
1339
1399
  return {
1340
1400
  ...this._clientContactChannelFromCrud(crud),
1341
1401
  async sendVerificationEmail() {
1342
- return await app._interface.sendServerContactChannelVerificationEmail(userId, crud.id, constructRedirectUrl(app.urls.emailVerification));
1402
+ await app._interface.sendServerContactChannelVerificationEmail(userId, crud.id, constructRedirectUrl(app.urls.emailVerification));
1343
1403
  },
1344
1404
  async update(data) {
1345
1405
  await app._interface.updateServerContactChannel(userId, crud.id, serverContactChannelUpdateOptionsToCrud(data));
@@ -1557,7 +1617,7 @@ var _StackServerAppImpl = class extends _StackClientAppImpl {
1557
1617
  await app._serverTeamMemberProfilesCache.refresh([crud.id]);
1558
1618
  },
1559
1619
  async inviteUser(options) {
1560
- return await app._interface.sendTeamInvitation({
1620
+ await app._interface.sendTeamInvitation({
1561
1621
  teamId: crud.id,
1562
1622
  email: options.email,
1563
1623
  session: null,
@@ -1639,15 +1699,17 @@ var _StackServerAppImpl = class extends _StackClientAppImpl {
1639
1699
  return crud && this._serverUserFromCrud(crud);
1640
1700
  }, [crud]);
1641
1701
  }
1642
- async listUsers() {
1643
- const crud = await this._serverUsersCache.getOrWait([], "write-only");
1644
- return crud.map((j) => this._serverUserFromCrud(j));
1702
+ async listUsers(options) {
1703
+ const crud = await this._serverUsersCache.getOrWait([options?.cursor, options?.limit, options?.orderBy, options?.desc, options?.query], "write-only");
1704
+ const result = crud.items.map((j) => this._serverUserFromCrud(j));
1705
+ result.nextCursor = crud.pagination?.next_cursor ?? null;
1706
+ return result;
1645
1707
  }
1646
- useUsers() {
1647
- const crud = useAsyncCache(this._serverUsersCache, [], "useServerUsers()");
1648
- return useMemo(() => {
1649
- return crud.map((j) => this._serverUserFromCrud(j));
1650
- }, [crud]);
1708
+ useUsers(options) {
1709
+ const crud = useAsyncCache(this._serverUsersCache, [options?.cursor, options?.limit, options?.orderBy, options?.desc, options?.query], "useServerUsers()");
1710
+ const result = crud.items.map((j) => this._serverUserFromCrud(j));
1711
+ result.nextCursor = crud.pagination?.next_cursor ?? null;
1712
+ return result;
1651
1713
  }
1652
1714
  _serverPermissionFromCrud(crud) {
1653
1715
  return {
@@ -1761,6 +1823,7 @@ var _StackAdminAppImpl = class extends _StackServerAppImpl {
1761
1823
  signUpEnabled: data.config.sign_up_enabled,
1762
1824
  credentialEnabled: data.config.credential_enabled,
1763
1825
  magicLinkEnabled: data.config.magic_link_enabled,
1826
+ passkeyEnabled: data.config.passkey_enabled,
1764
1827
  legacyGlobalJwtSigning: data.config.legacy_global_jwt_signing,
1765
1828
  clientTeamCreationEnabled: data.config.client_team_creation_enabled,
1766
1829
  clientUserDeletionEnabled: data.config.client_user_deletion_enabled,
@@ -1980,7 +2043,8 @@ function userUpdateOptionsToCrud(options) {
1980
2043
  selected_team_id: options.selectedTeamId,
1981
2044
  totp_secret_base64: options.totpMultiFactorSecret != null ? encodeBase64(options.totpMultiFactorSecret) : options.totpMultiFactorSecret,
1982
2045
  profile_image_url: options.profileImageUrl,
1983
- otp_auth_enabled: options.otpAuthEnabled
2046
+ otp_auth_enabled: options.otpAuthEnabled,
2047
+ passkey_auth_enabled: options.passkeyAuthEnabled
1984
2048
  };
1985
2049
  }
1986
2050
  function serverUserUpdateOptionsToCrud(options) {
@@ -2043,6 +2107,7 @@ function adminProjectUpdateOptionsToCrud(options) {
2043
2107
  sign_up_enabled: options.config?.signUpEnabled,
2044
2108
  credential_enabled: options.config?.credentialEnabled,
2045
2109
  magic_link_enabled: options.config?.magicLinkEnabled,
2110
+ passkey_enabled: options.config?.passkeyEnabled,
2046
2111
  allow_localhost: options.config?.allowLocalhost,
2047
2112
  create_team_on_sign_up: options.config?.createTeamOnSignUp,
2048
2113
  client_team_creation_enabled: options.config?.clientTeamCreationEnabled,