@stackframe/stack-shared 2.6.15 → 2.6.16

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,13 @@
1
1
  # @stackframe/stack-shared
2
2
 
3
+ ## 2.6.16
4
+
5
+ ### Patch Changes
6
+
7
+ - - list user pagination
8
+ - fixed visual glitches
9
+ - @stackframe/stack-sc@2.6.16
10
+
3
11
  ## 2.6.15
4
12
 
5
13
  ### Patch Changes
package/dist/crud.d.ts CHANGED
@@ -81,6 +81,9 @@ type InnerCrudTypeOf<S extends InnerCrudSchema> = (S['createSchema'] extends {}
81
81
  List: {
82
82
  items: yup.InferType<S['readSchema']>[];
83
83
  is_paginated: boolean;
84
+ pagination?: {
85
+ next_cursor: string | null;
86
+ };
84
87
  };
85
88
  } : {});
86
89
  export type CrudTypeOf<S extends CrudSchema> = {
@@ -146,19 +146,29 @@ export declare const contactChannelsCrud: import("../../crud").CrudSchemaFromOpt
146
146
  }, "">;
147
147
  docs: {
148
148
  clientRead: {
149
- hidden: true;
149
+ summary: string;
150
+ description: string;
151
+ tags: string[];
150
152
  };
151
153
  clientCreate: {
152
- hidden: true;
154
+ summary: string;
155
+ description: string;
156
+ tags: string[];
153
157
  };
154
158
  clientUpdate: {
155
- hidden: true;
159
+ summary: string;
160
+ description: string;
161
+ tags: string[];
156
162
  };
157
163
  clientDelete: {
158
- hidden: true;
164
+ summary: string;
165
+ description: string;
166
+ tags: string[];
159
167
  };
160
168
  clientList: {
161
- hidden: true;
169
+ summary: string;
170
+ description: string;
171
+ tags: string[];
162
172
  };
163
173
  };
164
174
  }>;
@@ -1,38 +1,32 @@
1
1
  import { createCrud } from "../../crud";
2
- import { userIdOrMeSchema, userIdSchema, yupBoolean, yupMixed, yupObject, yupString } from "../../schema-fields";
3
- const contactChannelsTypes = ['email'];
4
- const type = yupString().oneOf(contactChannelsTypes);
5
- const value = yupString().when('type', {
6
- is: 'email',
7
- then: (schema) => schema.email(),
8
- });
2
+ import { contactChannelIdSchema, contactChannelIsPrimarySchema, contactChannelIsVerifiedSchema, contactChannelTypeSchema, contactChannelUsedForAuthSchema, contactChannelValueSchema, userIdOrMeSchema, userIdSchema, yupMixed, yupObject } from "../../schema-fields";
9
3
  export const contactChannelsClientReadSchema = yupObject({
10
4
  user_id: userIdSchema.required(),
11
- id: yupString().required(),
12
- value: value.required(),
13
- type: type.required(),
14
- used_for_auth: yupBoolean().required(),
15
- is_verified: yupBoolean().required(),
16
- is_primary: yupBoolean().required(),
5
+ id: contactChannelIdSchema.required(),
6
+ value: contactChannelValueSchema.required(),
7
+ type: contactChannelTypeSchema.required(),
8
+ used_for_auth: contactChannelUsedForAuthSchema.required(),
9
+ is_verified: contactChannelIsVerifiedSchema.required(),
10
+ is_primary: contactChannelIsPrimarySchema.required(),
17
11
  }).required();
18
12
  export const contactChannelsCrudClientUpdateSchema = yupObject({
19
- value: value.optional(),
20
- type: type.optional(),
21
- used_for_auth: yupBoolean().optional(),
22
- is_primary: yupBoolean().optional(),
13
+ value: contactChannelValueSchema.optional(),
14
+ type: contactChannelTypeSchema.optional(),
15
+ used_for_auth: contactChannelUsedForAuthSchema.optional(),
16
+ is_primary: contactChannelIsPrimarySchema.optional(),
23
17
  }).required();
24
18
  export const contactChannelsCrudServerUpdateSchema = contactChannelsCrudClientUpdateSchema.concat(yupObject({
25
- is_verified: yupBoolean().optional(),
19
+ is_verified: contactChannelIsVerifiedSchema.optional(),
26
20
  }));
27
21
  export const contactChannelsCrudClientCreateSchema = yupObject({
28
22
  user_id: userIdOrMeSchema.required(),
29
- value: value.required(),
30
- type: type.required(),
31
- used_for_auth: yupBoolean().required(),
32
- is_primary: yupBoolean().optional(),
23
+ value: contactChannelValueSchema.required(),
24
+ type: contactChannelTypeSchema.required(),
25
+ used_for_auth: contactChannelUsedForAuthSchema.required(),
26
+ is_primary: contactChannelIsPrimarySchema.optional(),
33
27
  }).required();
34
28
  export const contactChannelsCrudServerCreateSchema = contactChannelsCrudClientCreateSchema.concat(yupObject({
35
- is_verified: yupBoolean().optional(),
29
+ is_verified: contactChannelIsVerifiedSchema.optional(),
36
30
  }));
37
31
  export const contactChannelsCrudClientDeleteSchema = yupMixed();
38
32
  export const contactChannelsCrud = createCrud({
@@ -44,19 +38,29 @@ export const contactChannelsCrud = createCrud({
44
38
  serverCreateSchema: contactChannelsCrudServerCreateSchema,
45
39
  docs: {
46
40
  clientRead: {
47
- hidden: true,
41
+ summary: "Get a contact channel",
42
+ description: "",
43
+ tags: ["Contact Channels"],
48
44
  },
49
45
  clientCreate: {
50
- hidden: true,
46
+ summary: "Create a contact channel",
47
+ description: "",
48
+ tags: ["Contact Channels"],
51
49
  },
52
50
  clientUpdate: {
53
- hidden: true,
51
+ summary: "Update a contact channel",
52
+ description: "",
53
+ tags: ["Contact Channels"],
54
54
  },
55
55
  clientDelete: {
56
- hidden: true,
56
+ summary: "Delete a contact channel",
57
+ description: "",
58
+ tags: ["Contact Channels"],
57
59
  },
58
60
  clientList: {
59
- hidden: true,
61
+ summary: "List contact channels",
62
+ description: "",
63
+ tags: ["Contact Channels"],
60
64
  }
61
65
  }
62
66
  });
@@ -45,7 +45,13 @@ export declare class StackServerInterface extends StackClientInterface {
45
45
  teamId?: string;
46
46
  recursive: boolean;
47
47
  }, session: InternalSession | null): Promise<TeamPermissionsCrud['Server']['Read'][]>;
48
- listServerUsers(): Promise<UsersCrud['Server']['Read'][]>;
48
+ listServerUsers(options: {
49
+ cursor?: string;
50
+ limit?: number;
51
+ orderBy?: 'signedUpAt';
52
+ desc?: boolean;
53
+ query?: string;
54
+ }): Promise<UsersCrud['Server']['List']>;
49
55
  listServerTeams(options?: {
50
56
  userId?: string;
51
57
  }): Promise<TeamsCrud['Server']['Read'][]>;
@@ -78,5 +84,5 @@ export declare class StackServerInterface extends StackClientInterface {
78
84
  updateServerContactChannel(userId: string, contactChannelId: string, data: ContactChannelsCrud['Server']['Update']): Promise<ContactChannelsCrud['Server']['Read']>;
79
85
  deleteServerContactChannel(userId: string, contactChannelId: string): Promise<void>;
80
86
  listServerContactChannels(userId: string): Promise<ContactChannelsCrud['Server']['Read'][]>;
81
- sendServerContactChannelVerificationEmail(userId: string, contactChannelId: string, callbackUrl: string): Promise<Result<undefined, KnownErrors["EmailAlreadyVerified"]>>;
87
+ sendServerContactChannelVerificationEmail(userId: string, contactChannelId: string, callbackUrl: string): Promise<void>;
82
88
  }
@@ -81,10 +81,22 @@ export class StackServerInterface extends StackClientInterface {
81
81
  const result = await response.json();
82
82
  return result.items;
83
83
  }
84
- async listServerUsers() {
85
- const response = await this.sendServerRequest("/users", {}, null);
86
- const result = await response.json();
87
- return result.items;
84
+ async listServerUsers(options) {
85
+ const searchParams = new URLSearchParams(filterUndefined({
86
+ cursor: options.cursor,
87
+ limit: options.limit?.toString(),
88
+ desc: options.desc?.toString(),
89
+ ...options.orderBy ? {
90
+ order_by: {
91
+ signedUpAt: "signed_up_at",
92
+ }[options.orderBy],
93
+ } : {},
94
+ ...options.query ? {
95
+ query: options.query,
96
+ } : {},
97
+ }));
98
+ const response = await this.sendServerRequest("/users?" + searchParams.toString(), {}, null);
99
+ return await response.json();
88
100
  }
89
101
  async listServerTeams(options) {
90
102
  const response = await this.sendServerRequest("/teams?" + new URLSearchParams(filterUndefined({
@@ -247,16 +259,12 @@ export class StackServerInterface extends StackClientInterface {
247
259
  return json.items;
248
260
  }
249
261
  async sendServerContactChannelVerificationEmail(userId, contactChannelId, callbackUrl) {
250
- const responseOrError = await this.sendServerRequestAndCatchKnownError(`/contact-channels/${userId}/${contactChannelId}/send-verification-code`, {
262
+ await this.sendServerRequest(`/contact-channels/${userId}/${contactChannelId}/send-verification-code`, {
251
263
  method: "POST",
252
264
  headers: {
253
265
  "content-type": "application/json",
254
266
  },
255
267
  body: JSON.stringify({ callback_url: callbackUrl }),
256
- }, null, [KnownErrors.EmailAlreadyVerified]);
257
- if (responseOrError.status === "error") {
258
- return Result.error(responseOrError.error);
259
- }
260
- return Result.ok(undefined);
268
+ }, null);
261
269
  }
262
270
  }
@@ -123,5 +123,11 @@ export declare const teamInvitationCallbackUrlSchema: yup.StringSchema<string |
123
123
  export declare const teamCreatorUserIdSchema: yup.StringSchema<string | undefined, yup.AnyObject, undefined, "">;
124
124
  export declare const teamMemberDisplayNameSchema: yup.StringSchema<string | undefined, yup.AnyObject, undefined, "">;
125
125
  export declare const teamMemberProfileImageUrlSchema: yup.StringSchema<string | undefined, yup.AnyObject, undefined, "">;
126
+ export declare const contactChannelIdSchema: yup.StringSchema<string | undefined, yup.AnyObject, undefined, "">;
127
+ export declare const contactChannelTypeSchema: yup.StringSchema<"email" | undefined, yup.AnyObject, undefined, "">;
128
+ export declare const contactChannelValueSchema: yup.StringSchema<string | undefined, yup.AnyObject, undefined, "">;
129
+ export declare const contactChannelUsedForAuthSchema: yup.BooleanSchema<boolean | undefined, yup.AnyObject, undefined, "">;
130
+ export declare const contactChannelIsVerifiedSchema: yup.BooleanSchema<boolean | undefined, yup.AnyObject, undefined, "">;
131
+ export declare const contactChannelIsPrimarySchema: yup.BooleanSchema<boolean | undefined, yup.AnyObject, undefined, "">;
126
132
  export declare function yupRequiredWhen<S extends yup.AnyObject>(schema: S, triggerName: string, isValue: any): S;
127
133
  export {};
@@ -53,7 +53,7 @@ export async function yupValidate(schema, obj, options) {
53
53
  throw error;
54
54
  }
55
55
  }
56
- const _idDescription = (identify) => `The unique identifier of this ${identify}`;
56
+ const _idDescription = (identify) => `The unique identifier of the ${identify}`;
57
57
  const _displayNameDescription = (identify) => `Human-readable ${identify} display name. This is not a unique identifier.`;
58
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.`;
59
59
  const _clientReadOnlyMetaDataDescription = (identify) => `Client read-only, server-writable metadata. Used as a data store, accessible from the client side. Do not store information that should not be exposed to the client. The client can read this data, but cannot modify it. This is useful for things like subscription status.`;
@@ -320,6 +320,16 @@ export const teamCreatorUserIdSchema = userIdOrMeSchema.meta({ openapiField: { d
320
320
  // Team member profiles
321
321
  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' } });
322
322
  export const teamMemberProfileImageUrlSchema = urlSchema.max(1000000).meta({ openapiField: { description: _profileImageUrlDescription('team member'), exampleValue: 'https://example.com/image.jpg' } });
323
+ // Contact channels
324
+ export const contactChannelIdSchema = yupString().uuid().meta({ openapiField: { description: _idDescription('contact channel'), exampleValue: 'b3d396b8-c574-4c80-97b3-50031675ceb2' } });
325
+ export const contactChannelTypeSchema = yupString().oneOf(['email']).meta({ openapiField: { description: `The type of the contact channel. Currently only "email" is supported.`, exampleValue: 'email' } });
326
+ export const contactChannelValueSchema = yupString().when('type', {
327
+ is: 'email',
328
+ then: (schema) => schema.email(),
329
+ }).meta({ openapiField: { description: 'The value of the contact channel. For email, this should be a valid email address.', exampleValue: 'johndoe@example.com' } });
330
+ export const contactChannelUsedForAuthSchema = yupBoolean().meta({ openapiField: { description: 'Whether the contact channel is used for authentication. If this is set to `true`, the user will be able to sign in with the contact channel with password or OTP.', exampleValue: true } });
331
+ export const contactChannelIsVerifiedSchema = yupBoolean().meta({ openapiField: { description: 'Whether the contact channel has been verified. If this is set to `true`, the contact channel has been verified to belong to the user.', exampleValue: true } });
332
+ export const contactChannelIsPrimarySchema = yupBoolean().meta({ openapiField: { description: 'Whether the contact channel is the primary contact channel. If this is set to `true`, it will be used for authentication and notifications by default.', exampleValue: true } });
323
333
  // Utils
324
334
  export function yupRequiredWhen(schema, triggerName, isValue) {
325
335
  return schema.when(triggerName, {
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@stackframe/stack-shared",
3
- "version": "2.6.15",
3
+ "version": "2.6.16",
4
4
  "main": "./dist/index.js",
5
5
  "types": "./dist/index.d.ts",
6
6
  "files": [
@@ -39,7 +39,7 @@
39
39
  "oauth4webapi": "^2.10.3",
40
40
  "semver": "^7.6.3",
41
41
  "uuid": "^9.0.1",
42
- "@stackframe/stack-sc": "2.6.15"
42
+ "@stackframe/stack-sc": "2.6.16"
43
43
  },
44
44
  "devDependencies": {
45
45
  "@simplewebauthn/types": "^11.0.0",