@stackframe/stack-shared 2.5.5 → 2.5.6

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,12 @@
1
1
  # @stackframe/stack-shared
2
2
 
3
+ ## 2.5.6
4
+
5
+ ### Patch Changes
6
+
7
+ - Various bugfixes
8
+ - @stackframe/stack-sc@2.5.6
9
+
3
10
  ## 2.5.5
4
11
 
5
12
  ### Patch Changes
@@ -3,7 +3,7 @@ import * as schemaFields from "../../schema-fields";
3
3
  import { yupMixed, yupObject } from "../../schema-fields";
4
4
  // =============== Team permissions =================
5
5
  export const teamPermissionsCrudClientReadSchema = yupObject({
6
- id: schemaFields.teamPermissionIdSchema.required(),
6
+ id: schemaFields.teamPermissionDefinitionIdSchema.required(),
7
7
  user_id: schemaFields.userIdSchema.required(),
8
8
  team_id: schemaFields.teamIdSchema.required(),
9
9
  }).required();
@@ -38,17 +38,17 @@ export const teamPermissionsCrud = createCrud({
38
38
  });
39
39
  // =============== Team permission definitions =================
40
40
  export const teamPermissionDefinitionsCrudAdminReadSchema = yupObject({
41
- id: schemaFields.teamPermissionIdSchema.required(),
41
+ id: schemaFields.teamPermissionDefinitionIdSchema.required(),
42
42
  description: schemaFields.teamPermissionDescriptionSchema.optional(),
43
43
  contained_permission_ids: schemaFields.containedPermissionIdsSchema.required()
44
44
  }).required();
45
45
  export const teamPermissionDefinitionsCrudAdminCreateSchema = yupObject({
46
- id: schemaFields.customTeamPermissionIdSchema.required(),
46
+ id: schemaFields.customTeamPermissionDefinitionIdSchema.required(),
47
47
  description: schemaFields.teamPermissionDescriptionSchema.optional(),
48
48
  contained_permission_ids: schemaFields.containedPermissionIdsSchema.optional()
49
49
  }).required();
50
50
  export const teamPermissionDefinitionsCrudAdminUpdateSchema = yupObject({
51
- id: schemaFields.customTeamPermissionIdSchema.optional(),
51
+ id: schemaFields.customTeamPermissionDefinitionIdSchema.optional(),
52
52
  description: schemaFields.teamPermissionDescriptionSchema.optional(),
53
53
  contained_permission_ids: schemaFields.containedPermissionIdsSchema.optional()
54
54
  }).required();
@@ -3,7 +3,7 @@ import * as schemaFields from "../../schema-fields";
3
3
  import { yupMixed, yupObject } from "../../schema-fields";
4
4
  // Team permissions
5
5
  export const teamPermissionsCrudClientReadSchema = yupObject({
6
- id: schemaFields.teamPermissionIdSchema.required(),
6
+ id: schemaFields.teamPermissionDefinitionIdSchema.required(),
7
7
  user_id: schemaFields.userIdSchema.required(),
8
8
  team_id: schemaFields.teamIdSchema.required(),
9
9
  }).required();
@@ -38,17 +38,17 @@ export const teamPermissionsCrud = createCrud({
38
38
  });
39
39
  // Team permission definitions
40
40
  export const teamPermissionDefinitionsCrudServerReadSchema = yupObject({
41
- id: schemaFields.teamPermissionIdSchema.required(),
41
+ id: schemaFields.teamPermissionDefinitionIdSchema.required(),
42
42
  description: schemaFields.teamPermissionDescriptionSchema.optional(),
43
43
  contained_permission_ids: schemaFields.containedPermissionIdsSchema.required()
44
44
  }).required();
45
45
  export const teamPermissionDefinitionsCrudServerCreateSchema = yupObject({
46
- id: schemaFields.customTeamPermissionIdSchema.required(),
46
+ id: schemaFields.customTeamPermissionDefinitionIdSchema.required(),
47
47
  description: schemaFields.teamPermissionDescriptionSchema.optional(),
48
48
  contained_permission_ids: schemaFields.containedPermissionIdsSchema.optional()
49
49
  }).required();
50
50
  export const teamPermissionDefinitionsCrudServerUpdateSchema = yupObject({
51
- id: schemaFields.customTeamPermissionIdSchema.required(),
51
+ id: schemaFields.customTeamPermissionDefinitionIdSchema.required(),
52
52
  description: schemaFields.teamPermissionDescriptionSchema.optional(),
53
53
  contained_permission_ids: schemaFields.containedPermissionIdsSchema.optional()
54
54
  }).required();
@@ -345,5 +345,8 @@ export declare const KnownErrors: {
345
345
  UserAuthenticationRequired: KnownErrorConstructor<KnownError & KnownErrorBrand<"USER_AUTHENTICATION_REQUIRED">, []> & {
346
346
  errorCode: "USER_AUTHENTICATION_REQUIRED";
347
347
  };
348
+ TeamMembershipAlreadyExists: KnownErrorConstructor<KnownError & KnownErrorBrand<"TEAM_MEMBERSHIP_ALREADY_EXISTS">, []> & {
349
+ errorCode: "TEAM_MEMBERSHIP_ALREADY_EXISTS";
350
+ };
348
351
  };
349
352
  export {};
@@ -394,6 +394,13 @@ const TeamNotFound = createKnownErrorConstructor(KnownError, "TEAM_NOT_FOUND", (
394
394
  team_id: teamId,
395
395
  },
396
396
  ], (json) => [json.team_id]);
397
+ const TeamAlreadyExists = createKnownErrorConstructor(KnownError, "TEAM_ALREADY_EXISTS", (teamId) => [
398
+ 400,
399
+ `Team ${teamId} already exists.`,
400
+ {
401
+ team_id: teamId,
402
+ },
403
+ ], (json) => [json.team_id]);
397
404
  const TeamMembershipNotFound = createKnownErrorConstructor(KnownError, "TEAM_MEMBERSHIP_NOT_FOUND", (teamId, userId) => [
398
405
  404,
399
406
  `User ${userId} is not found in team ${teamId}.`,
@@ -453,6 +460,10 @@ const UserAuthenticationRequired = createKnownErrorConstructor(KnownError, "USER
453
460
  401,
454
461
  "User authentication required for this endpoint.",
455
462
  ], () => []);
463
+ const TeamMembershipAlreadyExists = createKnownErrorConstructor(KnownError, "TEAM_MEMBERSHIP_ALREADY_EXISTS", () => [
464
+ 400,
465
+ "Team membership already exists.",
466
+ ], () => []);
456
467
  export const KnownErrors = {
457
468
  UnsupportedError,
458
469
  BodyParsingError,
@@ -529,6 +540,7 @@ export const KnownErrors = {
529
540
  OuterOAuthTimeout,
530
541
  OAuthProviderNotFoundOrNotEnabled,
531
542
  UserAuthenticationRequired,
543
+ TeamMembershipAlreadyExists,
532
544
  };
533
545
  // ensure that all known error codes are unique
534
546
  const knownErrorCodes = new Set();
@@ -79,8 +79,8 @@ export declare const signInResponseSchema: yup.ObjectSchema<{
79
79
  user_id: undefined;
80
80
  }, "">;
81
81
  export declare const teamSystemPermissions: readonly ["$update_team", "$delete_team", "$read_members", "$remove_members", "$invite_members"];
82
- export declare const teamPermissionIdSchema: yup.StringSchema<string | undefined, yup.AnyObject, undefined, "">;
83
- export declare const customTeamPermissionIdSchema: yup.StringSchema<string | undefined, yup.AnyObject, undefined, "">;
82
+ export declare const teamPermissionDefinitionIdSchema: yup.StringSchema<string | undefined, yup.AnyObject, undefined, "">;
83
+ export declare const customTeamPermissionDefinitionIdSchema: yup.StringSchema<string | undefined, yup.AnyObject, undefined, "">;
84
84
  export declare const teamPermissionDescriptionSchema: yup.StringSchema<string | undefined, yup.AnyObject, undefined, "">;
85
85
  export declare const containedPermissionIdsSchema: yup.ArraySchema<string[] | undefined, yup.AnyObject, undefined, "">;
86
86
  export declare const teamIdSchema: yup.StringSchema<string | undefined, yup.AnyObject, undefined, "">;
@@ -1,4 +1,5 @@
1
1
  import * as yup from "yup";
2
+ import { isUuid } from "./utils/uuids";
2
3
  const _idDescription = (identify) => `The immutable ID used to uniquely identify this ${identify}`;
3
4
  const _displayNameDescription = (identify) => `Human-readable ${identify} display name, used in places like frontend UI. This is not a unique identifier.`;
4
5
  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.`;
@@ -90,7 +91,7 @@ export const clientOrHigherAuthTypeSchema = yupString().oneOf(['client', 'server
90
91
  export const serverOrHigherAuthTypeSchema = yupString().oneOf(['server', 'admin']);
91
92
  export const adminAuthTypeSchema = yupString().oneOf(['admin']);
92
93
  // Projects
93
- export const projectIdSchema = yupString().meta({ openapiField: { description: _idDescription('project'), exampleValue: 'e0b52f4d-dece-408c-af49-d23061bb0f8d' } });
94
+ export const projectIdSchema = yupString().test((v) => v === undefined || v === "internal" || isUuid(v)).meta({ openapiField: { description: _idDescription('project'), exampleValue: 'e0b52f4d-dece-408c-af49-d23061bb0f8d' } });
94
95
  export const projectDisplayNameSchema = yupString().meta({ openapiField: { description: _displayNameDescription('project'), exampleValue: 'MyMusic' } });
95
96
  export const projectDescriptionSchema = yupString().nullable().meta({ openapiField: { description: 'A human readable description of the project', exampleValue: 'A music streaming service' } });
96
97
  export const projectCreatedAtMillisSchema = yupNumber().meta({ openapiField: { description: _createdAtMillisDescription('project'), exampleValue: 1630000000000 } });
@@ -166,7 +167,7 @@ export const teamSystemPermissions = [
166
167
  '$remove_members',
167
168
  '$invite_members',
168
169
  ];
169
- export const teamPermissionIdSchema = yupString()
170
+ export const teamPermissionDefinitionIdSchema = yupString()
170
171
  .matches(/^\$?[a-z0-9_:]+$/, 'Only lowercase letters, numbers, ":", "_" and optional "$" at the beginning are allowed')
171
172
  .test('is-system-permission', 'System permissions must start with a dollar sign', (value, ctx) => {
172
173
  if (!value)
@@ -177,11 +178,11 @@ export const teamPermissionIdSchema = yupString()
177
178
  return true;
178
179
  })
179
180
  .meta({ openapiField: { description: `The permission ID used to uniquely identify a permission. Can either be a custom permission with lowercase letters, numbers, ":", and "_" characters, or one of the system permissions: ${teamSystemPermissions.join(', ')}`, exampleValue: '$read_secret_info' } });
180
- export const customTeamPermissionIdSchema = yupString()
181
+ export const customTeamPermissionDefinitionIdSchema = yupString()
181
182
  .matches(/^[a-z0-9_:]+$/, 'Only lowercase letters, numbers, ":", "_" are allowed')
182
183
  .meta({ openapiField: { description: 'The permission ID used to uniquely identify a permission. Can only contain lowercase letters, numbers, ":", and "_" characters', exampleValue: 'read_secret_info' } });
183
184
  export const teamPermissionDescriptionSchema = yupString().meta({ openapiField: { description: 'A human-readable description of the permission', exampleValue: 'Read secret information' } });
184
- export const containedPermissionIdsSchema = yupArray(teamPermissionIdSchema.required()).meta({ openapiField: { description: 'The IDs of the permissions that are contained in this permission', exampleValue: ['read_public_info'] } });
185
+ export const containedPermissionIdsSchema = yupArray(teamPermissionDefinitionIdSchema.required()).meta({ openapiField: { description: 'The IDs of the permissions that are contained in this permission', exampleValue: ['read_public_info'] } });
185
186
  // Teams
186
187
  export const teamIdSchema = yupString().uuid().meta({ openapiField: { description: _idDescription('team'), exampleValue: 'ad962777-8244-496a-b6a2-e0c6a449c79e' } });
187
188
  export const teamDisplayNameSchema = yupString().meta({ openapiField: { description: _displayNameDescription('team'), exampleValue: 'My Team' } });
@@ -95,7 +95,7 @@ export function runAsynchronouslyWithAlert(...args) {
95
95
  return runAsynchronously(args[0], {
96
96
  ...args[1],
97
97
  onError: error => {
98
- alert(`An unhandled error occurred. Please ${process.env.NODE_ENV === "development" ? `check the browser console for the full error. ${error}` : "report this to the developer."}`);
98
+ alert(`An unhandled error occurred. Please ${process.env.NODE_ENV === "development" ? `check the browser console for the full error. ${error}` : "report this to the developer."}\n\n${error}`);
99
99
  args[1]?.onError?.(error);
100
100
  },
101
101
  }, ...args.slice(2));
@@ -101,6 +101,7 @@ class RetryError extends AggregateError {
101
101
  return this.errors.length;
102
102
  }
103
103
  }
104
+ RetryError.prototype.name = "RetryError";
104
105
  async function retry(fn, retries, { exponentialDelayBase = 2000 }) {
105
106
  const errors = [];
106
107
  for (let i = 0; i < retries; i++) {
@@ -1,3 +1,4 @@
1
1
  export type IsAny<T> = 0 extends (1 & T) ? true : false;
2
2
  export type isNullish<T> = T extends null | undefined ? true : false;
3
3
  export type NullishCoalesce<T, U> = T extends null | undefined ? U : T;
4
+ export type UnionToIntersection<U> = (U extends any ? (x: U) => void : never) extends ((x: infer I) => void) ? I : never;
@@ -1 +1,2 @@
1
1
  export declare function generateUuid(): string;
2
+ export declare function isUuid(str: string): boolean;
@@ -3,3 +3,6 @@ export function generateUuid() {
3
3
  // crypto.randomUuid is not supported in all browsers, so this is a polyfill
4
4
  return "10000000-1000-4000-8000-100000000000".replace(/[018]/g, c => (+c ^ globalVar.crypto.getRandomValues(new Uint8Array(1))[0] & 15 >> +c / 4).toString(16));
5
5
  }
6
+ export function isUuid(str) {
7
+ return /^[0-9a-f]{8}-[0-9a-f]{4}-4[0-9a-f]{3}-[89ab][0-9a-f]{3}-[0-9a-f]{12}$/.test(str);
8
+ }
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@stackframe/stack-shared",
3
- "version": "2.5.5",
3
+ "version": "2.5.6",
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.5"
39
+ "@stackframe/stack-sc": "2.5.6"
40
40
  },
41
41
  "devDependencies": {
42
42
  "rimraf": "^5.0.5",