@draftlab/auth 0.14.0 → 0.15.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.
Files changed (70) hide show
  1. package/dist/adapters/node.d.mts +0 -1
  2. package/dist/client.d.mts +293 -287
  3. package/dist/client.mjs +1 -0
  4. package/dist/core.d.mts +23 -24
  5. package/dist/core.mjs +6 -6
  6. package/dist/error.d.mts +53 -53
  7. package/dist/keys.d.mts +0 -1
  8. package/dist/mutex.d.mts +14 -14
  9. package/dist/provider/apple.d.mts +34 -35
  10. package/dist/provider/code.d.mts +75 -85
  11. package/dist/provider/code.mjs +83 -0
  12. package/dist/provider/discord.d.mts +49 -50
  13. package/dist/provider/facebook.d.mts +49 -50
  14. package/dist/provider/github.d.mts +50 -51
  15. package/dist/provider/gitlab.d.mts +34 -35
  16. package/dist/provider/google.d.mts +49 -50
  17. package/dist/provider/linkedin.d.mts +47 -48
  18. package/dist/provider/magiclink.d.mts +28 -38
  19. package/dist/provider/magiclink.mjs +57 -0
  20. package/dist/provider/microsoft.d.mts +67 -68
  21. package/dist/provider/oauth2.d.mts +75 -76
  22. package/dist/provider/oauth2.mjs +57 -0
  23. package/dist/provider/passkey.d.mts +20 -21
  24. package/dist/provider/password.d.mts +174 -202
  25. package/dist/provider/provider.d.mts +107 -109
  26. package/dist/provider/reddit.d.mts +33 -34
  27. package/dist/provider/slack.d.mts +34 -35
  28. package/dist/provider/spotify.d.mts +34 -35
  29. package/dist/provider/totp.d.mts +43 -44
  30. package/dist/provider/twitch.d.mts +33 -34
  31. package/dist/provider/vercel.d.mts +65 -66
  32. package/dist/revocation.d.mts +29 -30
  33. package/dist/router/context.d.mts +21 -0
  34. package/dist/router/context.mjs +193 -0
  35. package/dist/router/cookies.d.mts +8 -0
  36. package/dist/router/cookies.mjs +13 -0
  37. package/dist/router/index.d.mts +21 -0
  38. package/dist/router/index.mjs +107 -0
  39. package/dist/router/matcher.d.mts +15 -0
  40. package/dist/router/matcher.mjs +76 -0
  41. package/dist/router/middleware/cors.d.mts +15 -0
  42. package/dist/router/middleware/cors.mjs +114 -0
  43. package/dist/router/safe-request.d.mts +52 -0
  44. package/dist/router/safe-request.mjs +160 -0
  45. package/dist/router/types.d.mts +67 -0
  46. package/dist/router/types.mjs +1 -0
  47. package/dist/router/variables.d.mts +12 -0
  48. package/dist/router/variables.mjs +20 -0
  49. package/dist/storage/memory.d.mts +11 -12
  50. package/dist/storage/storage.d.mts +110 -110
  51. package/dist/storage/turso.d.mts +0 -1
  52. package/dist/storage/unstorage.d.mts +0 -1
  53. package/dist/subject.d.mts +0 -1
  54. package/dist/themes/theme.d.mts +101 -101
  55. package/dist/toolkit/client.d.mts +56 -57
  56. package/dist/toolkit/providers/facebook.d.mts +0 -1
  57. package/dist/toolkit/providers/github.d.mts +0 -1
  58. package/dist/toolkit/providers/google.d.mts +0 -1
  59. package/dist/toolkit/storage.d.mts +8 -8
  60. package/dist/ui/base.d.mts +0 -1
  61. package/dist/ui/code.d.mts +5 -6
  62. package/dist/ui/form.d.mts +6 -7
  63. package/dist/ui/icon.d.mts +0 -1
  64. package/dist/ui/magiclink.d.mts +5 -6
  65. package/dist/ui/passkey.d.mts +0 -1
  66. package/dist/ui/password.d.mts +2 -3
  67. package/dist/ui/select.d.mts +0 -1
  68. package/dist/ui/totp.d.mts +0 -1
  69. package/dist/util.d.mts +1 -2
  70. package/package.json +6 -7
@@ -6,6 +6,63 @@ import { createRemoteJWKSet, jwtVerify } from "jose";
6
6
 
7
7
  //#region src/provider/oauth2.ts
8
8
  /**
9
+ * OAuth 2.0 authentication provider for Draft Auth.
10
+ * Implements the Authorization Code Grant flow with optional PKCE support.
11
+ *
12
+ * ## Quick Setup
13
+ *
14
+ * ```ts
15
+ * import { Oauth2Provider } from "@draftlab/auth/provider/oauth2"
16
+ *
17
+ * export default issuer({
18
+ * providers: {
19
+ * github: Oauth2Provider({
20
+ * clientID: process.env.GITHUB_CLIENT_ID,
21
+ * clientSecret: process.env.GITHUB_CLIENT_SECRET,
22
+ * endpoint: {
23
+ * authorization: "https://github.com/login/oauth/authorize",
24
+ * token: "https://github.com/login/oauth/access_token"
25
+ * },
26
+ * scopes: ["user:email", "read:user"]
27
+ * }),
28
+ * discord: Oauth2Provider({
29
+ * clientID: process.env.DISCORD_CLIENT_ID,
30
+ * clientSecret: process.env.DISCORD_CLIENT_SECRET,
31
+ * endpoint: {
32
+ * authorization: "https://discord.com/api/oauth2/authorize",
33
+ * token: "https://discord.com/api/oauth2/token"
34
+ * },
35
+ * scopes: ["identify", "email"],
36
+ * pkce: true // Required by some providers
37
+ * })
38
+ * }
39
+ * })
40
+ * ```
41
+ *
42
+ * ## Features
43
+ *
44
+ * - **Authorization Code Grant**: Secure server-side OAuth 2.0 flow
45
+ * - **PKCE Support**: Optional Proof Key for Code Exchange for enhanced security
46
+ * - **Flexible Endpoints**: Configure custom authorization and token endpoints
47
+ * - **Custom Parameters**: Support for provider-specific authorization parameters
48
+ *
49
+ * ## User Data
50
+ *
51
+ * The provider returns access tokens:
52
+ *
53
+ * ```ts
54
+ * success: async (ctx, value) => {
55
+ * if (value.provider === "oauth2") {
56
+ * // Access token for API calls: value.tokenset.access
57
+ * // Refresh token (if provided): value.tokenset.refresh
58
+ * // Client ID used: value.clientID
59
+ * }
60
+ * }
61
+ * ```
62
+ *
63
+ * @packageDocumentation
64
+ */
65
+ /**
9
66
  * Creates an OAuth 2.0 authentication provider.
10
67
  * Implements the Authorization Code Grant flow with optional PKCE support.
11
68
  *
@@ -2,7 +2,6 @@ import { Provider } from "./provider.mjs";
2
2
  import { AuthenticatorSelectionCriteria, AuthenticatorTransportFuture, Base64URLString, CredentialDeviceType } from "@simplewebauthn/server";
3
3
 
4
4
  //#region src/provider/passkey.d.ts
5
-
6
5
  /**
7
6
  * User model for passkey authentication.
8
7
  * Contains the core user data needed for WebAuthn operations.
@@ -41,44 +40,44 @@ declare const DEFAULT_COPY: {
41
40
  */
42
41
  interface PasskeyProviderConfig {
43
42
  /**
44
- * Custom authorization handler that generates the UI for authorization.
45
- */
43
+ * Custom authorization handler that generates the UI for authorization.
44
+ */
46
45
  authorize: (req: Request) => Promise<Response>;
47
46
  /**
48
- * Custom registration handler that generates the UI for registration.
49
- */
47
+ * Custom registration handler that generates the UI for registration.
48
+ */
50
49
  register: (req: Request) => Promise<Response>;
51
50
  /**
52
- * The human-readable name of the relying party (your application).
53
- */
51
+ * The human-readable name of the relying party (your application).
52
+ */
54
53
  rpName: string;
55
54
  /**
56
- * The ID of the relying party, typically the domain name without protocol.
57
- */
55
+ * The ID of the relying party, typically the domain name without protocol.
56
+ */
58
57
  rpID?: string;
59
58
  /**
60
- * The origin URL(s) that are allowed to initiate WebAuthn ceremonies.
61
- */
59
+ * The origin URL(s) that are allowed to initiate WebAuthn ceremonies.
60
+ */
62
61
  origin?: string | string[];
63
62
  /**
64
- * Optional function to check if a user is allowed to register a passkey.
65
- */
63
+ * Optional function to check if a user is allowed to register a passkey.
64
+ */
66
65
  userCanRegisterPasskey?: (userId: string, req: Request) => Promise<boolean>;
67
66
  /**
68
- * Optional WebAuthn authenticator selection criteria.
69
- */
67
+ * Optional WebAuthn authenticator selection criteria.
68
+ */
70
69
  authenticatorSelection?: AuthenticatorSelectionCriteria;
71
70
  /**
72
- * Optional attestation type.
73
- */
71
+ * Optional attestation type.
72
+ */
74
73
  attestationType?: "none" | "direct" | "enterprise";
75
74
  /**
76
- * Optional timeout for challenges in milliseconds.
77
- */
75
+ * Optional timeout for challenges in milliseconds.
76
+ */
78
77
  timeout?: number;
79
78
  /**
80
- * Custom copy texts for error messages and UI elements.
81
- */
79
+ * Custom copy texts for error messages and UI elements.
80
+ */
82
81
  copy?: Partial<typeof DEFAULT_COPY>;
83
82
  }
84
83
  /**
@@ -2,7 +2,6 @@ import { Provider } from "./provider.mjs";
2
2
  import { StandardSchemaV1 } from "@standard-schema/spec";
3
3
 
4
4
  //#region src/provider/password.d.ts
5
-
6
5
  /**
7
6
  * Password-based authentication provider for Draft Auth.
8
7
  * Supports user registration, login, and password changes with email verification.
@@ -69,19 +68,19 @@ import { StandardSchemaV1 } from "@standard-schema/spec";
69
68
  */
70
69
  interface PasswordHasher<T> {
71
70
  /**
72
- * Hashes a plaintext password for secure storage.
73
- *
74
- * @param password - The plaintext password to hash
75
- * @returns Promise resolving to the hash data structure
76
- */
71
+ * Hashes a plaintext password for secure storage.
72
+ *
73
+ * @param password - The plaintext password to hash
74
+ * @returns Promise resolving to the hash data structure
75
+ */
77
76
  hash(password: string): Promise<T>;
78
77
  /**
79
- * Verifies a plaintext password against a stored hash.
80
- *
81
- * @param password - The plaintext password to verify
82
- * @param compare - The stored hash data to compare against
83
- * @returns Promise resolving to true if password matches
84
- */
78
+ * Verifies a plaintext password against a stored hash.
79
+ *
80
+ * @param password - The plaintext password to verify
81
+ * @param compare - The stored hash data to compare against
82
+ * @returns Promise resolving to true if password matches
83
+ */
85
84
  verify(password: string, compare: T): Promise<boolean>;
86
85
  }
87
86
  /**
@@ -89,158 +88,158 @@ interface PasswordHasher<T> {
89
88
  */
90
89
  interface PasswordConfig {
91
90
  /**
92
- * Length of verification codes sent to users.
93
- * @internal
94
- * @default 6
95
- */
91
+ * Length of verification codes sent to users.
92
+ * @internal
93
+ * @default 6
94
+ */
96
95
  readonly length?: number;
97
96
  /**
98
- * Password hashing implementation to use.
99
- * @internal
100
- * @default ScryptHasher()
101
- */
97
+ * Password hashing implementation to use.
98
+ * @internal
99
+ * @default ScryptHasher()
100
+ */
102
101
  readonly hasher?: PasswordHasher<unknown>;
103
102
  /**
104
- * Request handler for rendering the login screen.
105
- * Receives the request, optional form data, and any login errors.
106
- *
107
- * @param req - The HTTP request object
108
- * @param form - Form data from POST requests (if any)
109
- * @param error - Login error to display (if any)
110
- * @returns Promise resolving to the login page response
111
- *
112
- * @example
113
- * ```ts
114
- * login: async (req, form, error) => {
115
- * const html = renderLoginPage({
116
- * email: form?.get('email'),
117
- * error: error?.type
118
- * })
119
- * return new Response(html, {
120
- * headers: { 'Content-Type': 'text/html' }
121
- * })
122
- * }
123
- * ```
124
- */
103
+ * Request handler for rendering the login screen.
104
+ * Receives the request, optional form data, and any login errors.
105
+ *
106
+ * @param req - The HTTP request object
107
+ * @param form - Form data from POST requests (if any)
108
+ * @param error - Login error to display (if any)
109
+ * @returns Promise resolving to the login page response
110
+ *
111
+ * @example
112
+ * ```ts
113
+ * login: async (req, form, error) => {
114
+ * const html = renderLoginPage({
115
+ * email: form?.get('email'),
116
+ * error: error?.type
117
+ * })
118
+ * return new Response(html, {
119
+ * headers: { 'Content-Type': 'text/html' }
120
+ * })
121
+ * }
122
+ * ```
123
+ */
125
124
  login: (req: Request, form?: FormData, error?: PasswordLoginError) => Promise<Response>;
126
125
  /**
127
- * Request handler for rendering the registration screen.
128
- * Handles both initial registration form and email verification.
129
- *
130
- * @param req - The HTTP request object
131
- * @param state - Current registration state (start or code verification)
132
- * @param form - Form data from POST requests (if any)
133
- * @param error - Registration error to display (if any)
134
- * @returns Promise resolving to the registration page response
135
- *
136
- * @example
137
- * ```ts
138
- * register: async (req, state, form, error) => {
139
- * if (state.type === 'start') {
140
- * return new Response(renderRegistrationForm(error))
141
- * } else {
142
- * return new Response(renderCodeVerification(state.email, error))
143
- * }
144
- * }
145
- * ```
146
- */
126
+ * Request handler for rendering the registration screen.
127
+ * Handles both initial registration form and email verification.
128
+ *
129
+ * @param req - The HTTP request object
130
+ * @param state - Current registration state (start or code verification)
131
+ * @param form - Form data from POST requests (if any)
132
+ * @param error - Registration error to display (if any)
133
+ * @returns Promise resolving to the registration page response
134
+ *
135
+ * @example
136
+ * ```ts
137
+ * register: async (req, state, form, error) => {
138
+ * if (state.type === 'start') {
139
+ * return new Response(renderRegistrationForm(error))
140
+ * } else {
141
+ * return new Response(renderCodeVerification(state.email, error))
142
+ * }
143
+ * }
144
+ * ```
145
+ */
147
146
  register: (req: Request, state: PasswordRegisterState, form?: FormData, error?: PasswordRegisterError) => Promise<Response>;
148
147
  /**
149
- * Request handler for rendering the password change screen.
150
- * Handles email entry, code verification, and password update steps.
151
- *
152
- * @param req - The HTTP request object
153
- * @param state - Current password change state
154
- * @param form - Form data from POST requests (if any)
155
- * @param error - Password change error to display (if any)
156
- * @returns Promise resolving to the password change page response
157
- *
158
- * @example
159
- * ```ts
160
- * change: async (req, state, form, error) => {
161
- * switch (state.type) {
162
- * case 'start':
163
- * return new Response(renderEmailForm(error))
164
- * case 'code':
165
- * return new Response(renderCodeForm(state.email, error))
166
- * case 'update':
167
- * return new Response(renderPasswordForm(error))
168
- * }
169
- * }
170
- * ```
171
- */
148
+ * Request handler for rendering the password change screen.
149
+ * Handles email entry, code verification, and password update steps.
150
+ *
151
+ * @param req - The HTTP request object
152
+ * @param state - Current password change state
153
+ * @param form - Form data from POST requests (if any)
154
+ * @param error - Password change error to display (if any)
155
+ * @returns Promise resolving to the password change page response
156
+ *
157
+ * @example
158
+ * ```ts
159
+ * change: async (req, state, form, error) => {
160
+ * switch (state.type) {
161
+ * case 'start':
162
+ * return new Response(renderEmailForm(error))
163
+ * case 'code':
164
+ * return new Response(renderCodeForm(state.email, error))
165
+ * case 'update':
166
+ * return new Response(renderPasswordForm(error))
167
+ * }
168
+ * }
169
+ * ```
170
+ */
172
171
  change: (req: Request, state: PasswordChangeState, form?: FormData, error?: PasswordChangeError) => Promise<Response>;
173
172
  /**
174
- * Callback for sending verification codes to users via email.
175
- * Implement this to integrate with your email service provider.
176
- *
177
- * The context parameter indicates why the code is being sent:
178
- * - "register": User is registering for the first time
179
- * - "register:resend": User requested to resend registration code
180
- * - "reset": User is resetting their password
181
- * - "reset:resend": User requested to resend password reset code
182
- *
183
- * @param email - The recipient's email address
184
- * @param code - The verification code to send
185
- * @param context - The context of why the code is being sent
186
- * @returns Promise that resolves when email is sent
187
- *
188
- * @example
189
- * ```ts
190
- * sendCode: async (email, code, context) => {
191
- * const templates = {
192
- * "register": {
193
- * subject: "Welcome! Verify your email",
194
- * body: `Welcome! Your verification code is: ${code}`
195
- * },
196
- * "register:resend": {
197
- * subject: "Your verification code (resent)",
198
- * body: `Here's your code again: ${code}`
199
- * },
200
- * "reset": {
201
- * subject: "Reset your password",
202
- * body: `Your password reset code is: ${code}`
203
- * },
204
- * "reset:resend": {
205
- * subject: "Password reset code (resent)",
206
- * body: `Here's your reset code again: ${code}`
207
- * }
208
- * }
209
- *
210
- * const template = templates[context]
211
- * await emailService.send({
212
- * to: email,
213
- * subject: template.subject,
214
- * text: template.body
215
- * })
216
- * }
217
- * ```
218
- */
173
+ * Callback for sending verification codes to users via email.
174
+ * Implement this to integrate with your email service provider.
175
+ *
176
+ * The context parameter indicates why the code is being sent:
177
+ * - "register": User is registering for the first time
178
+ * - "register:resend": User requested to resend registration code
179
+ * - "reset": User is resetting their password
180
+ * - "reset:resend": User requested to resend password reset code
181
+ *
182
+ * @param email - The recipient's email address
183
+ * @param code - The verification code to send
184
+ * @param context - The context of why the code is being sent
185
+ * @returns Promise that resolves when email is sent
186
+ *
187
+ * @example
188
+ * ```ts
189
+ * sendCode: async (email, code, context) => {
190
+ * const templates = {
191
+ * "register": {
192
+ * subject: "Welcome! Verify your email",
193
+ * body: `Welcome! Your verification code is: ${code}`
194
+ * },
195
+ * "register:resend": {
196
+ * subject: "Your verification code (resent)",
197
+ * body: `Here's your code again: ${code}`
198
+ * },
199
+ * "reset": {
200
+ * subject: "Reset your password",
201
+ * body: `Your password reset code is: ${code}`
202
+ * },
203
+ * "reset:resend": {
204
+ * subject: "Password reset code (resent)",
205
+ * body: `Here's your reset code again: ${code}`
206
+ * }
207
+ * }
208
+ *
209
+ * const template = templates[context]
210
+ * await emailService.send({
211
+ * to: email,
212
+ * subject: template.subject,
213
+ * text: template.body
214
+ * })
215
+ * }
216
+ * ```
217
+ */
219
218
  sendCode: (email: string, code: string, context: "register" | "register:resend" | "reset" | "reset:resend") => Promise<void>;
220
219
  /**
221
- * Optional password validation function or schema.
222
- * Can be either a validation function or a standard-schema validator.
223
- *
224
- * @param password - The password to validate
225
- * @returns Error message if invalid, undefined if valid
226
- *
227
- * @example
228
- * ```ts
229
- * // Function-based validation
230
- * validatePassword: (password) => {
231
- * if (password.length < 8) return "Password must be at least 8 characters"
232
- * if (!/[A-Z]/.test(password)) return "Password must contain uppercase letter"
233
- * return undefined
234
- * }
235
- *
236
- * // Schema-based validation
237
- * validatePassword: pipe(
238
- * string(),
239
- * minLength(8, "Password must be at least 8 characters"),
240
- * regex(/[A-Z]/, "Password must contain uppercase letter")
241
- * )
242
- * ```
243
- */
220
+ * Optional password validation function or schema.
221
+ * Can be either a validation function or a standard-schema validator.
222
+ *
223
+ * @param password - The password to validate
224
+ * @returns Error message if invalid, undefined if valid
225
+ *
226
+ * @example
227
+ * ```ts
228
+ * // Function-based validation
229
+ * validatePassword: (password) => {
230
+ * if (password.length < 8) return "Password must be at least 8 characters"
231
+ * if (!/[A-Z]/.test(password)) return "Password must contain uppercase letter"
232
+ * return undefined
233
+ * }
234
+ *
235
+ * // Schema-based validation
236
+ * validatePassword: pipe(
237
+ * string(),
238
+ * minLength(8, "Password must be at least 8 characters"),
239
+ * regex(/[A-Z]/, "Password must contain uppercase letter")
240
+ * )
241
+ * ```
242
+ */
244
243
  readonly validatePassword?: StandardSchemaV1 | ((password: string) => Promise<string | undefined> | string | undefined);
245
244
  }
246
245
  /**
@@ -248,95 +247,68 @@ interface PasswordConfig {
248
247
  * The registration process moves through these states sequentially.
249
248
  */
250
249
  type PasswordRegisterState = {
251
- /** Initial state: user enters email and password */
252
- readonly type: "start";
250
+ /** Initial state: user enters email and password */readonly type: "start";
253
251
  } | {
254
- /** Code verification state: user enters emailed verification code */
255
- readonly type: "code";
256
- /** The verification code sent to the user */
257
- readonly code: string;
258
- /** The user's email address */
259
- readonly email: string;
260
- /** The hashed password (ready for storage) */
252
+ /** Code verification state: user enters emailed verification code */readonly type: "code"; /** The verification code sent to the user */
253
+ readonly code: string; /** The user's email address */
254
+ readonly email: string; /** The hashed password (ready for storage) */
261
255
  readonly password: unknown;
262
256
  };
263
257
  /**
264
258
  * Possible errors during user registration.
265
259
  */
266
260
  type PasswordRegisterError = {
267
- /** The verification code entered is incorrect */
268
- readonly type: "invalid_code";
261
+ /** The verification code entered is incorrect */readonly type: "invalid_code";
269
262
  } | {
270
- /** The email address is already registered */
271
- readonly type: "email_taken";
263
+ /** The email address is already registered */readonly type: "email_taken";
272
264
  } | {
273
- /** The email address format is invalid */
274
- readonly type: "invalid_email";
265
+ /** The email address format is invalid */readonly type: "invalid_email";
275
266
  } | {
276
- /** The password does not meet requirements */
277
- readonly type: "invalid_password";
267
+ /** The password does not meet requirements */readonly type: "invalid_password";
278
268
  } | {
279
- /** Password and confirmation password don't match */
280
- readonly type: "password_mismatch";
269
+ /** Password and confirmation password don't match */readonly type: "password_mismatch";
281
270
  } | {
282
- /** Custom validation error from validatePassword callback */
283
- readonly type: "validation_error";
271
+ /** Custom validation error from validatePassword callback */readonly type: "validation_error";
284
272
  readonly message?: string;
285
273
  };
286
274
  /**
287
275
  * Password change flow states that determine which UI to show.
288
276
  */
289
277
  type PasswordChangeState = {
290
- /** Initial state: user enters their email address */
291
- readonly type: "start";
292
- /** URL to redirect to after successful password change */
278
+ /** Initial state: user enters their email address */readonly type: "start"; /** URL to redirect to after successful password change */
293
279
  readonly redirect: string;
294
280
  } | {
295
- /** Code verification state: user enters emailed verification code */
296
- readonly type: "code";
297
- /** The verification code sent to the user */
298
- readonly code: string;
299
- /** The user's email address */
300
- readonly email: string;
301
- /** URL to redirect to after completion */
281
+ /** Code verification state: user enters emailed verification code */readonly type: "code"; /** The verification code sent to the user */
282
+ readonly code: string; /** The user's email address */
283
+ readonly email: string; /** URL to redirect to after completion */
302
284
  readonly redirect: string;
303
285
  } | {
304
- /** Password update state: user enters new password */
305
- readonly type: "update";
306
- /** URL to redirect to after completion */
307
- readonly redirect: string;
308
- /** The verified email address */
286
+ /** Password update state: user enters new password */readonly type: "update"; /** URL to redirect to after completion */
287
+ readonly redirect: string; /** The verified email address */
309
288
  readonly email: string;
310
289
  };
311
290
  /**
312
291
  * Possible errors during password changes.
313
292
  */
314
293
  type PasswordChangeError = {
315
- /** The email address format is invalid */
316
- readonly type: "invalid_email";
294
+ /** The email address format is invalid */readonly type: "invalid_email";
317
295
  } | {
318
- /** The verification code entered is incorrect */
319
- readonly type: "invalid_code";
296
+ /** The verification code entered is incorrect */readonly type: "invalid_code";
320
297
  } | {
321
- /** The new password does not meet requirements */
322
- readonly type: "invalid_password";
298
+ /** The new password does not meet requirements */readonly type: "invalid_password";
323
299
  } | {
324
- /** New password and confirmation don't match */
325
- readonly type: "password_mismatch";
300
+ /** New password and confirmation don't match */readonly type: "password_mismatch";
326
301
  } | {
327
- /** Custom validation error from validatePassword callback */
328
- readonly type: "validation_error";
302
+ /** Custom validation error from validatePassword callback */readonly type: "validation_error";
329
303
  readonly message: string;
330
304
  };
331
305
  /**
332
306
  * Possible errors during login attempts.
333
307
  */
334
308
  type PasswordLoginError = {
335
- /** The email address format is invalid */
336
- readonly type: "invalid_email";
309
+ /** The email address format is invalid */readonly type: "invalid_email";
337
310
  } | {
338
- /** The password is incorrect or email not found */
339
- readonly type: "invalid_password";
311
+ /** The password is incorrect or email not found */readonly type: "invalid_password";
340
312
  };
341
313
  /**
342
314
  * User data returned by successful password authentication.