@stackframe/react 2.8.41 → 2.8.44

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 (51) hide show
  1. package/CHANGELOG.md +29 -0
  2. package/dist/esm/integrations/convex/component/convex.config.js +8 -0
  3. package/dist/esm/integrations/convex/component/convex.config.js.map +1 -0
  4. package/dist/esm/integrations/convex.js +5 -4
  5. package/dist/esm/integrations/convex.js.map +1 -1
  6. package/dist/esm/lib/hooks.js +3 -0
  7. package/dist/esm/lib/hooks.js.map +1 -1
  8. package/dist/esm/lib/stack-app/apps/implementations/admin-app-impl.js +31 -42
  9. package/dist/esm/lib/stack-app/apps/implementations/admin-app-impl.js.map +1 -1
  10. package/dist/esm/lib/stack-app/apps/implementations/client-app-impl.js +106 -31
  11. package/dist/esm/lib/stack-app/apps/implementations/client-app-impl.js.map +1 -1
  12. package/dist/esm/lib/stack-app/apps/implementations/common.js +16 -2
  13. package/dist/esm/lib/stack-app/apps/implementations/common.js.map +1 -1
  14. package/dist/esm/lib/stack-app/apps/implementations/server-app-impl.js +119 -60
  15. package/dist/esm/lib/stack-app/apps/implementations/server-app-impl.js.map +1 -1
  16. package/dist/esm/lib/stack-app/apps/interfaces/admin-app.js.map +1 -1
  17. package/dist/esm/lib/stack-app/apps/interfaces/client-app.js.map +1 -1
  18. package/dist/esm/lib/stack-app/apps/interfaces/server-app.js.map +1 -1
  19. package/dist/esm/lib/stack-app/projects/index.js.map +1 -1
  20. package/dist/esm/lib/stack-app/users/index.js +16 -0
  21. package/dist/esm/lib/stack-app/users/index.js.map +1 -1
  22. package/dist/esm/providers/stack-provider.js +2 -6
  23. package/dist/esm/providers/stack-provider.js.map +1 -1
  24. package/dist/index.d.mts +86 -23
  25. package/dist/index.d.ts +86 -23
  26. package/dist/integrations/convex/component/convex.config.d.mts +5 -0
  27. package/dist/integrations/convex/component/convex.config.d.ts +5 -0
  28. package/dist/integrations/convex/component/convex.config.js +29 -0
  29. package/dist/integrations/convex/component/convex.config.js.map +1 -0
  30. package/dist/integrations/convex.js +4 -3
  31. package/dist/integrations/convex.js.map +1 -1
  32. package/dist/lib/hooks.js +3 -0
  33. package/dist/lib/hooks.js.map +1 -1
  34. package/dist/lib/stack-app/apps/implementations/admin-app-impl.js +30 -41
  35. package/dist/lib/stack-app/apps/implementations/admin-app-impl.js.map +1 -1
  36. package/dist/lib/stack-app/apps/implementations/client-app-impl.js +104 -29
  37. package/dist/lib/stack-app/apps/implementations/client-app-impl.js.map +1 -1
  38. package/dist/lib/stack-app/apps/implementations/common.js +17 -1
  39. package/dist/lib/stack-app/apps/implementations/common.js.map +1 -1
  40. package/dist/lib/stack-app/apps/implementations/server-app-impl.js +117 -58
  41. package/dist/lib/stack-app/apps/implementations/server-app-impl.js.map +1 -1
  42. package/dist/lib/stack-app/apps/interfaces/admin-app.js.map +1 -1
  43. package/dist/lib/stack-app/apps/interfaces/client-app.js.map +1 -1
  44. package/dist/lib/stack-app/apps/interfaces/server-app.js.map +1 -1
  45. package/dist/lib/stack-app/customers/index.js.map +1 -1
  46. package/dist/lib/stack-app/projects/index.js.map +1 -1
  47. package/dist/lib/stack-app/users/index.js +17 -0
  48. package/dist/lib/stack-app/users/index.js.map +1 -1
  49. package/dist/providers/stack-provider.js +1 -5
  50. package/dist/providers/stack-provider.js.map +1 -1
  51. package/package.json +16 -7
@@ -23,15 +23,14 @@ import { stackAppInternalsSymbol } from "../../common.js";
23
23
  import { contactChannelCreateOptionsToCrud, contactChannelUpdateOptionsToCrud } from "../../contact-channels/index.js";
24
24
  import { adminProjectCreateOptionsToCrud } from "../../projects/index.js";
25
25
  import { teamCreateOptionsToCrud, teamUpdateOptionsToCrud } from "../../teams/index.js";
26
- import { userUpdateOptionsToCrud } from "../../users/index.js";
27
- import { clientVersion, createCache, createCacheBySession, createEmptyTokenStore, getBaseUrl, getDefaultExtraRequestHeaders, getDefaultProjectId, getDefaultPublishableClientKey, getUrls } from "./common.js";
26
+ import { attachUserDestructureGuard, userUpdateOptionsToCrud } from "../../users/index.js";
27
+ import { clientVersion, createCache, createCacheBySession, createEmptyTokenStore, getBaseUrl, getDefaultExtraRequestHeaders, getDefaultProjectId, getDefaultPublishableClientKey, getUrls, resolveConstructorOptions } from "./common.js";
28
28
  import { useAsyncCache } from "./common.js";
29
29
  var isReactServer = false;
30
30
  var process = globalThis.process ?? { env: {} };
31
31
  var allClientApps = /* @__PURE__ */ new Map();
32
32
  var __StackClientAppImplIncomplete = class __StackClientAppImplIncomplete {
33
- constructor(_options) {
34
- this._options = _options;
33
+ constructor(options, extraOptions) {
35
34
  this._uniqueIdentifier = void 0;
36
35
  this.__DEMO_ENABLE_SLIGHT_FETCH_DELAY = false;
37
36
  this._ownedAdminApps = new DependenciesMap();
@@ -77,7 +76,7 @@ var __StackClientAppImplIncomplete = class __StackClientAppImplIncomplete {
77
76
  return await this._getUserOAuthConnectionCacheFn({
78
77
  getUser: async () => Result.orThrow(await this._currentUserCache.getOrWait([session], "write-only")),
79
78
  getOrWaitOAuthToken: async () => Result.orThrow(await this._currentUserOAuthConnectionAccessTokensCache.getOrWait([session, providerId, scope || ""], "write-only")),
80
- useOAuthToken: () => useAsyncCache(this._currentUserOAuthConnectionAccessTokensCache, [session, providerId, scope || ""], "useOAuthToken"),
79
+ useOAuthToken: () => useAsyncCache(this._currentUserOAuthConnectionAccessTokensCache, [session, providerId, scope || ""], "connection.useAccessToken()"),
81
80
  providerId,
82
81
  scope,
83
82
  redirect,
@@ -143,6 +142,36 @@ var __StackClientAppImplIncomplete = class __StackClientAppImplIncomplete {
143
142
  return await this._interface.getItem({ customCustomerId, itemId }, session);
144
143
  }
145
144
  );
145
+ this._userProductsCache = createCacheBySession(
146
+ async (session, [userId, cursor, limit]) => {
147
+ return await this._interface.listProducts({
148
+ customer_type: "user",
149
+ customer_id: userId,
150
+ cursor: cursor ?? void 0,
151
+ limit: limit ?? void 0
152
+ }, session);
153
+ }
154
+ );
155
+ this._teamProductsCache = createCacheBySession(
156
+ async (session, [teamId, cursor, limit]) => {
157
+ return await this._interface.listProducts({
158
+ customer_type: "team",
159
+ customer_id: teamId,
160
+ cursor: cursor ?? void 0,
161
+ limit: limit ?? void 0
162
+ }, session);
163
+ }
164
+ );
165
+ this._customProductsCache = createCacheBySession(
166
+ async (session, [customCustomerId, cursor, limit]) => {
167
+ return await this._interface.listProducts({
168
+ customer_type: "custom",
169
+ customer_id: customCustomerId,
170
+ cursor: cursor ?? void 0,
171
+ limit: limit ?? void 0
172
+ }, session);
173
+ }
174
+ );
146
175
  this._convexPartialUserCache = createCache(
147
176
  async ([ctx]) => await this._getPartialUserFromConvex(ctx)
148
177
  );
@@ -160,28 +189,31 @@ var __StackClientAppImplIncomplete = class __StackClientAppImplIncomplete {
160
189
  * - So different token stores are separated and don't leak information between each other, eg. if the same user sends two requests to the same server they should get a different session object
161
190
  */
162
191
  this._sessionsByTokenStoreAndSessionKey = /* @__PURE__ */ new WeakMap();
192
+ const resolvedOptions = resolveConstructorOptions(options);
163
193
  if (!__StackClientAppImplIncomplete.LazyStackAdminAppImpl.value) {
164
194
  throw new StackAssertionError("Admin app implementation not initialized. Did you import the _StackClientApp from stack-app/apps/implementations/index.ts? You can't import it directly from ./apps/implementations/client-app-impl.ts as that causes a circular dependency (see the comment at _LazyStackAdminAppImpl for more details).");
165
195
  }
166
- if ("interface" in _options) {
167
- this._interface = _options.interface;
196
+ this._options = resolvedOptions;
197
+ this._extraOptions = extraOptions;
198
+ if (extraOptions && extraOptions.interface) {
199
+ this._interface = extraOptions.interface;
168
200
  } else {
169
201
  this._interface = new StackClientInterface({
170
- getBaseUrl: () => getBaseUrl(_options.baseUrl),
171
- extraRequestHeaders: _options.extraRequestHeaders ?? getDefaultExtraRequestHeaders(),
172
- projectId: _options.projectId ?? getDefaultProjectId(),
202
+ getBaseUrl: () => getBaseUrl(resolvedOptions.baseUrl),
203
+ extraRequestHeaders: resolvedOptions.extraRequestHeaders ?? getDefaultExtraRequestHeaders(),
204
+ projectId: resolvedOptions.projectId ?? getDefaultProjectId(),
173
205
  clientVersion,
174
- publishableClientKey: _options.publishableClientKey ?? getDefaultPublishableClientKey(),
206
+ publishableClientKey: resolvedOptions.publishableClientKey ?? getDefaultPublishableClientKey(),
175
207
  prepareRequest: async () => {
176
208
  }
177
209
  });
178
210
  }
179
- this._tokenStoreInit = _options.tokenStore;
180
- this._redirectMethod = _options.redirectMethod || "none";
181
- this._urlOptions = _options.urls ?? {};
182
- this._oauthScopesOnSignIn = _options.oauthScopesOnSignIn ?? {};
183
- if (_options.uniqueIdentifier) {
184
- this._uniqueIdentifier = _options.uniqueIdentifier;
211
+ this._tokenStoreInit = resolvedOptions.tokenStore;
212
+ this._redirectMethod = resolvedOptions.redirectMethod || "none";
213
+ this._urlOptions = resolvedOptions.urls ?? {};
214
+ this._oauthScopesOnSignIn = resolvedOptions.oauthScopesOnSignIn ?? {};
215
+ if (extraOptions && extraOptions.uniqueIdentifier) {
216
+ this._uniqueIdentifier = extraOptions.uniqueIdentifier;
185
217
  this._initUniqueIdentifier();
186
218
  }
187
219
  }
@@ -249,7 +281,7 @@ var __StackClientAppImplIncomplete = class __StackClientAppImplIncomplete {
249
281
  if (allClientApps.has(this._uniqueIdentifier)) {
250
282
  throw new StackAssertionError("A Stack client app with the same unique identifier already exists");
251
283
  }
252
- allClientApps.set(this._uniqueIdentifier, [this._options.checkString ?? void 0, this]);
284
+ allClientApps.set(this._uniqueIdentifier, [this._extraOptions?.checkString ?? void 0, this]);
253
285
  }
254
286
  /**
255
287
  * Cloudflare workers does not allow use of randomness on the global scope (on which the Stack app is probably
@@ -698,6 +730,17 @@ var __StackClientAppImplIncomplete = class __StackClientAppImplIncomplete {
698
730
  nonNegativeQuantity: Math.max(0, crud.quantity)
699
731
  };
700
732
  }
733
+ _customerProductsFromResponse(response) {
734
+ const products = response.items.map((item) => ({
735
+ id: item.id,
736
+ quantity: item.quantity,
737
+ displayName: item.product.display_name,
738
+ customerType: item.product.customer_type,
739
+ isServerOnly: item.product.server_only,
740
+ stackable: item.product.stackable
741
+ }));
742
+ return Object.assign(products, { nextCursor: response.pagination.next_cursor ?? null });
743
+ }
701
744
  _createAuth(session) {
702
745
  const app = this;
703
746
  return {
@@ -1007,6 +1050,10 @@ var __StackClientAppImplIncomplete = class __StackClientAppImplIncomplete {
1007
1050
  createProject(newProject) {
1008
1051
  return app._createProject(session, newProject);
1009
1052
  },
1053
+ async transferProject(projectIdToTransfer, newTeamId) {
1054
+ await app._interface.transferProject(session, projectIdToTransfer, newTeamId);
1055
+ await app._refreshProject();
1056
+ },
1010
1057
  listOwnedProjects() {
1011
1058
  return app._listOwnedProjects(session);
1012
1059
  },
@@ -1017,18 +1064,22 @@ var __StackClientAppImplIncomplete = class __StackClientAppImplIncomplete {
1017
1064
  }
1018
1065
  _createCustomer(userIdOrTeamId, type, session) {
1019
1066
  const app = this;
1020
- const cache = type === "user" ? app._userItemCache : app._teamItemCache;
1067
+ const customerOptions = type === "user" ? { userId: userIdOrTeamId } : { teamId: userIdOrTeamId };
1021
1068
  return {
1022
1069
  async getItem(itemId) {
1023
- const result = Result.orThrow(await cache.getOrWait([session, userIdOrTeamId, itemId], "write-only"));
1024
- return app._clientItemFromCrud(result);
1070
+ return await app.getItem({ itemId, ...customerOptions });
1025
1071
  },
1026
1072
  useItem(itemId) {
1027
- const result = useAsyncCache(cache, [session, userIdOrTeamId, itemId], "team.useItem()");
1028
- return app._clientItemFromCrud(result);
1073
+ return app.useItem({ itemId, ...customerOptions });
1074
+ },
1075
+ async listProducts(options) {
1076
+ return await app.listProducts({ ...options, ...customerOptions });
1077
+ },
1078
+ useProducts(options) {
1079
+ return app.useProducts({ ...options, ...customerOptions });
1029
1080
  },
1030
1081
  async createCheckoutUrl(options) {
1031
- return await app._interface.createCheckoutUrl(type, userIdOrTeamId, options.offerId, session);
1082
+ return await app._interface.createCheckoutUrl(type, userIdOrTeamId, options.productId, session, options.returnUrl);
1032
1083
  }
1033
1084
  };
1034
1085
  }
@@ -1050,6 +1101,26 @@ var __StackClientAppImplIncomplete = class __StackClientAppImplIncomplete {
1050
1101
  const crud = useAsyncCache(cache, [session, ownerId, options.itemId], "app.useItem()");
1051
1102
  return this._clientItemFromCrud(crud);
1052
1103
  }
1104
+ async listProducts(options) {
1105
+ const session = await this._getSession();
1106
+ if ("userId" in options) {
1107
+ const response2 = Result.orThrow(await this._userProductsCache.getOrWait([session, options.userId, options.cursor ?? null, options.limit ?? null], "write-only"));
1108
+ return this._customerProductsFromResponse(response2);
1109
+ } else if ("teamId" in options) {
1110
+ const response2 = Result.orThrow(await this._teamProductsCache.getOrWait([session, options.teamId, options.cursor ?? null, options.limit ?? null], "write-only"));
1111
+ return this._customerProductsFromResponse(response2);
1112
+ }
1113
+ const response = Result.orThrow(await this._customProductsCache.getOrWait([session, options.customCustomerId, options.cursor ?? null, options.limit ?? null], "write-only"));
1114
+ return this._customerProductsFromResponse(response);
1115
+ }
1116
+ useProducts(options) {
1117
+ const session = this._useSession();
1118
+ const cache = "userId" in options ? this._userProductsCache : "teamId" in options ? this._teamProductsCache : this._customProductsCache;
1119
+ const debugLabel = "clientApp.useProducts()";
1120
+ const customerId = "userId" in options ? options.userId : "teamId" in options ? options.teamId : options.customCustomerId;
1121
+ const response = useAsyncCache(cache, [session, customerId, options.cursor ?? null, options.limit ?? null], debugLabel);
1122
+ return this._customerProductsFromResponse(response);
1123
+ }
1053
1124
  _currentUserFromCrud(crud, session) {
1054
1125
  const currentUser = {
1055
1126
  ...this._createBaseUser(crud),
@@ -1058,6 +1129,7 @@ var __StackClientAppImplIncomplete = class __StackClientAppImplIncomplete {
1058
1129
  ...this._isInternalProject() ? this._createInternalUserExtra(session) : {},
1059
1130
  ...this._createCustomer(crud.id, "user", session)
1060
1131
  };
1132
+ attachUserDestructureGuard(currentUser);
1061
1133
  Object.freeze(currentUser);
1062
1134
  return currentUser;
1063
1135
  }
@@ -1286,7 +1358,7 @@ var __StackClientAppImplIncomplete = class __StackClientAppImplIncomplete {
1286
1358
  useUser(options) {
1287
1359
  this._ensurePersistentTokenStore(options?.tokenStore);
1288
1360
  const session = this._useSession(options?.tokenStore);
1289
- let crud = useAsyncCache(this._currentUserCache, [session], "useUser()");
1361
+ let crud = useAsyncCache(this._currentUserCache, [session], "clientApp.useUser()");
1290
1362
  if (crud?.is_anonymous && options?.or !== "anonymous" && options?.or !== "anonymous-if-exists[deprecated]") {
1291
1363
  crud = null;
1292
1364
  }
@@ -1373,7 +1445,7 @@ var __StackClientAppImplIncomplete = class __StackClientAppImplIncomplete {
1373
1445
  return this._getTokenPartialUserFromSession(session, options);
1374
1446
  }
1375
1447
  case "convex": {
1376
- const result = useAsyncCache(this._convexPartialUserCache, [options.ctx], "usePartialUser(convex)");
1448
+ const result = useAsyncCache(this._convexPartialUserCache, [options.ctx], "clientApp.usePartialUser()");
1377
1449
  return result;
1378
1450
  }
1379
1451
  default: {
@@ -1383,7 +1455,7 @@ var __StackClientAppImplIncomplete = class __StackClientAppImplIncomplete {
1383
1455
  }
1384
1456
  getConvexClientAuth(options) {
1385
1457
  return async (args) => {
1386
- const session = await this._getSession(options.tokenStore);
1458
+ const session = await this._getSession(options.tokenStore ?? this._tokenStoreInit);
1387
1459
  if (!args.forceRefreshToken) {
1388
1460
  const tokens2 = await session.getOrFetchLikelyValidTokens(2e4);
1389
1461
  return tokens2?.accessToken.token ?? null;
@@ -1395,7 +1467,7 @@ var __StackClientAppImplIncomplete = class __StackClientAppImplIncomplete {
1395
1467
  async getConvexHttpClientAuth(options) {
1396
1468
  const session = await this._getSession(options.tokenStore);
1397
1469
  const tokens = await session.getOrFetchLikelyValidTokens(2e4);
1398
- return tokens?.accessToken.token ?? throwErr("No access token available");
1470
+ return tokens?.accessToken.token ?? "";
1399
1471
  }
1400
1472
  async _updateClientUser(update, session) {
1401
1473
  const res = await this._interface.updateClientUser(userUpdateOptionsToCrud(update), session);
@@ -1733,7 +1805,7 @@ ${url}`);
1733
1805
  return this._clientProjectFromCrud(crud);
1734
1806
  }
1735
1807
  useProject() {
1736
- const crud = useAsyncCache(this._currentProjectCache, [], "useProject()");
1808
+ const crud = useAsyncCache(this._currentProjectCache, [], "clientApp.useProject()");
1737
1809
  return useMemo(() => this._clientProjectFromCrud(crud), [crud]);
1738
1810
  }
1739
1811
  async _listOwnedProjects(session) {
@@ -1746,7 +1818,7 @@ ${url}`);
1746
1818
  }
1747
1819
  _useOwnedProjects(session) {
1748
1820
  this._ensureInternalProject();
1749
- const projects = useAsyncCache(this._ownedProjectsCache, [session], "useOwnedProjects()");
1821
+ const projects = useAsyncCache(this._ownedProjectsCache, [session], "clientApp.useOwnedProjects()");
1750
1822
  return useMemo(() => projects.map((j) => this._getOwnedAdminApp(j.id, session)._adminOwnedProjectFromCrud(
1751
1823
  j,
1752
1824
  () => this._refreshOwnedProjects(session)
@@ -1791,7 +1863,9 @@ ${url}`);
1791
1863
  return clientApp;
1792
1864
  }
1793
1865
  return new __StackClientAppImplIncomplete({
1794
- ...json,
1866
+ ...omit(json, ["uniqueIdentifier"])
1867
+ }, {
1868
+ uniqueIdentifier: json.uniqueIdentifier,
1795
1869
  checkString: providedCheckString
1796
1870
  });
1797
1871
  }
@@ -1823,6 +1897,7 @@ ${url}`);
1823
1897
  await this._currentUserCache.forceSetCachedValueAsync([await this._getSession()], Result.fromPromise(userJsonPromise));
1824
1898
  });
1825
1899
  },
1900
+ getConstructorOptions: () => this._options,
1826
1901
  sendRequest: async (path, requestOptions, requestType = "client") => {
1827
1902
  return await this._interface.sendClientRequest(path, requestOptions, await this._getSession(), requestType);
1828
1903
  }