@stackframe/stack-shared 2.7.25 → 2.7.27
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 +12 -0
- package/dist/interface/adminInterface.d.ts +2 -0
- package/dist/interface/adminInterface.js +6 -0
- package/dist/interface/clientInterface.d.ts +4 -0
- package/dist/interface/clientInterface.js +27 -0
- package/dist/interface/crud/emails.d.ts +34 -0
- package/dist/interface/crud/emails.js +13 -0
- package/dist/interface/crud/projects.d.ts +10 -0
- package/dist/interface/crud/projects.js +2 -0
- package/dist/interface/crud/sessions.d.ts +144 -0
- package/dist/interface/crud/sessions.js +55 -0
- package/dist/interface/crud/team-permissions.d.ts +34 -0
- package/dist/interface/crud/team-permissions.js +18 -0
- package/dist/interface/serverInterface.d.ts +4 -1
- package/dist/interface/serverInterface.js +18 -5
- package/dist/known-errors.d.ts +13 -2
- package/dist/known-errors.js +23 -5
- package/dist/schema-fields.d.ts +1 -0
- package/dist/schema-fields.js +1 -0
- package/dist/utils/geo.d.ts +19 -0
- package/dist/utils/geo.js +10 -0
- package/dist/utils/strings.js +6 -0
- package/package.json +1 -1
package/CHANGELOG.md
CHANGED
|
@@ -1,6 +1,7 @@
|
|
|
1
1
|
import { InternalSession } from "../sessions";
|
|
2
2
|
import { ApiKeysCrud } from "./crud/api-keys";
|
|
3
3
|
import { EmailTemplateCrud, EmailTemplateType } from "./crud/email-templates";
|
|
4
|
+
import { InternalEmailsCrud } from "./crud/emails";
|
|
4
5
|
import { ProjectsCrud } from "./crud/projects";
|
|
5
6
|
import { SvixTokenCrud } from "./crud/svix-token";
|
|
6
7
|
import { TeamPermissionDefinitionsCrud } from "./crud/team-permissions";
|
|
@@ -61,4 +62,5 @@ export declare class StackAdminInterface extends StackServerInterface {
|
|
|
61
62
|
success: boolean;
|
|
62
63
|
error_message?: string;
|
|
63
64
|
}>;
|
|
65
|
+
listSentEmails(): Promise<InternalEmailsCrud["Admin"]["List"]>;
|
|
64
66
|
}
|
|
@@ -136,4 +136,10 @@ export class StackAdminInterface extends StackServerInterface {
|
|
|
136
136
|
}, null);
|
|
137
137
|
return await response.json();
|
|
138
138
|
}
|
|
139
|
+
async listSentEmails() {
|
|
140
|
+
const response = await this.sendAdminRequest("/internal/emails", {
|
|
141
|
+
method: "GET",
|
|
142
|
+
}, null);
|
|
143
|
+
return await response.json();
|
|
144
|
+
}
|
|
139
145
|
}
|
|
@@ -7,6 +7,7 @@ import { ContactChannelsCrud } from './crud/contact-channels';
|
|
|
7
7
|
import { CurrentUserCrud } from './crud/current-user';
|
|
8
8
|
import { ConnectedAccountAccessTokenCrud } from './crud/oauth';
|
|
9
9
|
import { InternalProjectsCrud, ProjectsCrud } from './crud/projects';
|
|
10
|
+
import { SessionsCrud } from './crud/sessions';
|
|
10
11
|
import { TeamInvitationCrud } from './crud/team-invitation';
|
|
11
12
|
import { TeamMemberProfilesCrud } from './crud/team-member-profiles';
|
|
12
13
|
import { TeamPermissionsCrud } from './crud/team-permissions';
|
|
@@ -193,6 +194,9 @@ export declare class StackClientInterface {
|
|
|
193
194
|
createClientContactChannel(data: ContactChannelsCrud['Client']['Create'], session: InternalSession): Promise<ContactChannelsCrud['Client']['Read']>;
|
|
194
195
|
updateClientContactChannel(id: string, data: ContactChannelsCrud['Client']['Update'], session: InternalSession): Promise<ContactChannelsCrud['Client']['Read']>;
|
|
195
196
|
deleteClientContactChannel(id: string, session: InternalSession): Promise<void>;
|
|
197
|
+
deleteSession(sessionId: string, session: InternalSession): Promise<void>;
|
|
198
|
+
listSessions(session: InternalSession): Promise<SessionsCrud['Client']['List']>;
|
|
196
199
|
listClientContactChannels(session: InternalSession): Promise<ContactChannelsCrud['Client']['Read'][]>;
|
|
197
200
|
sendCurrentUserContactChannelVerificationEmail(contactChannelId: string, callbackUrl: string, session: InternalSession): Promise<Result<undefined, KnownErrors["EmailAlreadyVerified"]>>;
|
|
201
|
+
cliLogin(loginCode: string, refreshToken: string, session: InternalSession): Promise<Result<undefined, KnownErrors["SchemaError"]>>;
|
|
198
202
|
}
|
|
@@ -876,6 +876,17 @@ export class StackClientInterface {
|
|
|
876
876
|
method: "DELETE",
|
|
877
877
|
}, session);
|
|
878
878
|
}
|
|
879
|
+
async deleteSession(sessionId, session) {
|
|
880
|
+
await this.sendClientRequest(`/auth/sessions/${sessionId}?user_id=me`, {
|
|
881
|
+
method: "DELETE",
|
|
882
|
+
}, session);
|
|
883
|
+
}
|
|
884
|
+
async listSessions(session) {
|
|
885
|
+
const response = await this.sendClientRequest("/auth/sessions?user_id=me", {
|
|
886
|
+
method: "GET",
|
|
887
|
+
}, session);
|
|
888
|
+
return await response.json();
|
|
889
|
+
}
|
|
879
890
|
async listClientContactChannels(session) {
|
|
880
891
|
const response = await this.sendClientRequest("/contact-channels?user_id=me", {
|
|
881
892
|
method: "GET",
|
|
@@ -896,4 +907,20 @@ export class StackClientInterface {
|
|
|
896
907
|
}
|
|
897
908
|
return Result.ok(undefined);
|
|
898
909
|
}
|
|
910
|
+
async cliLogin(loginCode, refreshToken, session) {
|
|
911
|
+
const responseOrError = await this.sendClientRequestAndCatchKnownError("/auth/cli/complete", {
|
|
912
|
+
method: "POST",
|
|
913
|
+
headers: {
|
|
914
|
+
"Content-Type": "application/json"
|
|
915
|
+
},
|
|
916
|
+
body: JSON.stringify({
|
|
917
|
+
login_code: loginCode,
|
|
918
|
+
refresh_token: refreshToken,
|
|
919
|
+
}),
|
|
920
|
+
}, session, [KnownErrors.SchemaError]);
|
|
921
|
+
if (responseOrError.status === "error") {
|
|
922
|
+
return Result.error(responseOrError.error);
|
|
923
|
+
}
|
|
924
|
+
return Result.ok(undefined);
|
|
925
|
+
}
|
|
899
926
|
}
|
|
@@ -0,0 +1,34 @@
|
|
|
1
|
+
import { CrudTypeOf } from "../../crud";
|
|
2
|
+
export declare const sentEmailReadSchema: import("yup").ObjectSchema<{
|
|
3
|
+
id: string;
|
|
4
|
+
subject: string;
|
|
5
|
+
sent_at_millis: number;
|
|
6
|
+
to: string[] | undefined;
|
|
7
|
+
sender_config: {} | null;
|
|
8
|
+
error: {} | null | undefined;
|
|
9
|
+
}, import("yup").AnyObject, {
|
|
10
|
+
id: undefined;
|
|
11
|
+
subject: undefined;
|
|
12
|
+
sent_at_millis: undefined;
|
|
13
|
+
to: undefined;
|
|
14
|
+
sender_config: undefined;
|
|
15
|
+
error: undefined;
|
|
16
|
+
}, "">;
|
|
17
|
+
export declare const internalEmailsCrud: import("../../crud").CrudSchemaFromOptions<{
|
|
18
|
+
clientReadSchema: import("yup").ObjectSchema<{
|
|
19
|
+
id: string;
|
|
20
|
+
subject: string;
|
|
21
|
+
sent_at_millis: number;
|
|
22
|
+
to: string[] | undefined;
|
|
23
|
+
sender_config: {} | null;
|
|
24
|
+
error: {} | null | undefined;
|
|
25
|
+
}, import("yup").AnyObject, {
|
|
26
|
+
id: undefined;
|
|
27
|
+
subject: undefined;
|
|
28
|
+
sent_at_millis: undefined;
|
|
29
|
+
to: undefined;
|
|
30
|
+
sender_config: undefined;
|
|
31
|
+
error: undefined;
|
|
32
|
+
}, "">;
|
|
33
|
+
}>;
|
|
34
|
+
export type InternalEmailsCrud = CrudTypeOf<typeof internalEmailsCrud>;
|
|
@@ -0,0 +1,13 @@
|
|
|
1
|
+
import { createCrud } from "../../crud";
|
|
2
|
+
import * as fieldSchema from "../../schema-fields";
|
|
3
|
+
export const sentEmailReadSchema = fieldSchema.yupObject({
|
|
4
|
+
id: fieldSchema.yupString().defined(),
|
|
5
|
+
subject: fieldSchema.yupString().defined(),
|
|
6
|
+
sent_at_millis: fieldSchema.yupNumber().defined(),
|
|
7
|
+
to: fieldSchema.yupArray(fieldSchema.yupString().defined()),
|
|
8
|
+
sender_config: fieldSchema.yupMixed().nullable().defined(),
|
|
9
|
+
error: fieldSchema.yupMixed().nullable().optional(),
|
|
10
|
+
}).defined();
|
|
11
|
+
export const internalEmailsCrud = createCrud({
|
|
12
|
+
clientReadSchema: sentEmailReadSchema,
|
|
13
|
+
});
|
|
@@ -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({
|
|
@@ -0,0 +1,144 @@
|
|
|
1
|
+
import { CrudTypeOf } from "../../crud";
|
|
2
|
+
export declare const sessionsCrudServerCreateSchema: import("yup").ObjectSchema<{
|
|
3
|
+
user_id: string;
|
|
4
|
+
expires_in_millis: number;
|
|
5
|
+
is_impersonation: boolean;
|
|
6
|
+
}, import("yup").AnyObject, {
|
|
7
|
+
user_id: undefined;
|
|
8
|
+
expires_in_millis: number;
|
|
9
|
+
is_impersonation: false;
|
|
10
|
+
}, "">;
|
|
11
|
+
export declare const sessionsCreateOutputSchema: import("yup").ObjectSchema<{
|
|
12
|
+
refresh_token: string;
|
|
13
|
+
access_token: string;
|
|
14
|
+
}, import("yup").AnyObject, {
|
|
15
|
+
refresh_token: undefined;
|
|
16
|
+
access_token: undefined;
|
|
17
|
+
}, "">;
|
|
18
|
+
export declare const sessionsCrudReadSchema: import("yup").ObjectSchema<{
|
|
19
|
+
id: string;
|
|
20
|
+
user_id: string;
|
|
21
|
+
created_at: number;
|
|
22
|
+
is_impersonation: boolean;
|
|
23
|
+
last_used_at: number | undefined;
|
|
24
|
+
is_current_session: boolean | undefined;
|
|
25
|
+
last_used_at_end_user_ip_info: {
|
|
26
|
+
countryCode?: string | null | undefined;
|
|
27
|
+
regionCode?: string | null | undefined;
|
|
28
|
+
cityName?: string | null | undefined;
|
|
29
|
+
latitude?: number | null | undefined;
|
|
30
|
+
longitude?: number | null | undefined;
|
|
31
|
+
tzIdentifier?: string | null | undefined;
|
|
32
|
+
ip: string;
|
|
33
|
+
} | undefined;
|
|
34
|
+
}, import("yup").AnyObject, {
|
|
35
|
+
id: undefined;
|
|
36
|
+
user_id: undefined;
|
|
37
|
+
created_at: undefined;
|
|
38
|
+
is_impersonation: undefined;
|
|
39
|
+
last_used_at: undefined;
|
|
40
|
+
is_current_session: undefined;
|
|
41
|
+
last_used_at_end_user_ip_info: {
|
|
42
|
+
ip: undefined;
|
|
43
|
+
countryCode: undefined;
|
|
44
|
+
regionCode: undefined;
|
|
45
|
+
cityName: undefined;
|
|
46
|
+
latitude: undefined;
|
|
47
|
+
longitude: undefined;
|
|
48
|
+
tzIdentifier: undefined;
|
|
49
|
+
};
|
|
50
|
+
}, "">;
|
|
51
|
+
export declare const sessionsCrudDeleteSchema: import("yup").MixedSchema<{} | undefined, import("yup").AnyObject, undefined, "">;
|
|
52
|
+
export declare const sessionsCrud: import("../../crud").CrudSchemaFromOptions<{
|
|
53
|
+
serverReadSchema: import("yup").ObjectSchema<{
|
|
54
|
+
id: string;
|
|
55
|
+
user_id: string;
|
|
56
|
+
created_at: number;
|
|
57
|
+
is_impersonation: boolean;
|
|
58
|
+
last_used_at: number | undefined;
|
|
59
|
+
is_current_session: boolean | undefined;
|
|
60
|
+
last_used_at_end_user_ip_info: {
|
|
61
|
+
countryCode?: string | null | undefined;
|
|
62
|
+
regionCode?: string | null | undefined;
|
|
63
|
+
cityName?: string | null | undefined;
|
|
64
|
+
latitude?: number | null | undefined;
|
|
65
|
+
longitude?: number | null | undefined;
|
|
66
|
+
tzIdentifier?: string | null | undefined;
|
|
67
|
+
ip: string;
|
|
68
|
+
} | undefined;
|
|
69
|
+
}, import("yup").AnyObject, {
|
|
70
|
+
id: undefined;
|
|
71
|
+
user_id: undefined;
|
|
72
|
+
created_at: undefined;
|
|
73
|
+
is_impersonation: undefined;
|
|
74
|
+
last_used_at: undefined;
|
|
75
|
+
is_current_session: undefined;
|
|
76
|
+
last_used_at_end_user_ip_info: {
|
|
77
|
+
ip: undefined;
|
|
78
|
+
countryCode: undefined;
|
|
79
|
+
regionCode: undefined;
|
|
80
|
+
cityName: undefined;
|
|
81
|
+
latitude: undefined;
|
|
82
|
+
longitude: undefined;
|
|
83
|
+
tzIdentifier: undefined;
|
|
84
|
+
};
|
|
85
|
+
}, "">;
|
|
86
|
+
serverDeleteSchema: import("yup").MixedSchema<{} | undefined, import("yup").AnyObject, undefined, "">;
|
|
87
|
+
clientReadSchema: import("yup").ObjectSchema<{
|
|
88
|
+
id: string;
|
|
89
|
+
user_id: string;
|
|
90
|
+
created_at: number;
|
|
91
|
+
is_impersonation: boolean;
|
|
92
|
+
last_used_at: number | undefined;
|
|
93
|
+
is_current_session: boolean | undefined;
|
|
94
|
+
last_used_at_end_user_ip_info: {
|
|
95
|
+
countryCode?: string | null | undefined;
|
|
96
|
+
regionCode?: string | null | undefined;
|
|
97
|
+
cityName?: string | null | undefined;
|
|
98
|
+
latitude?: number | null | undefined;
|
|
99
|
+
longitude?: number | null | undefined;
|
|
100
|
+
tzIdentifier?: string | null | undefined;
|
|
101
|
+
ip: string;
|
|
102
|
+
} | undefined;
|
|
103
|
+
}, import("yup").AnyObject, {
|
|
104
|
+
id: undefined;
|
|
105
|
+
user_id: undefined;
|
|
106
|
+
created_at: undefined;
|
|
107
|
+
is_impersonation: undefined;
|
|
108
|
+
last_used_at: undefined;
|
|
109
|
+
is_current_session: undefined;
|
|
110
|
+
last_used_at_end_user_ip_info: {
|
|
111
|
+
ip: undefined;
|
|
112
|
+
countryCode: undefined;
|
|
113
|
+
regionCode: undefined;
|
|
114
|
+
cityName: undefined;
|
|
115
|
+
latitude: undefined;
|
|
116
|
+
longitude: undefined;
|
|
117
|
+
tzIdentifier: undefined;
|
|
118
|
+
};
|
|
119
|
+
}, "">;
|
|
120
|
+
clientDeleteSchema: import("yup").MixedSchema<{} | undefined, import("yup").AnyObject, undefined, "">;
|
|
121
|
+
docs: {
|
|
122
|
+
serverList: {
|
|
123
|
+
summary: string;
|
|
124
|
+
description: string;
|
|
125
|
+
tags: string[];
|
|
126
|
+
};
|
|
127
|
+
serverDelete: {
|
|
128
|
+
summary: string;
|
|
129
|
+
description: string;
|
|
130
|
+
tags: string[];
|
|
131
|
+
};
|
|
132
|
+
clientList: {
|
|
133
|
+
summary: string;
|
|
134
|
+
description: string;
|
|
135
|
+
tags: string[];
|
|
136
|
+
};
|
|
137
|
+
clientDelete: {
|
|
138
|
+
summary: string;
|
|
139
|
+
description: string;
|
|
140
|
+
tags: string[];
|
|
141
|
+
};
|
|
142
|
+
};
|
|
143
|
+
}>;
|
|
144
|
+
export type SessionsCrud = CrudTypeOf<typeof sessionsCrud>;
|
|
@@ -0,0 +1,55 @@
|
|
|
1
|
+
import { createCrud } from "../../crud";
|
|
2
|
+
import { yupBoolean, yupMixed, yupNumber, yupObject, yupString } from "../../schema-fields";
|
|
3
|
+
import { geoInfoSchema } from "../../utils/geo";
|
|
4
|
+
// Create
|
|
5
|
+
export const sessionsCrudServerCreateSchema = yupObject({
|
|
6
|
+
user_id: yupString().uuid().defined(),
|
|
7
|
+
expires_in_millis: yupNumber().max(1000 * 60 * 60 * 24 * 367).default(1000 * 60 * 60 * 24 * 365),
|
|
8
|
+
is_impersonation: yupBoolean().default(false),
|
|
9
|
+
}).defined();
|
|
10
|
+
export const sessionsCreateOutputSchema = yupObject({
|
|
11
|
+
refresh_token: yupString().defined(),
|
|
12
|
+
access_token: yupString().defined(),
|
|
13
|
+
}).defined();
|
|
14
|
+
export const sessionsCrudReadSchema = yupObject({
|
|
15
|
+
id: yupString().defined(),
|
|
16
|
+
user_id: yupString().uuid().defined(),
|
|
17
|
+
created_at: yupNumber().defined(),
|
|
18
|
+
is_impersonation: yupBoolean().defined(),
|
|
19
|
+
last_used_at: yupNumber().optional(),
|
|
20
|
+
is_current_session: yupBoolean(),
|
|
21
|
+
// TODO move this to a shared type
|
|
22
|
+
// TODO: what about if not trusted?
|
|
23
|
+
last_used_at_end_user_ip_info: geoInfoSchema.optional(),
|
|
24
|
+
}).defined();
|
|
25
|
+
// Delete
|
|
26
|
+
export const sessionsCrudDeleteSchema = yupMixed();
|
|
27
|
+
export const sessionsCrud = createCrud({
|
|
28
|
+
// serverCreateSchema: sessionsCrudServerCreateSchema,
|
|
29
|
+
serverReadSchema: sessionsCrudReadSchema,
|
|
30
|
+
serverDeleteSchema: sessionsCrudDeleteSchema,
|
|
31
|
+
clientReadSchema: sessionsCrudReadSchema,
|
|
32
|
+
clientDeleteSchema: sessionsCrudDeleteSchema,
|
|
33
|
+
docs: {
|
|
34
|
+
serverList: {
|
|
35
|
+
summary: "List sessions",
|
|
36
|
+
description: "List all sessions for the current user.",
|
|
37
|
+
tags: ["Sessions"],
|
|
38
|
+
},
|
|
39
|
+
serverDelete: {
|
|
40
|
+
summary: "Delete session",
|
|
41
|
+
description: "Delete a session by ID.",
|
|
42
|
+
tags: ["Sessions"],
|
|
43
|
+
},
|
|
44
|
+
clientList: {
|
|
45
|
+
summary: "List sessions",
|
|
46
|
+
description: "List all sessions for the current user.",
|
|
47
|
+
tags: ["Sessions"],
|
|
48
|
+
},
|
|
49
|
+
clientDelete: {
|
|
50
|
+
summary: "Delete session",
|
|
51
|
+
description: "Delete a session by ID.",
|
|
52
|
+
tags: ["Sessions"],
|
|
53
|
+
},
|
|
54
|
+
},
|
|
55
|
+
});
|
|
@@ -46,6 +46,40 @@ export declare const teamPermissionsCrud: import("../../crud").CrudSchemaFromOpt
|
|
|
46
46
|
};
|
|
47
47
|
}>;
|
|
48
48
|
export type TeamPermissionsCrud = CrudTypeOf<typeof teamPermissionsCrud>;
|
|
49
|
+
export declare const teamPermissionCreatedWebhookEvent: {
|
|
50
|
+
type: string;
|
|
51
|
+
schema: import("yup").ObjectSchema<{
|
|
52
|
+
id: string;
|
|
53
|
+
user_id: string;
|
|
54
|
+
team_id: string;
|
|
55
|
+
}, import("yup").AnyObject, {
|
|
56
|
+
id: undefined;
|
|
57
|
+
user_id: undefined;
|
|
58
|
+
team_id: undefined;
|
|
59
|
+
}, "">;
|
|
60
|
+
metadata: {
|
|
61
|
+
summary: string;
|
|
62
|
+
description: string;
|
|
63
|
+
tags: string[];
|
|
64
|
+
};
|
|
65
|
+
};
|
|
66
|
+
export declare const teamPermissionDeletedWebhookEvent: {
|
|
67
|
+
type: string;
|
|
68
|
+
schema: import("yup").ObjectSchema<{
|
|
69
|
+
id: string;
|
|
70
|
+
user_id: string;
|
|
71
|
+
team_id: string;
|
|
72
|
+
}, import("yup").AnyObject, {
|
|
73
|
+
id: undefined;
|
|
74
|
+
user_id: undefined;
|
|
75
|
+
team_id: undefined;
|
|
76
|
+
}, "">;
|
|
77
|
+
metadata: {
|
|
78
|
+
summary: string;
|
|
79
|
+
description: string;
|
|
80
|
+
tags: string[];
|
|
81
|
+
};
|
|
82
|
+
};
|
|
49
83
|
export declare const teamPermissionDefinitionsCrudAdminReadSchema: import("yup").ObjectSchema<{
|
|
50
84
|
id: string;
|
|
51
85
|
description: string | undefined;
|
|
@@ -36,6 +36,24 @@ export const teamPermissionsCrud = createCrud({
|
|
|
36
36
|
},
|
|
37
37
|
},
|
|
38
38
|
});
|
|
39
|
+
export const teamPermissionCreatedWebhookEvent = {
|
|
40
|
+
type: "team_permission.created",
|
|
41
|
+
schema: teamPermissionsCrud.server.readSchema,
|
|
42
|
+
metadata: {
|
|
43
|
+
summary: "Team Permission Created",
|
|
44
|
+
description: "This event is triggered when a team permission is created.",
|
|
45
|
+
tags: ["Teams"],
|
|
46
|
+
},
|
|
47
|
+
};
|
|
48
|
+
export const teamPermissionDeletedWebhookEvent = {
|
|
49
|
+
type: "team_permission.deleted",
|
|
50
|
+
schema: teamPermissionsCrud.server.readSchema,
|
|
51
|
+
metadata: {
|
|
52
|
+
summary: "Team Permission Deleted",
|
|
53
|
+
description: "This event is triggered when a team permission is deleted.",
|
|
54
|
+
tags: ["Teams"],
|
|
55
|
+
},
|
|
56
|
+
};
|
|
39
57
|
// =============== Team permission definitions =================
|
|
40
58
|
export const teamPermissionDefinitionsCrudAdminReadSchema = yupObject({
|
|
41
59
|
id: schemaFields.teamPermissionDefinitionIdSchema.defined(),
|
|
@@ -5,6 +5,7 @@ import { ClientInterfaceOptions, StackClientInterface } from "./clientInterface"
|
|
|
5
5
|
import { ContactChannelsCrud } from "./crud/contact-channels";
|
|
6
6
|
import { CurrentUserCrud } from "./crud/current-user";
|
|
7
7
|
import { ConnectedAccountAccessTokenCrud } from "./crud/oauth";
|
|
8
|
+
import { SessionsCrud } from "./crud/sessions";
|
|
8
9
|
import { TeamInvitationCrud } from "./crud/team-invitation";
|
|
9
10
|
import { TeamMemberProfilesCrud } from "./crud/team-member-profiles";
|
|
10
11
|
import { TeamMembershipsCrud } from "./crud/team-memberships";
|
|
@@ -74,7 +75,7 @@ export declare class StackServerInterface extends StackClientInterface {
|
|
|
74
75
|
}): Promise<void>;
|
|
75
76
|
updateServerUser(userId: string, update: UsersCrud['Server']['Update']): Promise<UsersCrud['Server']['Read']>;
|
|
76
77
|
createServerProviderAccessToken(userId: string, provider: string, scope: string): Promise<ConnectedAccountAccessTokenCrud['Server']['Read']>;
|
|
77
|
-
createServerUserSession(userId: string, expiresInMillis: number): Promise<{
|
|
78
|
+
createServerUserSession(userId: string, expiresInMillis: number, isImpersonation: boolean): Promise<{
|
|
78
79
|
accessToken: string;
|
|
79
80
|
refreshToken: string;
|
|
80
81
|
}>;
|
|
@@ -95,6 +96,8 @@ export declare class StackServerInterface extends StackClientInterface {
|
|
|
95
96
|
deleteServerContactChannel(userId: string, contactChannelId: string): Promise<void>;
|
|
96
97
|
listServerContactChannels(userId: string): Promise<ContactChannelsCrud['Server']['Read'][]>;
|
|
97
98
|
sendServerContactChannelVerificationEmail(userId: string, contactChannelId: string, callbackUrl: string): Promise<void>;
|
|
99
|
+
listServerSessions(userId: string): Promise<SessionsCrud['Server']['Read'][]>;
|
|
100
|
+
deleteServerSession(sessionId: string): Promise<void>;
|
|
98
101
|
sendServerTeamInvitation(options: {
|
|
99
102
|
email: string;
|
|
100
103
|
teamId: string;
|
|
@@ -58,10 +58,11 @@ export class StackServerInterface extends StackClientInterface {
|
|
|
58
58
|
return user;
|
|
59
59
|
}
|
|
60
60
|
async getServerUserById(userId) {
|
|
61
|
-
const
|
|
62
|
-
|
|
63
|
-
|
|
64
|
-
|
|
61
|
+
const responseOrError = await this.sendServerRequestAndCatchKnownError(urlString `/users/${userId}`, {}, null, [KnownErrors.UserNotFound]);
|
|
62
|
+
if (responseOrError.status === "error") {
|
|
63
|
+
return Result.error(responseOrError.error);
|
|
64
|
+
}
|
|
65
|
+
const user = await responseOrError.data.json();
|
|
65
66
|
return Result.ok(user);
|
|
66
67
|
}
|
|
67
68
|
async listServerTeamInvitations(options) {
|
|
@@ -182,7 +183,7 @@ export class StackServerInterface extends StackClientInterface {
|
|
|
182
183
|
}, null);
|
|
183
184
|
return await response.json();
|
|
184
185
|
}
|
|
185
|
-
async createServerUserSession(userId, expiresInMillis) {
|
|
186
|
+
async createServerUserSession(userId, expiresInMillis, isImpersonation) {
|
|
186
187
|
const response = await this.sendServerRequest("/auth/sessions", {
|
|
187
188
|
method: "POST",
|
|
188
189
|
headers: {
|
|
@@ -191,6 +192,7 @@ export class StackServerInterface extends StackClientInterface {
|
|
|
191
192
|
body: JSON.stringify({
|
|
192
193
|
user_id: userId,
|
|
193
194
|
expires_in_millis: expiresInMillis,
|
|
195
|
+
is_impersonation: isImpersonation,
|
|
194
196
|
}),
|
|
195
197
|
}, null);
|
|
196
198
|
const result = await response.json();
|
|
@@ -285,6 +287,17 @@ export class StackServerInterface extends StackClientInterface {
|
|
|
285
287
|
body: JSON.stringify({ callback_url: callbackUrl }),
|
|
286
288
|
}, null);
|
|
287
289
|
}
|
|
290
|
+
async listServerSessions(userId) {
|
|
291
|
+
const response = await this.sendServerRequest(urlString `/auth/sessions?user_id=${userId}`, {
|
|
292
|
+
method: "GET",
|
|
293
|
+
}, null);
|
|
294
|
+
return await response.json();
|
|
295
|
+
}
|
|
296
|
+
async deleteServerSession(sessionId) {
|
|
297
|
+
await this.sendServerRequest(urlString `/auth/sessions/${sessionId}`, {
|
|
298
|
+
method: "DELETE",
|
|
299
|
+
}, null);
|
|
300
|
+
}
|
|
288
301
|
async sendServerTeamInvitation(options) {
|
|
289
302
|
await this.sendServerRequest("/team-invitations/send-code", {
|
|
290
303
|
method: "POST",
|
package/dist/known-errors.d.ts
CHANGED
|
@@ -46,6 +46,11 @@ export type KnownErrors = {
|
|
|
46
46
|
[K in keyof typeof KnownErrors]: InstanceType<typeof KnownErrors[K]>;
|
|
47
47
|
};
|
|
48
48
|
export declare const KnownErrors: {
|
|
49
|
+
CannotDeleteCurrentSession: KnownErrorConstructor<KnownError & KnownErrorBrand<"REFRESH_TOKEN_ERROR"> & {
|
|
50
|
+
constructorArgs: [statusCode: number, humanReadableMessage: string, details?: Json | undefined];
|
|
51
|
+
} & KnownErrorBrand<"CANNOT_DELETE_CURRENT_SESSION">, []> & {
|
|
52
|
+
errorCode: "CANNOT_DELETE_CURRENT_SESSION";
|
|
53
|
+
};
|
|
49
54
|
UnsupportedError: KnownErrorConstructor<KnownError & KnownErrorBrand<"UNSUPPORTED_ERROR">, [originalErrorCode: string]> & {
|
|
50
55
|
errorCode: "UNSUPPORTED_ERROR";
|
|
51
56
|
};
|
|
@@ -194,7 +199,7 @@ export declare const KnownErrors: {
|
|
|
194
199
|
};
|
|
195
200
|
AccessTokenExpired: KnownErrorConstructor<KnownError & KnownErrorBrand<"SESSION_AUTHENTICATION_ERROR"> & {
|
|
196
201
|
constructorArgs: [statusCode: number, humanReadableMessage: string, details?: Json | undefined];
|
|
197
|
-
} & KnownErrorBrand<"INVALID_SESSION_AUTHENTICATION"> & KnownErrorBrand<"INVALID_ACCESS_TOKEN"> & KnownErrorBrand<"ACCESS_TOKEN_EXPIRED">, [
|
|
202
|
+
} & KnownErrorBrand<"INVALID_SESSION_AUTHENTICATION"> & KnownErrorBrand<"INVALID_ACCESS_TOKEN"> & KnownErrorBrand<"ACCESS_TOKEN_EXPIRED">, [Date | undefined]> & {
|
|
198
203
|
errorCode: "ACCESS_TOKEN_EXPIRED";
|
|
199
204
|
};
|
|
200
205
|
InvalidProjectForAccessToken: KnownErrorConstructor<KnownError & KnownErrorBrand<"SESSION_AUTHENTICATION_ERROR"> & {
|
|
@@ -218,6 +223,9 @@ export declare const KnownErrors: {
|
|
|
218
223
|
UserEmailAlreadyExists: KnownErrorConstructor<KnownError & KnownErrorBrand<"USER_EMAIL_ALREADY_EXISTS">, []> & {
|
|
219
224
|
errorCode: "USER_EMAIL_ALREADY_EXISTS";
|
|
220
225
|
};
|
|
226
|
+
EmailNotVerified: KnownErrorConstructor<KnownError & KnownErrorBrand<"EMAIL_NOT_VERIFIED">, []> & {
|
|
227
|
+
errorCode: "EMAIL_NOT_VERIFIED";
|
|
228
|
+
};
|
|
221
229
|
UserIdDoesNotExist: KnownErrorConstructor<KnownError & KnownErrorBrand<"USER_ID_DOES_NOT_EXIST">, [userId: string]> & {
|
|
222
230
|
errorCode: "USER_ID_DOES_NOT_EXIST";
|
|
223
231
|
};
|
|
@@ -380,8 +388,11 @@ export declare const KnownErrors: {
|
|
|
380
388
|
OAuthProviderAccessDenied: KnownErrorConstructor<KnownError & KnownErrorBrand<"OAUTH_PROVIDER_ACCESS_DENIED">, []> & {
|
|
381
389
|
errorCode: "OAUTH_PROVIDER_ACCESS_DENIED";
|
|
382
390
|
};
|
|
383
|
-
ContactChannelAlreadyUsedForAuthBySomeoneElse: KnownErrorConstructor<KnownError & KnownErrorBrand<"CONTACT_CHANNEL_ALREADY_USED_FOR_AUTH_BY_SOMEONE_ELSE">, [type: "email"]> & {
|
|
391
|
+
ContactChannelAlreadyUsedForAuthBySomeoneElse: KnownErrorConstructor<KnownError & KnownErrorBrand<"CONTACT_CHANNEL_ALREADY_USED_FOR_AUTH_BY_SOMEONE_ELSE">, [type: "email", contactChannelValue?: string | undefined]> & {
|
|
384
392
|
errorCode: "CONTACT_CHANNEL_ALREADY_USED_FOR_AUTH_BY_SOMEONE_ELSE";
|
|
385
393
|
};
|
|
394
|
+
InvalidPollingCodeError: KnownErrorConstructor<KnownError & KnownErrorBrand<"INVALID_POLLING_CODE">, [details?: Json | undefined]> & {
|
|
395
|
+
errorCode: "INVALID_POLLING_CODE";
|
|
396
|
+
};
|
|
386
397
|
};
|
|
387
398
|
export {};
|
package/dist/known-errors.js
CHANGED
|
@@ -245,7 +245,7 @@ const AccessTokenExpired = createKnownErrorConstructor(InvalidAccessToken, "ACCE
|
|
|
245
245
|
401,
|
|
246
246
|
`Access token has expired. Please refresh it and try again.${expiredAt ? ` (The access token expired at ${expiredAt.toISOString()}.)` : ""}`,
|
|
247
247
|
{ expired_at_millis: expiredAt?.getTime() ?? null },
|
|
248
|
-
], (json) => [json.expired_at_millis
|
|
248
|
+
], (json) => [json.expired_at_millis ? new Date(json.expired_at_millis) : undefined]);
|
|
249
249
|
const InvalidProjectForAccessToken = createKnownErrorConstructor(InvalidAccessToken, "INVALID_PROJECT_FOR_ACCESS_TOKEN", () => [
|
|
250
250
|
401,
|
|
251
251
|
"Access token not valid for this project.",
|
|
@@ -255,6 +255,10 @@ const RefreshTokenNotFoundOrExpired = createKnownErrorConstructor(RefreshTokenEr
|
|
|
255
255
|
401,
|
|
256
256
|
"Refresh token not found for this project, or the session has expired/been revoked.",
|
|
257
257
|
], () => []);
|
|
258
|
+
const CannotDeleteCurrentSession = createKnownErrorConstructor(RefreshTokenError, "CANNOT_DELETE_CURRENT_SESSION", () => [
|
|
259
|
+
400,
|
|
260
|
+
"Cannot delete the current session.",
|
|
261
|
+
], () => []);
|
|
258
262
|
const ProviderRejected = createKnownErrorConstructor(RefreshTokenError, "PROVIDER_REJECTED", () => [
|
|
259
263
|
401,
|
|
260
264
|
"The provider refused to refresh their token. This usually means that the provider used to authenticate the user no longer regards this session as valid, and the user must re-authenticate.",
|
|
@@ -263,6 +267,10 @@ const UserEmailAlreadyExists = createKnownErrorConstructor(KnownError, "USER_EMA
|
|
|
263
267
|
409,
|
|
264
268
|
"User email already exists.",
|
|
265
269
|
], () => []);
|
|
270
|
+
const EmailNotVerified = createKnownErrorConstructor(KnownError, "EMAIL_NOT_VERIFIED", () => [
|
|
271
|
+
400,
|
|
272
|
+
"The email is not verified.",
|
|
273
|
+
], () => []);
|
|
266
274
|
const CannotGetOwnUserWithoutUser = createKnownErrorConstructor(KnownError, "CANNOT_GET_OWN_USER_WITHOUT_USER", () => [
|
|
267
275
|
400,
|
|
268
276
|
"You have specified 'me' as a userId, but did not provide authentication for a user.",
|
|
@@ -531,12 +539,20 @@ const OAuthProviderAccessDenied = createKnownErrorConstructor(KnownError, "OAUTH
|
|
|
531
539
|
400,
|
|
532
540
|
"The OAuth provider denied access to the user.",
|
|
533
541
|
], () => []);
|
|
534
|
-
const ContactChannelAlreadyUsedForAuthBySomeoneElse = createKnownErrorConstructor(KnownError, "CONTACT_CHANNEL_ALREADY_USED_FOR_AUTH_BY_SOMEONE_ELSE", (type) => [
|
|
542
|
+
const ContactChannelAlreadyUsedForAuthBySomeoneElse = createKnownErrorConstructor(KnownError, "CONTACT_CHANNEL_ALREADY_USED_FOR_AUTH_BY_SOMEONE_ELSE", (type, contactChannelValue) => [
|
|
535
543
|
409,
|
|
536
|
-
|
|
537
|
-
|
|
538
|
-
|
|
544
|
+
contactChannelValue ?
|
|
545
|
+
`The ${type} (${contactChannelValue}) is already used for authentication by another account.` :
|
|
546
|
+
`This ${type} is already used for authentication by another account.`,
|
|
547
|
+
{ type, contact_channel_value: contactChannelValue ?? null },
|
|
548
|
+
], (json) => [json.type, json.contact_channel_value]);
|
|
549
|
+
const InvalidPollingCodeError = createKnownErrorConstructor(KnownError, "INVALID_POLLING_CODE", (details) => [
|
|
550
|
+
400,
|
|
551
|
+
"The polling code is invalid or does not exist.",
|
|
552
|
+
details,
|
|
553
|
+
], (json) => [json]);
|
|
539
554
|
export const KnownErrors = {
|
|
555
|
+
CannotDeleteCurrentSession,
|
|
540
556
|
UnsupportedError,
|
|
541
557
|
BodyParsingError,
|
|
542
558
|
SchemaError,
|
|
@@ -575,6 +591,7 @@ export const KnownErrors = {
|
|
|
575
591
|
ProviderRejected,
|
|
576
592
|
RefreshTokenNotFoundOrExpired,
|
|
577
593
|
UserEmailAlreadyExists,
|
|
594
|
+
EmailNotVerified,
|
|
578
595
|
UserIdDoesNotExist,
|
|
579
596
|
UserNotFound,
|
|
580
597
|
ApiKeyNotFound,
|
|
@@ -626,6 +643,7 @@ export const KnownErrors = {
|
|
|
626
643
|
TeamPermissionNotFound,
|
|
627
644
|
OAuthProviderAccessDenied,
|
|
628
645
|
ContactChannelAlreadyUsedForAuthBySomeoneElse,
|
|
646
|
+
InvalidPollingCodeError,
|
|
629
647
|
};
|
|
630
648
|
// ensure that all known error codes are unique
|
|
631
649
|
const knownErrorCodes = new Set();
|
package/dist/schema-fields.d.ts
CHANGED
|
@@ -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, "">;
|
package/dist/schema-fields.js
CHANGED
|
@@ -248,6 +248,7 @@ export const oauthClientIdSchema = yupString().meta({ openapiField: { descriptio
|
|
|
248
248
|
export const oauthClientSecretSchema = yupString().meta({ openapiField: { description: 'OAuth client secret. Needs to be specified when using type="standard"', exampleValue: 'google-oauth-client-secret' } });
|
|
249
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.' } });
|
|
250
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' } });
|
|
251
252
|
// Project email config
|
|
252
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' } });
|
|
253
254
|
export const emailSenderNameSchema = yupString().meta({ openapiField: { description: 'Email sender name. Needs to be specified when using type="standard"', exampleValue: 'Stack' } });
|
|
@@ -0,0 +1,19 @@
|
|
|
1
|
+
import * as yup from "yup";
|
|
2
|
+
export declare const geoInfoSchema: yup.ObjectSchema<{
|
|
3
|
+
ip: string;
|
|
4
|
+
countryCode: string | null | undefined;
|
|
5
|
+
regionCode: string | null | undefined;
|
|
6
|
+
cityName: string | null | undefined;
|
|
7
|
+
latitude: number | null | undefined;
|
|
8
|
+
longitude: number | null | undefined;
|
|
9
|
+
tzIdentifier: string | null | undefined;
|
|
10
|
+
}, yup.AnyObject, {
|
|
11
|
+
ip: undefined;
|
|
12
|
+
countryCode: undefined;
|
|
13
|
+
regionCode: undefined;
|
|
14
|
+
cityName: undefined;
|
|
15
|
+
latitude: undefined;
|
|
16
|
+
longitude: undefined;
|
|
17
|
+
tzIdentifier: undefined;
|
|
18
|
+
}, "">;
|
|
19
|
+
export type GeoInfo = yup.InferType<typeof geoInfoSchema>;
|
|
@@ -0,0 +1,10 @@
|
|
|
1
|
+
import { yupNumber, yupObject, yupString } from "../schema-fields";
|
|
2
|
+
export const geoInfoSchema = yupObject({
|
|
3
|
+
ip: yupString().defined(),
|
|
4
|
+
countryCode: yupString().nullable(),
|
|
5
|
+
regionCode: yupString().nullable(),
|
|
6
|
+
cityName: yupString().nullable(),
|
|
7
|
+
latitude: yupNumber().nullable(),
|
|
8
|
+
longitude: yupNumber().nullable(),
|
|
9
|
+
tzIdentifier: yupString().nullable(),
|
|
10
|
+
});
|
package/dist/utils/strings.js
CHANGED
|
@@ -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);
|