@draftlab/auth 0.15.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 (51) 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 +22 -23
  5. package/dist/core.mjs +3 -3
  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/discord.d.mts +49 -50
  12. package/dist/provider/facebook.d.mts +49 -50
  13. package/dist/provider/github.d.mts +50 -51
  14. package/dist/provider/gitlab.d.mts +34 -35
  15. package/dist/provider/google.d.mts +49 -50
  16. package/dist/provider/linkedin.d.mts +47 -48
  17. package/dist/provider/magiclink.d.mts +28 -38
  18. package/dist/provider/microsoft.d.mts +67 -68
  19. package/dist/provider/oauth2.d.mts +75 -76
  20. package/dist/provider/passkey.d.mts +20 -21
  21. package/dist/provider/password.d.mts +174 -202
  22. package/dist/provider/provider.d.mts +105 -107
  23. package/dist/provider/reddit.d.mts +33 -34
  24. package/dist/provider/slack.d.mts +34 -35
  25. package/dist/provider/spotify.d.mts +34 -35
  26. package/dist/provider/totp.d.mts +43 -44
  27. package/dist/provider/twitch.d.mts +33 -34
  28. package/dist/provider/vercel.d.mts +65 -66
  29. package/dist/revocation.d.mts +29 -30
  30. package/dist/storage/memory.d.mts +11 -12
  31. package/dist/storage/storage.d.mts +110 -110
  32. package/dist/storage/turso.d.mts +0 -1
  33. package/dist/storage/unstorage.d.mts +0 -1
  34. package/dist/subject.d.mts +0 -1
  35. package/dist/themes/theme.d.mts +101 -101
  36. package/dist/toolkit/client.d.mts +56 -57
  37. package/dist/toolkit/providers/facebook.d.mts +0 -1
  38. package/dist/toolkit/providers/github.d.mts +0 -1
  39. package/dist/toolkit/providers/google.d.mts +0 -1
  40. package/dist/toolkit/storage.d.mts +8 -8
  41. package/dist/ui/base.d.mts +0 -1
  42. package/dist/ui/code.d.mts +5 -6
  43. package/dist/ui/form.d.mts +6 -7
  44. package/dist/ui/icon.d.mts +0 -1
  45. package/dist/ui/magiclink.d.mts +5 -6
  46. package/dist/ui/passkey.d.mts +0 -1
  47. package/dist/ui/password.d.mts +2 -3
  48. package/dist/ui/select.d.mts +0 -1
  49. package/dist/ui/totp.d.mts +0 -1
  50. package/dist/util.d.mts +0 -1
  51. package/package.json +3 -3
@@ -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.