@stackframe/stack-shared 2.7.23 → 2.7.26

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,15 @@
1
1
  # @stackframe/stack-shared
2
2
 
3
+ ## 2.7.26
4
+
5
+ ### Patch Changes
6
+
7
+ - Various changes
8
+
9
+ ## 2.7.25
10
+
11
+ ## 2.7.24
12
+
3
13
  ## 2.7.23
4
14
 
5
15
  ### Patch Changes
@@ -64,6 +64,7 @@ export declare const projectsCrudAdminReadSchema: import("yup").ObjectSchema<{
64
64
  team_member_default_permissions: {
65
65
  id: string;
66
66
  }[];
67
+ oauth_account_merge_strategy: "link_method" | "raise_error" | "allow_duplicates";
67
68
  };
68
69
  }, import("yup").AnyObject, {
69
70
  id: undefined;
@@ -96,6 +97,7 @@ export declare const projectsCrudAdminReadSchema: import("yup").ObjectSchema<{
96
97
  create_team_on_sign_up: undefined;
97
98
  team_creator_default_permissions: undefined;
98
99
  team_member_default_permissions: undefined;
100
+ oauth_account_merge_strategy: undefined;
99
101
  };
100
102
  }, "">;
101
103
  export declare const projectsCrudClientReadSchema: import("yup").ObjectSchema<{
@@ -166,6 +168,7 @@ export declare const projectsCrudAdminUpdateSchema: import("yup").ObjectSchema<{
166
168
  team_member_default_permissions?: {
167
169
  id: string;
168
170
  }[] | undefined;
171
+ oauth_account_merge_strategy?: "link_method" | "raise_error" | "allow_duplicates" | undefined;
169
172
  } | undefined;
170
173
  }, import("yup").AnyObject, {
171
174
  display_name: undefined;
@@ -214,6 +217,7 @@ export declare const projectsCrudAdminCreateSchema: import("yup").ObjectSchema<{
214
217
  team_member_default_permissions?: {
215
218
  id: string;
216
219
  }[] | undefined;
220
+ oauth_account_merge_strategy?: "link_method" | "raise_error" | "allow_duplicates" | undefined;
217
221
  } | undefined;
218
222
  } & {
219
223
  display_name: string;
@@ -300,6 +304,7 @@ export declare const projectsCrud: import("../../crud").CrudSchemaFromOptions<{
300
304
  team_member_default_permissions: {
301
305
  id: string;
302
306
  }[];
307
+ oauth_account_merge_strategy: "link_method" | "raise_error" | "allow_duplicates";
303
308
  };
304
309
  }, import("yup").AnyObject, {
305
310
  id: undefined;
@@ -332,6 +337,7 @@ export declare const projectsCrud: import("../../crud").CrudSchemaFromOptions<{
332
337
  create_team_on_sign_up: undefined;
333
338
  team_creator_default_permissions: undefined;
334
339
  team_member_default_permissions: undefined;
340
+ oauth_account_merge_strategy: undefined;
335
341
  };
336
342
  }, "">;
337
343
  adminUpdateSchema: import("yup").ObjectSchema<{
@@ -375,6 +381,7 @@ export declare const projectsCrud: import("../../crud").CrudSchemaFromOptions<{
375
381
  team_member_default_permissions?: {
376
382
  id: string;
377
383
  }[] | undefined;
384
+ oauth_account_merge_strategy?: "link_method" | "raise_error" | "allow_duplicates" | undefined;
378
385
  } | undefined;
379
386
  }, import("yup").AnyObject, {
380
387
  display_name: undefined;
@@ -456,6 +463,7 @@ export declare const internalProjectsCrud: import("../../crud").CrudSchemaFromOp
456
463
  team_member_default_permissions: {
457
464
  id: string;
458
465
  }[];
466
+ oauth_account_merge_strategy: "link_method" | "raise_error" | "allow_duplicates";
459
467
  };
460
468
  }, import("yup").AnyObject, {
461
469
  id: undefined;
@@ -488,6 +496,7 @@ export declare const internalProjectsCrud: import("../../crud").CrudSchemaFromOp
488
496
  create_team_on_sign_up: undefined;
489
497
  team_creator_default_permissions: undefined;
490
498
  team_member_default_permissions: undefined;
499
+ oauth_account_merge_strategy: undefined;
491
500
  };
492
501
  }, "">;
493
502
  clientCreateSchema: import("yup").ObjectSchema<{
@@ -531,6 +540,7 @@ export declare const internalProjectsCrud: import("../../crud").CrudSchemaFromOp
531
540
  team_member_default_permissions?: {
532
541
  id: string;
533
542
  }[] | undefined;
543
+ oauth_account_merge_strategy?: "link_method" | "raise_error" | "allow_duplicates" | undefined;
534
544
  } | undefined;
535
545
  } & {
536
546
  display_name: string;
@@ -74,6 +74,7 @@ export const projectsCrudAdminReadSchema = yupObject({
74
74
  create_team_on_sign_up: schemaFields.projectCreateTeamOnSignUpSchema.defined(),
75
75
  team_creator_default_permissions: yupArray(teamPermissionSchema.defined()).defined(),
76
76
  team_member_default_permissions: yupArray(teamPermissionSchema.defined()).defined(),
77
+ oauth_account_merge_strategy: schemaFields.oauthAccountMergeStrategySchema.defined(),
77
78
  }).defined(),
78
79
  }).defined();
79
80
  export const projectsCrudClientReadSchema = yupObject({
@@ -107,6 +108,7 @@ export const projectsCrudAdminUpdateSchema = yupObject({
107
108
  create_team_on_sign_up: schemaFields.projectCreateTeamOnSignUpSchema.optional(),
108
109
  team_creator_default_permissions: yupArray(teamPermissionSchema.defined()).optional(),
109
110
  team_member_default_permissions: yupArray(teamPermissionSchema.defined()).optional(),
111
+ oauth_account_merge_strategy: schemaFields.oauthAccountMergeStrategySchema.optional(),
110
112
  }).optional().default(undefined),
111
113
  }).defined();
112
114
  export const projectsCrudAdminCreateSchema = projectsCrudAdminUpdateSchema.concat(yupObject({
@@ -218,6 +218,9 @@ export declare const KnownErrors: {
218
218
  UserEmailAlreadyExists: KnownErrorConstructor<KnownError & KnownErrorBrand<"USER_EMAIL_ALREADY_EXISTS">, []> & {
219
219
  errorCode: "USER_EMAIL_ALREADY_EXISTS";
220
220
  };
221
+ EmailNotVerified: KnownErrorConstructor<KnownError & KnownErrorBrand<"EMAIL_NOT_VERIFIED">, []> & {
222
+ errorCode: "EMAIL_NOT_VERIFIED";
223
+ };
221
224
  UserIdDoesNotExist: KnownErrorConstructor<KnownError & KnownErrorBrand<"USER_ID_DOES_NOT_EXIST">, [userId: string]> & {
222
225
  errorCode: "USER_ID_DOES_NOT_EXIST";
223
226
  };
@@ -380,7 +383,7 @@ export declare const KnownErrors: {
380
383
  OAuthProviderAccessDenied: KnownErrorConstructor<KnownError & KnownErrorBrand<"OAUTH_PROVIDER_ACCESS_DENIED">, []> & {
381
384
  errorCode: "OAUTH_PROVIDER_ACCESS_DENIED";
382
385
  };
383
- ContactChannelAlreadyUsedForAuthBySomeoneElse: KnownErrorConstructor<KnownError & KnownErrorBrand<"CONTACT_CHANNEL_ALREADY_USED_FOR_AUTH_BY_SOMEONE_ELSE">, [type: "email"]> & {
386
+ ContactChannelAlreadyUsedForAuthBySomeoneElse: KnownErrorConstructor<KnownError & KnownErrorBrand<"CONTACT_CHANNEL_ALREADY_USED_FOR_AUTH_BY_SOMEONE_ELSE">, [type: "email", contactChannelValue?: string | undefined]> & {
384
387
  errorCode: "CONTACT_CHANNEL_ALREADY_USED_FOR_AUTH_BY_SOMEONE_ELSE";
385
388
  };
386
389
  };
@@ -263,6 +263,10 @@ const UserEmailAlreadyExists = createKnownErrorConstructor(KnownError, "USER_EMA
263
263
  409,
264
264
  "User email already exists.",
265
265
  ], () => []);
266
+ const EmailNotVerified = createKnownErrorConstructor(KnownError, "EMAIL_NOT_VERIFIED", () => [
267
+ 400,
268
+ "The email is not verified.",
269
+ ], () => []);
266
270
  const CannotGetOwnUserWithoutUser = createKnownErrorConstructor(KnownError, "CANNOT_GET_OWN_USER_WITHOUT_USER", () => [
267
271
  400,
268
272
  "You have specified 'me' as a userId, but did not provide authentication for a user.",
@@ -531,11 +535,13 @@ const OAuthProviderAccessDenied = createKnownErrorConstructor(KnownError, "OAUTH
531
535
  400,
532
536
  "The OAuth provider denied access to the user.",
533
537
  ], () => []);
534
- const ContactChannelAlreadyUsedForAuthBySomeoneElse = createKnownErrorConstructor(KnownError, "CONTACT_CHANNEL_ALREADY_USED_FOR_AUTH_BY_SOMEONE_ELSE", (type) => [
538
+ const ContactChannelAlreadyUsedForAuthBySomeoneElse = createKnownErrorConstructor(KnownError, "CONTACT_CHANNEL_ALREADY_USED_FOR_AUTH_BY_SOMEONE_ELSE", (type, contactChannelValue) => [
535
539
  409,
536
- `This ${type} is already used for authentication by another account.`,
537
- { type },
538
- ], (json) => [json.type]);
540
+ contactChannelValue ?
541
+ `The ${type} (${contactChannelValue}) is already used for authentication by another account.` :
542
+ `This ${type} is already used for authentication by another account.`,
543
+ { type, contact_channel_value: contactChannelValue ?? null },
544
+ ], (json) => [json.type, json.contact_channel_value]);
539
545
  export const KnownErrors = {
540
546
  UnsupportedError,
541
547
  BodyParsingError,
@@ -575,6 +581,7 @@ export const KnownErrors = {
575
581
  ProviderRejected,
576
582
  RefreshTokenNotFoundOrExpired,
577
583
  UserEmailAlreadyExists,
584
+ EmailNotVerified,
578
585
  UserIdDoesNotExist,
579
586
  UserNotFound,
580
587
  ApiKeyNotFound,
@@ -72,6 +72,7 @@ export declare const oauthClientIdSchema: yup.StringSchema<string | undefined, y
72
72
  export declare const oauthClientSecretSchema: yup.StringSchema<string | undefined, yup.AnyObject, undefined, "">;
73
73
  export declare const oauthFacebookConfigIdSchema: yup.StringSchema<string | undefined, yup.AnyObject, undefined, "">;
74
74
  export declare const oauthMicrosoftTenantIdSchema: yup.StringSchema<string | undefined, yup.AnyObject, undefined, "">;
75
+ export declare const oauthAccountMergeStrategySchema: yup.StringSchema<"link_method" | "raise_error" | "allow_duplicates" | undefined, yup.AnyObject, undefined, "">;
75
76
  export declare const emailTypeSchema: yup.StringSchema<"shared" | "standard" | undefined, yup.AnyObject, undefined, "">;
76
77
  export declare const emailSenderNameSchema: yup.StringSchema<string | undefined, yup.AnyObject, undefined, "">;
77
78
  export declare const emailHostSchema: yup.StringSchema<string | undefined, yup.AnyObject, undefined, "">;
@@ -171,6 +171,10 @@ export const adaptSchema = yupMixed();
171
171
  * Yup's URL schema does not recognize some URLs (including `http://localhost`) as a valid URL. This schema is a workaround for that.
172
172
  */
173
173
  export const urlSchema = yupString().test({
174
+ name: 'no-spaces',
175
+ message: (params) => `${params.path} contains spaces`,
176
+ test: (value) => value == null || !value.includes(' ')
177
+ }).test({
174
178
  name: 'url',
175
179
  message: (params) => `${params.path} is not a valid URL`,
176
180
  test: (value) => value == null || isValidUrl(value)
@@ -244,6 +248,7 @@ export const oauthClientIdSchema = yupString().meta({ openapiField: { descriptio
244
248
  export const oauthClientSecretSchema = yupString().meta({ openapiField: { description: 'OAuth client secret. Needs to be specified when using type="standard"', exampleValue: 'google-oauth-client-secret' } });
245
249
  export const oauthFacebookConfigIdSchema = yupString().meta({ openapiField: { description: 'The configuration id for Facebook business login (for things like ads and marketing). This is only required if you are using the standard OAuth with Facebook and you are using Facebook business login.' } });
246
250
  export const oauthMicrosoftTenantIdSchema = yupString().meta({ openapiField: { description: 'The Microsoft tenant id for Microsoft directory. This is only required if you are using the standard OAuth with Microsoft and you have an Azure AD tenant.' } });
251
+ export const oauthAccountMergeStrategySchema = yupString().oneOf(['link_method', 'raise_error', 'allow_duplicates']).meta({ openapiField: { description: 'Determines how to handle OAuth logins that match an existing user by email. `link_method` adds the OAuth method to the existing user. `raise_error` rejects the login with an error. `allow_duplicates` creates a new user.', exampleValue: 'link_method' } });
247
252
  // Project email config
248
253
  export const emailTypeSchema = yupString().oneOf(['shared', 'standard']).meta({ openapiField: { description: 'Email provider type, one of shared, standard. "shared" uses Stack shared email provider and it is only meant for development. "standard" uses your own email server and will have your email address as the sender.', exampleValue: 'standard' } });
249
254
  export const emailSenderNameSchema = yupString().meta({ openapiField: { description: 'Email sender name. Needs to be specified when using type="standard"', exampleValue: 'Stack' } });
@@ -75,7 +75,6 @@ import.meta.vitest?.test("groupBy", ({ expect }) => {
75
75
  expect(grouped.get("odd")).toEqual([1, 3, 5]);
76
76
  // Check the actual lengths of the words to ensure our test is correct
77
77
  const words = ["apple", "banana", "cherry", "date", "elderberry"];
78
- console.log("Word lengths:", words.map(w => `${w}: ${w.length}`));
79
78
  const byLength = groupBy(words, (w) => w.length);
80
79
  // Adjust expectations based on actual word lengths
81
80
  expect(byLength.get(5)).toEqual(["apple"]);
@@ -57,37 +57,6 @@ export function logged(name, toLog, options = {}) {
57
57
  });
58
58
  return proxy;
59
59
  }
60
- import.meta.vitest?.test("logged", ({ expect }) => {
61
- // Test with a simple object
62
- const obj = {
63
- value: 42,
64
- method(x) { return x * 2; }
65
- };
66
- const loggedObj = logged("testObj", obj);
67
- // Test property access
68
- expect(loggedObj.value).toBe(42);
69
- // Test method call
70
- const result = loggedObj.method(21);
71
- expect(result).toBe(42);
72
- // Test property setting
73
- loggedObj.value = 100;
74
- expect(loggedObj.value).toBe(100);
75
- // Test with a promise-returning method
76
- const asyncObj = {
77
- async asyncMethod(x) { return x * 3; }
78
- };
79
- const loggedAsyncObj = logged("asyncObj", asyncObj);
80
- // Test async method
81
- const promise = loggedAsyncObj.asyncMethod(7);
82
- expect(promise instanceof Promise).toBe(true);
83
- // Test error handling
84
- const errorObj = {
85
- throwError() { throw new Error("Test error"); }
86
- };
87
- const loggedErrorObj = logged("errorObj", errorObj);
88
- // Test error throwing
89
- expect(() => loggedErrorObj.throwError()).toThrow("Test error");
90
- });
91
60
  export function createLazyProxy(factory) {
92
61
  let cache = undefined;
93
62
  let initialized = false;
@@ -2,6 +2,8 @@ import { findLastIndex, unique } from "./arrays";
2
2
  import { StackAssertionError } from "./errors";
3
3
  import { filterUndefined } from "./objects";
4
4
  export function typedToLowercase(s) {
5
+ if (typeof s !== "string")
6
+ throw new StackAssertionError("Expected a string for typedToLowercase", { s });
5
7
  return s.toLowerCase();
6
8
  }
7
9
  import.meta.vitest?.test("typedToLowercase", ({ expect }) => {
@@ -12,8 +14,11 @@ import.meta.vitest?.test("typedToLowercase", ({ expect }) => {
12
14
  expect(typedToLowercase("123")).toBe("123");
13
15
  expect(typedToLowercase("MIXED123case")).toBe("mixed123case");
14
16
  expect(typedToLowercase("Special@Chars!")).toBe("special@chars!");
17
+ expect(() => typedToLowercase(123)).toThrow("Expected a string for typedToLowercase");
15
18
  });
16
19
  export function typedToUppercase(s) {
20
+ if (typeof s !== "string")
21
+ throw new StackAssertionError("Expected a string for typedToUppercase", { s });
17
22
  return s.toUpperCase();
18
23
  }
19
24
  import.meta.vitest?.test("typedToUppercase", ({ expect }) => {
@@ -24,6 +29,7 @@ import.meta.vitest?.test("typedToUppercase", ({ expect }) => {
24
29
  expect(typedToUppercase("123")).toBe("123");
25
30
  expect(typedToUppercase("mixed123Case")).toBe("MIXED123CASE");
26
31
  expect(typedToUppercase("special@chars!")).toBe("SPECIAL@CHARS!");
32
+ expect(() => typedToUppercase(123)).toThrow("Expected a string for typedToUppercase");
27
33
  });
28
34
  export function typedCapitalize(s) {
29
35
  return s.charAt(0).toUpperCase() + s.slice(1);
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@stackframe/stack-shared",
3
- "version": "2.7.23",
3
+ "version": "2.7.26",
4
4
  "main": "./dist/index.js",
5
5
  "types": "./dist/index.d.ts",
6
6
  "type": "module",