@stackframe/stack-shared 2.5.18 → 2.5.20

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 CHANGED
@@ -1,5 +1,20 @@
1
1
  # @stackframe/stack-shared
2
2
 
3
+ ## 2.5.20
4
+
5
+ ### Patch Changes
6
+
7
+ - Improved account settings
8
+ - @stackframe/stack-sc@2.5.20
9
+
10
+ ## 2.5.19
11
+
12
+ ### Patch Changes
13
+
14
+ - Team frontend components
15
+ - Updated dependencies
16
+ - @stackframe/stack-sc@2.5.19
17
+
3
18
  ## 2.5.18
4
19
 
5
20
  ### Patch Changes
@@ -45,4 +45,5 @@ export declare class StackAdminInterface extends StackServerInterface {
45
45
  updatePermissionDefinition(permissionId: string, data: TeamPermissionDefinitionsCrud['Admin']['Update']): Promise<TeamPermissionDefinitionsCrud['Admin']['Read']>;
46
46
  deletePermissionDefinition(permissionId: string): Promise<void>;
47
47
  getSvixToken(): Promise<SvixTokenCrud["Admin"]["Read"]>;
48
+ deleteProject(): Promise<void>;
48
49
  }
@@ -115,4 +115,9 @@ export class StackAdminInterface extends StackServerInterface {
115
115
  }, null);
116
116
  return await response.json();
117
117
  }
118
+ async deleteProject() {
119
+ await this.sendAdminRequest("/projects/current", {
120
+ method: "DELETE",
121
+ }, null);
122
+ }
118
123
  }
@@ -5,6 +5,7 @@ import { Result } from "../utils/results";
5
5
  import { CurrentUserCrud } from './crud/current-user';
6
6
  import { ConnectedAccountAccessTokenCrud } from './crud/oauth';
7
7
  import { InternalProjectsCrud, ProjectsCrud } from './crud/projects';
8
+ import { TeamMemberProfilesCrud } from './crud/team-member-profiles';
8
9
  import { TeamPermissionsCrud } from './crud/team-permissions';
9
10
  import { TeamsCrud } from './crud/teams';
10
11
  export type ClientInterfaceOptions = {
@@ -81,6 +82,7 @@ export declare class StackClientInterface {
81
82
  totpMfa(attemptCode: string, totp: string, session: InternalSession): Promise<{
82
83
  accessToken: any;
83
84
  refreshToken: any;
85
+ newUser: any;
84
86
  }>;
85
87
  signInWithCredential(email: string, password: string, session: InternalSession): Promise<KnownErrors["EmailPasswordMismatch"] | {
86
88
  accessToken: string;
@@ -123,6 +125,24 @@ export declare class StackClientInterface {
123
125
  }>;
124
126
  signOut(session: InternalSession): Promise<void>;
125
127
  getClientUserByToken(session: InternalSession): Promise<CurrentUserCrud["Client"]["Read"] | null>;
128
+ listTeamMemberProfiles(options: {
129
+ teamId?: string;
130
+ userId?: string;
131
+ }, session: InternalSession): Promise<TeamMemberProfilesCrud['Client']['Read'][]>;
132
+ getTeamMemberProfile(options: {
133
+ teamId: string;
134
+ userId: string;
135
+ }, session: InternalSession): Promise<TeamMemberProfilesCrud['Client']['Read']>;
136
+ leaveTeam(teamId: string, session: InternalSession): Promise<void>;
137
+ updateTeamMemberProfile(options: {
138
+ teamId: string;
139
+ userId: string;
140
+ profile: TeamMemberProfilesCrud['Client']['Update'];
141
+ }, session: InternalSession): Promise<void>;
142
+ updateTeam(options: {
143
+ teamId: string;
144
+ data: TeamsCrud['Client']['Update'];
145
+ }, session: InternalSession): Promise<void>;
126
146
  listCurrentUserTeamPermissions(options: {
127
147
  teamId: string;
128
148
  recursive: boolean;
@@ -5,6 +5,7 @@ import { AccessToken, InternalSession } from '../sessions';
5
5
  import { generateSecureRandomString } from '../utils/crypto';
6
6
  import { StackAssertionError, throwErr } from '../utils/errors';
7
7
  import { globalVar } from '../utils/globals';
8
+ import { filterUndefined } from '../utils/objects';
8
9
  import { Result } from "../utils/results";
9
10
  import { deindent } from '../utils/strings';
10
11
  export class StackClientInterface {
@@ -441,6 +442,7 @@ export class StackClientInterface {
441
442
  return {
442
443
  accessToken: result.access_token,
443
444
  refreshToken: result.refresh_token,
445
+ newUser: result.is_new_user,
444
446
  };
445
447
  }
446
448
  async signInWithCredential(email, password, session) {
@@ -562,6 +564,9 @@ export class StackClientInterface {
562
564
  const response = await oauth.authorizationCodeGrantRequest(as, client, params, options.redirectUri, options.codeVerifier);
563
565
  const result = await oauth.processAuthorizationCodeOAuth2Response(as, client, response);
564
566
  if (oauth.isOAuth2Error(result)) {
567
+ if ("code" in result && result.code === "MULTI_FACTOR_AUTHENTICATION_REQUIRED") {
568
+ throw new KnownErrors.MultiFactorAuthenticationRequired(result.details.attempt_code);
569
+ }
565
570
  // TODO Handle OAuth 2.0 response body error
566
571
  throw new StackAssertionError("Outer OAuth error during authorization code response", { result });
567
572
  }
@@ -613,6 +618,45 @@ export class StackClientInterface {
613
618
  throw new StackAssertionError("User endpoint returned null; this should never happen");
614
619
  return user;
615
620
  }
621
+ async listTeamMemberProfiles(options, session) {
622
+ const response = await this.sendClientRequest("/team-member-profiles?" + new URLSearchParams(filterUndefined({
623
+ team_id: options.teamId,
624
+ user_id: options.userId,
625
+ })), {}, session);
626
+ const result = await response.json();
627
+ return result.items;
628
+ }
629
+ async getTeamMemberProfile(options, session) {
630
+ const response = await this.sendClientRequest(`/team-member-profiles/${options.teamId}/${options.userId}`, {}, session);
631
+ return await response.json();
632
+ }
633
+ async leaveTeam(teamId, session) {
634
+ await this.sendClientRequest(`/team-memberships/${teamId}/me`, {
635
+ method: "DELETE",
636
+ headers: {
637
+ "content-type": "application/json",
638
+ },
639
+ body: JSON.stringify({}),
640
+ }, session);
641
+ }
642
+ async updateTeamMemberProfile(options, session) {
643
+ await this.sendClientRequest(`/team-member-profiles/${options.teamId}/${options.userId}`, {
644
+ method: "PATCH",
645
+ headers: {
646
+ "content-type": "application/json",
647
+ },
648
+ body: JSON.stringify(options.profile),
649
+ }, session);
650
+ }
651
+ async updateTeam(options, session) {
652
+ await this.sendClientRequest(`/teams/${options.teamId}`, {
653
+ method: "PATCH",
654
+ headers: {
655
+ "content-type": "application/json",
656
+ },
657
+ body: JSON.stringify(options.data),
658
+ }, session);
659
+ }
616
660
  async listCurrentUserTeamPermissions(options, session) {
617
661
  const response = await this.sendClientRequest(`/team-permissions?team_id=${options.teamId}&user_id=me&recursive=${options.recursive}`, {}, session);
618
662
  const result = await response.json();
@@ -1,5 +1,5 @@
1
1
  import { CrudTypeOf } from "../../crud";
2
- export declare const projectsCrudServerReadSchema: import("yup").ObjectSchema<{
2
+ export declare const projectsCrudAdminReadSchema: import("yup").ObjectSchema<{
3
3
  id: string;
4
4
  display_name: string;
5
5
  description: string;
@@ -12,6 +12,7 @@ export declare const projectsCrudServerReadSchema: import("yup").ObjectSchema<{
12
12
  sign_up_enabled: NonNullable<boolean | undefined>;
13
13
  credential_enabled: NonNullable<boolean | undefined>;
14
14
  magic_link_enabled: NonNullable<boolean | undefined>;
15
+ client_team_creation_enabled: NonNullable<boolean | undefined>;
15
16
  oauth_providers: {
16
17
  client_id?: string | undefined;
17
18
  client_secret?: string | undefined;
@@ -57,6 +58,7 @@ export declare const projectsCrudServerReadSchema: import("yup").ObjectSchema<{
57
58
  sign_up_enabled: undefined;
58
59
  credential_enabled: undefined;
59
60
  magic_link_enabled: undefined;
61
+ client_team_creation_enabled: undefined;
60
62
  oauth_providers: undefined;
61
63
  enabled_oauth_providers: undefined;
62
64
  domains: undefined;
@@ -81,6 +83,7 @@ export declare const projectsCrudClientReadSchema: import("yup").ObjectSchema<{
81
83
  sign_up_enabled: NonNullable<boolean | undefined>;
82
84
  credential_enabled: NonNullable<boolean | undefined>;
83
85
  magic_link_enabled: NonNullable<boolean | undefined>;
86
+ client_team_creation_enabled: NonNullable<boolean | undefined>;
84
87
  enabled_oauth_providers: {
85
88
  id: NonNullable<"google" | "github" | "facebook" | "microsoft" | "spotify" | undefined>;
86
89
  }[];
@@ -92,10 +95,11 @@ export declare const projectsCrudClientReadSchema: import("yup").ObjectSchema<{
92
95
  sign_up_enabled: undefined;
93
96
  credential_enabled: undefined;
94
97
  magic_link_enabled: undefined;
98
+ client_team_creation_enabled: undefined;
95
99
  enabled_oauth_providers: undefined;
96
100
  };
97
101
  }, "">;
98
- export declare const projectsCrudServerUpdateSchema: import("yup").ObjectSchema<{
102
+ export declare const projectsCrudAdminUpdateSchema: import("yup").ObjectSchema<{
99
103
  display_name: string | undefined;
100
104
  description: string | null | undefined;
101
105
  is_production_mode: boolean | undefined;
@@ -104,6 +108,7 @@ export declare const projectsCrudServerUpdateSchema: import("yup").ObjectSchema<
104
108
  sign_up_enabled?: boolean | undefined;
105
109
  credential_enabled?: boolean | undefined;
106
110
  magic_link_enabled?: boolean | undefined;
111
+ client_team_creation_enabled?: boolean | undefined;
107
112
  oauth_providers?: {
108
113
  client_id?: string | undefined;
109
114
  client_secret?: string | undefined;
@@ -139,7 +144,7 @@ export declare const projectsCrudServerUpdateSchema: import("yup").ObjectSchema<
139
144
  is_production_mode: undefined;
140
145
  config: undefined;
141
146
  }, "">;
142
- export declare const projectsCrudServerCreateSchema: import("yup").ObjectSchema<{
147
+ export declare const projectsCrudAdminCreateSchema: import("yup").ObjectSchema<{
143
148
  display_name: string;
144
149
  description: string | null | undefined;
145
150
  is_production_mode: boolean | undefined;
@@ -148,6 +153,7 @@ export declare const projectsCrudServerCreateSchema: import("yup").ObjectSchema<
148
153
  sign_up_enabled?: boolean | undefined;
149
154
  credential_enabled?: boolean | undefined;
150
155
  magic_link_enabled?: boolean | undefined;
156
+ client_team_creation_enabled?: boolean | undefined;
151
157
  oauth_providers?: {
152
158
  client_id?: string | undefined;
153
159
  client_secret?: string | undefined;
@@ -185,6 +191,7 @@ export declare const projectsCrudServerCreateSchema: import("yup").ObjectSchema<
185
191
  is_production_mode: undefined;
186
192
  config: undefined;
187
193
  }, "">;
194
+ export declare const projectsCrudAdminDeleteSchema: import("yup").MixedSchema<{} | undefined, import("yup").AnyObject, undefined, "">;
188
195
  export declare const projectsCrud: import("../../crud").CrudSchemaFromOptions<{
189
196
  clientReadSchema: import("yup").ObjectSchema<{
190
197
  id: string;
@@ -193,6 +200,7 @@ export declare const projectsCrud: import("../../crud").CrudSchemaFromOptions<{
193
200
  sign_up_enabled: NonNullable<boolean | undefined>;
194
201
  credential_enabled: NonNullable<boolean | undefined>;
195
202
  magic_link_enabled: NonNullable<boolean | undefined>;
203
+ client_team_creation_enabled: NonNullable<boolean | undefined>;
196
204
  enabled_oauth_providers: {
197
205
  id: NonNullable<"google" | "github" | "facebook" | "microsoft" | "spotify" | undefined>;
198
206
  }[];
@@ -204,10 +212,11 @@ export declare const projectsCrud: import("../../crud").CrudSchemaFromOptions<{
204
212
  sign_up_enabled: undefined;
205
213
  credential_enabled: undefined;
206
214
  magic_link_enabled: undefined;
215
+ client_team_creation_enabled: undefined;
207
216
  enabled_oauth_providers: undefined;
208
217
  };
209
218
  }, "">;
210
- serverReadSchema: import("yup").ObjectSchema<{
219
+ adminReadSchema: import("yup").ObjectSchema<{
211
220
  id: string;
212
221
  display_name: string;
213
222
  description: string;
@@ -220,6 +229,7 @@ export declare const projectsCrud: import("../../crud").CrudSchemaFromOptions<{
220
229
  sign_up_enabled: NonNullable<boolean | undefined>;
221
230
  credential_enabled: NonNullable<boolean | undefined>;
222
231
  magic_link_enabled: NonNullable<boolean | undefined>;
232
+ client_team_creation_enabled: NonNullable<boolean | undefined>;
223
233
  oauth_providers: {
224
234
  client_id?: string | undefined;
225
235
  client_secret?: string | undefined;
@@ -265,6 +275,7 @@ export declare const projectsCrud: import("../../crud").CrudSchemaFromOptions<{
265
275
  sign_up_enabled: undefined;
266
276
  credential_enabled: undefined;
267
277
  magic_link_enabled: undefined;
278
+ client_team_creation_enabled: undefined;
268
279
  oauth_providers: undefined;
269
280
  enabled_oauth_providers: undefined;
270
281
  domains: undefined;
@@ -282,7 +293,7 @@ export declare const projectsCrud: import("../../crud").CrudSchemaFromOptions<{
282
293
  team_member_default_permissions: undefined;
283
294
  };
284
295
  }, "">;
285
- serverUpdateSchema: import("yup").ObjectSchema<{
296
+ adminUpdateSchema: import("yup").ObjectSchema<{
286
297
  display_name: string | undefined;
287
298
  description: string | null | undefined;
288
299
  is_production_mode: boolean | undefined;
@@ -291,6 +302,7 @@ export declare const projectsCrud: import("../../crud").CrudSchemaFromOptions<{
291
302
  sign_up_enabled?: boolean | undefined;
292
303
  credential_enabled?: boolean | undefined;
293
304
  magic_link_enabled?: boolean | undefined;
305
+ client_team_creation_enabled?: boolean | undefined;
294
306
  oauth_providers?: {
295
307
  client_id?: string | undefined;
296
308
  client_secret?: string | undefined;
@@ -326,18 +338,24 @@ export declare const projectsCrud: import("../../crud").CrudSchemaFromOptions<{
326
338
  is_production_mode: undefined;
327
339
  config: undefined;
328
340
  }, "">;
341
+ adminDeleteSchema: import("yup").MixedSchema<{} | undefined, import("yup").AnyObject, undefined, "">;
329
342
  docs: {
330
343
  clientRead: {
331
344
  summary: string;
332
345
  description: string;
333
346
  tags: string[];
334
347
  };
335
- serverRead: {
348
+ adminRead: {
336
349
  summary: string;
337
350
  description: string;
338
351
  tags: string[];
339
352
  };
340
- serverUpdate: {
353
+ adminUpdate: {
354
+ summary: string;
355
+ description: string;
356
+ tags: string[];
357
+ };
358
+ adminDelete: {
341
359
  summary: string;
342
360
  description: string;
343
361
  tags: string[];
@@ -359,6 +377,7 @@ export declare const internalProjectsCrud: import("../../crud").CrudSchemaFromOp
359
377
  sign_up_enabled: NonNullable<boolean | undefined>;
360
378
  credential_enabled: NonNullable<boolean | undefined>;
361
379
  magic_link_enabled: NonNullable<boolean | undefined>;
380
+ client_team_creation_enabled: NonNullable<boolean | undefined>;
362
381
  oauth_providers: {
363
382
  client_id?: string | undefined;
364
383
  client_secret?: string | undefined;
@@ -404,6 +423,7 @@ export declare const internalProjectsCrud: import("../../crud").CrudSchemaFromOp
404
423
  sign_up_enabled: undefined;
405
424
  credential_enabled: undefined;
406
425
  magic_link_enabled: undefined;
426
+ client_team_creation_enabled: undefined;
407
427
  oauth_providers: undefined;
408
428
  enabled_oauth_providers: undefined;
409
429
  domains: undefined;
@@ -430,6 +450,7 @@ export declare const internalProjectsCrud: import("../../crud").CrudSchemaFromOp
430
450
  sign_up_enabled?: boolean | undefined;
431
451
  credential_enabled?: boolean | undefined;
432
452
  magic_link_enabled?: boolean | undefined;
453
+ client_team_creation_enabled?: boolean | undefined;
433
454
  oauth_providers?: {
434
455
  client_id?: string | undefined;
435
456
  client_secret?: string | undefined;
@@ -29,7 +29,7 @@ const domainSchema = yupObject({
29
29
  domain: schemaFields.domainSchema.required(),
30
30
  handler_path: schemaFields.handlerPathSchema.required(),
31
31
  });
32
- export const projectsCrudServerReadSchema = yupObject({
32
+ export const projectsCrudAdminReadSchema = yupObject({
33
33
  id: schemaFields.projectIdSchema.required(),
34
34
  display_name: schemaFields.projectDisplayNameSchema.required(),
35
35
  description: schemaFields.projectDescriptionSchema.nonNullable().defined(),
@@ -42,6 +42,7 @@ export const projectsCrudServerReadSchema = yupObject({
42
42
  sign_up_enabled: schemaFields.projectSignUpEnabledSchema.required(),
43
43
  credential_enabled: schemaFields.projectCredentialEnabledSchema.required(),
44
44
  magic_link_enabled: schemaFields.projectMagicLinkEnabledSchema.required(),
45
+ client_team_creation_enabled: schemaFields.projectClientTeamCreationEnabledSchema.required(),
45
46
  oauth_providers: yupArray(oauthProviderSchema.required()).required(),
46
47
  enabled_oauth_providers: yupArray(enabledOAuthProviderSchema.required()).required(),
47
48
  domains: yupArray(domainSchema.required()).required(),
@@ -58,10 +59,11 @@ export const projectsCrudClientReadSchema = yupObject({
58
59
  sign_up_enabled: schemaFields.projectSignUpEnabledSchema.required(),
59
60
  credential_enabled: schemaFields.projectCredentialEnabledSchema.required(),
60
61
  magic_link_enabled: schemaFields.projectMagicLinkEnabledSchema.required(),
62
+ client_team_creation_enabled: schemaFields.projectClientTeamCreationEnabledSchema.required(),
61
63
  enabled_oauth_providers: yupArray(enabledOAuthProviderSchema.required()).required(),
62
64
  }).required(),
63
65
  }).required();
64
- export const projectsCrudServerUpdateSchema = yupObject({
66
+ export const projectsCrudAdminUpdateSchema = yupObject({
65
67
  display_name: schemaFields.projectDisplayNameSchema.optional(),
66
68
  description: schemaFields.projectDescriptionSchema.optional(),
67
69
  is_production_mode: schemaFields.projectIsProductionModeSchema.optional(),
@@ -69,6 +71,7 @@ export const projectsCrudServerUpdateSchema = yupObject({
69
71
  sign_up_enabled: schemaFields.projectSignUpEnabledSchema.optional(),
70
72
  credential_enabled: schemaFields.projectCredentialEnabledSchema.optional(),
71
73
  magic_link_enabled: schemaFields.projectMagicLinkEnabledSchema.optional(),
74
+ client_team_creation_enabled: schemaFields.projectClientTeamCreationEnabledSchema.optional(),
72
75
  allow_localhost: schemaFields.projectAllowLocalhostSchema.optional(),
73
76
  email_config: emailConfigSchema.optional().default(undefined),
74
77
  domains: yupArray(domainSchema.required()).optional().default(undefined),
@@ -78,34 +81,41 @@ export const projectsCrudServerUpdateSchema = yupObject({
78
81
  team_member_default_permissions: yupArray(teamPermissionSchema.required()).optional(),
79
82
  }).optional().default(undefined),
80
83
  }).required();
81
- export const projectsCrudServerCreateSchema = projectsCrudServerUpdateSchema.concat(yupObject({
84
+ export const projectsCrudAdminCreateSchema = projectsCrudAdminUpdateSchema.concat(yupObject({
82
85
  display_name: schemaFields.projectDisplayNameSchema.required(),
83
86
  }).required());
87
+ export const projectsCrudAdminDeleteSchema = schemaFields.yupMixed();
84
88
  export const projectsCrud = createCrud({
85
89
  clientReadSchema: projectsCrudClientReadSchema,
86
- serverReadSchema: projectsCrudServerReadSchema,
87
- serverUpdateSchema: projectsCrudServerUpdateSchema,
90
+ adminReadSchema: projectsCrudAdminReadSchema,
91
+ adminUpdateSchema: projectsCrudAdminUpdateSchema,
92
+ adminDeleteSchema: projectsCrudAdminDeleteSchema,
88
93
  docs: {
89
94
  clientRead: {
90
95
  summary: 'Get the current project',
91
96
  description: 'Get the current project information including display name, oauth providers and authentication methods. Useful for display the available login options to the user.',
92
97
  tags: ['Projects'],
93
98
  },
94
- serverRead: {
99
+ adminRead: {
95
100
  summary: 'Get the current project',
96
101
  description: 'Get the current project information and configuration including display name, oauth providers, email configuration, etc.',
97
102
  tags: ['Projects'],
98
103
  },
99
- serverUpdate: {
104
+ adminUpdate: {
100
105
  summary: 'Update the current project',
101
106
  description: 'Update the current project information and configuration including display name, oauth providers, email configuration, etc.',
102
107
  tags: ['Projects'],
103
108
  },
109
+ adminDelete: {
110
+ summary: 'Delete the current project',
111
+ description: 'Delete the current project and all associated data (including users, teams, API keys, project configs, etc.). Be careful, this action is irreversible.',
112
+ tags: ['Projects'],
113
+ },
104
114
  },
105
115
  });
106
116
  export const internalProjectsCrud = createCrud({
107
- clientReadSchema: projectsCrudServerReadSchema,
108
- clientCreateSchema: projectsCrudServerCreateSchema,
117
+ clientReadSchema: projectsCrudAdminReadSchema,
118
+ clientCreateSchema: projectsCrudAdminCreateSchema,
109
119
  docs: {
110
120
  clientList: {
111
121
  hidden: true,
@@ -10,6 +10,89 @@ export declare const teamMemberProfilesCrudClientReadSchema: import("yup").Objec
10
10
  display_name: undefined;
11
11
  profile_image_url: undefined;
12
12
  }, "">;
13
+ export declare const teamMemberProfilesCrudServerReadSchema: import("yup").ObjectSchema<NonNullable<{
14
+ team_id: string;
15
+ user_id: string;
16
+ display_name: string | null;
17
+ profile_image_url: string | null;
18
+ } & {
19
+ user: {
20
+ id: string;
21
+ display_name: string | null;
22
+ oauth_providers: {
23
+ email?: string | null | undefined;
24
+ id: string;
25
+ account_id: string;
26
+ }[];
27
+ primary_email: string | null;
28
+ profile_image_url: string | null;
29
+ client_metadata: {} | null;
30
+ server_metadata: {} | null;
31
+ primary_email_verified: NonNullable<boolean | undefined>;
32
+ selected_team_id: string | null;
33
+ selected_team: {
34
+ id: string;
35
+ created_at_millis: number;
36
+ display_name: string;
37
+ profile_image_url: string | null;
38
+ } | null;
39
+ signed_up_at_millis: number;
40
+ has_password: NonNullable<boolean | undefined>;
41
+ auth_with_email: NonNullable<boolean | undefined>;
42
+ requires_totp_mfa: NonNullable<boolean | undefined>;
43
+ auth_methods: ({
44
+ type: "password";
45
+ identifier: string;
46
+ } | {
47
+ type: "otp";
48
+ contact_channel: {
49
+ type: "email";
50
+ email: string;
51
+ };
52
+ } | {
53
+ type: "oauth";
54
+ provider: {
55
+ type: string;
56
+ provider_user_id: string;
57
+ };
58
+ })[];
59
+ connected_accounts: {
60
+ type: "oauth";
61
+ provider: {
62
+ type: string;
63
+ provider_user_id: string;
64
+ };
65
+ }[];
66
+ };
67
+ }>, import("yup").AnyObject, {
68
+ team_id: undefined;
69
+ user_id: undefined;
70
+ display_name: undefined;
71
+ profile_image_url: undefined;
72
+ user: {
73
+ id: undefined;
74
+ primary_email: undefined;
75
+ primary_email_verified: undefined;
76
+ display_name: undefined;
77
+ selected_team: {
78
+ id: undefined;
79
+ display_name: undefined;
80
+ profile_image_url: undefined;
81
+ created_at_millis: undefined;
82
+ };
83
+ selected_team_id: undefined;
84
+ profile_image_url: undefined;
85
+ signed_up_at_millis: undefined;
86
+ has_password: undefined;
87
+ auth_with_email: undefined;
88
+ requires_totp_mfa: undefined;
89
+ oauth_providers: undefined;
90
+ auth_methods: undefined;
91
+ connected_accounts: undefined;
92
+ client_metadata: undefined;
93
+ server_metadata: undefined;
94
+ };
95
+ }, "">;
13
96
  export declare const teamMemberProfilesCrudClientUpdateSchema: import("yup").ObjectSchema<{
14
97
  display_name: string | undefined;
15
98
  profile_image_url: string | null | undefined;
@@ -29,6 +112,89 @@ export declare const teamMemberProfilesCrud: import("../../crud").CrudSchemaFrom
29
112
  display_name: undefined;
30
113
  profile_image_url: undefined;
31
114
  }, "">;
115
+ serverReadSchema: import("yup").ObjectSchema<NonNullable<{
116
+ team_id: string;
117
+ user_id: string;
118
+ display_name: string | null;
119
+ profile_image_url: string | null;
120
+ } & {
121
+ user: {
122
+ id: string;
123
+ display_name: string | null;
124
+ oauth_providers: {
125
+ email?: string | null | undefined;
126
+ id: string;
127
+ account_id: string;
128
+ }[];
129
+ primary_email: string | null;
130
+ profile_image_url: string | null;
131
+ client_metadata: {} | null;
132
+ server_metadata: {} | null;
133
+ primary_email_verified: NonNullable<boolean | undefined>;
134
+ selected_team_id: string | null;
135
+ selected_team: {
136
+ id: string;
137
+ created_at_millis: number;
138
+ display_name: string;
139
+ profile_image_url: string | null;
140
+ } | null;
141
+ signed_up_at_millis: number;
142
+ has_password: NonNullable<boolean | undefined>;
143
+ auth_with_email: NonNullable<boolean | undefined>;
144
+ requires_totp_mfa: NonNullable<boolean | undefined>;
145
+ auth_methods: ({
146
+ type: "password";
147
+ identifier: string;
148
+ } | {
149
+ type: "otp";
150
+ contact_channel: {
151
+ type: "email";
152
+ email: string;
153
+ };
154
+ } | {
155
+ type: "oauth";
156
+ provider: {
157
+ type: string;
158
+ provider_user_id: string;
159
+ };
160
+ })[];
161
+ connected_accounts: {
162
+ type: "oauth";
163
+ provider: {
164
+ type: string;
165
+ provider_user_id: string;
166
+ };
167
+ }[];
168
+ };
169
+ }>, import("yup").AnyObject, {
170
+ team_id: undefined;
171
+ user_id: undefined;
172
+ display_name: undefined;
173
+ profile_image_url: undefined;
174
+ user: {
175
+ id: undefined;
176
+ primary_email: undefined;
177
+ primary_email_verified: undefined;
178
+ display_name: undefined;
179
+ selected_team: {
180
+ id: undefined;
181
+ display_name: undefined;
182
+ profile_image_url: undefined;
183
+ created_at_millis: undefined;
184
+ };
185
+ selected_team_id: undefined;
186
+ profile_image_url: undefined;
187
+ signed_up_at_millis: undefined;
188
+ has_password: undefined;
189
+ auth_with_email: undefined;
190
+ requires_totp_mfa: undefined;
191
+ oauth_providers: undefined;
192
+ auth_methods: undefined;
193
+ connected_accounts: undefined;
194
+ client_metadata: undefined;
195
+ server_metadata: undefined;
196
+ };
197
+ }, "">;
32
198
  clientUpdateSchema: import("yup").ObjectSchema<{
33
199
  display_name: string | undefined;
34
200
  profile_image_url: string | null | undefined;
@@ -1,18 +1,23 @@
1
1
  import { createCrud } from "../../crud";
2
2
  import * as schemaFields from "../../schema-fields";
3
3
  import { yupObject } from "../../schema-fields";
4
+ import { usersCrudServerReadSchema } from "./users";
4
5
  export const teamMemberProfilesCrudClientReadSchema = yupObject({
5
6
  team_id: schemaFields.teamIdSchema.required(),
6
7
  user_id: schemaFields.userIdSchema.required(),
7
8
  display_name: schemaFields.teamMemberDisplayNameSchema.nullable().defined(),
8
9
  profile_image_url: schemaFields.teamMemberProfileImageUrlSchema.nullable().defined(),
9
10
  }).required();
11
+ export const teamMemberProfilesCrudServerReadSchema = teamMemberProfilesCrudClientReadSchema.concat(yupObject({
12
+ user: usersCrudServerReadSchema.required(),
13
+ })).required();
10
14
  export const teamMemberProfilesCrudClientUpdateSchema = yupObject({
11
15
  display_name: schemaFields.teamMemberDisplayNameSchema.optional(),
12
16
  profile_image_url: schemaFields.teamMemberProfileImageUrlSchema.nullable().optional(),
13
17
  }).required();
14
18
  export const teamMemberProfilesCrud = createCrud({
15
19
  clientReadSchema: teamMemberProfilesCrudClientReadSchema,
20
+ serverReadSchema: teamMemberProfilesCrudServerReadSchema,
16
21
  clientUpdateSchema: teamMemberProfilesCrudClientUpdateSchema,
17
22
  docs: {
18
23
  clientList: {
@@ -4,6 +4,7 @@ import { Result } from "../utils/results";
4
4
  import { ClientInterfaceOptions, StackClientInterface } from "./clientInterface";
5
5
  import { CurrentUserCrud } from "./crud/current-user";
6
6
  import { ConnectedAccountAccessTokenCrud } from "./crud/oauth";
7
+ import { TeamMemberProfilesCrud } from "./crud/team-member-profiles";
7
8
  import { TeamMembershipsCrud } from "./crud/team-memberships";
8
9
  import { TeamPermissionsCrud } from "./crud/team-permissions";
9
10
  import { TeamsCrud } from "./crud/teams";
@@ -31,6 +32,13 @@ export declare class StackServerInterface extends StackClientInterface {
31
32
  createServerUser(data: UsersCrud['Server']['Create']): Promise<UsersCrud['Server']['Read']>;
32
33
  getServerUserByToken(session: InternalSession): Promise<CurrentUserCrud['Server']['Read'] | null>;
33
34
  getServerUserById(userId: string): Promise<Result<UsersCrud['Server']['Read']>>;
35
+ listServerTeamMemberProfiles(options: {
36
+ teamId: string;
37
+ }): Promise<TeamMemberProfilesCrud['Server']['Read'][]>;
38
+ getServerTeamMemberProfile(options: {
39
+ teamId: string;
40
+ userId: string;
41
+ }): Promise<TeamMemberProfilesCrud['Client']['Read']>;
34
42
  listServerTeamPermissions(options: {
35
43
  userId?: string;
36
44
  teamId?: string;
@@ -58,6 +66,10 @@ export declare class StackServerInterface extends StackClientInterface {
58
66
  accessToken: string;
59
67
  refreshToken: string;
60
68
  }>;
69
+ leaveServerTeam(options: {
70
+ teamId: string;
71
+ userId: string;
72
+ }): Promise<void>;
61
73
  grantServerTeamUserPermission(teamId: string, userId: string, permissionId: string): Promise<void>;
62
74
  revokeServerTeamUserPermission(teamId: string, userId: string, permissionId: string): Promise<void>;
63
75
  deleteServerServerUser(userId: string): Promise<void>;
@@ -63,6 +63,15 @@ 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 listServerTeamMemberProfiles(options) {
67
+ const response = await this.sendServerRequest("/team-member-profiles?team_id=" + options.teamId, {}, null);
68
+ const result = await response.json();
69
+ return result.items;
70
+ }
71
+ async getServerTeamMemberProfile(options) {
72
+ const response = await this.sendServerRequest(`/team-member-profiles/${options.teamId}/${options.userId}`, {}, null);
73
+ return await response.json();
74
+ }
66
75
  async listServerTeamPermissions(options, session) {
67
76
  const response = await this.sendServerRequest("/team-permissions?" + new URLSearchParams(filterUndefined({
68
77
  user_id: options.userId,
@@ -169,6 +178,15 @@ export class StackServerInterface extends StackClientInterface {
169
178
  refreshToken: result.refresh_token,
170
179
  };
171
180
  }
181
+ async leaveServerTeam(options) {
182
+ await this.sendClientRequest(`/team-memberships/${options.teamId}/${options.userId}`, {
183
+ method: "DELETE",
184
+ headers: {
185
+ "content-type": "application/json",
186
+ },
187
+ body: JSON.stringify({}),
188
+ }, null);
189
+ }
172
190
  async grantServerTeamUserPermission(teamId, userId, permissionId) {
173
191
  await this.sendServerRequest(`/team-permissions/${teamId}/${userId}/${permissionId}`, {
174
192
  method: "POST",
@@ -206,7 +206,7 @@ const AdminAccessTokenExpired = createKnownErrorConstructor(InvalidAdminAccessTo
206
206
  ], () => []);
207
207
  const InvalidProjectForAdminAccessToken = createKnownErrorConstructor(InvalidAdminAccessToken, "INVALID_PROJECT_FOR_ADMIN_ACCESS_TOKEN", () => [
208
208
  401,
209
- "Admin access token not valid for this project.",
209
+ "Admin access tokens must be created on the internal project.",
210
210
  ], () => []);
211
211
  const AdminAccessTokenIsNotAdmin = createKnownErrorConstructor(InvalidAdminAccessToken, "ADMIN_ACCESS_TOKEN_IS_NOT_ADMIN", () => [
212
212
  401,
@@ -36,6 +36,7 @@ export declare const projectConfigIdSchema: yup.StringSchema<string | undefined,
36
36
  export declare const projectAllowLocalhostSchema: yup.BooleanSchema<boolean | undefined, yup.AnyObject, undefined, "">;
37
37
  export declare const projectCreateTeamOnSignUpSchema: yup.BooleanSchema<boolean | undefined, yup.AnyObject, undefined, "">;
38
38
  export declare const projectMagicLinkEnabledSchema: yup.BooleanSchema<boolean | undefined, yup.AnyObject, undefined, "">;
39
+ export declare const projectClientTeamCreationEnabledSchema: yup.BooleanSchema<boolean | undefined, yup.AnyObject, undefined, "">;
39
40
  export declare const projectSignUpEnabledSchema: yup.BooleanSchema<boolean | undefined, yup.AnyObject, undefined, "">;
40
41
  export declare const projectCredentialEnabledSchema: yup.BooleanSchema<boolean | undefined, yup.AnyObject, undefined, "">;
41
42
  export declare const oauthIdSchema: yup.StringSchema<"google" | "github" | "facebook" | "microsoft" | "spotify" | undefined, yup.AnyObject, undefined, "">;
@@ -40,15 +40,17 @@ export function yupTuple(...args) {
40
40
  export function yupObject(...args) {
41
41
  const object = yup.object(...args).test('no-unknown-object-properties', ({ path }) => `${path} contains unknown properties`, (value, context) => {
42
42
  if (context.options.context?.noUnknownPathPrefixes?.some((prefix) => context.path.startsWith(prefix))) {
43
- const availableKeys = new Set(Object.keys(context.schema.fields));
44
- const unknownKeys = Object.keys(value ?? {}).filter(key => !availableKeys.has(key));
45
- if (unknownKeys.length > 0) {
46
- // TODO "did you mean XYZ"
47
- return context.createError({
48
- message: `${context.path} contains unknown properties: ${unknownKeys.join(', ')}`,
49
- path: context.path,
50
- params: { unknownKeys },
51
- });
43
+ if (context.schema.spec.noUnknown !== false) {
44
+ const availableKeys = new Set(Object.keys(context.schema.fields));
45
+ const unknownKeys = Object.keys(value ?? {}).filter(key => !availableKeys.has(key));
46
+ if (unknownKeys.length > 0) {
47
+ // TODO "did you mean XYZ"
48
+ return context.createError({
49
+ message: `${context.path} contains unknown properties: ${unknownKeys.join(', ')}`,
50
+ path: context.path,
51
+ params: { unknownKeys },
52
+ });
53
+ }
52
54
  }
53
55
  }
54
56
  return true;
@@ -146,6 +148,7 @@ export const projectConfigIdSchema = yupString().meta({ openapiField: { descript
146
148
  export const projectAllowLocalhostSchema = yupBoolean().meta({ openapiField: { description: 'Whether localhost is allowed as a domain for this project. Should only be allowed in development mode', exampleValue: true } });
147
149
  export const projectCreateTeamOnSignUpSchema = yupBoolean().meta({ openapiField: { description: 'Whether a team should be created for each user that signs up', exampleValue: true } });
148
150
  export const projectMagicLinkEnabledSchema = yupBoolean().meta({ openapiField: { description: 'Whether magic link authentication is enabled for this project', exampleValue: true } });
151
+ export const projectClientTeamCreationEnabledSchema = yupBoolean().meta({ openapiField: { description: 'Whether client users can create teams', exampleValue: true } });
149
152
  export const projectSignUpEnabledSchema = yupBoolean().meta({ openapiField: { description: 'Whether users can sign up new accounts, or whether they are only allowed to sign in to existing accounts. Regardless of this option, the server API can always create new users with the `POST /users` endpoint.', exampleValue: true } });
150
153
  export const projectCredentialEnabledSchema = yupBoolean().meta({ openapiField: { description: 'Whether email password authentication is enabled for this project', exampleValue: true } });
151
154
  // Project OAuth config
@@ -2,10 +2,16 @@ import { Json } from "./json";
2
2
  export declare function throwErr(errorMessage: string, extraData?: any): never;
3
3
  export declare function throwErr(error: Error): never;
4
4
  export declare function throwErr(...args: StatusErrorConstructorParameters): never;
5
- export declare class StackAssertionError extends Error {
5
+ export declare class StackAssertionError extends Error implements ErrorWithCustomCapture {
6
6
  readonly extraData?: Record<string, any> | undefined;
7
7
  constructor(message: string, extraData?: Record<string, any> | undefined, options?: ErrorOptions);
8
+ customCaptureExtraArgs: {
9
+ cause?: {} | undefined;
10
+ }[];
8
11
  }
12
+ export type ErrorWithCustomCapture = {
13
+ customCaptureExtraArgs: any[];
14
+ };
9
15
  export declare function registerErrorSink(sink: (location: string, error: unknown) => void): void;
10
16
  export declare function captureError(location: string, error: unknown): void;
11
17
  type Status = {
@@ -16,6 +16,12 @@ export class StackAssertionError extends Error {
16
16
  const disclaimer = `\n\nThis is likely an error in Stack. Please make sure you are running the newest version and report it.`;
17
17
  super(`${message}${message.endsWith(disclaimer) ? "" : disclaimer}`, options);
18
18
  this.extraData = extraData;
19
+ this.customCaptureExtraArgs = [
20
+ {
21
+ ...this.extraData,
22
+ ...this.cause ? { cause: this.cause } : {},
23
+ },
24
+ ];
19
25
  }
20
26
  }
21
27
  StackAssertionError.prototype.name = "StackAssertionError";
@@ -35,7 +41,7 @@ registerErrorSink((location, error, ...extraArgs) => {
35
41
  });
36
42
  export function captureError(location, error) {
37
43
  for (const sink of errorSinks) {
38
- sink(location, error);
44
+ sink(location, error, ...error && (typeof error === 'object' || typeof error === 'function') && "customCaptureExtraArgs" in error && Array.isArray(error.customCaptureExtraArgs) ? error.customCaptureExtraArgs : []);
39
45
  }
40
46
  }
41
47
  export class StatusError extends Error {
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@stackframe/stack-shared",
3
- "version": "2.5.18",
3
+ "version": "2.5.20",
4
4
  "main": "./dist/index.js",
5
5
  "types": "./dist/index.d.ts",
6
6
  "files": [
@@ -36,7 +36,7 @@
36
36
  "jose": "^5.2.2",
37
37
  "oauth4webapi": "^2.10.3",
38
38
  "uuid": "^9.0.1",
39
- "@stackframe/stack-sc": "2.5.18"
39
+ "@stackframe/stack-sc": "2.5.20"
40
40
  },
41
41
  "devDependencies": {
42
42
  "rimraf": "^5.0.5",