@stackframe/stack 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 +107 -32
  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 +105 -30
  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 +19 -10
@@ -25,8 +25,8 @@ import { stackAppInternalsSymbol } from "../../common.js";
25
25
  import { contactChannelCreateOptionsToCrud, contactChannelUpdateOptionsToCrud } from "../../contact-channels/index.js";
26
26
  import { adminProjectCreateOptionsToCrud } from "../../projects/index.js";
27
27
  import { teamCreateOptionsToCrud, teamUpdateOptionsToCrud } from "../../teams/index.js";
28
- import { userUpdateOptionsToCrud } from "../../users/index.js";
29
- import { clientVersion, createCache, createCacheBySession, createEmptyTokenStore, getBaseUrl, getDefaultExtraRequestHeaders, getDefaultProjectId, getDefaultPublishableClientKey, getUrls } from "./common.js";
28
+ import { attachUserDestructureGuard, userUpdateOptionsToCrud } from "../../users/index.js";
29
+ import { clientVersion, createCache, createCacheBySession, createEmptyTokenStore, getBaseUrl, getDefaultExtraRequestHeaders, getDefaultProjectId, getDefaultPublishableClientKey, getUrls, resolveConstructorOptions } from "./common.js";
30
30
  import { useAsyncCache } from "./common.js";
31
31
  import * as sc from "@stackframe/stack-sc";
32
32
  import { cookies } from "@stackframe/stack-sc";
@@ -35,8 +35,7 @@ isReactServer2 = sc.isReactServer;
35
35
  var NextNavigation = scrambleDuringCompileTime(NextNavigationUnscrambled);
36
36
  var allClientApps = /* @__PURE__ */ new Map();
37
37
  var __StackClientAppImplIncomplete = class __StackClientAppImplIncomplete {
38
- constructor(_options) {
39
- this._options = _options;
38
+ constructor(options, extraOptions) {
40
39
  this._uniqueIdentifier = void 0;
41
40
  this.__DEMO_ENABLE_SLIGHT_FETCH_DELAY = false;
42
41
  this._ownedAdminApps = new DependenciesMap();
@@ -82,7 +81,7 @@ var __StackClientAppImplIncomplete = class __StackClientAppImplIncomplete {
82
81
  return await this._getUserOAuthConnectionCacheFn({
83
82
  getUser: async () => Result.orThrow(await this._currentUserCache.getOrWait([session], "write-only")),
84
83
  getOrWaitOAuthToken: async () => Result.orThrow(await this._currentUserOAuthConnectionAccessTokensCache.getOrWait([session, providerId, scope || ""], "write-only")),
85
- useOAuthToken: () => useAsyncCache(this._currentUserOAuthConnectionAccessTokensCache, [session, providerId, scope || ""], "useOAuthToken"),
84
+ useOAuthToken: () => useAsyncCache(this._currentUserOAuthConnectionAccessTokensCache, [session, providerId, scope || ""], "connection.useAccessToken()"),
86
85
  providerId,
87
86
  scope,
88
87
  redirect,
@@ -148,6 +147,36 @@ var __StackClientAppImplIncomplete = class __StackClientAppImplIncomplete {
148
147
  return await this._interface.getItem({ customCustomerId, itemId }, session);
149
148
  }
150
149
  );
150
+ this._userProductsCache = createCacheBySession(
151
+ async (session, [userId, cursor, limit]) => {
152
+ return await this._interface.listProducts({
153
+ customer_type: "user",
154
+ customer_id: userId,
155
+ cursor: cursor ?? void 0,
156
+ limit: limit ?? void 0
157
+ }, session);
158
+ }
159
+ );
160
+ this._teamProductsCache = createCacheBySession(
161
+ async (session, [teamId, cursor, limit]) => {
162
+ return await this._interface.listProducts({
163
+ customer_type: "team",
164
+ customer_id: teamId,
165
+ cursor: cursor ?? void 0,
166
+ limit: limit ?? void 0
167
+ }, session);
168
+ }
169
+ );
170
+ this._customProductsCache = createCacheBySession(
171
+ async (session, [customCustomerId, cursor, limit]) => {
172
+ return await this._interface.listProducts({
173
+ customer_type: "custom",
174
+ customer_id: customCustomerId,
175
+ cursor: cursor ?? void 0,
176
+ limit: limit ?? void 0
177
+ }, session);
178
+ }
179
+ );
151
180
  this._convexPartialUserCache = createCache(
152
181
  async ([ctx]) => await this._getPartialUserFromConvex(ctx)
153
182
  );
@@ -165,30 +194,33 @@ var __StackClientAppImplIncomplete = class __StackClientAppImplIncomplete {
165
194
  * - 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
166
195
  */
167
196
  this._sessionsByTokenStoreAndSessionKey = /* @__PURE__ */ new WeakMap();
197
+ const resolvedOptions = resolveConstructorOptions(options);
168
198
  if (!__StackClientAppImplIncomplete.LazyStackAdminAppImpl.value) {
169
199
  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).");
170
200
  }
171
- if ("interface" in _options) {
172
- this._interface = _options.interface;
201
+ this._options = resolvedOptions;
202
+ this._extraOptions = extraOptions;
203
+ if (extraOptions && extraOptions.interface) {
204
+ this._interface = extraOptions.interface;
173
205
  } else {
174
206
  this._interface = new StackClientInterface({
175
- getBaseUrl: () => getBaseUrl(_options.baseUrl),
176
- extraRequestHeaders: _options.extraRequestHeaders ?? getDefaultExtraRequestHeaders(),
177
- projectId: _options.projectId ?? getDefaultProjectId(),
207
+ getBaseUrl: () => getBaseUrl(resolvedOptions.baseUrl),
208
+ extraRequestHeaders: resolvedOptions.extraRequestHeaders ?? getDefaultExtraRequestHeaders(),
209
+ projectId: resolvedOptions.projectId ?? getDefaultProjectId(),
178
210
  clientVersion,
179
- publishableClientKey: _options.publishableClientKey ?? getDefaultPublishableClientKey(),
211
+ publishableClientKey: resolvedOptions.publishableClientKey ?? getDefaultPublishableClientKey(),
180
212
  prepareRequest: async () => {
181
213
  await cookies?.();
182
214
  }
183
215
  });
184
216
  }
185
- this._tokenStoreInit = _options.tokenStore;
186
- this._redirectMethod = _options.redirectMethod || "none";
187
- this._redirectMethod = _options.redirectMethod || "nextjs";
188
- this._urlOptions = _options.urls ?? {};
189
- this._oauthScopesOnSignIn = _options.oauthScopesOnSignIn ?? {};
190
- if (_options.uniqueIdentifier) {
191
- this._uniqueIdentifier = _options.uniqueIdentifier;
217
+ this._tokenStoreInit = resolvedOptions.tokenStore;
218
+ this._redirectMethod = resolvedOptions.redirectMethod || "none";
219
+ this._redirectMethod = resolvedOptions.redirectMethod || "nextjs";
220
+ this._urlOptions = resolvedOptions.urls ?? {};
221
+ this._oauthScopesOnSignIn = resolvedOptions.oauthScopesOnSignIn ?? {};
222
+ if (extraOptions && extraOptions.uniqueIdentifier) {
223
+ this._uniqueIdentifier = extraOptions.uniqueIdentifier;
192
224
  this._initUniqueIdentifier();
193
225
  }
194
226
  }
@@ -256,7 +288,7 @@ var __StackClientAppImplIncomplete = class __StackClientAppImplIncomplete {
256
288
  if (allClientApps.has(this._uniqueIdentifier)) {
257
289
  throw new StackAssertionError("A Stack client app with the same unique identifier already exists");
258
290
  }
259
- allClientApps.set(this._uniqueIdentifier, [this._options.checkString ?? void 0, this]);
291
+ allClientApps.set(this._uniqueIdentifier, [this._extraOptions?.checkString ?? void 0, this]);
260
292
  }
261
293
  /**
262
294
  * Cloudflare workers does not allow use of randomness on the global scope (on which the Stack app is probably
@@ -705,6 +737,17 @@ var __StackClientAppImplIncomplete = class __StackClientAppImplIncomplete {
705
737
  nonNegativeQuantity: Math.max(0, crud.quantity)
706
738
  };
707
739
  }
740
+ _customerProductsFromResponse(response) {
741
+ const products = response.items.map((item) => ({
742
+ id: item.id,
743
+ quantity: item.quantity,
744
+ displayName: item.product.display_name,
745
+ customerType: item.product.customer_type,
746
+ isServerOnly: item.product.server_only,
747
+ stackable: item.product.stackable
748
+ }));
749
+ return Object.assign(products, { nextCursor: response.pagination.next_cursor ?? null });
750
+ }
708
751
  _createAuth(session) {
709
752
  const app = this;
710
753
  return {
@@ -1014,6 +1057,10 @@ var __StackClientAppImplIncomplete = class __StackClientAppImplIncomplete {
1014
1057
  createProject(newProject) {
1015
1058
  return app._createProject(session, newProject);
1016
1059
  },
1060
+ async transferProject(projectIdToTransfer, newTeamId) {
1061
+ await app._interface.transferProject(session, projectIdToTransfer, newTeamId);
1062
+ await app._refreshProject();
1063
+ },
1017
1064
  listOwnedProjects() {
1018
1065
  return app._listOwnedProjects(session);
1019
1066
  },
@@ -1024,18 +1071,22 @@ var __StackClientAppImplIncomplete = class __StackClientAppImplIncomplete {
1024
1071
  }
1025
1072
  _createCustomer(userIdOrTeamId, type, session) {
1026
1073
  const app = this;
1027
- const cache = type === "user" ? app._userItemCache : app._teamItemCache;
1074
+ const customerOptions = type === "user" ? { userId: userIdOrTeamId } : { teamId: userIdOrTeamId };
1028
1075
  return {
1029
1076
  async getItem(itemId) {
1030
- const result = Result.orThrow(await cache.getOrWait([session, userIdOrTeamId, itemId], "write-only"));
1031
- return app._clientItemFromCrud(result);
1077
+ return await app.getItem({ itemId, ...customerOptions });
1032
1078
  },
1033
1079
  useItem(itemId) {
1034
- const result = useAsyncCache(cache, [session, userIdOrTeamId, itemId], "team.useItem()");
1035
- return app._clientItemFromCrud(result);
1080
+ return app.useItem({ itemId, ...customerOptions });
1081
+ },
1082
+ async listProducts(options) {
1083
+ return await app.listProducts({ ...options, ...customerOptions });
1084
+ },
1085
+ useProducts(options) {
1086
+ return app.useProducts({ ...options, ...customerOptions });
1036
1087
  },
1037
1088
  async createCheckoutUrl(options) {
1038
- return await app._interface.createCheckoutUrl(type, userIdOrTeamId, options.offerId, session);
1089
+ return await app._interface.createCheckoutUrl(type, userIdOrTeamId, options.productId, session, options.returnUrl);
1039
1090
  }
1040
1091
  };
1041
1092
  }
@@ -1057,6 +1108,26 @@ var __StackClientAppImplIncomplete = class __StackClientAppImplIncomplete {
1057
1108
  const crud = useAsyncCache(cache, [session, ownerId, options.itemId], "app.useItem()");
1058
1109
  return this._clientItemFromCrud(crud);
1059
1110
  }
1111
+ async listProducts(options) {
1112
+ const session = await this._getSession();
1113
+ if ("userId" in options) {
1114
+ const response2 = Result.orThrow(await this._userProductsCache.getOrWait([session, options.userId, options.cursor ?? null, options.limit ?? null], "write-only"));
1115
+ return this._customerProductsFromResponse(response2);
1116
+ } else if ("teamId" in options) {
1117
+ const response2 = Result.orThrow(await this._teamProductsCache.getOrWait([session, options.teamId, options.cursor ?? null, options.limit ?? null], "write-only"));
1118
+ return this._customerProductsFromResponse(response2);
1119
+ }
1120
+ const response = Result.orThrow(await this._customProductsCache.getOrWait([session, options.customCustomerId, options.cursor ?? null, options.limit ?? null], "write-only"));
1121
+ return this._customerProductsFromResponse(response);
1122
+ }
1123
+ useProducts(options) {
1124
+ const session = this._useSession();
1125
+ const cache = "userId" in options ? this._userProductsCache : "teamId" in options ? this._teamProductsCache : this._customProductsCache;
1126
+ const debugLabel = "clientApp.useProducts()";
1127
+ const customerId = "userId" in options ? options.userId : "teamId" in options ? options.teamId : options.customCustomerId;
1128
+ const response = useAsyncCache(cache, [session, customerId, options.cursor ?? null, options.limit ?? null], debugLabel);
1129
+ return this._customerProductsFromResponse(response);
1130
+ }
1060
1131
  _currentUserFromCrud(crud, session) {
1061
1132
  const currentUser = {
1062
1133
  ...this._createBaseUser(crud),
@@ -1065,6 +1136,7 @@ var __StackClientAppImplIncomplete = class __StackClientAppImplIncomplete {
1065
1136
  ...this._isInternalProject() ? this._createInternalUserExtra(session) : {},
1066
1137
  ...this._createCustomer(crud.id, "user", session)
1067
1138
  };
1139
+ attachUserDestructureGuard(currentUser);
1068
1140
  Object.freeze(currentUser);
1069
1141
  return currentUser;
1070
1142
  }
@@ -1298,7 +1370,7 @@ var __StackClientAppImplIncomplete = class __StackClientAppImplIncomplete {
1298
1370
  useUser(options) {
1299
1371
  this._ensurePersistentTokenStore(options?.tokenStore);
1300
1372
  const session = this._useSession(options?.tokenStore);
1301
- let crud = useAsyncCache(this._currentUserCache, [session], "useUser()");
1373
+ let crud = useAsyncCache(this._currentUserCache, [session], "clientApp.useUser()");
1302
1374
  if (crud?.is_anonymous && options?.or !== "anonymous" && options?.or !== "anonymous-if-exists[deprecated]") {
1303
1375
  crud = null;
1304
1376
  }
@@ -1385,7 +1457,7 @@ var __StackClientAppImplIncomplete = class __StackClientAppImplIncomplete {
1385
1457
  return this._getTokenPartialUserFromSession(session, options);
1386
1458
  }
1387
1459
  case "convex": {
1388
- const result = useAsyncCache(this._convexPartialUserCache, [options.ctx], "usePartialUser(convex)");
1460
+ const result = useAsyncCache(this._convexPartialUserCache, [options.ctx], "clientApp.usePartialUser()");
1389
1461
  return result;
1390
1462
  }
1391
1463
  default: {
@@ -1395,7 +1467,7 @@ var __StackClientAppImplIncomplete = class __StackClientAppImplIncomplete {
1395
1467
  }
1396
1468
  getConvexClientAuth(options) {
1397
1469
  return async (args) => {
1398
- const session = await this._getSession(options.tokenStore);
1470
+ const session = await this._getSession(options.tokenStore ?? this._tokenStoreInit);
1399
1471
  if (!args.forceRefreshToken) {
1400
1472
  const tokens2 = await session.getOrFetchLikelyValidTokens(2e4);
1401
1473
  return tokens2?.accessToken.token ?? null;
@@ -1407,7 +1479,7 @@ var __StackClientAppImplIncomplete = class __StackClientAppImplIncomplete {
1407
1479
  async getConvexHttpClientAuth(options) {
1408
1480
  const session = await this._getSession(options.tokenStore);
1409
1481
  const tokens = await session.getOrFetchLikelyValidTokens(2e4);
1410
- return tokens?.accessToken.token ?? throwErr("No access token available");
1482
+ return tokens?.accessToken.token ?? "";
1411
1483
  }
1412
1484
  async _updateClientUser(update, session) {
1413
1485
  const res = await this._interface.updateClientUser(userUpdateOptionsToCrud(update), session);
@@ -1745,7 +1817,7 @@ ${url}`);
1745
1817
  return this._clientProjectFromCrud(crud);
1746
1818
  }
1747
1819
  useProject() {
1748
- const crud = useAsyncCache(this._currentProjectCache, [], "useProject()");
1820
+ const crud = useAsyncCache(this._currentProjectCache, [], "clientApp.useProject()");
1749
1821
  return useMemo(() => this._clientProjectFromCrud(crud), [crud]);
1750
1822
  }
1751
1823
  async _listOwnedProjects(session) {
@@ -1758,7 +1830,7 @@ ${url}`);
1758
1830
  }
1759
1831
  _useOwnedProjects(session) {
1760
1832
  this._ensureInternalProject();
1761
- const projects = useAsyncCache(this._ownedProjectsCache, [session], "useOwnedProjects()");
1833
+ const projects = useAsyncCache(this._ownedProjectsCache, [session], "clientApp.useOwnedProjects()");
1762
1834
  return useMemo(() => projects.map((j) => this._getOwnedAdminApp(j.id, session)._adminOwnedProjectFromCrud(
1763
1835
  j,
1764
1836
  () => this._refreshOwnedProjects(session)
@@ -1803,7 +1875,9 @@ ${url}`);
1803
1875
  return clientApp;
1804
1876
  }
1805
1877
  return new __StackClientAppImplIncomplete({
1806
- ...json,
1878
+ ...omit(json, ["uniqueIdentifier"])
1879
+ }, {
1880
+ uniqueIdentifier: json.uniqueIdentifier,
1807
1881
  checkString: providedCheckString
1808
1882
  });
1809
1883
  }
@@ -1835,6 +1909,7 @@ ${url}`);
1835
1909
  await this._currentUserCache.forceSetCachedValueAsync([await this._getSession()], Result.fromPromise(userJsonPromise));
1836
1910
  });
1837
1911
  },
1912
+ getConstructorOptions: () => this._options,
1838
1913
  sendRequest: async (path, requestOptions, requestType = "client") => {
1839
1914
  return await this._interface.sendClientRequest(path, requestOptions, await this._getSession(), requestType);
1840
1915
  }