@stackframe/stack 2.8.36 → 2.8.40

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 (48) hide show
  1. package/CHANGELOG.md +40 -0
  2. package/dist/components/user-button.js +2 -2
  3. package/dist/components/user-button.js.map +1 -1
  4. package/dist/esm/components/user-button.js +2 -2
  5. package/dist/esm/components/user-button.js.map +1 -1
  6. package/dist/esm/index.js +3 -1
  7. package/dist/esm/index.js.map +1 -1
  8. package/dist/esm/integrations/convex.js +18 -0
  9. package/dist/esm/integrations/convex.js.map +1 -0
  10. package/dist/esm/lib/stack-app/apps/implementations/admin-app-impl.js +59 -6
  11. package/dist/esm/lib/stack-app/apps/implementations/admin-app-impl.js.map +1 -1
  12. package/dist/esm/lib/stack-app/apps/implementations/client-app-impl.js +140 -3
  13. package/dist/esm/lib/stack-app/apps/implementations/client-app-impl.js.map +1 -1
  14. package/dist/esm/lib/stack-app/apps/implementations/common.js +7 -7
  15. package/dist/esm/lib/stack-app/apps/implementations/common.js.map +1 -1
  16. package/dist/esm/lib/stack-app/apps/implementations/server-app-impl.js +112 -4
  17. package/dist/esm/lib/stack-app/apps/implementations/server-app-impl.js.map +1 -1
  18. package/dist/esm/lib/stack-app/apps/interfaces/admin-app.js.map +1 -1
  19. package/dist/esm/lib/stack-app/apps/interfaces/client-app.js.map +1 -1
  20. package/dist/esm/lib/stack-app/apps/interfaces/server-app.js.map +1 -1
  21. package/dist/esm/lib/stack-app/common.js.map +1 -1
  22. package/dist/esm/lib/stack-app/index.js.map +1 -1
  23. package/dist/esm/lib/stack-app/users/index.js.map +1 -1
  24. package/dist/esm/providers/stack-provider-client.js.map +1 -1
  25. package/dist/index.d.mts +200 -43
  26. package/dist/index.d.ts +200 -43
  27. package/dist/index.js +4 -1
  28. package/dist/index.js.map +1 -1
  29. package/dist/integrations/convex.js +43 -0
  30. package/dist/integrations/convex.js.map +1 -0
  31. package/dist/lib/stack-app/apps/implementations/admin-app-impl.js +58 -5
  32. package/dist/lib/stack-app/apps/implementations/admin-app-impl.js.map +1 -1
  33. package/dist/lib/stack-app/apps/implementations/client-app-impl.js +140 -3
  34. package/dist/lib/stack-app/apps/implementations/client-app-impl.js.map +1 -1
  35. package/dist/lib/stack-app/apps/implementations/common.js +7 -7
  36. package/dist/lib/stack-app/apps/implementations/common.js.map +1 -1
  37. package/dist/lib/stack-app/apps/implementations/server-app-impl.js +111 -3
  38. package/dist/lib/stack-app/apps/implementations/server-app-impl.js.map +1 -1
  39. package/dist/lib/stack-app/apps/interfaces/admin-app.js.map +1 -1
  40. package/dist/lib/stack-app/apps/interfaces/client-app.js.map +1 -1
  41. package/dist/lib/stack-app/apps/interfaces/server-app.js.map +1 -1
  42. package/dist/lib/stack-app/common.js.map +1 -1
  43. package/dist/lib/stack-app/email/index.js.map +1 -1
  44. package/dist/lib/stack-app/index.js.map +1 -1
  45. package/dist/lib/stack-app/project-configs/index.js.map +1 -1
  46. package/dist/lib/stack-app/users/index.js.map +1 -1
  47. package/dist/providers/stack-provider-client.js.map +1 -1
  48. package/package.json +6 -5
@@ -128,6 +128,11 @@ var __StackClientAppImplIncomplete = class __StackClientAppImplIncomplete {
128
128
  return results;
129
129
  }
130
130
  );
131
+ this._currentUserOAuthProvidersCache = createCacheBySession(
132
+ async (session) => {
133
+ return await this._interface.listOAuthProviders({ user_id: "me" }, session);
134
+ }
135
+ );
131
136
  this._userItemCache = createCacheBySession(
132
137
  async (session, [userId, itemId]) => {
133
138
  return await this._interface.getItem({ userId, itemId }, session);
@@ -143,6 +148,9 @@ var __StackClientAppImplIncomplete = class __StackClientAppImplIncomplete {
143
148
  return await this._interface.getItem({ customCustomerId, itemId }, session);
144
149
  }
145
150
  );
151
+ this._convexPartialUserCache = createCache(
152
+ async ([ctx]) => await this._getPartialUserFromConvex(ctx)
153
+ );
146
154
  this._anonymousSignUpInProgress = null;
147
155
  this._memoryTokenStore = createEmptyTokenStore();
148
156
  this._nextServerCookiesTokenStores = /* @__PURE__ */ new WeakMap();
@@ -432,7 +440,8 @@ var __StackClientAppImplIncomplete = class __StackClientAppImplIncomplete {
432
440
  }
433
441
  async _getSession(overrideTokenStoreInit) {
434
442
  const tokenStore = this._getOrCreateTokenStore(await this._createCookieHelper(), overrideTokenStoreInit);
435
- return this._getSessionFromTokenStore(tokenStore);
443
+ const session = this._getSessionFromTokenStore(tokenStore);
444
+ return session;
436
445
  }
437
446
  _useSession(overrideTokenStoreInit) {
438
447
  const tokenStore = this._useTokenStore(overrideTokenStoreInit);
@@ -653,6 +662,41 @@ var __StackClientAppImplIncomplete = class __StackClientAppImplIncomplete {
653
662
  }
654
663
  };
655
664
  }
665
+ _clientOAuthProviderFromCrud(crud, session) {
666
+ const app = this;
667
+ return {
668
+ id: crud.id,
669
+ type: crud.type,
670
+ userId: crud.user_id,
671
+ email: crud.email,
672
+ allowSignIn: crud.allow_sign_in,
673
+ allowConnectedAccounts: crud.allow_connected_accounts,
674
+ async update(data) {
675
+ try {
676
+ await app._interface.updateOAuthProvider(
677
+ crud.user_id,
678
+ crud.id,
679
+ {
680
+ allow_sign_in: data.allowSignIn,
681
+ allow_connected_accounts: data.allowConnectedAccounts
682
+ },
683
+ session
684
+ );
685
+ await app._currentUserOAuthProvidersCache.refresh([session]);
686
+ return Result.ok(void 0);
687
+ } catch (error) {
688
+ if (KnownErrors.OAuthProviderAccountIdAlreadyUsedForSignIn.isInstance(error)) {
689
+ return Result.error(error);
690
+ }
691
+ throw error;
692
+ }
693
+ },
694
+ async delete() {
695
+ await app._interface.deleteOAuthProvider(crud.user_id, crud.id, session);
696
+ await app._currentUserOAuthProvidersCache.refresh([session]);
697
+ }
698
+ };
699
+ }
656
700
  _clientItemFromCrud(crud) {
657
701
  const app = this;
658
702
  return {
@@ -944,6 +988,22 @@ var __StackClientAppImplIncomplete = class __StackClientAppImplIncomplete {
944
988
  );
945
989
  await app._userApiKeysCache.refresh([session]);
946
990
  return app._clientApiKeyFromCrud(session, result);
991
+ },
992
+ useOAuthProviders() {
993
+ const results = useAsyncCache(app._currentUserOAuthProvidersCache, [session], "user.useOAuthProviders()");
994
+ return results.map((crud2) => app._clientOAuthProviderFromCrud(crud2, session));
995
+ },
996
+ async listOAuthProviders() {
997
+ const results = Result.orThrow(await app._currentUserOAuthProvidersCache.getOrWait([session], "write-only"));
998
+ return results.map((crud2) => app._clientOAuthProviderFromCrud(crud2, session));
999
+ },
1000
+ useOAuthProvider(id) {
1001
+ const providers = this.useOAuthProviders();
1002
+ return useMemo(() => providers.find((p) => p.id === id) ?? null, [providers, id]);
1003
+ },
1004
+ async getOAuthProvider(id) {
1005
+ const providers = await this.listOAuthProviders();
1006
+ return providers.find((p) => p.id === id) ?? null;
947
1007
  }
948
1008
  };
949
1009
  }
@@ -1272,12 +1332,89 @@ var __StackClientAppImplIncomplete = class __StackClientAppImplIncomplete {
1272
1332
  return crud && this._currentUserFromCrud(crud, session);
1273
1333
  }, [crud, session, options?.or]);
1274
1334
  }
1335
+ _getTokenPartialUserFromSession(session, options) {
1336
+ const accessToken = session.getAccessTokenIfNotExpiredYet(0);
1337
+ if (!accessToken) {
1338
+ return null;
1339
+ }
1340
+ const isAnonymous = accessToken.payload.is_anonymous;
1341
+ if (isAnonymous && options.or !== "anonymous") {
1342
+ return null;
1343
+ }
1344
+ return {
1345
+ id: accessToken.payload.sub,
1346
+ primaryEmail: accessToken.payload.email,
1347
+ displayName: accessToken.payload.name,
1348
+ primaryEmailVerified: accessToken.payload.email_verified,
1349
+ isAnonymous
1350
+ };
1351
+ }
1352
+ async _getPartialUserFromConvex(ctx) {
1353
+ const auth = await ctx.auth.getUserIdentity();
1354
+ if (!auth) {
1355
+ return null;
1356
+ }
1357
+ return {
1358
+ id: auth.subject,
1359
+ displayName: auth.name ?? null,
1360
+ primaryEmail: auth.email ?? null,
1361
+ primaryEmailVerified: auth.email_verified,
1362
+ isAnonymous: auth.is_anonymous
1363
+ };
1364
+ }
1365
+ async getPartialUser(options) {
1366
+ switch (options.from) {
1367
+ case "token": {
1368
+ this._ensurePersistentTokenStore(options.tokenStore ?? this._tokenStoreInit);
1369
+ const session = await this._getSession(options.tokenStore);
1370
+ return this._getTokenPartialUserFromSession(session, options);
1371
+ }
1372
+ case "convex": {
1373
+ return await this._getPartialUserFromConvex(options.ctx);
1374
+ }
1375
+ default: {
1376
+ throw new Error(`Invalid 'from' option: ${options.from}`);
1377
+ }
1378
+ }
1379
+ }
1380
+ usePartialUser(options) {
1381
+ switch (options.from) {
1382
+ case "token": {
1383
+ this._ensurePersistentTokenStore(options.tokenStore ?? this._tokenStoreInit);
1384
+ const session = this._useSession(options.tokenStore);
1385
+ return this._getTokenPartialUserFromSession(session, options);
1386
+ }
1387
+ case "convex": {
1388
+ const result = useAsyncCache(this._convexPartialUserCache, [options.ctx], "usePartialUser(convex)");
1389
+ return result;
1390
+ }
1391
+ default: {
1392
+ throw new Error(`Invalid 'from' option: ${options.from}`);
1393
+ }
1394
+ }
1395
+ }
1396
+ getConvexClientAuth(options) {
1397
+ return async (args) => {
1398
+ const session = await this._getSession(options.tokenStore);
1399
+ if (!args.forceRefreshToken) {
1400
+ const tokens2 = await session.getOrFetchLikelyValidTokens(2e4);
1401
+ return tokens2?.accessToken.token ?? null;
1402
+ }
1403
+ const tokens = await session.fetchNewTokens();
1404
+ return tokens?.accessToken.token ?? null;
1405
+ };
1406
+ }
1407
+ async getConvexHttpClientAuth(options) {
1408
+ const session = await this._getSession(options.tokenStore);
1409
+ const tokens = await session.getOrFetchLikelyValidTokens(2e4);
1410
+ return tokens?.accessToken.token ?? throwErr("No access token available");
1411
+ }
1275
1412
  async _updateClientUser(update, session) {
1276
1413
  const res = await this._interface.updateClientUser(userUpdateOptionsToCrud(update), session);
1277
1414
  await this._refreshUser(session);
1278
1415
  return res;
1279
1416
  }
1280
- async signInWithOAuth(provider) {
1417
+ async signInWithOAuth(provider, options) {
1281
1418
  if (typeof window === "undefined") {
1282
1419
  throw new Error("signInWithOAuth can currently only be called in a browser environment");
1283
1420
  }
@@ -1287,7 +1424,7 @@ var __StackClientAppImplIncomplete = class __StackClientAppImplIncomplete {
1287
1424
  this._interface,
1288
1425
  {
1289
1426
  provider,
1290
- redirectUrl: this.urls.oauthCallback,
1427
+ redirectUrl: options?.returnTo ?? this.urls.oauthCallback,
1291
1428
  errorRedirectUrl: this.urls.error,
1292
1429
  providerScope: this._oauthScopesOnSignIn[provider]?.join(" ")
1293
1430
  },