@stackframe/stack-shared 2.4.28 → 2.5.1
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 +17 -0
- package/dist/crud.d.ts +26 -15
- package/dist/crud.js +16 -0
- package/dist/interface/clientInterface.d.ts +4 -4
- package/dist/interface/clientInterface.js +4 -4
- package/dist/interface/crud/current-user.d.ts +98 -85
- package/dist/interface/crud/current-user.js +35 -17
- package/dist/interface/crud/oauth.d.ts +4 -4
- package/dist/interface/crud/oauth.js +1 -1
- package/dist/interface/crud/users.d.ts +144 -80
- package/dist/interface/crud/users.js +56 -24
- package/dist/known-errors.d.ts +139 -77
- package/dist/known-errors.js +116 -84
- package/dist/schema-fields.d.ts +43 -0
- package/dist/schema-fields.js +68 -0
- package/dist/utils/env.d.ts +3 -2
- package/dist/utils/env.js +6 -3
- package/dist/utils/errors.js +1 -1
- package/dist/utils/jwt.js +3 -3
- package/dist/utils/objects.d.ts +4 -1
- package/dist/utils/objects.js +32 -1
- package/dist/utils/strings.d.ts +5 -1
- package/dist/utils/strings.js +29 -17
- package/dist/utils/yup.d.ts +1 -0
- package/dist/utils/yup.js +11 -0
- package/package.json +2 -2
- package/dist/hooks/use-trigger.d.ts +0 -1
- package/dist/hooks/use-trigger.js +0 -10
- package/dist/interface/crud/fields.d.ts +0 -11
- package/dist/interface/crud/fields.js +0 -12
package/dist/known-errors.js
CHANGED
|
@@ -15,9 +15,8 @@ export class KnownError extends StatusError {
|
|
|
15
15
|
getBody() {
|
|
16
16
|
return new TextEncoder().encode(JSON.stringify({
|
|
17
17
|
code: this.errorCode,
|
|
18
|
-
message: this.humanReadableMessage,
|
|
19
18
|
details: this.details,
|
|
20
|
-
error:
|
|
19
|
+
error: this.humanReadableMessage,
|
|
21
20
|
}, undefined, 2));
|
|
22
21
|
}
|
|
23
22
|
getHeaders() {
|
|
@@ -55,9 +54,11 @@ function createKnownErrorConstructor(SuperClass, errorCode, create, constructorA
|
|
|
55
54
|
class KnownErrorImpl extends SuperClass {
|
|
56
55
|
static errorCode = errorCode;
|
|
57
56
|
name = `KnownError<${errorCode}>`;
|
|
57
|
+
constructorArgs;
|
|
58
58
|
constructor(...args) {
|
|
59
59
|
// @ts-expect-error
|
|
60
60
|
super(...createFn(...args));
|
|
61
|
+
this.constructorArgs = args;
|
|
61
62
|
}
|
|
62
63
|
static constructorArgsFromJson(json) {
|
|
63
64
|
return constructorArgsFromJsonFn(json);
|
|
@@ -94,52 +95,93 @@ const AllOverloadsFailed = createKnownErrorConstructor(KnownError, "ALL_OVERLOAD
|
|
|
94
95
|
`).join("\n\n")}
|
|
95
96
|
`,
|
|
96
97
|
{
|
|
97
|
-
overloadErrors,
|
|
98
|
+
overload_errors: overloadErrors,
|
|
98
99
|
},
|
|
99
100
|
], (json) => [
|
|
100
|
-
json.details?.
|
|
101
|
+
json.details?.overload_errors ?? throwErr("overload_errors not found in AllOverloadsFailed details"),
|
|
101
102
|
]);
|
|
102
103
|
const ProjectAuthenticationError = createKnownErrorConstructor(KnownError, "PROJECT_AUTHENTICATION_ERROR", "inherit", "inherit");
|
|
103
|
-
const
|
|
104
|
-
|
|
104
|
+
const InvalidProjectAccess = createKnownErrorConstructor(ProjectAuthenticationError, "INVALID_PROJECT_AUTHENTICATION", "inherit", "inherit");
|
|
105
|
+
/**
|
|
106
|
+
* @deprecated Use ProjectKeyWithoutAccessType instead
|
|
107
|
+
*/
|
|
108
|
+
const ProjectKeyWithoutRequestType = createKnownErrorConstructor(InvalidProjectAccess, "PROJECT_KEY_WITHOUT_REQUEST_TYPE", () => [
|
|
105
109
|
400,
|
|
106
110
|
"Either an API key or an admin access token was provided, but the x-stack-request-type header is missing. Set it to 'client', 'server', or 'admin' as appropriate.",
|
|
107
111
|
], () => []);
|
|
108
|
-
|
|
112
|
+
/**
|
|
113
|
+
* @deprecated Use InvalidAccessType instead
|
|
114
|
+
*/
|
|
115
|
+
const InvalidRequestType = createKnownErrorConstructor(InvalidProjectAccess, "INVALID_REQUEST_TYPE", (requestType) => [
|
|
109
116
|
400,
|
|
110
117
|
`The x-stack-request-type header must be 'client', 'server', or 'admin', but was '${requestType}'.`,
|
|
111
118
|
], (json) => [
|
|
112
119
|
json.details?.requestType ?? throwErr("requestType not found in InvalidRequestType details"),
|
|
113
120
|
]);
|
|
114
|
-
|
|
121
|
+
/**
|
|
122
|
+
* @deprecated Use AccessTypeWithoutProjectId instead
|
|
123
|
+
*/
|
|
124
|
+
const RequestTypeWithoutProjectId = createKnownErrorConstructor(InvalidProjectAccess, "REQUEST_TYPE_WITHOUT_PROJECT_ID", (requestType) => [
|
|
115
125
|
400,
|
|
116
126
|
`The x-stack-request-type header was '${requestType}', but the x-stack-project-id header was not provided.`,
|
|
117
127
|
{
|
|
118
|
-
requestType,
|
|
128
|
+
request_type: requestType,
|
|
119
129
|
},
|
|
120
|
-
], (json) => [json.
|
|
121
|
-
const
|
|
130
|
+
], (json) => [json.request_type]);
|
|
131
|
+
const ProjectKeyWithoutAccessType = createKnownErrorConstructor(InvalidProjectAccess, "PROJECT_KEY_WITHOUT_ACCESS_TYPE", () => [
|
|
132
|
+
400,
|
|
133
|
+
"Either an API key or an admin access token was provided, but the x-stack-access-type header is missing. Set it to 'client', 'server', or 'admin' as appropriate.",
|
|
134
|
+
], () => []);
|
|
135
|
+
const InvalidAccessType = createKnownErrorConstructor(InvalidProjectAccess, "INVALID_ACCESS_TYPE", (requestType) => [
|
|
136
|
+
400,
|
|
137
|
+
`The x-stack-access-type header must be 'client', 'server', or 'admin', but was '${requestType}'.`,
|
|
138
|
+
], (json) => [
|
|
139
|
+
json.details?.requestType ?? throwErr("requestType not found in InvalidRequestType details"),
|
|
140
|
+
]);
|
|
141
|
+
const AccessTypeWithoutProjectId = createKnownErrorConstructor(InvalidProjectAccess, "ACCESS_TYPE_WITHOUT_PROJECT_ID", (requestType) => [
|
|
142
|
+
400,
|
|
143
|
+
`The x-stack-access-type header was '${requestType}', but the x-stack-project-id header was not provided.`,
|
|
144
|
+
{
|
|
145
|
+
request_type: requestType,
|
|
146
|
+
},
|
|
147
|
+
], (json) => [json.request_type]);
|
|
148
|
+
const AccessTypeRequired = createKnownErrorConstructor(InvalidProjectAccess, "ACCESS_TYPE_REQUIRED", () => [
|
|
149
|
+
400,
|
|
150
|
+
`You must specify an access level for this Stack project. Make sure project API keys are provided (eg. x-stack-publishable-client-key) and you set the x-stack-access-type header to 'client', 'server', or 'admin'.`,
|
|
151
|
+
], () => []);
|
|
152
|
+
const InsufficientAccessType = createKnownErrorConstructor(InvalidProjectAccess, "INSUFFICIENT_ACCESS_TYPE", (actualAccessType, allowedAccessTypes) => [
|
|
153
|
+
401,
|
|
154
|
+
`The x-stack-access-type header must be ${allowedAccessTypes.map(s => `'${s}'`).join(" or ")}, but was '${actualAccessType}'.`,
|
|
155
|
+
{
|
|
156
|
+
actual_access_type: actualAccessType,
|
|
157
|
+
allowed_access_types: allowedAccessTypes,
|
|
158
|
+
},
|
|
159
|
+
], (json) => [
|
|
160
|
+
json.details.actual_access_type,
|
|
161
|
+
json.details.allowed_access_types,
|
|
162
|
+
]);
|
|
163
|
+
const InvalidPublishableClientKey = createKnownErrorConstructor(InvalidProjectAccess, "INVALID_PUBLISHABLE_CLIENT_KEY", (projectId) => [
|
|
122
164
|
401,
|
|
123
165
|
`The publishable key is not valid for the project ${JSON.stringify(projectId)}. Does the project and/or the key exist?`,
|
|
124
166
|
{
|
|
125
|
-
projectId,
|
|
167
|
+
project_id: projectId,
|
|
126
168
|
},
|
|
127
|
-
], (json) => [json.
|
|
128
|
-
const InvalidSecretServerKey = createKnownErrorConstructor(
|
|
169
|
+
], (json) => [json.project_id]);
|
|
170
|
+
const InvalidSecretServerKey = createKnownErrorConstructor(InvalidProjectAccess, "INVALID_SECRET_SERVER_KEY", (projectId) => [
|
|
129
171
|
401,
|
|
130
172
|
`The secret server key is not valid for the project ${JSON.stringify(projectId)}. Does the project and/or the key exist?`,
|
|
131
173
|
{
|
|
132
|
-
projectId,
|
|
174
|
+
project_id: projectId,
|
|
133
175
|
},
|
|
134
|
-
], (json) => [json.
|
|
135
|
-
const InvalidSuperSecretAdminKey = createKnownErrorConstructor(
|
|
176
|
+
], (json) => [json.project_id]);
|
|
177
|
+
const InvalidSuperSecretAdminKey = createKnownErrorConstructor(InvalidProjectAccess, "INVALID_SUPER_SECRET_ADMIN_KEY", (projectId) => [
|
|
136
178
|
401,
|
|
137
179
|
`The super secret admin key is not valid for the project ${JSON.stringify(projectId)}. Does the project and/or the key exist?`,
|
|
138
180
|
{
|
|
139
|
-
projectId,
|
|
181
|
+
project_id: projectId,
|
|
140
182
|
},
|
|
141
|
-
], (json) => [json.
|
|
142
|
-
const InvalidAdminAccessToken = createKnownErrorConstructor(
|
|
183
|
+
], (json) => [json.project_id]);
|
|
184
|
+
const InvalidAdminAccessToken = createKnownErrorConstructor(InvalidProjectAccess, "INVALID_ADMIN_ACCESS_TOKEN", "inherit", "inherit");
|
|
143
185
|
const UnparsableAdminAccessToken = createKnownErrorConstructor(InvalidAdminAccessToken, "UNPARSABLE_ADMIN_ACCESS_TOKEN", () => [
|
|
144
186
|
401,
|
|
145
187
|
"Admin access token is not parsable.",
|
|
@@ -156,27 +198,48 @@ const AdminAccessTokenIsNotAdmin = createKnownErrorConstructor(InvalidAdminAcces
|
|
|
156
198
|
401,
|
|
157
199
|
"Admin access token does not have the required permissions to access this project.",
|
|
158
200
|
], () => []);
|
|
201
|
+
/**
|
|
202
|
+
* @deprecated Use InsufficientAccessType instead
|
|
203
|
+
*/
|
|
159
204
|
const ProjectAuthenticationRequired = createKnownErrorConstructor(ProjectAuthenticationError, "PROJECT_AUTHENTICATION_REQUIRED", "inherit", "inherit");
|
|
205
|
+
/**
|
|
206
|
+
* @deprecated Use InsufficientAccessType instead
|
|
207
|
+
*/
|
|
160
208
|
const ClientAuthenticationRequired = createKnownErrorConstructor(ProjectAuthenticationRequired, "CLIENT_AUTHENTICATION_REQUIRED", () => [
|
|
161
209
|
401,
|
|
162
210
|
"The publishable client key must be provided.",
|
|
163
211
|
], () => []);
|
|
212
|
+
/**
|
|
213
|
+
* @deprecated Use InsufficientAccessType instead
|
|
214
|
+
*/
|
|
164
215
|
const ServerAuthenticationRequired = createKnownErrorConstructor(ProjectAuthenticationRequired, "SERVER_AUTHENTICATION_REQUIRED", () => [
|
|
165
216
|
401,
|
|
166
217
|
"The secret server key must be provided.",
|
|
167
218
|
], () => []);
|
|
219
|
+
/**
|
|
220
|
+
* @deprecated Use InsufficientAccessType instead
|
|
221
|
+
*/
|
|
168
222
|
const ClientOrServerAuthenticationRequired = createKnownErrorConstructor(ProjectAuthenticationRequired, "CLIENT_OR_SERVER_AUTHENTICATION_REQUIRED", () => [
|
|
169
223
|
401,
|
|
170
224
|
"Either the publishable client key or the secret server key must be provided.",
|
|
171
225
|
], () => []);
|
|
226
|
+
/**
|
|
227
|
+
* @deprecated Use InsufficientAccessType instead
|
|
228
|
+
*/
|
|
172
229
|
const ClientOrAdminAuthenticationRequired = createKnownErrorConstructor(ProjectAuthenticationRequired, "CLIENT_OR_ADMIN_AUTHENTICATION_REQUIRED", () => [
|
|
173
230
|
401,
|
|
174
231
|
"Either the publishable client key or the super secret admin key must be provided.",
|
|
175
232
|
], () => []);
|
|
233
|
+
/**
|
|
234
|
+
* @deprecated Use InsufficientAccessType instead
|
|
235
|
+
*/
|
|
176
236
|
const ClientOrServerOrAdminAuthenticationRequired = createKnownErrorConstructor(ProjectAuthenticationRequired, "CLIENT_OR_SERVER_OR_ADMIN_AUTHENTICATION_REQUIRED", () => [
|
|
177
237
|
401,
|
|
178
238
|
"Either the publishable client key, the secret server key, or the super secret admin key must be provided.",
|
|
179
239
|
], () => []);
|
|
240
|
+
/**
|
|
241
|
+
* @deprecated Use InsufficientAccessType instead
|
|
242
|
+
*/
|
|
180
243
|
const AdminAuthenticationRequired = createKnownErrorConstructor(ProjectAuthenticationRequired, "ADMIN_AUTHENTICATION_REQUIRED", () => [
|
|
181
244
|
401,
|
|
182
245
|
"The super secret admin key must be provided.",
|
|
@@ -221,6 +284,10 @@ const UserEmailAlreadyExists = createKnownErrorConstructor(KnownError, "USER_EMA
|
|
|
221
284
|
400,
|
|
222
285
|
"User already exists.",
|
|
223
286
|
], () => []);
|
|
287
|
+
const CannotGetOwnUserWithoutUser = createKnownErrorConstructor(KnownError, "CANNOT_GET_OWN_USER_WITHOUT_USER", () => [
|
|
288
|
+
400,
|
|
289
|
+
"You have specified 'me' as a userId, but did not provide authentication for a user.",
|
|
290
|
+
], () => []);
|
|
224
291
|
const UserNotFound = createKnownErrorConstructor(KnownError, "USER_NOT_FOUND", () => [
|
|
225
292
|
404,
|
|
226
293
|
"User not found.",
|
|
@@ -260,52 +327,23 @@ const PasswordTooLong = createKnownErrorConstructor(PasswordRequirementsNotMet,
|
|
|
260
327
|
], (json) => [
|
|
261
328
|
json.details?.maxLength ?? throwErr("maxLength not found in PasswordTooLong details"),
|
|
262
329
|
]);
|
|
263
|
-
const
|
|
264
|
-
const
|
|
265
|
-
const EmailVerificationCodeNotFound = createKnownErrorConstructor(EmailVerificationCodeError, "EMAIL_VERIFICATION_CODE_NOT_FOUND", () => [
|
|
330
|
+
const VerificationCodeError = createKnownErrorConstructor(KnownError, "VERIFICATION_ERROR", "inherit", "inherit");
|
|
331
|
+
const VerificationCodeNotFound = createKnownErrorConstructor(VerificationCodeError, "VERIFICATION_CODE_NOT_FOUND", () => [
|
|
266
332
|
404,
|
|
267
|
-
"The
|
|
268
|
-
], () => []);
|
|
269
|
-
const EmailVerificationCodeExpired = createKnownErrorConstructor(EmailVerificationCodeError, "EMAIL_VERIFICATION_CODE_EXPIRED", () => [
|
|
270
|
-
400,
|
|
271
|
-
"The e-mail verification code has expired.",
|
|
333
|
+
"The verification code does not exist for this project.",
|
|
272
334
|
], () => []);
|
|
273
|
-
const
|
|
335
|
+
const VerificationCodeExpired = createKnownErrorConstructor(VerificationCodeError, "VERIFICATION_CODE_EXPIRED", () => [
|
|
274
336
|
400,
|
|
275
|
-
"The
|
|
276
|
-
], () => []);
|
|
277
|
-
const MagicLinkError = createKnownErrorConstructor(KnownError, "MAGIC_LINK_ERROR", "inherit", "inherit");
|
|
278
|
-
const MagicLinkCodeError = createKnownErrorConstructor(MagicLinkError, "MAGIC_LINK_CODE_ERROR", "inherit", "inherit");
|
|
279
|
-
const MagicLinkCodeNotFound = createKnownErrorConstructor(MagicLinkCodeError, "MAGIC_LINK_CODE_NOT_FOUND", () => [
|
|
280
|
-
404,
|
|
281
|
-
"The e-mail verification code does not exist for this project.",
|
|
337
|
+
"The verification code has expired.",
|
|
282
338
|
], () => []);
|
|
283
|
-
const
|
|
339
|
+
const VerificationCodeAlreadyUsed = createKnownErrorConstructor(VerificationCodeError, "VERIFICATION_CODE_ALREADY_USED", () => [
|
|
284
340
|
400,
|
|
285
|
-
"The
|
|
286
|
-
], () => []);
|
|
287
|
-
const MagicLinkCodeAlreadyUsed = createKnownErrorConstructor(MagicLinkCodeError, "MAGIC_LINK_CODE_ALREADY_USED", () => [
|
|
288
|
-
400,
|
|
289
|
-
"The e-mail verification link has already been used.",
|
|
341
|
+
"The verification link has already been used.",
|
|
290
342
|
], () => []);
|
|
291
343
|
const PasswordMismatch = createKnownErrorConstructor(KnownError, "PASSWORD_MISMATCH", () => [
|
|
292
344
|
400,
|
|
293
345
|
"Passwords do not match.",
|
|
294
346
|
], () => []);
|
|
295
|
-
const PasswordResetError = createKnownErrorConstructor(KnownError, "PASSWORD_RESET_ERROR", "inherit", "inherit");
|
|
296
|
-
const PasswordResetCodeError = createKnownErrorConstructor(PasswordResetError, "PASSWORD_RESET_CODE_ERROR", "inherit", "inherit");
|
|
297
|
-
const PasswordResetCodeNotFound = createKnownErrorConstructor(PasswordResetCodeError, "PASSWORD_RESET_CODE_NOT_FOUND", () => [
|
|
298
|
-
404,
|
|
299
|
-
"The password reset code does not exist for this project.",
|
|
300
|
-
], () => []);
|
|
301
|
-
const PasswordResetCodeExpired = createKnownErrorConstructor(PasswordResetCodeError, "PASSWORD_RESET_CODE_EXPIRED", () => [
|
|
302
|
-
400,
|
|
303
|
-
"The password reset code has expired.",
|
|
304
|
-
], () => []);
|
|
305
|
-
const PasswordResetCodeAlreadyUsed = createKnownErrorConstructor(PasswordResetCodeError, "PASSWORD_RESET_CODE_ALREADY_USED", () => [
|
|
306
|
-
400,
|
|
307
|
-
"The password reset code has already been used.",
|
|
308
|
-
], () => []);
|
|
309
347
|
const EmailAlreadyVerified = createKnownErrorConstructor(KnownError, "EMAIL_ALREADY_VERIFIED", () => [
|
|
310
348
|
400,
|
|
311
349
|
"The e-mail is already verified.",
|
|
@@ -314,9 +352,9 @@ const PermissionNotFound = createKnownErrorConstructor(KnownError, "PERMISSION_N
|
|
|
314
352
|
404,
|
|
315
353
|
`Permission ${permissionId} not found. Make sure you created it on the dashboard.`,
|
|
316
354
|
{
|
|
317
|
-
permissionId,
|
|
355
|
+
permission_id: permissionId,
|
|
318
356
|
},
|
|
319
|
-
], (json) => [json.details.
|
|
357
|
+
], (json) => [json.details.permission_id]);
|
|
320
358
|
const PermissionScopeMismatch = createKnownErrorConstructor(KnownError, "PERMISSION_SCOPE_MISMATCH", (permissionId, permissionScope, testScope) => {
|
|
321
359
|
return [
|
|
322
360
|
400,
|
|
@@ -326,27 +364,27 @@ const PermissionScopeMismatch = createKnownErrorConstructor(KnownError, "PERMISS
|
|
|
326
364
|
"specific-team": `Please specify the team. For example: \`user.hasPermission(team, ${JSON.stringify(permissionId)})\`.`,
|
|
327
365
|
}[permissionScope.type]}`,
|
|
328
366
|
{
|
|
329
|
-
permissionId,
|
|
330
|
-
permissionScope,
|
|
331
|
-
testScope,
|
|
367
|
+
permission_id: permissionId,
|
|
368
|
+
permission_scope: permissionScope,
|
|
369
|
+
test_scope: testScope,
|
|
332
370
|
},
|
|
333
371
|
];
|
|
334
|
-
}, (json) => [json.details.
|
|
372
|
+
}, (json) => [json.details.permission_id, json.details.permission_scope, json.details.test_scope]);
|
|
335
373
|
const UserNotInTeam = createKnownErrorConstructor(KnownError, "USER_NOT_IN_TEAM", (userId, teamId) => [
|
|
336
374
|
400,
|
|
337
375
|
`User ${userId} is not in team ${teamId}.`,
|
|
338
376
|
{
|
|
339
|
-
userId,
|
|
340
|
-
teamId,
|
|
377
|
+
user_id: userId,
|
|
378
|
+
team_id: teamId,
|
|
341
379
|
},
|
|
342
|
-
], (json) => [json.details.
|
|
380
|
+
], (json) => [json.details.user_id, json.details.team_id]);
|
|
343
381
|
const TeamNotFound = createKnownErrorConstructor(KnownError, "TEAM_NOT_FOUND", (teamId) => [
|
|
344
382
|
404,
|
|
345
383
|
`Team ${teamId} not found.`,
|
|
346
384
|
{
|
|
347
|
-
teamId,
|
|
385
|
+
team_id: teamId,
|
|
348
386
|
},
|
|
349
|
-
], (json) => [json.details.
|
|
387
|
+
], (json) => [json.details.team_id]);
|
|
350
388
|
const EmailTemplateAlreadyExists = createKnownErrorConstructor(KnownError, "EMAIL_TEMPLATE_ALREADY_EXISTS", () => [
|
|
351
389
|
400,
|
|
352
390
|
"Email template already exists.",
|
|
@@ -385,10 +423,16 @@ export const KnownErrors = {
|
|
|
385
423
|
SchemaError,
|
|
386
424
|
AllOverloadsFailed,
|
|
387
425
|
ProjectAuthenticationError,
|
|
388
|
-
InvalidProjectAuthentication,
|
|
426
|
+
InvalidProjectAuthentication: InvalidProjectAccess,
|
|
389
427
|
ProjectKeyWithoutRequestType,
|
|
390
428
|
InvalidRequestType,
|
|
391
429
|
RequestTypeWithoutProjectId,
|
|
430
|
+
ProjectKeyWithoutAccessType,
|
|
431
|
+
InvalidAccessType,
|
|
432
|
+
AccessTypeWithoutProjectId,
|
|
433
|
+
AccessTypeRequired,
|
|
434
|
+
CannotGetOwnUserWithoutUser,
|
|
435
|
+
InsufficientAccessType,
|
|
392
436
|
InvalidPublishableClientKey,
|
|
393
437
|
InvalidSecretServerKey,
|
|
394
438
|
InvalidSuperSecretAdminKey,
|
|
@@ -425,26 +469,14 @@ export const KnownErrors = {
|
|
|
425
469
|
PasswordRequirementsNotMet,
|
|
426
470
|
PasswordTooShort,
|
|
427
471
|
PasswordTooLong,
|
|
428
|
-
|
|
429
|
-
|
|
430
|
-
|
|
431
|
-
|
|
432
|
-
EmailVerificationCodeAlreadyUsed,
|
|
433
|
-
MagicLinkError,
|
|
434
|
-
MagicLinkCodeError,
|
|
435
|
-
MagicLinkCodeNotFound,
|
|
436
|
-
MagicLinkCodeExpired,
|
|
437
|
-
MagicLinkCodeAlreadyUsed,
|
|
438
|
-
PasswordResetError,
|
|
439
|
-
PasswordResetCodeError,
|
|
440
|
-
PasswordResetCodeNotFound,
|
|
441
|
-
PasswordResetCodeExpired,
|
|
442
|
-
PasswordResetCodeAlreadyUsed,
|
|
472
|
+
VerificationCodeError,
|
|
473
|
+
VerificationCodeNotFound,
|
|
474
|
+
VerificationCodeExpired,
|
|
475
|
+
VerificationCodeAlreadyUsed,
|
|
443
476
|
PasswordMismatch,
|
|
444
477
|
EmailAlreadyVerified,
|
|
445
478
|
PermissionNotFound,
|
|
446
479
|
PermissionScopeMismatch,
|
|
447
|
-
UserNotInTeam,
|
|
448
480
|
TeamNotFound,
|
|
449
481
|
EmailTemplateAlreadyExists,
|
|
450
482
|
OAuthConnectionNotConnectedToUser,
|
|
@@ -0,0 +1,43 @@
|
|
|
1
|
+
import * as yup from "yup";
|
|
2
|
+
declare const StackAdaptSentinel: unique symbol;
|
|
3
|
+
export type StackAdaptSentinel = typeof StackAdaptSentinel;
|
|
4
|
+
export declare const adaptSchema: yup.MixedSchema<typeof StackAdaptSentinel | undefined, yup.AnyObject, undefined, "">;
|
|
5
|
+
/**
|
|
6
|
+
* Yup's URL schema does not recognize some URLs (including `http://localhost`) as a valid URL. This schema is a workaround for that.
|
|
7
|
+
*/
|
|
8
|
+
export declare const urlSchema: yup.StringSchema<string | undefined, yup.AnyObject, undefined, "">;
|
|
9
|
+
export declare const clientOrHigherAuthTypeSchema: yup.StringSchema<"client" | "server" | "admin" | undefined, yup.AnyObject, undefined, "">;
|
|
10
|
+
export declare const serverOrHigherAuthTypeSchema: yup.StringSchema<"server" | "admin" | undefined, yup.AnyObject, undefined, "">;
|
|
11
|
+
export declare const adminAuthTypeSchema: yup.StringSchema<"admin" | undefined, yup.AnyObject, undefined, "">;
|
|
12
|
+
export declare const projectIdSchema: yup.StringSchema<string | undefined, yup.AnyObject, undefined, "">;
|
|
13
|
+
export declare const userIdRequestSchema: yup.StringSchema<string | undefined, yup.AnyObject, undefined, "">;
|
|
14
|
+
export declare class ReplaceFieldWithOwnUserId extends Error {
|
|
15
|
+
readonly path: string;
|
|
16
|
+
constructor(path: string);
|
|
17
|
+
}
|
|
18
|
+
export declare const userIdOrMeRequestSchema: yup.StringSchema<string | undefined, yup.AnyObject, undefined, "">;
|
|
19
|
+
export declare const userIdResponseSchema: yup.StringSchema<string | undefined, yup.AnyObject, undefined, "">;
|
|
20
|
+
export declare const primaryEmailSchema: yup.StringSchema<string | undefined, yup.AnyObject, undefined, "">;
|
|
21
|
+
export declare const primaryEmailVerifiedSchema: yup.BooleanSchema<boolean | undefined, yup.AnyObject, undefined, "">;
|
|
22
|
+
export declare const userDisplayNameSchema: yup.StringSchema<string | null | undefined, yup.AnyObject, undefined, "">;
|
|
23
|
+
export declare const selectedTeamIdSchema: yup.StringSchema<string | undefined, yup.AnyObject, undefined, "">;
|
|
24
|
+
export declare const profileImageUrlSchema: yup.StringSchema<string | undefined, yup.AnyObject, undefined, "">;
|
|
25
|
+
export declare const signedUpAtMillisSchema: yup.NumberSchema<number | undefined, yup.AnyObject, undefined, "">;
|
|
26
|
+
export declare const userClientMetadataSchema: yup.MixedSchema<{} | null, yup.AnyObject, undefined, "">;
|
|
27
|
+
export declare const userServerMetadataSchema: yup.MixedSchema<{} | null, yup.AnyObject, undefined, "">;
|
|
28
|
+
export declare const signInEmailSchema: yup.StringSchema<string | undefined, yup.AnyObject, undefined, "">;
|
|
29
|
+
export declare const verificationLinkRedirectUrlSchema: yup.StringSchema<string | undefined, yup.AnyObject, undefined, "">;
|
|
30
|
+
export declare const accessTokenResponseSchema: yup.StringSchema<string | undefined, yup.AnyObject, undefined, "">;
|
|
31
|
+
export declare const refreshTokenResponseSchema: yup.StringSchema<string | undefined, yup.AnyObject, undefined, "">;
|
|
32
|
+
export declare const signInResponseSchema: yup.ObjectSchema<{
|
|
33
|
+
refresh_token: string;
|
|
34
|
+
access_token: string;
|
|
35
|
+
is_new_user: NonNullable<boolean | undefined>;
|
|
36
|
+
user_id: string;
|
|
37
|
+
}, yup.AnyObject, {
|
|
38
|
+
refresh_token: undefined;
|
|
39
|
+
access_token: undefined;
|
|
40
|
+
is_new_user: undefined;
|
|
41
|
+
user_id: undefined;
|
|
42
|
+
}, "">;
|
|
43
|
+
export {};
|
|
@@ -0,0 +1,68 @@
|
|
|
1
|
+
import * as yup from "yup";
|
|
2
|
+
import { yupJson } from "./utils/yup";
|
|
3
|
+
// Common
|
|
4
|
+
export const adaptSchema = yup.mixed();
|
|
5
|
+
/**
|
|
6
|
+
* Yup's URL schema does not recognize some URLs (including `http://localhost`) as a valid URL. This schema is a workaround for that.
|
|
7
|
+
*/
|
|
8
|
+
export const urlSchema = yup.string().test({
|
|
9
|
+
name: 'url',
|
|
10
|
+
message: 'Invalid URL',
|
|
11
|
+
test: (value) => {
|
|
12
|
+
if (value === undefined)
|
|
13
|
+
return true;
|
|
14
|
+
try {
|
|
15
|
+
new URL(value);
|
|
16
|
+
return true;
|
|
17
|
+
}
|
|
18
|
+
catch {
|
|
19
|
+
return false;
|
|
20
|
+
}
|
|
21
|
+
},
|
|
22
|
+
});
|
|
23
|
+
// Request auth
|
|
24
|
+
export const clientOrHigherAuthTypeSchema = yup.string().oneOf(['client', 'server', 'admin']);
|
|
25
|
+
export const serverOrHigherAuthTypeSchema = yup.string().oneOf(['server', 'admin']);
|
|
26
|
+
export const adminAuthTypeSchema = yup.string().oneOf(['admin']);
|
|
27
|
+
// Projects
|
|
28
|
+
export const projectIdSchema = yup.string().meta({ openapiField: { description: 'Project ID as retrieved on Stack\'s dashboard', exampleValue: 'project-id' } });
|
|
29
|
+
// Users
|
|
30
|
+
export const userIdRequestSchema = yup.string().uuid().meta({ openapiField: { description: 'The ID of the user', exampleValue: '3241a285-8329-4d69-8f3d-316e08cf140c' } });
|
|
31
|
+
export class ReplaceFieldWithOwnUserId extends Error {
|
|
32
|
+
path;
|
|
33
|
+
constructor(path) {
|
|
34
|
+
super(`This error should be caught by whoever validated the schema, and the field in the path '${path}' should be replaced with the current user's id. This is a workaround to yup not providing access to the context inside the transform function.`);
|
|
35
|
+
this.path = path;
|
|
36
|
+
}
|
|
37
|
+
}
|
|
38
|
+
const userIdMeSentinelUuid = "cad564fd-f81b-43f4-b390-98abf3fcc17e";
|
|
39
|
+
export const userIdOrMeRequestSchema = yup.string().uuid().transform(v => {
|
|
40
|
+
if (v === "me")
|
|
41
|
+
return userIdMeSentinelUuid;
|
|
42
|
+
else
|
|
43
|
+
return v;
|
|
44
|
+
}).test((v, context) => {
|
|
45
|
+
if (v === userIdMeSentinelUuid)
|
|
46
|
+
throw new ReplaceFieldWithOwnUserId(context.path);
|
|
47
|
+
return true;
|
|
48
|
+
}).meta({ openapiField: { description: 'The ID of the user, or the special value `me` to signify the currently authenticated user', exampleValue: '3241a285-8329-4d69-8f3d-316e08cf140c' } });
|
|
49
|
+
export const userIdResponseSchema = yup.string().uuid().meta({ openapiField: { description: 'The immutable user ID used to uniquely identify this user', exampleValue: '3241a285-8329-4d69-8f3d-316e08cf140c' } });
|
|
50
|
+
export const primaryEmailSchema = yup.string().email().meta({ openapiField: { description: 'Primary email', exampleValue: 'johndoe@example.com' } });
|
|
51
|
+
export const primaryEmailVerifiedSchema = yup.boolean().meta({ openapiField: { description: 'Whether the primary email has been verified to belong to this user', exampleValue: true } });
|
|
52
|
+
export const userDisplayNameSchema = yup.string().nullable().meta({ openapiField: { description: 'Human-readable display name', exampleValue: 'John Doe' } });
|
|
53
|
+
export const selectedTeamIdSchema = yup.string().meta({ openapiField: { description: 'ID of the team currently selected by the user', exampleValue: 'team-id' } });
|
|
54
|
+
export const profileImageUrlSchema = yup.string().meta({ openapiField: { description: 'Profile image URL', exampleValue: 'https://example.com/image.jpg' } });
|
|
55
|
+
export const signedUpAtMillisSchema = yup.number().meta({ openapiField: { description: 'Signed up at milliseconds', exampleValue: 1630000000000 } });
|
|
56
|
+
export const userClientMetadataSchema = yupJson.meta({ openapiField: { description: 'Client metadata. Used as a data store, accessible from the client side', exampleValue: { key: 'value' } } });
|
|
57
|
+
export const userServerMetadataSchema = yupJson.meta({ openapiField: { description: 'Server metadata. Used as a data store, only accessible from the server side', exampleValue: { key: 'value' } } });
|
|
58
|
+
// Auth
|
|
59
|
+
export const signInEmailSchema = yup.string().email().meta({ openapiField: { description: 'The email to sign in with.', exampleValue: 'johndoe@example.com' } });
|
|
60
|
+
export const verificationLinkRedirectUrlSchema = urlSchema.meta({ openapiField: { description: 'The URL to redirect to after the user has verified their email. A query argument `code` with the verification code will be appended to it.', exampleValue: 'https://example.com/handler' } });
|
|
61
|
+
export const accessTokenResponseSchema = yup.string().meta({ openapiField: { description: 'Short-lived access token that can be used to authenticate the user', exampleValue: 'eyJhmMiJBMTO...diI4QT' } });
|
|
62
|
+
export const refreshTokenResponseSchema = yup.string().meta({ openapiField: { description: 'Long-lived refresh token that can be used to obtain a new access token', exampleValue: 'i8nsoaq2...14y' } });
|
|
63
|
+
export const signInResponseSchema = yup.object({
|
|
64
|
+
refresh_token: refreshTokenResponseSchema.required(),
|
|
65
|
+
access_token: accessTokenResponseSchema.required(),
|
|
66
|
+
is_new_user: yup.boolean().meta({ openapiField: { description: 'Whether the user is a new user', exampleValue: true } }).required(),
|
|
67
|
+
user_id: userIdResponseSchema.required(),
|
|
68
|
+
});
|
package/dist/utils/env.d.ts
CHANGED
|
@@ -1,5 +1,6 @@
|
|
|
1
1
|
export declare function isBrowserLike(): boolean;
|
|
2
2
|
/**
|
|
3
|
-
* Returns the environment variable with the given name, throwing an error if it's undefined or the empty string.
|
|
3
|
+
* Returns the environment variable with the given name, returning the default (if given) or throwing an error (otherwise) if it's undefined or the empty string.
|
|
4
4
|
*/
|
|
5
|
-
export declare function getEnvVariable(name: string): string;
|
|
5
|
+
export declare function getEnvVariable(name: string, defaultValue?: string | undefined): string;
|
|
6
|
+
export declare function getNodeEnvironment(): string;
|
package/dist/utils/env.js
CHANGED
|
@@ -4,9 +4,9 @@ export function isBrowserLike() {
|
|
|
4
4
|
return typeof window !== "undefined" && typeof document !== "undefined" && typeof document.createElement !== "undefined";
|
|
5
5
|
}
|
|
6
6
|
/**
|
|
7
|
-
* Returns the environment variable with the given name, throwing an error if it's undefined or the empty string.
|
|
7
|
+
* Returns the environment variable with the given name, returning the default (if given) or throwing an error (otherwise) if it's undefined or the empty string.
|
|
8
8
|
*/
|
|
9
|
-
export function getEnvVariable(name) {
|
|
9
|
+
export function getEnvVariable(name, defaultValue) {
|
|
10
10
|
if (isBrowserLike()) {
|
|
11
11
|
throw new Error(deindent `
|
|
12
12
|
Can't use getEnvVariable on the client because Next.js transpiles expressions of the kind process.env.XYZ at build-time on the client.
|
|
@@ -14,5 +14,8 @@ export function getEnvVariable(name) {
|
|
|
14
14
|
Use process.env.XYZ directly instead.
|
|
15
15
|
`);
|
|
16
16
|
}
|
|
17
|
-
return (process.env[name] ?? throwErr(`Missing environment variable: ${name}`)) || throwErr(`Empty environment variable: ${name}`);
|
|
17
|
+
return ((process.env[name] || defaultValue) ?? throwErr(`Missing environment variable: ${name}`)) || (defaultValue ?? throwErr(`Empty environment variable: ${name}`));
|
|
18
|
+
}
|
|
19
|
+
export function getNodeEnvironment() {
|
|
20
|
+
return getEnvVariable("NODE_ENV", "");
|
|
18
21
|
}
|
package/dist/utils/errors.js
CHANGED
package/dist/utils/jwt.js
CHANGED
|
@@ -1,16 +1,16 @@
|
|
|
1
1
|
import * as jose from "jose";
|
|
2
2
|
import { getEnvVariable } from "./env";
|
|
3
|
-
const
|
|
3
|
+
const STACK_SERVER_SECRET = jose.base64url.decode(getEnvVariable("STACK_SERVER_SECRET"));
|
|
4
4
|
export async function encryptJWT(payload, expirationTime = "5m") {
|
|
5
5
|
return await new jose.EncryptJWT(payload)
|
|
6
6
|
.setProtectedHeader({ alg: "dir", enc: "A128CBC-HS256" })
|
|
7
7
|
.setIssuedAt()
|
|
8
8
|
.setExpirationTime(expirationTime)
|
|
9
|
-
.encrypt(
|
|
9
|
+
.encrypt(STACK_SERVER_SECRET);
|
|
10
10
|
}
|
|
11
11
|
export async function decryptJWT(jwt) {
|
|
12
12
|
if (!jwt) {
|
|
13
13
|
throw new Error("Provided JWT is empty");
|
|
14
14
|
}
|
|
15
|
-
return (await jose.jwtDecrypt(jwt,
|
|
15
|
+
return (await jose.jwtDecrypt(jwt, STACK_SERVER_SECRET)).payload;
|
|
16
16
|
}
|
package/dist/utils/objects.d.ts
CHANGED
|
@@ -7,11 +7,14 @@ export type DeepPartial<T> = T extends object ? {
|
|
|
7
7
|
* Note that since they are assumed to be plain objects, this function does not compare prototypes.
|
|
8
8
|
*/
|
|
9
9
|
export declare function deepPlainEquals<T>(obj1: T, obj2: unknown): obj2 is T;
|
|
10
|
+
export declare function deepPlainClone<T>(obj: T): T;
|
|
11
|
+
export declare function deepPlainSnakeCaseToCamelCase(snakeCaseObj: any): any;
|
|
12
|
+
export declare function deepPlainCamelCaseToSnakeCase(camelCaseObj: any): any;
|
|
10
13
|
export declare function typedEntries<T extends {}>(obj: T): [keyof T, T[keyof T]][];
|
|
11
14
|
export declare function typedFromEntries<K extends PropertyKey, V>(entries: [K, V][]): Record<K, V>;
|
|
12
15
|
export declare function typedKeys<T extends {}>(obj: T): (keyof T)[];
|
|
13
16
|
export declare function typedValues<T extends {}>(obj: T): T[keyof T][];
|
|
14
|
-
export declare function typedAssign<T extends {}, U extends {}>(target: T, source: U):
|
|
17
|
+
export declare function typedAssign<T extends {}, U extends {}>(target: T, source: U): T & U;
|
|
15
18
|
export type FilterUndefined<T> = {
|
|
16
19
|
[k in keyof T as (undefined extends T[k] ? (T[k] extends undefined | void ? never : k) : never)]+?: T[k] & ({} | null);
|
|
17
20
|
} & {
|
package/dist/utils/objects.js
CHANGED
|
@@ -1,3 +1,5 @@
|
|
|
1
|
+
import { StackAssertionError } from "./errors";
|
|
2
|
+
import { camelCaseToSnakeCase, snakeCaseToCamelCase } from "./strings";
|
|
1
3
|
/**
|
|
2
4
|
* Assumes both objects are primitives, arrays, or non-function plain objects, and compares them deeply.
|
|
3
5
|
*
|
|
@@ -39,6 +41,35 @@ export function deepPlainEquals(obj1, obj2) {
|
|
|
39
41
|
}
|
|
40
42
|
}
|
|
41
43
|
}
|
|
44
|
+
export function deepPlainClone(obj) {
|
|
45
|
+
if (typeof obj === 'function')
|
|
46
|
+
throw new StackAssertionError("deepPlainClone does not support functions");
|
|
47
|
+
if (typeof obj === 'symbol')
|
|
48
|
+
throw new StackAssertionError("deepPlainClone does not support symbols");
|
|
49
|
+
if (typeof obj !== 'object' || !obj)
|
|
50
|
+
return obj;
|
|
51
|
+
if (Array.isArray(obj))
|
|
52
|
+
return obj.map(deepPlainClone);
|
|
53
|
+
return Object.fromEntries(Object.entries(obj).map(([k, v]) => [k, deepPlainClone(v)]));
|
|
54
|
+
}
|
|
55
|
+
export function deepPlainSnakeCaseToCamelCase(snakeCaseObj) {
|
|
56
|
+
if (typeof snakeCaseObj === 'function')
|
|
57
|
+
throw new StackAssertionError("deepPlainSnakeCaseToCamelCase does not support functions");
|
|
58
|
+
if (typeof snakeCaseObj !== 'object' || !snakeCaseObj)
|
|
59
|
+
return snakeCaseObj;
|
|
60
|
+
if (Array.isArray(snakeCaseObj))
|
|
61
|
+
return snakeCaseObj.map(deepPlainSnakeCaseToCamelCase);
|
|
62
|
+
return Object.fromEntries(Object.entries(snakeCaseObj).map(([k, v]) => [snakeCaseToCamelCase(k), deepPlainSnakeCaseToCamelCase(v)]));
|
|
63
|
+
}
|
|
64
|
+
export function deepPlainCamelCaseToSnakeCase(camelCaseObj) {
|
|
65
|
+
if (typeof camelCaseObj === 'function')
|
|
66
|
+
throw new StackAssertionError("deepPlainCamelCaseToSnakeCase does not support functions");
|
|
67
|
+
if (typeof camelCaseObj !== 'object' || !camelCaseObj)
|
|
68
|
+
return camelCaseObj;
|
|
69
|
+
if (Array.isArray(camelCaseObj))
|
|
70
|
+
return camelCaseObj.map(deepPlainCamelCaseToSnakeCase);
|
|
71
|
+
return Object.fromEntries(Object.entries(camelCaseObj).map(([k, v]) => [camelCaseToSnakeCase(k), deepPlainCamelCaseToSnakeCase(v)]));
|
|
72
|
+
}
|
|
42
73
|
export function typedEntries(obj) {
|
|
43
74
|
return Object.entries(obj);
|
|
44
75
|
}
|
|
@@ -52,7 +83,7 @@ export function typedValues(obj) {
|
|
|
52
83
|
return Object.values(obj);
|
|
53
84
|
}
|
|
54
85
|
export function typedAssign(target, source) {
|
|
55
|
-
Object.assign(target, source);
|
|
86
|
+
return Object.assign(target, source);
|
|
56
87
|
}
|
|
57
88
|
/**
|
|
58
89
|
* Returns a new object with all undefined values removed. Useful when spreading optional parameters on an object, as
|
package/dist/utils/strings.d.ts
CHANGED
|
@@ -41,6 +41,8 @@ export declare function deindent(code: string): string;
|
|
|
41
41
|
export declare function deindent(strings: TemplateStringsArray | readonly string[], ...values: any[]): string;
|
|
42
42
|
export declare function extractScopes(scope: string, removeDuplicates?: boolean): string[];
|
|
43
43
|
export declare function mergeScopeStrings(...scopes: string[]): string;
|
|
44
|
+
export declare function snakeCaseToCamelCase(snakeCase: string): string;
|
|
45
|
+
export declare function camelCaseToSnakeCase(camelCase: string): string;
|
|
44
46
|
export type Nicifiable = {
|
|
45
47
|
getNicifiableKeys?(): PropertyKey[];
|
|
46
48
|
getNicifiedObjectExtraLines?(): string[];
|
|
@@ -57,6 +59,8 @@ export type NicifyOptions = {
|
|
|
57
59
|
value: unknown;
|
|
58
60
|
};
|
|
59
61
|
keyInParent: PropertyKey | null;
|
|
60
|
-
|
|
62
|
+
hideFields: PropertyKey[];
|
|
63
|
+
overrides: (...args: Parameters<typeof nicify>) => string | null;
|
|
61
64
|
};
|
|
62
65
|
export declare function nicify(value: unknown, options?: Partial<NicifyOptions>): string;
|
|
66
|
+
export declare function replaceAll(input: string, searchValue: string, replaceValue: string): string;
|