@stackframe/stack-shared 2.5.35 → 2.6.0

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 (38) hide show
  1. package/CHANGELOG.md +26 -0
  2. package/dist/interface/clientInterface.d.ts +14 -11
  3. package/dist/interface/clientInterface.js +35 -16
  4. package/dist/interface/crud/current-user.d.ts +6 -6
  5. package/dist/interface/crud/current-user.js +2 -2
  6. package/dist/interface/crud/projects.d.ts +26 -12
  7. package/dist/interface/crud/projects.js +3 -0
  8. package/dist/interface/crud/team-member-profiles.d.ts +6 -6
  9. package/dist/interface/crud/users.d.ts +16 -12
  10. package/dist/interface/crud/users.js +3 -0
  11. package/dist/interface/webhooks.d.ts +8 -4
  12. package/dist/known-errors.d.ts +8 -0
  13. package/dist/known-errors.js +10 -0
  14. package/dist/schema-fields.d.ts +6 -2
  15. package/dist/schema-fields.js +63 -5
  16. package/dist/utils/jwt.d.ts +1 -1
  17. package/dist/utils/jwt.js +2 -2
  18. package/dist/utils/oauth.d.ts +2 -2
  19. package/dist/utils/oauth.js +1 -1
  20. package/package.json +4 -2
  21. package/dist/interface/crud-deprecated/api-keys.d.ts +0 -134
  22. package/dist/interface/crud-deprecated/api-keys.js +0 -61
  23. package/dist/interface/crud-deprecated/current-user.d.ts +0 -127
  24. package/dist/interface/crud-deprecated/current-user.js +0 -49
  25. package/dist/interface/crud-deprecated/email-templates.d.ts +0 -75
  26. package/dist/interface/crud-deprecated/email-templates.js +0 -41
  27. package/dist/interface/crud-deprecated/oauth.d.ts +0 -24
  28. package/dist/interface/crud-deprecated/oauth.js +0 -12
  29. package/dist/interface/crud-deprecated/projects.d.ts +0 -440
  30. package/dist/interface/crud-deprecated/projects.js +0 -109
  31. package/dist/interface/crud-deprecated/team-memberships.d.ts +0 -22
  32. package/dist/interface/crud-deprecated/team-memberships.js +0 -22
  33. package/dist/interface/crud-deprecated/team-permissions.d.ts +0 -129
  34. package/dist/interface/crud-deprecated/team-permissions.js +0 -83
  35. package/dist/interface/crud-deprecated/teams.d.ts +0 -126
  36. package/dist/interface/crud-deprecated/teams.js +0 -78
  37. package/dist/interface/crud-deprecated/users.d.ts +0 -199
  38. package/dist/interface/crud-deprecated/users.js +0 -75
@@ -61,7 +61,7 @@ export declare const usersCrudServerReadSchema: import("yup").ObjectSchema<{
61
61
  } | {
62
62
  type: "oauth";
63
63
  provider: {
64
- type: NonNullable<"google" | "github" | "microsoft" | "spotify" | "facebook" | "discord" | "gitlab" | "bitbucket" | "linkedin" | undefined>;
64
+ type: NonNullable<"google" | "github" | "microsoft" | "spotify" | "facebook" | "discord" | "gitlab" | "bitbucket" | "linkedin" | "apple" | "x" | undefined>;
65
65
  id: string;
66
66
  provider_user_id: string;
67
67
  };
@@ -69,7 +69,7 @@ export declare const usersCrudServerReadSchema: import("yup").ObjectSchema<{
69
69
  connected_accounts: {
70
70
  type: "oauth";
71
71
  provider: {
72
- type: NonNullable<"google" | "github" | "microsoft" | "spotify" | "facebook" | "discord" | "gitlab" | "bitbucket" | "linkedin" | undefined>;
72
+ type: NonNullable<"google" | "github" | "microsoft" | "spotify" | "facebook" | "discord" | "gitlab" | "bitbucket" | "linkedin" | "apple" | "x" | undefined>;
73
73
  id: string;
74
74
  provider_user_id: string;
75
75
  };
@@ -107,9 +107,9 @@ export declare const usersCrudServerReadSchema: import("yup").ObjectSchema<{
107
107
  last_active_at_millis: undefined;
108
108
  }, "">;
109
109
  export declare const usersCrudServerCreateSchema: import("yup").ObjectSchema<{
110
+ primary_email: string | null | undefined;
110
111
  password: string | null | undefined;
111
112
  display_name: string | null | undefined;
112
- primary_email: string | null | undefined;
113
113
  profile_image_url: string | null | undefined;
114
114
  client_metadata: {} | null | undefined;
115
115
  client_read_only_metadata: {} | null | undefined;
@@ -119,8 +119,8 @@ export declare const usersCrudServerCreateSchema: import("yup").ObjectSchema<{
119
119
  totp_secret_base64: string | null | undefined;
120
120
  } & {
121
121
  oauth_providers: {
122
- id: string;
123
122
  email: string | null;
123
+ id: string;
124
124
  account_id: string;
125
125
  }[] | undefined;
126
126
  }, import("yup").AnyObject, {
@@ -176,7 +176,7 @@ export declare const usersCrud: import("../../crud").CrudSchemaFromOptions<{
176
176
  } | {
177
177
  type: "oauth";
178
178
  provider: {
179
- type: NonNullable<"google" | "github" | "microsoft" | "spotify" | "facebook" | "discord" | "gitlab" | "bitbucket" | "linkedin" | undefined>;
179
+ type: NonNullable<"google" | "github" | "microsoft" | "spotify" | "facebook" | "discord" | "gitlab" | "bitbucket" | "linkedin" | "apple" | "x" | undefined>;
180
180
  id: string;
181
181
  provider_user_id: string;
182
182
  };
@@ -184,7 +184,7 @@ export declare const usersCrud: import("../../crud").CrudSchemaFromOptions<{
184
184
  connected_accounts: {
185
185
  type: "oauth";
186
186
  provider: {
187
- type: NonNullable<"google" | "github" | "microsoft" | "spotify" | "facebook" | "discord" | "gitlab" | "bitbucket" | "linkedin" | undefined>;
187
+ type: NonNullable<"google" | "github" | "microsoft" | "spotify" | "facebook" | "discord" | "gitlab" | "bitbucket" | "linkedin" | "apple" | "x" | undefined>;
188
188
  id: string;
189
189
  provider_user_id: string;
190
190
  };
@@ -247,9 +247,9 @@ export declare const usersCrud: import("../../crud").CrudSchemaFromOptions<{
247
247
  selected_team_id: undefined;
248
248
  }, "">;
249
249
  serverCreateSchema: import("yup").ObjectSchema<{
250
+ primary_email: string | null | undefined;
250
251
  password: string | null | undefined;
251
252
  display_name: string | null | undefined;
252
- primary_email: string | null | undefined;
253
253
  profile_image_url: string | null | undefined;
254
254
  client_metadata: {} | null | undefined;
255
255
  client_read_only_metadata: {} | null | undefined;
@@ -259,8 +259,8 @@ export declare const usersCrud: import("../../crud").CrudSchemaFromOptions<{
259
259
  totp_secret_base64: string | null | undefined;
260
260
  } & {
261
261
  oauth_providers: {
262
- id: string;
263
262
  email: string | null;
263
+ id: string;
264
264
  account_id: string;
265
265
  }[] | undefined;
266
266
  }, import("yup").AnyObject, {
@@ -346,7 +346,7 @@ export declare const userCreatedWebhookEvent: {
346
346
  } | {
347
347
  type: "oauth";
348
348
  provider: {
349
- type: NonNullable<"google" | "github" | "microsoft" | "spotify" | "facebook" | "discord" | "gitlab" | "bitbucket" | "linkedin" | undefined>;
349
+ type: NonNullable<"google" | "github" | "microsoft" | "spotify" | "facebook" | "discord" | "gitlab" | "bitbucket" | "linkedin" | "apple" | "x" | undefined>;
350
350
  id: string;
351
351
  provider_user_id: string;
352
352
  };
@@ -354,7 +354,7 @@ export declare const userCreatedWebhookEvent: {
354
354
  connected_accounts: {
355
355
  type: "oauth";
356
356
  provider: {
357
- type: NonNullable<"google" | "github" | "microsoft" | "spotify" | "facebook" | "discord" | "gitlab" | "bitbucket" | "linkedin" | undefined>;
357
+ type: NonNullable<"google" | "github" | "microsoft" | "spotify" | "facebook" | "discord" | "gitlab" | "bitbucket" | "linkedin" | "apple" | "x" | undefined>;
358
358
  id: string;
359
359
  provider_user_id: string;
360
360
  };
@@ -436,7 +436,7 @@ export declare const userUpdatedWebhookEvent: {
436
436
  } | {
437
437
  type: "oauth";
438
438
  provider: {
439
- type: NonNullable<"google" | "github" | "microsoft" | "spotify" | "facebook" | "discord" | "gitlab" | "bitbucket" | "linkedin" | undefined>;
439
+ type: NonNullable<"google" | "github" | "microsoft" | "spotify" | "facebook" | "discord" | "gitlab" | "bitbucket" | "linkedin" | "apple" | "x" | undefined>;
440
440
  id: string;
441
441
  provider_user_id: string;
442
442
  };
@@ -444,7 +444,7 @@ export declare const userUpdatedWebhookEvent: {
444
444
  connected_accounts: {
445
445
  type: "oauth";
446
446
  provider: {
447
- type: NonNullable<"google" | "github" | "microsoft" | "spotify" | "facebook" | "discord" | "gitlab" | "bitbucket" | "linkedin" | undefined>;
447
+ type: NonNullable<"google" | "github" | "microsoft" | "spotify" | "facebook" | "discord" | "gitlab" | "bitbucket" | "linkedin" | "apple" | "x" | undefined>;
448
448
  id: string;
449
449
  provider_user_id: string;
450
450
  };
@@ -491,8 +491,12 @@ export declare const userDeletedWebhookEvent: {
491
491
  type: string;
492
492
  schema: import("yup").ObjectSchema<{
493
493
  id: string;
494
+ teams: {
495
+ id: string;
496
+ }[];
494
497
  }, import("yup").AnyObject, {
495
498
  id: undefined;
499
+ teams: undefined;
496
500
  }, "">;
497
501
  metadata: {
498
502
  summary: string;
@@ -123,6 +123,9 @@ export const userUpdatedWebhookEvent = {
123
123
  };
124
124
  const webhookUserDeletedSchema = fieldSchema.yupObject({
125
125
  id: fieldSchema.userIdSchema.required(),
126
+ teams: fieldSchema.yupArray(fieldSchema.yupObject({
127
+ id: fieldSchema.yupString().required(),
128
+ })).required(),
126
129
  }).required();
127
130
  export const userDeletedWebhookEvent = {
128
131
  type: "user.deleted",
@@ -47,7 +47,7 @@ export declare const webhookEvents: readonly [{
47
47
  } | {
48
48
  type: "oauth";
49
49
  provider: {
50
- type: NonNullable<"google" | "github" | "microsoft" | "spotify" | "facebook" | "discord" | "gitlab" | "bitbucket" | "linkedin" | undefined>;
50
+ type: NonNullable<"google" | "github" | "microsoft" | "spotify" | "facebook" | "discord" | "gitlab" | "bitbucket" | "linkedin" | "apple" | "x" | undefined>;
51
51
  id: string;
52
52
  provider_user_id: string;
53
53
  };
@@ -55,7 +55,7 @@ export declare const webhookEvents: readonly [{
55
55
  connected_accounts: {
56
56
  type: "oauth";
57
57
  provider: {
58
- type: NonNullable<"google" | "github" | "microsoft" | "spotify" | "facebook" | "discord" | "gitlab" | "bitbucket" | "linkedin" | undefined>;
58
+ type: NonNullable<"google" | "github" | "microsoft" | "spotify" | "facebook" | "discord" | "gitlab" | "bitbucket" | "linkedin" | "apple" | "x" | undefined>;
59
59
  id: string;
60
60
  provider_user_id: string;
61
61
  };
@@ -136,7 +136,7 @@ export declare const webhookEvents: readonly [{
136
136
  } | {
137
137
  type: "oauth";
138
138
  provider: {
139
- type: NonNullable<"google" | "github" | "microsoft" | "spotify" | "facebook" | "discord" | "gitlab" | "bitbucket" | "linkedin" | undefined>;
139
+ type: NonNullable<"google" | "github" | "microsoft" | "spotify" | "facebook" | "discord" | "gitlab" | "bitbucket" | "linkedin" | "apple" | "x" | undefined>;
140
140
  id: string;
141
141
  provider_user_id: string;
142
142
  };
@@ -144,7 +144,7 @@ export declare const webhookEvents: readonly [{
144
144
  connected_accounts: {
145
145
  type: "oauth";
146
146
  provider: {
147
- type: NonNullable<"google" | "github" | "microsoft" | "spotify" | "facebook" | "discord" | "gitlab" | "bitbucket" | "linkedin" | undefined>;
147
+ type: NonNullable<"google" | "github" | "microsoft" | "spotify" | "facebook" | "discord" | "gitlab" | "bitbucket" | "linkedin" | "apple" | "x" | undefined>;
148
148
  id: string;
149
149
  provider_user_id: string;
150
150
  };
@@ -190,8 +190,12 @@ export declare const webhookEvents: readonly [{
190
190
  type: string;
191
191
  schema: yup.ObjectSchema<{
192
192
  id: string;
193
+ teams: {
194
+ id: string;
195
+ }[];
193
196
  }, yup.AnyObject, {
194
197
  id: undefined;
198
+ teams: undefined;
195
199
  }, "">;
196
200
  metadata: {
197
201
  summary: string;
@@ -291,6 +291,11 @@ export declare const KnownErrors: {
291
291
  } & KnownErrorBrand<"VERIFICATION_CODE_ALREADY_USED">, []> & {
292
292
  errorCode: "VERIFICATION_CODE_ALREADY_USED";
293
293
  };
294
+ VerificationCodeMaxAttemptsReached: KnownErrorConstructor<KnownError & KnownErrorBrand<"VERIFICATION_ERROR"> & {
295
+ constructorArgs: [statusCode: number, humanReadableMessage: string, details?: Json | undefined];
296
+ } & KnownErrorBrand<"VERIFICATION_CODE_MAX_ATTEMPTS_REACHED">, []> & {
297
+ errorCode: "VERIFICATION_CODE_MAX_ATTEMPTS_REACHED";
298
+ };
294
299
  PasswordConfirmationMismatch: KnownErrorConstructor<KnownError & KnownErrorBrand<"PASSWORD_CONFIRMATION_MISMATCH">, []> & {
295
300
  errorCode: "PASSWORD_CONFIRMATION_MISMATCH";
296
301
  };
@@ -375,5 +380,8 @@ export declare const KnownErrors: {
375
380
  TeamPermissionNotFound: KnownErrorConstructor<KnownError & KnownErrorBrand<"TEAM_PERMISSION_NOT_FOUND">, [any, any, any]> & {
376
381
  errorCode: "TEAM_PERMISSION_NOT_FOUND";
377
382
  };
383
+ OAuthProviderAccessDenied: KnownErrorConstructor<KnownError & KnownErrorBrand<"OAUTH_PROVIDER_ACCESS_DENIED">, []> & {
384
+ errorCode: "OAUTH_PROVIDER_ACCESS_DENIED";
385
+ };
378
386
  };
379
387
  export {};
@@ -372,6 +372,10 @@ const VerificationCodeAlreadyUsed = createKnownErrorConstructor(VerificationCode
372
372
  400,
373
373
  "The verification link has already been used.",
374
374
  ], () => []);
375
+ const VerificationCodeMaxAttemptsReached = createKnownErrorConstructor(VerificationCodeError, "VERIFICATION_CODE_MAX_ATTEMPTS_REACHED", () => [
376
+ 400,
377
+ "The verification code nonce has reached the maximum number of attempts. This code is not valid anymore.",
378
+ ], () => []);
375
379
  const PasswordConfirmationMismatch = createKnownErrorConstructor(KnownError, "PASSWORD_CONFIRMATION_MISMATCH", () => [
376
380
  400,
377
381
  "Passwords do not match.",
@@ -530,6 +534,10 @@ const InvalidAuthorizationCode = createKnownErrorConstructor(KnownError, "INVALI
530
534
  400,
531
535
  "The given authorization code is invalid.",
532
536
  ], () => []);
537
+ const OAuthProviderAccessDenied = createKnownErrorConstructor(KnownError, "OAUTH_PROVIDER_ACCESS_DENIED", () => [
538
+ 400,
539
+ "The OAuth provider denied access to the user.",
540
+ ], () => []);
533
541
  export const KnownErrors = {
534
542
  UnsupportedError,
535
543
  BodyParsingError,
@@ -588,6 +596,7 @@ export const KnownErrors = {
588
596
  VerificationCodeNotFound,
589
597
  VerificationCodeExpired,
590
598
  VerificationCodeAlreadyUsed,
599
+ VerificationCodeMaxAttemptsReached,
591
600
  PasswordConfirmationMismatch,
592
601
  EmailAlreadyVerified,
593
602
  EmailNotAssociatedWithUser,
@@ -616,6 +625,7 @@ export const KnownErrors = {
616
625
  InvalidStandardOAuthProviderId,
617
626
  InvalidAuthorizationCode,
618
627
  TeamPermissionNotFound,
628
+ OAuthProviderAccessDenied,
619
629
  };
620
630
  // ensure that all known error codes are unique
621
631
  const knownErrorCodes = new Set();
@@ -1,4 +1,7 @@
1
1
  import * as yup from "yup";
2
+ export declare function yupValidate<S extends yup.ISchema<any>>(schema: S, obj: unknown, options?: yup.ValidateOptions & {
3
+ currentUserId?: string | null;
4
+ }): Promise<yup.InferType<S>>;
2
5
  declare const StackAdaptSentinel: unique symbol;
3
6
  export type StackAdaptSentinel = typeof StackAdaptSentinel;
4
7
  export declare function yupString<A extends string, B extends yup.Maybe<yup.AnyObject> = yup.AnyObject>(...args: Parameters<typeof yup.string<A, B>>): yup.StringSchema<string | undefined, yup.AnyObject, undefined, "">;
@@ -37,9 +40,10 @@ export declare const projectAllowLocalhostSchema: yup.BooleanSchema<boolean | un
37
40
  export declare const projectCreateTeamOnSignUpSchema: yup.BooleanSchema<boolean | undefined, yup.AnyObject, undefined, "">;
38
41
  export declare const projectMagicLinkEnabledSchema: yup.BooleanSchema<boolean | undefined, yup.AnyObject, undefined, "">;
39
42
  export declare const projectClientTeamCreationEnabledSchema: yup.BooleanSchema<boolean | undefined, yup.AnyObject, undefined, "">;
43
+ export declare const projectClientUserDeletionEnabledSchema: yup.BooleanSchema<boolean | undefined, yup.AnyObject, undefined, "">;
40
44
  export declare const projectSignUpEnabledSchema: yup.BooleanSchema<boolean | undefined, yup.AnyObject, undefined, "">;
41
45
  export declare const projectCredentialEnabledSchema: yup.BooleanSchema<boolean | undefined, yup.AnyObject, undefined, "">;
42
- export declare const oauthIdSchema: yup.StringSchema<"google" | "github" | "microsoft" | "spotify" | "facebook" | "discord" | "gitlab" | "bitbucket" | "linkedin" | undefined, yup.AnyObject, undefined, "">;
46
+ export declare const oauthIdSchema: yup.StringSchema<"google" | "github" | "microsoft" | "spotify" | "facebook" | "discord" | "gitlab" | "bitbucket" | "linkedin" | "apple" | "x" | undefined, yup.AnyObject, undefined, "">;
43
47
  export declare const oauthEnabledSchema: yup.BooleanSchema<boolean | undefined, yup.AnyObject, undefined, "">;
44
48
  export declare const oauthTypeSchema: yup.StringSchema<"shared" | "standard" | undefined, yup.AnyObject, undefined, "">;
45
49
  export declare const oauthClientIdSchema: yup.StringSchema<string | undefined, yup.AnyObject, undefined, "">;
@@ -70,7 +74,7 @@ export declare const userClientReadOnlyMetadataSchema: yup.MixedSchema<{} | null
70
74
  export declare const userServerMetadataSchema: yup.MixedSchema<{} | null, yup.AnyObject, undefined, "">;
71
75
  export declare const userOAuthProviderSchema: yup.ObjectSchema<{
72
76
  id: string;
73
- type: NonNullable<"google" | "github" | "microsoft" | "spotify" | "facebook" | "discord" | "gitlab" | "bitbucket" | "linkedin" | undefined>;
77
+ type: NonNullable<"google" | "github" | "microsoft" | "spotify" | "facebook" | "discord" | "gitlab" | "bitbucket" | "linkedin" | "apple" | "x" | undefined>;
74
78
  provider_user_id: string;
75
79
  }, yup.AnyObject, {
76
80
  id: undefined;
@@ -1,8 +1,58 @@
1
1
  import * as yup from "yup";
2
+ import { KnownErrors } from ".";
2
3
  import { isBase64 } from "./utils/bytes";
3
4
  import { StackAssertionError } from "./utils/errors";
4
5
  import { allProviders } from "./utils/oauth";
6
+ import { deepPlainClone, omit } from "./utils/objects";
5
7
  import { isUuid } from "./utils/uuids";
8
+ export async function yupValidate(schema, obj, options) {
9
+ try {
10
+ return await schema.validate(obj, {
11
+ ...omit(options ?? {}, ['currentUserId']),
12
+ context: {
13
+ ...options?.context,
14
+ stackAllowUserIdMe: options?.currentUserId !== undefined,
15
+ },
16
+ });
17
+ }
18
+ catch (error) {
19
+ if (error instanceof ReplaceFieldWithOwnUserId) {
20
+ const currentUserId = options?.currentUserId;
21
+ if (!currentUserId)
22
+ throw new KnownErrors.CannotGetOwnUserWithoutUser();
23
+ // parse yup path
24
+ let pathRemaining = error.path;
25
+ const fieldPath = [];
26
+ while (pathRemaining.length > 0) {
27
+ if (pathRemaining.startsWith("[")) {
28
+ const index = pathRemaining.indexOf("]");
29
+ if (index < 0)
30
+ throw new StackAssertionError("Invalid path");
31
+ fieldPath.push(JSON.parse(pathRemaining.slice(1, index)));
32
+ pathRemaining = pathRemaining.slice(index + 1);
33
+ }
34
+ else {
35
+ let dotIndex = pathRemaining.indexOf(".");
36
+ if (dotIndex === -1)
37
+ dotIndex = pathRemaining.length;
38
+ fieldPath.push(pathRemaining.slice(0, dotIndex));
39
+ pathRemaining = pathRemaining.slice(dotIndex + 1);
40
+ }
41
+ }
42
+ const newObj = deepPlainClone(obj);
43
+ let it = newObj;
44
+ for (const field of fieldPath.slice(0, -1)) {
45
+ if (!Object.prototype.hasOwnProperty.call(it, field)) {
46
+ throw new StackAssertionError(`Segment ${field} of path ${error.path} not found in object`);
47
+ }
48
+ it = it[field];
49
+ }
50
+ it[fieldPath[fieldPath.length - 1]] = currentUserId;
51
+ return await yupValidate(schema, newObj, options);
52
+ }
53
+ throw error;
54
+ }
55
+ }
6
56
  const _idDescription = (identify) => `The unique identifier of this ${identify}`;
7
57
  const _displayNameDescription = (identify) => `Human-readable ${identify} display name. This is not a unique identifier.`;
8
58
  const _clientMetaDataDescription = (identify) => `Client metadata. Used as a data store, accessible from the client side. Do not store information that should not be exposed to the client.`;
@@ -82,7 +132,10 @@ export function yupUnion(...args) {
82
132
  errors.push(e);
83
133
  }
84
134
  }
85
- throw new AggregateError(errors, 'Invalid value; must be one of the provided schemas');
135
+ return context.createError({
136
+ message: `${context.path} is not matched by any of the provided schemas:\n${errors.map((e, i) => '\tSchema ' + i + ": \n\t\t" + e.errors.join('\n\t\t')).join('\n')}`,
137
+ path: context.path,
138
+ });
86
139
  });
87
140
  }
88
141
  // Common
@@ -151,6 +204,7 @@ export const projectAllowLocalhostSchema = yupBoolean().meta({ openapiField: { d
151
204
  export const projectCreateTeamOnSignUpSchema = yupBoolean().meta({ openapiField: { description: 'Whether a team should be created for each user that signs up', exampleValue: true } });
152
205
  export const projectMagicLinkEnabledSchema = yupBoolean().meta({ openapiField: { description: 'Whether magic link authentication is enabled for this project', exampleValue: true } });
153
206
  export const projectClientTeamCreationEnabledSchema = yupBoolean().meta({ openapiField: { description: 'Whether client users can create teams', exampleValue: true } });
207
+ export const projectClientUserDeletionEnabledSchema = yupBoolean().meta({ openapiField: { description: 'Whether client users can delete their own account from the client', exampleValue: true } });
154
208
  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 } });
155
209
  export const projectCredentialEnabledSchema = yupBoolean().meta({ openapiField: { description: 'Whether email password authentication is enabled for this project', exampleValue: true } });
156
210
  // Project OAuth config
@@ -184,6 +238,10 @@ export const userIdOrMeSchema = yupString().uuid().transform(v => {
184
238
  else
185
239
  return v;
186
240
  }).test((v, context) => {
241
+ if (!("stackAllowUserIdMe" in (context.options.context ?? {})))
242
+ throw new StackAssertionError('userIdOrMeSchema is not allowed in this context. Make sure you\'re using yupValidate from schema-fields.ts to validate, instead of schema.validate(...).');
243
+ if (!context.options.context?.stackAllowUserIdMe)
244
+ throw new StackAssertionError('userIdOrMeSchema is not allowed in this context. Make sure you\'re passing in the currentUserId option in yupValidate.');
187
245
  if (v === userIdMeSentinelUuid)
188
246
  throw new ReplaceFieldWithOwnUserId(context.path);
189
247
  return true;
@@ -206,8 +264,8 @@ export const userOAuthProviderSchema = yupObject({
206
264
  export const userLastActiveAtMillisSchema = yupNumber().nullable().meta({ openapiField: { description: _lastActiveAtMillisDescription, exampleValue: 1630000000000 } });
207
265
  // Auth
208
266
  export const signInEmailSchema = emailSchema.meta({ openapiField: { description: 'The email to sign in with.', exampleValue: 'johndoe@example.com' } });
209
- export const emailOtpSignInCallbackUrlSchema = urlSchema.meta({ openapiField: { description: 'The base callback URL to construct the magic link from. A query argument `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' } });
210
- export const emailVerificationCallbackUrlSchema = urlSchema.meta({ openapiField: { description: 'The base callback URL to construct a verification link for the verification e-mail. A query argument `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' } });
267
+ 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' } });
268
+ 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' } });
211
269
  export const accessTokenResponseSchema = yupString().meta({ openapiField: { description: 'Short-lived access token that can be used to authenticate the user', exampleValue: 'eyJhmMiJB2TO...diI4QT' } });
212
270
  export const refreshTokenResponseSchema = yupString().meta({ openapiField: { description: 'Long-lived refresh token that can be used to obtain a new access token', exampleValue: 'i8ns3aq2...14y' } });
213
271
  export const signInResponseSchema = yupObject({
@@ -248,8 +306,8 @@ export const teamClientMetadataSchema = jsonSchema.meta({ openapiField: { descri
248
306
  export const teamClientReadOnlyMetadataSchema = jsonSchema.meta({ openapiField: { description: _clientReadOnlyMetaDataDescription('team'), exampleValue: { key: 'value' } } });
249
307
  export const teamServerMetadataSchema = jsonSchema.meta({ openapiField: { description: _serverMetaDataDescription('team'), exampleValue: { key: 'value' } } });
250
308
  export const teamCreatedAtMillisSchema = yupNumber().meta({ openapiField: { description: _createdAtMillisDescription('team'), exampleValue: 1630000000000 } });
251
- export const teamInvitationEmailSchema = emailSchema.meta({ openapiField: { description: 'The email to sign in with.', exampleValue: 'johndoe@example.com' } });
252
- export const teamInvitationCallbackUrlSchema = urlSchema.meta({ openapiField: { description: 'The base callback URL to construct a verification link for the verification e-mail. A query argument `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' } });
309
+ export const teamInvitationEmailSchema = emailSchema.meta({ openapiField: { description: 'The email of the user to invite.', exampleValue: 'johndoe@example.com' } });
310
+ export const teamInvitationCallbackUrlSchema = urlSchema.meta({ openapiField: { description: 'The base callback URL to construct an invite link with. A query parameter `code` with the verification code will be appended to it. The page should then make a request to the `/team-invitations/accept` endpoint.', exampleValue: 'https://example.com/handler/team-invitation' } });
253
311
  // Team member profiles
254
312
  export const teamMemberDisplayNameSchema = yupString().meta({ openapiField: { description: _displayNameDescription('team member') + ' Note that this is separate from the display_name of the user.', exampleValue: 'John Doe' } });
255
313
  export const teamMemberProfileImageUrlSchema = urlSchema.max(1000000).meta({ openapiField: { description: _profileImageUrlDescription('team member'), exampleValue: 'https://example.com/image.jpg' } });
@@ -15,7 +15,7 @@ export declare function getPublicJwkSet(): Promise<{
15
15
  d: string;
16
16
  x: string;
17
17
  y: string;
18
- }, "kty" | "crv" | "x" | "y">[];
18
+ }, "x" | "kty" | "crv" | "y">[];
19
19
  }>;
20
20
  export declare function encryptJWE(payload: any, expirationTime?: string): Promise<string>;
21
21
  export declare function decryptJWE(jwt: string): Promise<jose.JWTPayload>;
package/dist/utils/jwt.js CHANGED
@@ -1,8 +1,8 @@
1
+ import elliptic from "elliptic";
1
2
  import * as jose from "jose";
3
+ import { encodeBase64 } from "./bytes";
2
4
  import { getEnvVariable } from "./env";
3
- import elliptic from "elliptic";
4
5
  import { globalVar } from "./globals";
5
- import { encodeBase64 } from "./bytes";
6
6
  import { pick } from "./objects";
7
7
  const STACK_SERVER_SECRET = jose.base64url.decode(getEnvVariable("STACK_SERVER_SECRET"));
8
8
  export async function signJWT(issuer, payload, expirationTime = "5m") {
@@ -1,6 +1,6 @@
1
- export declare const standardProviders: readonly ["google", "github", "microsoft", "spotify", "facebook", "discord", "gitlab", "bitbucket", "linkedin"];
1
+ export declare const standardProviders: readonly ["google", "github", "microsoft", "spotify", "facebook", "discord", "gitlab", "bitbucket", "linkedin", "apple", "x"];
2
2
  export declare const sharedProviders: readonly ["google", "github", "microsoft", "spotify"];
3
- export declare const allProviders: readonly ["google", "github", "microsoft", "spotify", "facebook", "discord", "gitlab", "bitbucket", "linkedin"];
3
+ export declare const allProviders: readonly ["google", "github", "microsoft", "spotify", "facebook", "discord", "gitlab", "bitbucket", "linkedin", "apple", "x"];
4
4
  export type ProviderType = typeof allProviders[number];
5
5
  export type StandardProviderType = typeof standardProviders[number];
6
6
  export type SharedProviderType = typeof sharedProviders[number];
@@ -1,4 +1,4 @@
1
- export const standardProviders = ["google", "github", "microsoft", "spotify", "facebook", "discord", "gitlab", "bitbucket", "linkedin"];
1
+ export const standardProviders = ["google", "github", "microsoft", "spotify", "facebook", "discord", "gitlab", "bitbucket", "linkedin", "apple", "x"];
2
2
  // No more shared providers should be added except for special cases
3
3
  export const sharedProviders = ["google", "github", "microsoft", "spotify"];
4
4
  export const allProviders = standardProviders;
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@stackframe/stack-shared",
3
- "version": "2.5.35",
3
+ "version": "2.6.0",
4
4
  "main": "./dist/index.js",
5
5
  "types": "./dist/index.d.ts",
6
6
  "files": [
@@ -36,13 +36,15 @@
36
36
  "elliptic": "^6.5.7",
37
37
  "jose": "^5.2.2",
38
38
  "oauth4webapi": "^2.10.3",
39
+ "semver": "^7.6.3",
39
40
  "uuid": "^9.0.1",
40
- "@stackframe/stack-sc": "2.5.35"
41
+ "@stackframe/stack-sc": "2.6.0"
41
42
  },
42
43
  "devDependencies": {
43
44
  "@types/bcrypt": "^5.0.2",
44
45
  "@types/elliptic": "^6.4.18",
45
46
  "@types/react": "^18.2.66",
47
+ "@types/semver": "^7.5.8",
46
48
  "@types/uuid": "^9.0.8",
47
49
  "next": "^14.1.0",
48
50
  "react": "^18.2.0",
@@ -1,134 +0,0 @@
1
- import { CrudTypeOf } from "../../crud";
2
- export declare const apiKeysCreateInputSchema: import("yup").ObjectSchema<{
3
- description: string;
4
- expires_at_millis: number;
5
- has_publishable_client_key: NonNullable<boolean | undefined>;
6
- has_secret_server_key: NonNullable<boolean | undefined>;
7
- has_super_secret_admin_key: NonNullable<boolean | undefined>;
8
- }, import("yup").AnyObject, {
9
- description: undefined;
10
- expires_at_millis: undefined;
11
- has_publishable_client_key: undefined;
12
- has_secret_server_key: undefined;
13
- has_super_secret_admin_key: undefined;
14
- }, "">;
15
- export declare const apiKeysCreateOutputSchema: import("yup").ObjectSchema<{
16
- id: string;
17
- description: string;
18
- expires_at_millis: number;
19
- manually_revoked_at_millis: number | undefined;
20
- created_at_millis: number;
21
- } & {
22
- publishable_client_key: string | undefined;
23
- secret_server_key: string | undefined;
24
- super_secret_admin_key: string | undefined;
25
- }, import("yup").AnyObject, {
26
- id: undefined;
27
- description: undefined;
28
- expires_at_millis: undefined;
29
- manually_revoked_at_millis: undefined;
30
- created_at_millis: undefined;
31
- publishable_client_key: undefined;
32
- secret_server_key: undefined;
33
- super_secret_admin_key: undefined;
34
- }, "">;
35
- export declare const apiKeysCrudAdminObfuscatedReadSchema: import("yup").ObjectSchema<{
36
- id: string;
37
- description: string;
38
- expires_at_millis: number;
39
- manually_revoked_at_millis: number | undefined;
40
- created_at_millis: number;
41
- } & {
42
- publishable_client_key: {
43
- last_four: string;
44
- } | undefined;
45
- secret_server_key: {
46
- last_four: string;
47
- } | undefined;
48
- super_secret_admin_key: {
49
- last_four: string;
50
- } | undefined;
51
- }, import("yup").AnyObject, {
52
- id: undefined;
53
- description: undefined;
54
- expires_at_millis: undefined;
55
- manually_revoked_at_millis: undefined;
56
- created_at_millis: undefined;
57
- publishable_client_key: {
58
- last_four: undefined;
59
- };
60
- secret_server_key: {
61
- last_four: undefined;
62
- };
63
- super_secret_admin_key: {
64
- last_four: undefined;
65
- };
66
- }, "">;
67
- export declare const apiKeysCrudAdminUpdateSchema: import("yup").ObjectSchema<{
68
- description: string | undefined;
69
- revoked: boolean | undefined;
70
- }, import("yup").AnyObject, {
71
- description: undefined;
72
- revoked: undefined;
73
- }, "">;
74
- export declare const apiKeysCrudAdminDeleteSchema: import("yup").MixedSchema<{} | undefined, import("yup").AnyObject, undefined, "">;
75
- export declare const apiKeysCrud: import("../../crud").CrudSchemaFromOptions<{
76
- adminReadSchema: import("yup").ObjectSchema<{
77
- id: string;
78
- description: string;
79
- expires_at_millis: number;
80
- manually_revoked_at_millis: number | undefined;
81
- created_at_millis: number;
82
- } & {
83
- publishable_client_key: {
84
- last_four: string;
85
- } | undefined;
86
- secret_server_key: {
87
- last_four: string;
88
- } | undefined;
89
- super_secret_admin_key: {
90
- last_four: string;
91
- } | undefined;
92
- }, import("yup").AnyObject, {
93
- id: undefined;
94
- description: undefined;
95
- expires_at_millis: undefined;
96
- manually_revoked_at_millis: undefined;
97
- created_at_millis: undefined;
98
- publishable_client_key: {
99
- last_four: undefined;
100
- };
101
- secret_server_key: {
102
- last_four: undefined;
103
- };
104
- super_secret_admin_key: {
105
- last_four: undefined;
106
- };
107
- }, "">;
108
- adminUpdateSchema: import("yup").ObjectSchema<{
109
- description: string | undefined;
110
- revoked: boolean | undefined;
111
- }, import("yup").AnyObject, {
112
- description: undefined;
113
- revoked: undefined;
114
- }, "">;
115
- adminDeleteSchema: import("yup").MixedSchema<{} | undefined, import("yup").AnyObject, undefined, "">;
116
- docs: {
117
- adminList: {
118
- hidden: true;
119
- };
120
- adminRead: {
121
- hidden: true;
122
- };
123
- adminCreate: {
124
- hidden: true;
125
- };
126
- adminUpdate: {
127
- hidden: true;
128
- };
129
- adminDelete: {
130
- hidden: true;
131
- };
132
- };
133
- }>;
134
- export type ApiKeysCrud = CrudTypeOf<typeof apiKeysCrud>;
@@ -1,61 +0,0 @@
1
- import { createCrud } from "../../crud";
2
- import { yupBoolean, yupMixed, yupNumber, yupObject, yupString } from "../../schema-fields";
3
- const baseApiKeysReadSchema = yupObject({
4
- id: yupString().required(),
5
- description: yupString().required(),
6
- expires_at_millis: yupNumber().required(),
7
- manually_revoked_at_millis: yupNumber().optional(),
8
- created_at_millis: yupNumber().required(),
9
- });
10
- // Used for the result of the create endpoint
11
- export const apiKeysCreateInputSchema = yupObject({
12
- description: yupString().required(),
13
- expires_at_millis: yupNumber().required(),
14
- has_publishable_client_key: yupBoolean().required(),
15
- has_secret_server_key: yupBoolean().required(),
16
- has_super_secret_admin_key: yupBoolean().required(),
17
- });
18
- export const apiKeysCreateOutputSchema = baseApiKeysReadSchema.concat(yupObject({
19
- publishable_client_key: yupString().optional(),
20
- secret_server_key: yupString().optional(),
21
- super_secret_admin_key: yupString().optional(),
22
- }).required());
23
- // Used for list, read and update endpoints after the initial creation
24
- export const apiKeysCrudAdminObfuscatedReadSchema = baseApiKeysReadSchema.concat(yupObject({
25
- publishable_client_key: yupObject({
26
- last_four: yupString().required(),
27
- }).optional(),
28
- secret_server_key: yupObject({
29
- last_four: yupString().required(),
30
- }).optional(),
31
- super_secret_admin_key: yupObject({
32
- last_four: yupString().required(),
33
- }).optional(),
34
- }));
35
- export const apiKeysCrudAdminUpdateSchema = yupObject({
36
- description: yupString().optional(),
37
- revoked: yupBoolean().oneOf([true]).optional(),
38
- }).required();
39
- export const apiKeysCrudAdminDeleteSchema = yupMixed();
40
- export const apiKeysCrud = createCrud({
41
- adminReadSchema: apiKeysCrudAdminObfuscatedReadSchema,
42
- adminUpdateSchema: apiKeysCrudAdminUpdateSchema,
43
- adminDeleteSchema: apiKeysCrudAdminDeleteSchema,
44
- docs: {
45
- adminList: {
46
- hidden: true,
47
- },
48
- adminRead: {
49
- hidden: true,
50
- },
51
- adminCreate: {
52
- hidden: true,
53
- },
54
- adminUpdate: {
55
- hidden: true,
56
- },
57
- adminDelete: {
58
- hidden: true,
59
- },
60
- },
61
- });