@stackframe/stack 2.5.2 → 2.5.3
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.
- package/CHANGELOG.md +10 -0
- package/dist/esm/lib/stack-app.js +125 -129
- package/dist/esm/lib/stack-app.js.map +1 -1
- package/dist/lib/stack-app.js +125 -129
- package/dist/lib/stack-app.js.map +1 -1
- package/package.json +4 -4
package/dist/lib/stack-app.js
CHANGED
|
@@ -59,7 +59,7 @@ var cookie = __toESM(require("cookie"));
|
|
|
59
59
|
var import_sessions = require("@stackframe/stack-shared/dist/sessions");
|
|
60
60
|
var import_strings = require("@stackframe/stack-shared/dist/utils/strings");
|
|
61
61
|
var NextNavigation = (0, import_compile_time.scrambleDuringCompileTime)(NextNavigationUnscrambled);
|
|
62
|
-
var clientVersion = "js @stackframe/stack@2.5.
|
|
62
|
+
var clientVersion = "js @stackframe/stack@2.5.3";
|
|
63
63
|
function permissionDefinitionScopeToType(scope) {
|
|
64
64
|
return { "any-team": "team", "specific-team": "team", "global": "global" }[scope.type];
|
|
65
65
|
}
|
|
@@ -165,6 +165,97 @@ var numberOfAppsCreated = 0;
|
|
|
165
165
|
var _StackClientAppImpl = class __StackClientAppImpl {
|
|
166
166
|
constructor(_options) {
|
|
167
167
|
this._options = _options;
|
|
168
|
+
this._uniqueIdentifier = void 0;
|
|
169
|
+
this.__DEMO_ENABLE_SLIGHT_FETCH_DELAY = false;
|
|
170
|
+
this._currentUserCache = createCacheBySession(async (session) => {
|
|
171
|
+
if (this.__DEMO_ENABLE_SLIGHT_FETCH_DELAY) {
|
|
172
|
+
await (0, import_promises.wait)(2e3);
|
|
173
|
+
}
|
|
174
|
+
const user = await this._interface.getClientUserByToken(session);
|
|
175
|
+
return import_results.Result.or(user, null);
|
|
176
|
+
});
|
|
177
|
+
this._currentProjectCache = createCache(async () => {
|
|
178
|
+
return import_results.Result.orThrow(await this._interface.getClientProject());
|
|
179
|
+
});
|
|
180
|
+
this._ownedProjectsCache = createCacheBySession(async (session) => {
|
|
181
|
+
return await this._interface.listProjects(session);
|
|
182
|
+
});
|
|
183
|
+
this._currentUserPermissionsCache = createCacheBySession(async (session, [teamId, type, direct]) => {
|
|
184
|
+
return await this._interface.listClientUserTeamPermissions({ teamId, type, direct }, session);
|
|
185
|
+
});
|
|
186
|
+
this._currentUserTeamsCache = createCacheBySession(async (session) => {
|
|
187
|
+
return await this._interface.listClientUserTeams(session);
|
|
188
|
+
});
|
|
189
|
+
this._currentUserOAuthConnectionAccessTokensCache = createCacheBySession(
|
|
190
|
+
async (session, [accountId, scope]) => {
|
|
191
|
+
try {
|
|
192
|
+
return await this._interface.getAccessToken(accountId, scope || "", session);
|
|
193
|
+
} catch (err) {
|
|
194
|
+
if (!(err instanceof import_stack_shared.KnownErrors.OAuthConnectionDoesNotHaveRequiredScope || err instanceof import_stack_shared.KnownErrors.OAuthConnectionNotConnectedToUser)) {
|
|
195
|
+
throw err;
|
|
196
|
+
}
|
|
197
|
+
}
|
|
198
|
+
return null;
|
|
199
|
+
}
|
|
200
|
+
);
|
|
201
|
+
this._currentUserOAuthConnectionCache = createCacheBySession(
|
|
202
|
+
async (session, [connectionId, scope, redirect]) => {
|
|
203
|
+
const user = await this._currentUserCache.getOrWait([session], "write-only");
|
|
204
|
+
let hasConnection = true;
|
|
205
|
+
if (!user || !user.oauthProviders.find((p) => p === connectionId)) {
|
|
206
|
+
hasConnection = false;
|
|
207
|
+
}
|
|
208
|
+
const token = await this._currentUserOAuthConnectionAccessTokensCache.getOrWait([session, connectionId, scope || ""], "write-only");
|
|
209
|
+
if (!token) {
|
|
210
|
+
hasConnection = false;
|
|
211
|
+
}
|
|
212
|
+
if (!hasConnection && redirect) {
|
|
213
|
+
await (0, import_auth.addNewOAuthProviderOrScope)(
|
|
214
|
+
this._interface,
|
|
215
|
+
{
|
|
216
|
+
provider: connectionId,
|
|
217
|
+
redirectUrl: this.urls.oauthCallback,
|
|
218
|
+
errorRedirectUrl: this.urls.error,
|
|
219
|
+
providerScope: (0, import_strings.mergeScopeStrings)(scope || "", (this._oauthScopesOnSignIn[connectionId] ?? []).join(" "))
|
|
220
|
+
},
|
|
221
|
+
session
|
|
222
|
+
);
|
|
223
|
+
return await (0, import_promises.neverResolve)();
|
|
224
|
+
} else if (!hasConnection) {
|
|
225
|
+
return null;
|
|
226
|
+
}
|
|
227
|
+
const app = this;
|
|
228
|
+
return {
|
|
229
|
+
id: connectionId,
|
|
230
|
+
async getAccessToken() {
|
|
231
|
+
const result = await app._currentUserOAuthConnectionAccessTokensCache.getOrWait([session, connectionId, scope || ""], "write-only");
|
|
232
|
+
if (!result) {
|
|
233
|
+
throw new import_errors.StackAssertionError("No access token available");
|
|
234
|
+
}
|
|
235
|
+
return result;
|
|
236
|
+
},
|
|
237
|
+
useAccessToken() {
|
|
238
|
+
const result = useAsyncCache(app._currentUserOAuthConnectionAccessTokensCache, [session, connectionId, scope || ""], "oauthAccount.useAccessToken()");
|
|
239
|
+
if (!result) {
|
|
240
|
+
throw new import_errors.StackAssertionError("No access token available");
|
|
241
|
+
}
|
|
242
|
+
return result;
|
|
243
|
+
}
|
|
244
|
+
};
|
|
245
|
+
}
|
|
246
|
+
);
|
|
247
|
+
this._memoryTokenStore = createEmptyTokenStore();
|
|
248
|
+
this._requestTokenStores = /* @__PURE__ */ new WeakMap();
|
|
249
|
+
this._storedCookieTokenStore = null;
|
|
250
|
+
/**
|
|
251
|
+
* A map from token stores and session keys to sessions.
|
|
252
|
+
*
|
|
253
|
+
* This isn't just a map from session keys to sessions for two reasons:
|
|
254
|
+
*
|
|
255
|
+
* - So we can garbage-collect Session objects when the token store is garbage-collected
|
|
256
|
+
* - 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
|
|
257
|
+
*/
|
|
258
|
+
this._sessionsByTokenStoreAndSessionKey = /* @__PURE__ */ new WeakMap();
|
|
168
259
|
if ("interface" in _options) {
|
|
169
260
|
this._interface = _options.interface;
|
|
170
261
|
} else {
|
|
@@ -187,89 +278,6 @@ var _StackClientAppImpl = class __StackClientAppImpl {
|
|
|
187
278
|
(process.env.NODE_ENV === "development" ? console.log : console.warn)(`You have created more than 10 Stack apps (${numberOfAppsCreated}). This is usually a sign of a memory leak, but can sometimes be caused by hot reload of your tech stack. In production, make sure to minimize the number of Stack apps per page (usually, one per project).`);
|
|
188
279
|
}
|
|
189
280
|
}
|
|
190
|
-
_uniqueIdentifier = void 0;
|
|
191
|
-
_interface;
|
|
192
|
-
_tokenStoreInit;
|
|
193
|
-
_urlOptions;
|
|
194
|
-
_oauthScopesOnSignIn;
|
|
195
|
-
__DEMO_ENABLE_SLIGHT_FETCH_DELAY = false;
|
|
196
|
-
_currentUserCache = createCacheBySession(async (session) => {
|
|
197
|
-
if (this.__DEMO_ENABLE_SLIGHT_FETCH_DELAY) {
|
|
198
|
-
await (0, import_promises.wait)(2e3);
|
|
199
|
-
}
|
|
200
|
-
const user = await this._interface.getClientUserByToken(session);
|
|
201
|
-
return import_results.Result.or(user, null);
|
|
202
|
-
});
|
|
203
|
-
_currentProjectCache = createCache(async () => {
|
|
204
|
-
return import_results.Result.orThrow(await this._interface.getClientProject());
|
|
205
|
-
});
|
|
206
|
-
_ownedProjectsCache = createCacheBySession(async (session) => {
|
|
207
|
-
return await this._interface.listProjects(session);
|
|
208
|
-
});
|
|
209
|
-
_currentUserPermissionsCache = createCacheBySession(async (session, [teamId, type, direct]) => {
|
|
210
|
-
return await this._interface.listClientUserTeamPermissions({ teamId, type, direct }, session);
|
|
211
|
-
});
|
|
212
|
-
_currentUserTeamsCache = createCacheBySession(async (session) => {
|
|
213
|
-
return await this._interface.listClientUserTeams(session);
|
|
214
|
-
});
|
|
215
|
-
_currentUserOAuthConnectionAccessTokensCache = createCacheBySession(
|
|
216
|
-
async (session, [accountId, scope]) => {
|
|
217
|
-
try {
|
|
218
|
-
return await this._interface.getAccessToken(accountId, scope || "", session);
|
|
219
|
-
} catch (err) {
|
|
220
|
-
if (!(err instanceof import_stack_shared.KnownErrors.OAuthConnectionDoesNotHaveRequiredScope || err instanceof import_stack_shared.KnownErrors.OAuthConnectionNotConnectedToUser)) {
|
|
221
|
-
throw err;
|
|
222
|
-
}
|
|
223
|
-
}
|
|
224
|
-
return null;
|
|
225
|
-
}
|
|
226
|
-
);
|
|
227
|
-
_currentUserOAuthConnectionCache = createCacheBySession(
|
|
228
|
-
async (session, [connectionId, scope, redirect]) => {
|
|
229
|
-
const user = await this._currentUserCache.getOrWait([session], "write-only");
|
|
230
|
-
let hasConnection = true;
|
|
231
|
-
if (!user || !user.oauthProviders.find((p) => p === connectionId)) {
|
|
232
|
-
hasConnection = false;
|
|
233
|
-
}
|
|
234
|
-
const token = await this._currentUserOAuthConnectionAccessTokensCache.getOrWait([session, connectionId, scope || ""], "write-only");
|
|
235
|
-
if (!token) {
|
|
236
|
-
hasConnection = false;
|
|
237
|
-
}
|
|
238
|
-
if (!hasConnection && redirect) {
|
|
239
|
-
await (0, import_auth.addNewOAuthProviderOrScope)(
|
|
240
|
-
this._interface,
|
|
241
|
-
{
|
|
242
|
-
provider: connectionId,
|
|
243
|
-
redirectUrl: this.urls.oauthCallback,
|
|
244
|
-
errorRedirectUrl: this.urls.error,
|
|
245
|
-
providerScope: (0, import_strings.mergeScopeStrings)(scope || "", (this._oauthScopesOnSignIn[connectionId] ?? []).join(" "))
|
|
246
|
-
},
|
|
247
|
-
session
|
|
248
|
-
);
|
|
249
|
-
return await (0, import_promises.neverResolve)();
|
|
250
|
-
} else if (!hasConnection) {
|
|
251
|
-
return null;
|
|
252
|
-
}
|
|
253
|
-
const app = this;
|
|
254
|
-
return {
|
|
255
|
-
id: connectionId,
|
|
256
|
-
async getAccessToken() {
|
|
257
|
-
const result = await app._currentUserOAuthConnectionAccessTokensCache.getOrWait([session, connectionId, scope || ""], "write-only");
|
|
258
|
-
if (!result) {
|
|
259
|
-
throw new import_errors.StackAssertionError("No access token available");
|
|
260
|
-
}
|
|
261
|
-
return result;
|
|
262
|
-
},
|
|
263
|
-
useAccessToken() {
|
|
264
|
-
const result = useAsyncCache(app._currentUserOAuthConnectionAccessTokensCache, [session, connectionId, scope || ""], "oauthAccount.useAccessToken()");
|
|
265
|
-
if (!result) {
|
|
266
|
-
throw new import_errors.StackAssertionError("No access token available");
|
|
267
|
-
}
|
|
268
|
-
return result;
|
|
269
|
-
}
|
|
270
|
-
};
|
|
271
|
-
}
|
|
272
|
-
);
|
|
273
281
|
_initUniqueIdentifier() {
|
|
274
282
|
if (!this._uniqueIdentifier) {
|
|
275
283
|
throw new import_errors.StackAssertionError("Unique identifier not initialized");
|
|
@@ -297,9 +305,6 @@ var _StackClientAppImpl = class __StackClientAppImpl {
|
|
|
297
305
|
(0, import_promises.runAsynchronously)(this._checkFeatureSupport(featureName, options));
|
|
298
306
|
throw new import_errors.StackAssertionError(`${featureName} is not currently supported. Please reach out to Stack support for more information.`);
|
|
299
307
|
}
|
|
300
|
-
_memoryTokenStore = createEmptyTokenStore();
|
|
301
|
-
_requestTokenStores = /* @__PURE__ */ new WeakMap();
|
|
302
|
-
_storedCookieTokenStore = null;
|
|
303
308
|
get _refreshTokenCookieName() {
|
|
304
309
|
return `stack-refresh-${this.projectId}`;
|
|
305
310
|
}
|
|
@@ -427,15 +432,6 @@ var _StackClientAppImpl = class __StackClientAppImpl {
|
|
|
427
432
|
}
|
|
428
433
|
}
|
|
429
434
|
}
|
|
430
|
-
/**
|
|
431
|
-
* A map from token stores and session keys to sessions.
|
|
432
|
-
*
|
|
433
|
-
* This isn't just a map from session keys to sessions for two reasons:
|
|
434
|
-
*
|
|
435
|
-
* - So we can garbage-collect Session objects when the token store is garbage-collected
|
|
436
|
-
* - 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
|
|
437
|
-
*/
|
|
438
|
-
_sessionsByTokenStoreAndSessionKey = /* @__PURE__ */ new WeakMap();
|
|
439
435
|
_getSessionFromTokenStore(tokenStore) {
|
|
440
436
|
const tokenObj = tokenStore.get();
|
|
441
437
|
const sessionKey = import_sessions.InternalSession.calculateSessionKey(tokenObj);
|
|
@@ -1040,33 +1036,6 @@ var _StackClientAppImpl = class __StackClientAppImpl {
|
|
|
1040
1036
|
}
|
|
1041
1037
|
};
|
|
1042
1038
|
var _StackServerAppImpl = class extends _StackClientAppImpl {
|
|
1043
|
-
// TODO override the client user cache to use the server user cache, so we save some requests
|
|
1044
|
-
_currentServerUserCache = createCacheBySession(async (session) => {
|
|
1045
|
-
const user = await this._interface.getServerUserByToken(session);
|
|
1046
|
-
return import_results.Result.or(user, null);
|
|
1047
|
-
});
|
|
1048
|
-
_serverUsersCache = createCache(async () => {
|
|
1049
|
-
return await this._interface.listServerUsers();
|
|
1050
|
-
});
|
|
1051
|
-
_serverUserCache = createCache(async ([userId]) => {
|
|
1052
|
-
const user = await this._interface.getServerUserById(userId);
|
|
1053
|
-
return import_results.Result.or(user, null);
|
|
1054
|
-
});
|
|
1055
|
-
_serverTeamsCache = createCache(async () => {
|
|
1056
|
-
return await this._interface.listServerTeams();
|
|
1057
|
-
});
|
|
1058
|
-
_serverTeamMembersCache = createCache(async ([teamId]) => {
|
|
1059
|
-
return await this._interface.listServerTeamMembers(teamId);
|
|
1060
|
-
});
|
|
1061
|
-
_serverTeamPermissionDefinitionsCache = createCache(async () => {
|
|
1062
|
-
return await this._interface.listPermissionDefinitions();
|
|
1063
|
-
});
|
|
1064
|
-
_serverTeamUserPermissionsCache = createCache(async ([teamId, userId, type, direct]) => {
|
|
1065
|
-
return await this._interface.listServerTeamMemberPermissions({ teamId, userId, type, direct });
|
|
1066
|
-
});
|
|
1067
|
-
_serverEmailTemplatesCache = createCache(async () => {
|
|
1068
|
-
return await this._interface.listEmailTemplates();
|
|
1069
|
-
});
|
|
1070
1039
|
constructor(options) {
|
|
1071
1040
|
super("interface" in options ? {
|
|
1072
1041
|
interface: options.interface,
|
|
@@ -1085,6 +1054,33 @@ var _StackServerAppImpl = class extends _StackClientAppImpl {
|
|
|
1085
1054
|
urls: options.urls ?? {},
|
|
1086
1055
|
oauthScopesOnSignIn: options.oauthScopesOnSignIn ?? {}
|
|
1087
1056
|
});
|
|
1057
|
+
// TODO override the client user cache to use the server user cache, so we save some requests
|
|
1058
|
+
this._currentServerUserCache = createCacheBySession(async (session) => {
|
|
1059
|
+
const user = await this._interface.getServerUserByToken(session);
|
|
1060
|
+
return import_results.Result.or(user, null);
|
|
1061
|
+
});
|
|
1062
|
+
this._serverUsersCache = createCache(async () => {
|
|
1063
|
+
return await this._interface.listServerUsers();
|
|
1064
|
+
});
|
|
1065
|
+
this._serverUserCache = createCache(async ([userId]) => {
|
|
1066
|
+
const user = await this._interface.getServerUserById(userId);
|
|
1067
|
+
return import_results.Result.or(user, null);
|
|
1068
|
+
});
|
|
1069
|
+
this._serverTeamsCache = createCache(async () => {
|
|
1070
|
+
return await this._interface.listServerTeams();
|
|
1071
|
+
});
|
|
1072
|
+
this._serverTeamMembersCache = createCache(async ([teamId]) => {
|
|
1073
|
+
return await this._interface.listServerTeamMembers(teamId);
|
|
1074
|
+
});
|
|
1075
|
+
this._serverTeamPermissionDefinitionsCache = createCache(async () => {
|
|
1076
|
+
return await this._interface.listPermissionDefinitions();
|
|
1077
|
+
});
|
|
1078
|
+
this._serverTeamUserPermissionsCache = createCache(async ([teamId, userId, type, direct]) => {
|
|
1079
|
+
return await this._interface.listServerTeamMemberPermissions({ teamId, userId, type, direct });
|
|
1080
|
+
});
|
|
1081
|
+
this._serverEmailTemplatesCache = createCache(async () => {
|
|
1082
|
+
return await this._interface.listEmailTemplates();
|
|
1083
|
+
});
|
|
1088
1084
|
}
|
|
1089
1085
|
_createBaseUser(json) {
|
|
1090
1086
|
return {
|
|
@@ -1411,12 +1407,6 @@ var _StackServerAppImpl = class extends _StackClientAppImpl {
|
|
|
1411
1407
|
}
|
|
1412
1408
|
};
|
|
1413
1409
|
var _StackAdminAppImpl = class extends _StackServerAppImpl {
|
|
1414
|
-
_adminProjectCache = createCache(async () => {
|
|
1415
|
-
return await this._interface.getProject();
|
|
1416
|
-
});
|
|
1417
|
-
_apiKeySetsCache = createCache(async () => {
|
|
1418
|
-
return await this._interface.listApiKeySets();
|
|
1419
|
-
});
|
|
1420
1410
|
constructor(options) {
|
|
1421
1411
|
super({
|
|
1422
1412
|
interface: new import_stack_shared.StackAdminInterface({
|
|
@@ -1435,6 +1425,12 @@ var _StackAdminAppImpl = class extends _StackServerAppImpl {
|
|
|
1435
1425
|
urls: options.urls,
|
|
1436
1426
|
oauthScopesOnSignIn: options.oauthScopesOnSignIn
|
|
1437
1427
|
});
|
|
1428
|
+
this._adminProjectCache = createCache(async () => {
|
|
1429
|
+
return await this._interface.getProject();
|
|
1430
|
+
});
|
|
1431
|
+
this._apiKeySetsCache = createCache(async () => {
|
|
1432
|
+
return await this._interface.listApiKeySets();
|
|
1433
|
+
});
|
|
1438
1434
|
}
|
|
1439
1435
|
_createApiKeySetBaseFromJson(data) {
|
|
1440
1436
|
const app = this;
|