@stackframe/stack-shared 2.6.27 → 2.6.29
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 +14 -0
- package/dist/interface/clientInterface.d.ts +5 -0
- package/dist/interface/clientInterface.js +8 -0
- package/dist/interface/crud/team-invitation.d.ts +34 -0
- package/dist/interface/crud/team-invitation.js +20 -0
- package/dist/interface/serverInterface.d.ts +5 -0
- package/dist/interface/serverInterface.js +8 -0
- package/dist/known-errors.d.ts +3 -0
- package/dist/known-errors.js +6 -0
- package/dist/schema-fields.js +1 -1
- package/dist/utils/env.d.ts +1 -0
- package/dist/utils/env.js +11 -0
- package/dist/utils/promises.js +2 -2
- package/dist/utils/urls.d.ts +1 -0
- package/dist/utils/urls.js +14 -2
- package/package.json +2 -2
package/CHANGELOG.md
CHANGED
|
@@ -7,6 +7,7 @@ import { ContactChannelsCrud } from './crud/contact-channels';
|
|
|
7
7
|
import { CurrentUserCrud } from './crud/current-user';
|
|
8
8
|
import { ConnectedAccountAccessTokenCrud } from './crud/oauth';
|
|
9
9
|
import { InternalProjectsCrud, ProjectsCrud } from './crud/projects';
|
|
10
|
+
import { TeamInvitationCrud } from './crud/team-invitation';
|
|
10
11
|
import { TeamMemberProfilesCrud } from './crud/team-member-profiles';
|
|
11
12
|
import { TeamPermissionsCrud } from './crud/team-permissions';
|
|
12
13
|
import { TeamsCrud } from './crud/teams';
|
|
@@ -152,6 +153,10 @@ export declare class StackClientInterface {
|
|
|
152
153
|
}>;
|
|
153
154
|
signOut(session: InternalSession): Promise<void>;
|
|
154
155
|
getClientUserByToken(session: InternalSession): Promise<CurrentUserCrud["Client"]["Read"] | null>;
|
|
156
|
+
listTeamInvitations(options: {
|
|
157
|
+
teamId: string;
|
|
158
|
+
}, session: InternalSession): Promise<TeamInvitationCrud['Client']['Read'][]>;
|
|
159
|
+
revokeTeamInvitation(invitationId: string, teamId: string, session: InternalSession): Promise<void>;
|
|
155
160
|
listTeamMemberProfiles(options: {
|
|
156
161
|
teamId?: string;
|
|
157
162
|
userId?: string;
|
|
@@ -695,6 +695,14 @@ export class StackClientInterface {
|
|
|
695
695
|
throw new StackAssertionError("User endpoint returned null; this should never happen");
|
|
696
696
|
return user;
|
|
697
697
|
}
|
|
698
|
+
async listTeamInvitations(options, session) {
|
|
699
|
+
const response = await this.sendClientRequest("/team-invitations?" + new URLSearchParams({ team_id: options.teamId }), {}, session);
|
|
700
|
+
const result = await response.json();
|
|
701
|
+
return result.items;
|
|
702
|
+
}
|
|
703
|
+
async revokeTeamInvitation(invitationId, teamId, session) {
|
|
704
|
+
await this.sendClientRequest(`/team-invitations/${invitationId}?team_id=${teamId}`, { method: "DELETE" }, session);
|
|
705
|
+
}
|
|
698
706
|
async listTeamMemberProfiles(options, session) {
|
|
699
707
|
const response = await this.sendClientRequest("/team-member-profiles?" + new URLSearchParams(filterUndefined({
|
|
700
708
|
team_id: options.teamId,
|
|
@@ -0,0 +1,34 @@
|
|
|
1
|
+
import { CrudTypeOf } from "../../crud";
|
|
2
|
+
export declare const teamInvitationDetailsClientReadSchema: import("yup").ObjectSchema<{
|
|
3
|
+
id: string;
|
|
4
|
+
team_id: string;
|
|
5
|
+
expires_at_millis: number;
|
|
6
|
+
recipient_email: string;
|
|
7
|
+
}, import("yup").AnyObject, {
|
|
8
|
+
id: undefined;
|
|
9
|
+
team_id: undefined;
|
|
10
|
+
expires_at_millis: undefined;
|
|
11
|
+
recipient_email: undefined;
|
|
12
|
+
}, "">;
|
|
13
|
+
export declare const teamInvitationCrud: import("../../crud").CrudSchemaFromOptions<{
|
|
14
|
+
clientReadSchema: import("yup").ObjectSchema<{
|
|
15
|
+
id: string;
|
|
16
|
+
team_id: string;
|
|
17
|
+
expires_at_millis: number;
|
|
18
|
+
recipient_email: string;
|
|
19
|
+
}, import("yup").AnyObject, {
|
|
20
|
+
id: undefined;
|
|
21
|
+
team_id: undefined;
|
|
22
|
+
expires_at_millis: undefined;
|
|
23
|
+
recipient_email: undefined;
|
|
24
|
+
}, "">;
|
|
25
|
+
clientDeleteSchema: import("yup").MixedSchema<any, import("yup").AnyObject, undefined, "">;
|
|
26
|
+
docs: {
|
|
27
|
+
clientRead: {
|
|
28
|
+
summary: string;
|
|
29
|
+
description: string;
|
|
30
|
+
tags: string[];
|
|
31
|
+
};
|
|
32
|
+
};
|
|
33
|
+
}>;
|
|
34
|
+
export type TeamInvitationCrud = CrudTypeOf<typeof teamInvitationCrud>;
|
|
@@ -0,0 +1,20 @@
|
|
|
1
|
+
import { createCrud } from "../../crud";
|
|
2
|
+
import * as schemaFields from "../../schema-fields";
|
|
3
|
+
import { yupObject } from "../../schema-fields";
|
|
4
|
+
export const teamInvitationDetailsClientReadSchema = yupObject({
|
|
5
|
+
id: schemaFields.yupString().uuid().defined(),
|
|
6
|
+
team_id: schemaFields.teamIdSchema.defined(),
|
|
7
|
+
expires_at_millis: schemaFields.yupNumber().defined(),
|
|
8
|
+
recipient_email: schemaFields.emailSchema.defined(),
|
|
9
|
+
}).defined();
|
|
10
|
+
export const teamInvitationCrud = createCrud({
|
|
11
|
+
clientReadSchema: teamInvitationDetailsClientReadSchema,
|
|
12
|
+
clientDeleteSchema: schemaFields.yupMixed(),
|
|
13
|
+
docs: {
|
|
14
|
+
clientRead: {
|
|
15
|
+
summary: "Get the team details with invitation code",
|
|
16
|
+
description: "",
|
|
17
|
+
tags: ["Teams"],
|
|
18
|
+
},
|
|
19
|
+
},
|
|
20
|
+
});
|
|
@@ -5,6 +5,7 @@ import { ClientInterfaceOptions, StackClientInterface } from "./clientInterface"
|
|
|
5
5
|
import { ContactChannelsCrud } from "./crud/contact-channels";
|
|
6
6
|
import { CurrentUserCrud } from "./crud/current-user";
|
|
7
7
|
import { ConnectedAccountAccessTokenCrud } from "./crud/oauth";
|
|
8
|
+
import { TeamInvitationCrud } from "./crud/team-invitation";
|
|
8
9
|
import { TeamMemberProfilesCrud } from "./crud/team-member-profiles";
|
|
9
10
|
import { TeamMembershipsCrud } from "./crud/team-memberships";
|
|
10
11
|
import { TeamPermissionsCrud } from "./crud/team-permissions";
|
|
@@ -33,6 +34,10 @@ export declare class StackServerInterface extends StackClientInterface {
|
|
|
33
34
|
createServerUser(data: UsersCrud['Server']['Create']): Promise<UsersCrud['Server']['Read']>;
|
|
34
35
|
getServerUserByToken(session: InternalSession): Promise<CurrentUserCrud['Server']['Read'] | null>;
|
|
35
36
|
getServerUserById(userId: string): Promise<Result<UsersCrud['Server']['Read']>>;
|
|
37
|
+
listServerTeamInvitations(options: {
|
|
38
|
+
teamId: string;
|
|
39
|
+
}): Promise<TeamInvitationCrud['Server']['Read'][]>;
|
|
40
|
+
revokeServerTeamInvitation(invitationId: string, teamId: string): Promise<void>;
|
|
36
41
|
listServerTeamMemberProfiles(options: {
|
|
37
42
|
teamId: string;
|
|
38
43
|
}): Promise<TeamMemberProfilesCrud['Server']['Read'][]>;
|
|
@@ -63,6 +63,14 @@ export class StackServerInterface extends StackClientInterface {
|
|
|
63
63
|
return Result.error(new Error("Failed to get user"));
|
|
64
64
|
return Result.ok(user);
|
|
65
65
|
}
|
|
66
|
+
async listServerTeamInvitations(options) {
|
|
67
|
+
const response = await this.sendServerRequest("/team-invitations?team_id=" + options.teamId, {}, null);
|
|
68
|
+
const result = await response.json();
|
|
69
|
+
return result.items;
|
|
70
|
+
}
|
|
71
|
+
async revokeServerTeamInvitation(invitationId, teamId) {
|
|
72
|
+
await this.sendServerRequest(`/team-invitations/${invitationId}?team_id=${teamId}`, { method: "DELETE" }, null);
|
|
73
|
+
}
|
|
66
74
|
async listServerTeamMemberProfiles(options) {
|
|
67
75
|
const response = await this.sendServerRequest("/team-member-profiles?team_id=" + options.teamId, {}, null);
|
|
68
76
|
const result = await response.json();
|
package/dist/known-errors.d.ts
CHANGED
|
@@ -395,5 +395,8 @@ export declare const KnownErrors: {
|
|
|
395
395
|
OAuthProviderAccessDenied: KnownErrorConstructor<KnownError & KnownErrorBrand<"OAUTH_PROVIDER_ACCESS_DENIED">, []> & {
|
|
396
396
|
errorCode: "OAUTH_PROVIDER_ACCESS_DENIED";
|
|
397
397
|
};
|
|
398
|
+
ContactChannelAlreadyUsedForAuthBySomeoneElse: KnownErrorConstructor<KnownError & KnownErrorBrand<"CONTACT_CHANNEL_ALREADY_USED_FOR_AUTH_BY_SOMEONE_ELSE">, [type: "email"]> & {
|
|
399
|
+
errorCode: "CONTACT_CHANNEL_ALREADY_USED_FOR_AUTH_BY_SOMEONE_ELSE";
|
|
400
|
+
};
|
|
398
401
|
};
|
|
399
402
|
export {};
|
package/dist/known-errors.js
CHANGED
|
@@ -558,6 +558,11 @@ const OAuthProviderAccessDenied = createKnownErrorConstructor(KnownError, "OAUTH
|
|
|
558
558
|
400,
|
|
559
559
|
"The OAuth provider denied access to the user.",
|
|
560
560
|
], () => []);
|
|
561
|
+
const ContactChannelAlreadyUsedForAuthBySomeoneElse = createKnownErrorConstructor(KnownError, "CONTACT_CHANNEL_ALREADY_USED_FOR_AUTH_BY_SOMEONE_ELSE", (type) => [
|
|
562
|
+
400,
|
|
563
|
+
`This ${type} is already used for authentication by another account.`,
|
|
564
|
+
{ type },
|
|
565
|
+
], (json) => [json.type]);
|
|
561
566
|
export const KnownErrors = {
|
|
562
567
|
UnsupportedError,
|
|
563
568
|
BodyParsingError,
|
|
@@ -650,6 +655,7 @@ export const KnownErrors = {
|
|
|
650
655
|
InvalidAuthorizationCode,
|
|
651
656
|
TeamPermissionNotFound,
|
|
652
657
|
OAuthProviderAccessDenied,
|
|
658
|
+
ContactChannelAlreadyUsedForAuthBySomeoneElse,
|
|
653
659
|
};
|
|
654
660
|
// ensure that all known error codes are unique
|
|
655
661
|
const knownErrorCodes = new Set();
|
package/dist/schema-fields.js
CHANGED
|
@@ -296,7 +296,7 @@ export const userPasswordHashMutationSchema = yupString()
|
|
|
296
296
|
.meta({ openapiField: { description: 'If `password` is not given, sets the user\'s password hash to the given string in Modular Crypt Format (ex.: `$2a$10$VIhIOofSMqGdGlL4wzE//e.77dAQGqNtF/1dT7bqCrVtQuInWy2qi`). Doing so revokes all current sessions.' } }); // we don't set an exampleValue here because it's exclusive with the password field and having both would break the generated example
|
|
297
297
|
export const userTotpSecretMutationSchema = base64Schema.nullable().meta({ openapiField: { description: 'Enables 2FA and sets a TOTP secret for the user. Set to null to disable 2FA.', exampleValue: 'dG90cC1zZWNyZXQ=' } });
|
|
298
298
|
// Auth
|
|
299
|
-
export const signInEmailSchema =
|
|
299
|
+
export const signInEmailSchema = strictEmailSchema(undefined).meta({ openapiField: { description: 'The email to sign in with.', exampleValue: 'johndoe@example.com' } });
|
|
300
300
|
export const emailOtpSignInCallbackUrlSchema = urlSchema.meta({ openapiField: { description: 'The base callback URL to construct the magic link from. A query parameter `code` with the verification code will be appended to it. The page should then make a request to the `/auth/otp/sign-in` endpoint.', exampleValue: 'https://example.com/handler/magic-link-callback' } });
|
|
301
301
|
export const emailVerificationCallbackUrlSchema = urlSchema.meta({ openapiField: { description: 'The base callback URL to construct a verification link for the verification e-mail. A query parameter `code` with the verification code will be appended to it. The page should then make a request to the `/contact-channels/verify` endpoint.', exampleValue: 'https://example.com/handler/email-verification' } });
|
|
302
302
|
export const accessTokenResponseSchema = yupString().meta({ openapiField: { description: 'Short-lived access token that can be used to authenticate the user', exampleValue: 'eyJhmMiJB2TO...diI4QT' } });
|
package/dist/utils/env.d.ts
CHANGED
|
@@ -3,4 +3,5 @@ export declare function isBrowserLike(): boolean;
|
|
|
3
3
|
* Returns the environment variable with the given name, returning the default (if given) or throwing an error (otherwise) if it's undefined or the empty string.
|
|
4
4
|
*/
|
|
5
5
|
export declare function getEnvVariable(name: string, defaultValue?: string | undefined): string;
|
|
6
|
+
export declare function getNextRuntime(): string;
|
|
6
7
|
export declare function getNodeEnvironment(): string;
|
package/dist/utils/env.js
CHANGED
|
@@ -14,8 +14,19 @@ export function getEnvVariable(name, defaultValue) {
|
|
|
14
14
|
Use process.env.XYZ directly instead.
|
|
15
15
|
`);
|
|
16
16
|
}
|
|
17
|
+
if (name === "NEXT_RUNTIME") {
|
|
18
|
+
throw new Error(deindent `
|
|
19
|
+
Can't use getEnvVariable to access the NEXT_RUNTIME environment variable because it's compiled into the client bundle.
|
|
20
|
+
|
|
21
|
+
Use getNextRuntime() instead.
|
|
22
|
+
`);
|
|
23
|
+
}
|
|
17
24
|
return ((process.env[name] || defaultValue) ?? throwErr(`Missing environment variable: ${name}`)) || (defaultValue ?? throwErr(`Empty environment variable: ${name}`));
|
|
18
25
|
}
|
|
26
|
+
export function getNextRuntime() {
|
|
27
|
+
// This variable is compiled into the client bundle, so we can't use getEnvVariable here.
|
|
28
|
+
return process.env.NEXT_RUNTIME || throwErr("Missing environment variable: NEXT_RUNTIME");
|
|
29
|
+
}
|
|
19
30
|
export function getNodeEnvironment() {
|
|
20
31
|
return getEnvVariable("NODE_ENV", "");
|
|
21
32
|
}
|
package/dist/utils/promises.js
CHANGED
|
@@ -105,7 +105,7 @@ export function runAsynchronouslyWithAlert(...args) {
|
|
|
105
105
|
return runAsynchronously(args[0], {
|
|
106
106
|
...args[1],
|
|
107
107
|
onError: error => {
|
|
108
|
-
alert(`An unhandled error occurred. Please ${process.env.NODE_ENV === "development" ? `check the browser console for the full error
|
|
108
|
+
alert(`An unhandled error occurred. Please ${process.env.NODE_ENV === "development" ? `check the browser console for the full error.` : "report this to the developer."}\n\n${error}`);
|
|
109
109
|
args[1]?.onError?.(error);
|
|
110
110
|
},
|
|
111
111
|
}, ...args.slice(2));
|
|
@@ -116,9 +116,9 @@ export function runAsynchronously(promiseOrFunc, options = {}) {
|
|
|
116
116
|
}
|
|
117
117
|
const duringError = new Error();
|
|
118
118
|
promiseOrFunc?.catch(error => {
|
|
119
|
+
options.onError?.(error);
|
|
119
120
|
const newError = new StackAssertionError("Uncaught error in asynchronous function: " + error.toString(), { cause: error });
|
|
120
121
|
concatStacktraces(newError, duringError);
|
|
121
|
-
options.onError?.(newError);
|
|
122
122
|
if (!options.noErrorLogging) {
|
|
123
123
|
captureError("runAsynchronously", newError);
|
|
124
124
|
}
|
package/dist/utils/urls.d.ts
CHANGED
|
@@ -1,3 +1,4 @@
|
|
|
1
|
+
export declare function createUrlIfValid(...args: ConstructorParameters<typeof URL>): URL | null;
|
|
1
2
|
export declare function isLocalhost(urlOrString: string | URL): boolean;
|
|
2
3
|
export declare function isRelative(url: string): boolean;
|
|
3
4
|
export declare function getRelativePart(url: URL): string;
|
package/dist/utils/urls.js
CHANGED
|
@@ -1,6 +1,16 @@
|
|
|
1
1
|
import { generateSecureRandomString } from "./crypto";
|
|
2
|
+
export function createUrlIfValid(...args) {
|
|
3
|
+
try {
|
|
4
|
+
return new URL(...args);
|
|
5
|
+
}
|
|
6
|
+
catch (e) {
|
|
7
|
+
return null;
|
|
8
|
+
}
|
|
9
|
+
}
|
|
2
10
|
export function isLocalhost(urlOrString) {
|
|
3
|
-
const url =
|
|
11
|
+
const url = createUrlIfValid(urlOrString);
|
|
12
|
+
if (!url)
|
|
13
|
+
return false;
|
|
4
14
|
if (url.hostname === "localhost" || url.hostname.endsWith(".localhost"))
|
|
5
15
|
return true;
|
|
6
16
|
if (url.hostname.match(/^127\.\d+\.\d+\.\d+$/))
|
|
@@ -9,7 +19,9 @@ export function isLocalhost(urlOrString) {
|
|
|
9
19
|
}
|
|
10
20
|
export function isRelative(url) {
|
|
11
21
|
const randomDomain = `${generateSecureRandomString()}.stack-auth.example.com`;
|
|
12
|
-
const u =
|
|
22
|
+
const u = createUrlIfValid(url, `https://${randomDomain}`);
|
|
23
|
+
if (!u)
|
|
24
|
+
return false;
|
|
13
25
|
if (u.host !== randomDomain)
|
|
14
26
|
return false;
|
|
15
27
|
if (u.protocol !== "https:")
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@stackframe/stack-shared",
|
|
3
|
-
"version": "2.6.
|
|
3
|
+
"version": "2.6.29",
|
|
4
4
|
"main": "./dist/index.js",
|
|
5
5
|
"types": "./dist/index.d.ts",
|
|
6
6
|
"files": [
|
|
@@ -50,7 +50,7 @@
|
|
|
50
50
|
"oauth4webapi": "^2.10.3",
|
|
51
51
|
"semver": "^7.6.3",
|
|
52
52
|
"uuid": "^9.0.1",
|
|
53
|
-
"@stackframe/stack-sc": "2.6.
|
|
53
|
+
"@stackframe/stack-sc": "2.6.29"
|
|
54
54
|
},
|
|
55
55
|
"devDependencies": {
|
|
56
56
|
"@simplewebauthn/types": "^11.0.0",
|