@draftlab/auth 0.15.1 → 0.16.0

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 (272) hide show
  1. package/dist/esm/allow.js +26 -0
  2. package/dist/esm/client.js +254 -0
  3. package/dist/esm/core.js +597 -0
  4. package/dist/esm/css.d.js +0 -0
  5. package/dist/esm/error.js +88 -0
  6. package/dist/esm/index.js +5 -0
  7. package/dist/esm/keys.js +126 -0
  8. package/dist/esm/mutex.js +53 -0
  9. package/dist/esm/pkce.js +87 -0
  10. package/dist/esm/provider/apple.js +15 -0
  11. package/dist/esm/provider/code.js +62 -0
  12. package/dist/esm/provider/discord.js +15 -0
  13. package/dist/esm/provider/facebook.js +15 -0
  14. package/dist/esm/provider/github.js +15 -0
  15. package/dist/esm/provider/gitlab.js +15 -0
  16. package/dist/esm/provider/google.js +16 -0
  17. package/dist/esm/provider/linkedin.js +15 -0
  18. package/dist/esm/provider/magiclink.js +83 -0
  19. package/dist/esm/provider/microsoft.js +15 -0
  20. package/dist/esm/provider/oauth2.js +130 -0
  21. package/dist/esm/provider/password.js +331 -0
  22. package/dist/esm/provider/provider.js +18 -0
  23. package/dist/esm/provider/reddit.js +15 -0
  24. package/dist/esm/provider/slack.js +15 -0
  25. package/dist/esm/provider/spotify.js +15 -0
  26. package/dist/esm/provider/twitch.js +15 -0
  27. package/dist/esm/provider/vercel.js +17 -0
  28. package/dist/esm/random.js +40 -0
  29. package/dist/esm/revocation.js +27 -0
  30. package/dist/esm/storage/memory.js +110 -0
  31. package/dist/esm/storage/storage.js +56 -0
  32. package/dist/esm/storage/turso.js +93 -0
  33. package/dist/esm/storage/unstorage.js +78 -0
  34. package/dist/esm/subject.js +7 -0
  35. package/dist/esm/themes/theme.js +115 -0
  36. package/dist/esm/toolkit/client.js +119 -0
  37. package/dist/esm/toolkit/index.js +25 -0
  38. package/dist/esm/toolkit/providers/facebook.js +11 -0
  39. package/dist/esm/toolkit/providers/github.js +11 -0
  40. package/dist/esm/toolkit/providers/google.js +11 -0
  41. package/dist/esm/toolkit/providers/strategy.js +0 -0
  42. package/dist/esm/toolkit/storage.js +81 -0
  43. package/dist/esm/toolkit/utils.js +18 -0
  44. package/dist/esm/types.js +0 -0
  45. package/dist/esm/ui/base.js +478 -0
  46. package/dist/esm/ui/code.js +186 -0
  47. package/dist/esm/ui/form.js +46 -0
  48. package/dist/esm/ui/icon.js +242 -0
  49. package/dist/esm/ui/magiclink.js +158 -0
  50. package/dist/esm/ui/password.js +435 -0
  51. package/dist/esm/ui/select.js +102 -0
  52. package/dist/esm/util.js +59 -0
  53. package/dist/{allow.d.mts → types/allow.d.ts} +9 -11
  54. package/dist/types/allow.d.ts.map +1 -0
  55. package/dist/types/client.d.ts +462 -0
  56. package/dist/types/client.d.ts.map +1 -0
  57. package/dist/types/core.d.ts +113 -0
  58. package/dist/types/core.d.ts.map +1 -0
  59. package/dist/{error.d.mts → types/error.d.ts} +95 -97
  60. package/dist/types/error.d.ts.map +1 -0
  61. package/dist/types/index.d.ts +2 -0
  62. package/dist/types/index.d.ts.map +1 -0
  63. package/dist/{keys.d.mts → types/keys.d.ts} +20 -23
  64. package/dist/types/keys.d.ts.map +1 -0
  65. package/dist/types/mutex.d.ts +42 -0
  66. package/dist/types/mutex.d.ts.map +1 -0
  67. package/dist/{pkce.d.mts → types/pkce.d.ts} +10 -11
  68. package/dist/types/pkce.d.ts.map +1 -0
  69. package/dist/types/provider/apple.d.ts +197 -0
  70. package/dist/types/provider/apple.d.ts.map +1 -0
  71. package/dist/types/provider/code.d.ts +288 -0
  72. package/dist/types/provider/code.d.ts.map +1 -0
  73. package/dist/types/provider/discord.d.ts +206 -0
  74. package/dist/types/provider/discord.d.ts.map +1 -0
  75. package/dist/types/provider/facebook.d.ts +200 -0
  76. package/dist/types/provider/facebook.d.ts.map +1 -0
  77. package/dist/types/provider/github.d.ts +220 -0
  78. package/dist/types/provider/github.d.ts.map +1 -0
  79. package/dist/types/provider/gitlab.d.ts +180 -0
  80. package/dist/types/provider/gitlab.d.ts.map +1 -0
  81. package/dist/types/provider/google.d.ts +158 -0
  82. package/dist/types/provider/google.d.ts.map +1 -0
  83. package/dist/types/provider/linkedin.d.ts +190 -0
  84. package/dist/types/provider/linkedin.d.ts.map +1 -0
  85. package/dist/types/provider/magiclink.d.ts +141 -0
  86. package/dist/types/provider/magiclink.d.ts.map +1 -0
  87. package/dist/types/provider/microsoft.d.ts +247 -0
  88. package/dist/types/provider/microsoft.d.ts.map +1 -0
  89. package/dist/types/provider/oauth2.d.ts +229 -0
  90. package/dist/types/provider/oauth2.d.ts.map +1 -0
  91. package/dist/types/provider/password.d.ts +408 -0
  92. package/dist/types/provider/password.d.ts.map +1 -0
  93. package/dist/types/provider/provider.d.ts +226 -0
  94. package/dist/types/provider/provider.d.ts.map +1 -0
  95. package/dist/types/provider/reddit.d.ts +159 -0
  96. package/dist/types/provider/reddit.d.ts.map +1 -0
  97. package/dist/types/provider/slack.d.ts +171 -0
  98. package/dist/types/provider/slack.d.ts.map +1 -0
  99. package/dist/types/provider/spotify.d.ts +168 -0
  100. package/dist/types/provider/spotify.d.ts.map +1 -0
  101. package/dist/types/provider/twitch.d.ts +163 -0
  102. package/dist/types/provider/twitch.d.ts.map +1 -0
  103. package/dist/types/provider/vercel.d.ts +294 -0
  104. package/dist/types/provider/vercel.d.ts.map +1 -0
  105. package/dist/{random.d.mts → types/random.d.ts} +4 -6
  106. package/dist/types/random.d.ts.map +1 -0
  107. package/dist/types/revocation.d.ts +76 -0
  108. package/dist/types/revocation.d.ts.map +1 -0
  109. package/dist/{storage/memory.d.mts → types/storage/memory.d.ts} +17 -20
  110. package/dist/types/storage/memory.d.ts.map +1 -0
  111. package/dist/types/storage/storage.d.ts +177 -0
  112. package/dist/types/storage/storage.d.ts.map +1 -0
  113. package/dist/{storage/turso.d.mts → types/storage/turso.d.ts} +4 -7
  114. package/dist/types/storage/turso.d.ts.map +1 -0
  115. package/dist/{storage/unstorage.d.mts → types/storage/unstorage.d.ts} +12 -10
  116. package/dist/types/storage/unstorage.d.ts.map +1 -0
  117. package/dist/types/subject.d.ts +115 -0
  118. package/dist/types/subject.d.ts.map +1 -0
  119. package/dist/types/themes/theme.d.ts +207 -0
  120. package/dist/types/themes/theme.d.ts.map +1 -0
  121. package/dist/types/toolkit/client.d.ts +235 -0
  122. package/dist/types/toolkit/client.d.ts.map +1 -0
  123. package/dist/types/toolkit/index.d.ts +45 -0
  124. package/dist/types/toolkit/index.d.ts.map +1 -0
  125. package/dist/types/toolkit/providers/facebook.d.ts +8 -0
  126. package/dist/types/toolkit/providers/facebook.d.ts.map +1 -0
  127. package/dist/types/toolkit/providers/github.d.ts +8 -0
  128. package/dist/types/toolkit/providers/github.d.ts.map +1 -0
  129. package/dist/types/toolkit/providers/google.d.ts +8 -0
  130. package/dist/types/toolkit/providers/google.d.ts.map +1 -0
  131. package/dist/types/toolkit/providers/strategy.d.ts +38 -0
  132. package/dist/types/toolkit/providers/strategy.d.ts.map +1 -0
  133. package/dist/{toolkit/storage.d.mts → types/toolkit/storage.d.ts} +37 -39
  134. package/dist/types/toolkit/storage.d.ts.map +1 -0
  135. package/dist/{toolkit/utils.d.mts → types/toolkit/utils.d.ts} +2 -4
  136. package/dist/types/toolkit/utils.d.ts.map +1 -0
  137. package/dist/types/types.d.ts +92 -0
  138. package/dist/types/types.d.ts.map +1 -0
  139. package/dist/types/ui/base.d.ts +18 -0
  140. package/dist/types/ui/base.d.ts.map +1 -0
  141. package/dist/types/ui/code.d.ts +43 -0
  142. package/dist/types/ui/code.d.ts.map +1 -0
  143. package/dist/types/ui/form.d.ts +24 -0
  144. package/dist/types/ui/form.d.ts.map +1 -0
  145. package/dist/types/ui/icon.d.ts +60 -0
  146. package/dist/types/ui/icon.d.ts.map +1 -0
  147. package/dist/types/ui/magiclink.d.ts +41 -0
  148. package/dist/types/ui/magiclink.d.ts.map +1 -0
  149. package/dist/types/ui/password.d.ts +43 -0
  150. package/dist/types/ui/password.d.ts.map +1 -0
  151. package/dist/types/ui/select.d.ts +33 -0
  152. package/dist/types/ui/select.d.ts.map +1 -0
  153. package/dist/{util.d.mts → types/util.d.ts} +11 -12
  154. package/dist/types/util.d.ts.map +1 -0
  155. package/package.json +10 -16
  156. package/dist/adapters/node.d.mts +0 -17
  157. package/dist/adapters/node.mjs +0 -69
  158. package/dist/allow.mjs +0 -63
  159. package/dist/client.d.mts +0 -462
  160. package/dist/client.mjs +0 -284
  161. package/dist/core.d.mts +0 -109
  162. package/dist/core.mjs +0 -595
  163. package/dist/error.mjs +0 -237
  164. package/dist/index.d.mts +0 -2
  165. package/dist/index.mjs +0 -3
  166. package/dist/keys.mjs +0 -146
  167. package/dist/mutex.d.mts +0 -44
  168. package/dist/mutex.mjs +0 -110
  169. package/dist/pkce.mjs +0 -157
  170. package/dist/provider/apple.d.mts +0 -110
  171. package/dist/provider/apple.mjs +0 -164
  172. package/dist/provider/code.d.mts +0 -218
  173. package/dist/provider/code.mjs +0 -246
  174. package/dist/provider/discord.d.mts +0 -145
  175. package/dist/provider/discord.mjs +0 -156
  176. package/dist/provider/facebook.d.mts +0 -141
  177. package/dist/provider/facebook.mjs +0 -150
  178. package/dist/provider/github.d.mts +0 -139
  179. package/dist/provider/github.mjs +0 -169
  180. package/dist/provider/gitlab.d.mts +0 -105
  181. package/dist/provider/gitlab.mjs +0 -147
  182. package/dist/provider/google.d.mts +0 -111
  183. package/dist/provider/google.mjs +0 -109
  184. package/dist/provider/linkedin.d.mts +0 -131
  185. package/dist/provider/linkedin.mjs +0 -142
  186. package/dist/provider/magiclink.d.mts +0 -79
  187. package/dist/provider/magiclink.mjs +0 -143
  188. package/dist/provider/microsoft.d.mts +0 -177
  189. package/dist/provider/microsoft.mjs +0 -177
  190. package/dist/provider/oauth2.d.mts +0 -175
  191. package/dist/provider/oauth2.mjs +0 -222
  192. package/dist/provider/passkey.d.mts +0 -103
  193. package/dist/provider/passkey.mjs +0 -320
  194. package/dist/provider/password.d.mts +0 -384
  195. package/dist/provider/password.mjs +0 -363
  196. package/dist/provider/provider.d.mts +0 -225
  197. package/dist/provider/provider.mjs +0 -44
  198. package/dist/provider/reddit.d.mts +0 -106
  199. package/dist/provider/reddit.mjs +0 -127
  200. package/dist/provider/slack.d.mts +0 -113
  201. package/dist/provider/slack.mjs +0 -138
  202. package/dist/provider/spotify.d.mts +0 -112
  203. package/dist/provider/spotify.mjs +0 -135
  204. package/dist/provider/totp.d.mts +0 -111
  205. package/dist/provider/totp.mjs +0 -191
  206. package/dist/provider/twitch.d.mts +0 -107
  207. package/dist/provider/twitch.mjs +0 -131
  208. package/dist/provider/vercel.d.mts +0 -176
  209. package/dist/provider/vercel.mjs +0 -230
  210. package/dist/random.mjs +0 -86
  211. package/dist/revocation.d.mts +0 -54
  212. package/dist/revocation.mjs +0 -63
  213. package/dist/router/context.d.mts +0 -21
  214. package/dist/router/context.mjs +0 -193
  215. package/dist/router/cookies.d.mts +0 -8
  216. package/dist/router/cookies.mjs +0 -13
  217. package/dist/router/index.d.mts +0 -21
  218. package/dist/router/index.mjs +0 -107
  219. package/dist/router/matcher.d.mts +0 -15
  220. package/dist/router/matcher.mjs +0 -76
  221. package/dist/router/middleware/cors.d.mts +0 -15
  222. package/dist/router/middleware/cors.mjs +0 -114
  223. package/dist/router/safe-request.d.mts +0 -52
  224. package/dist/router/safe-request.mjs +0 -160
  225. package/dist/router/types.d.mts +0 -67
  226. package/dist/router/types.mjs +0 -1
  227. package/dist/router/variables.d.mts +0 -12
  228. package/dist/router/variables.mjs +0 -20
  229. package/dist/storage/memory.mjs +0 -125
  230. package/dist/storage/storage.d.mts +0 -179
  231. package/dist/storage/storage.mjs +0 -104
  232. package/dist/storage/turso.mjs +0 -117
  233. package/dist/storage/unstorage.mjs +0 -103
  234. package/dist/subject.d.mts +0 -61
  235. package/dist/subject.mjs +0 -36
  236. package/dist/themes/theme.d.mts +0 -209
  237. package/dist/themes/theme.mjs +0 -120
  238. package/dist/toolkit/client.d.mts +0 -168
  239. package/dist/toolkit/client.mjs +0 -209
  240. package/dist/toolkit/index.d.mts +0 -9
  241. package/dist/toolkit/index.mjs +0 -9
  242. package/dist/toolkit/providers/facebook.d.mts +0 -11
  243. package/dist/toolkit/providers/facebook.mjs +0 -16
  244. package/dist/toolkit/providers/github.d.mts +0 -11
  245. package/dist/toolkit/providers/github.mjs +0 -16
  246. package/dist/toolkit/providers/google.d.mts +0 -11
  247. package/dist/toolkit/providers/google.mjs +0 -20
  248. package/dist/toolkit/providers/strategy.d.mts +0 -40
  249. package/dist/toolkit/providers/strategy.mjs +0 -1
  250. package/dist/toolkit/storage.mjs +0 -157
  251. package/dist/toolkit/utils.mjs +0 -30
  252. package/dist/types.d.mts +0 -94
  253. package/dist/types.mjs +0 -1
  254. package/dist/ui/base.d.mts +0 -29
  255. package/dist/ui/base.mjs +0 -407
  256. package/dist/ui/code.d.mts +0 -42
  257. package/dist/ui/code.mjs +0 -173
  258. package/dist/ui/form.d.mts +0 -31
  259. package/dist/ui/form.mjs +0 -49
  260. package/dist/ui/icon.d.mts +0 -57
  261. package/dist/ui/icon.mjs +0 -247
  262. package/dist/ui/magiclink.d.mts +0 -40
  263. package/dist/ui/magiclink.mjs +0 -152
  264. package/dist/ui/passkey.d.mts +0 -26
  265. package/dist/ui/passkey.mjs +0 -323
  266. package/dist/ui/password.d.mts +0 -41
  267. package/dist/ui/password.mjs +0 -402
  268. package/dist/ui/select.d.mts +0 -33
  269. package/dist/ui/select.mjs +0 -98
  270. package/dist/ui/totp.d.mts +0 -33
  271. package/dist/ui/totp.mjs +0 -270
  272. package/dist/util.mjs +0 -128
@@ -1,384 +0,0 @@
1
- import { Provider } from "./provider.mjs";
2
- import { StandardSchemaV1 } from "@standard-schema/spec";
3
-
4
- //#region src/provider/password.d.ts
5
- /**
6
- * Password-based authentication provider for Draft Auth.
7
- * Supports user registration, login, and password changes with email verification.
8
- *
9
- * ## Quick Setup
10
- *
11
- * ```ts
12
- * import { PasswordUI } from "@draftlab/auth/ui/password"
13
- * import { PasswordProvider } from "@draftlab/auth/provider/password"
14
- *
15
- * export default issuer({
16
- * providers: {
17
- * password: PasswordProvider(
18
- * PasswordUI({
19
- * copy: {
20
- * error_email_taken: "This email is already taken."
21
- * },
22
- * sendCode: async (email, code) => {
23
- * await sendEmail(email, `Your verification code: ${code}`)
24
- * }
25
- * })
26
- * )
27
- * }
28
- * })
29
- * ```
30
- *
31
- * ## Custom UI Implementation
32
- *
33
- * For full control over the user interface, implement the handlers directly:
34
- *
35
- * ```ts
36
- * PasswordProvider({
37
- * login: async (req, form, error) => {
38
- * return new Response(renderLoginPage(form, error))
39
- * },
40
- * register: async (req, state, form, error) => {
41
- * return new Response(renderRegisterPage(state, form, error))
42
- * },
43
- * change: async (req, state, form, error) => {
44
- * return new Response(renderChangePage(state, form, error))
45
- * },
46
- * sendCode: async (email, code) => {
47
- * await yourEmailService.send(email, code)
48
- * }
49
- * })
50
- * ```
51
- *
52
- * ## Features
53
- *
54
- * - **Email verification**: Secure registration with email confirmation codes
55
- * - **Password hashing**: Built-in Scrypt and PBKDF2 support with secure defaults
56
- * - **Password validation**: Configurable password strength requirements
57
- * - **Password reset**: Secure password change flow with email verification
58
- * - **Session management**: Automatic invalidation on password changes
59
- *
60
- * @packageDocumentation
61
- */
62
- /**
63
- * Password hashing interface for secure password storage.
64
- * Implement this interface to use custom password hashing algorithms.
65
- *
66
- * @template T - The hash storage format (usually an object with hash, salt, and params)
67
- * @internal
68
- */
69
- interface PasswordHasher<T> {
70
- /**
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
- */
76
- hash(password: string): Promise<T>;
77
- /**
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
- */
84
- verify(password: string, compare: T): Promise<boolean>;
85
- }
86
- /**
87
- * Configuration for the password authentication provider.
88
- */
89
- interface PasswordConfig {
90
- /**
91
- * Length of verification codes sent to users.
92
- * @internal
93
- * @default 6
94
- */
95
- readonly length?: number;
96
- /**
97
- * Password hashing implementation to use.
98
- * @internal
99
- * @default ScryptHasher()
100
- */
101
- readonly hasher?: PasswordHasher<unknown>;
102
- /**
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
- */
124
- login: (req: Request, form?: FormData, error?: PasswordLoginError) => Promise<Response>;
125
- /**
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
- */
146
- register: (req: Request, state: PasswordRegisterState, form?: FormData, error?: PasswordRegisterError) => Promise<Response>;
147
- /**
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
- */
171
- change: (req: Request, state: PasswordChangeState, form?: FormData, error?: PasswordChangeError) => Promise<Response>;
172
- /**
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
- */
218
- sendCode: (email: string, code: string, context: "register" | "register:resend" | "reset" | "reset:resend") => Promise<void>;
219
- /**
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
- */
243
- readonly validatePassword?: StandardSchemaV1 | ((password: string) => Promise<string | undefined> | string | undefined);
244
- }
245
- /**
246
- * Registration flow states that determine which UI to show.
247
- * The registration process moves through these states sequentially.
248
- */
249
- type PasswordRegisterState = {
250
- /** Initial state: user enters email and password */readonly type: "start";
251
- } | {
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) */
255
- readonly password: unknown;
256
- };
257
- /**
258
- * Possible errors during user registration.
259
- */
260
- type PasswordRegisterError = {
261
- /** The verification code entered is incorrect */readonly type: "invalid_code";
262
- } | {
263
- /** The email address is already registered */readonly type: "email_taken";
264
- } | {
265
- /** The email address format is invalid */readonly type: "invalid_email";
266
- } | {
267
- /** The password does not meet requirements */readonly type: "invalid_password";
268
- } | {
269
- /** Password and confirmation password don't match */readonly type: "password_mismatch";
270
- } | {
271
- /** Custom validation error from validatePassword callback */readonly type: "validation_error";
272
- readonly message?: string;
273
- };
274
- /**
275
- * Password change flow states that determine which UI to show.
276
- */
277
- type PasswordChangeState = {
278
- /** Initial state: user enters their email address */readonly type: "start"; /** URL to redirect to after successful password change */
279
- readonly redirect: string;
280
- } | {
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 */
284
- readonly redirect: string;
285
- } | {
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 */
288
- readonly email: string;
289
- };
290
- /**
291
- * Possible errors during password changes.
292
- */
293
- type PasswordChangeError = {
294
- /** The email address format is invalid */readonly type: "invalid_email";
295
- } | {
296
- /** The verification code entered is incorrect */readonly type: "invalid_code";
297
- } | {
298
- /** The new password does not meet requirements */readonly type: "invalid_password";
299
- } | {
300
- /** New password and confirmation don't match */readonly type: "password_mismatch";
301
- } | {
302
- /** Custom validation error from validatePassword callback */readonly type: "validation_error";
303
- readonly message: string;
304
- };
305
- /**
306
- * Possible errors during login attempts.
307
- */
308
- type PasswordLoginError = {
309
- /** The email address format is invalid */readonly type: "invalid_email";
310
- } | {
311
- /** The password is incorrect or email not found */readonly type: "invalid_password";
312
- };
313
- /**
314
- * User data returned by successful password authentication.
315
- */
316
- interface PasswordUserData {
317
- /** The authenticated user's email address */
318
- readonly email: string;
319
- }
320
- /**
321
- * Creates a password authentication provider with email verification.
322
- * Implements secure registration, login, and password change flows.
323
- *
324
- * @param config - Provider configuration including UI handlers and email service
325
- * @returns Provider instance implementing password authentication
326
- *
327
- * @example
328
- * ```ts
329
- * const provider = PasswordProvider({
330
- * login: async (req, form, error) => {
331
- * return new Response(renderLogin(form, error))
332
- * },
333
- * register: async (req, state, form, error) => {
334
- * return new Response(renderRegister(state, form, error))
335
- * },
336
- * change: async (req, state, form, error) => {
337
- * return new Response(renderChange(state, form, error))
338
- * },
339
- * sendCode: async (email, code) => {
340
- * await emailService.send(email, `Code: ${code}`)
341
- * },
342
- * validatePassword: (pwd) => {
343
- * return pwd.length >= 8 ? undefined : "Too short"
344
- * }
345
- * })
346
- * ```
347
- */
348
- declare const PasswordProvider: (config: PasswordConfig) => Provider<PasswordUserData>;
349
- /**
350
- * PBKDF2 password hasher with configurable iterations.
351
- * Good choice for compatibility but slower than Scrypt.
352
- *
353
- * @param opts - Configuration options
354
- * @returns Password hasher using PBKDF2 algorithm
355
- * @internal
356
- */
357
- declare const PBKDF2Hasher: (opts?: {
358
- iterations?: number;
359
- }) => PasswordHasher<{
360
- hash: string;
361
- salt: string;
362
- iterations: number;
363
- }>;
364
- /**
365
- * Scrypt password hasher with secure defaults.
366
- * Recommended choice for new applications due to memory-hard properties.
367
- *
368
- * @param opts - Scrypt parameters (N, r, p)
369
- * @returns Password hasher using Scrypt algorithm
370
- * @internal
371
- */
372
- declare const ScryptHasher: (opts?: {
373
- N?: number;
374
- r?: number;
375
- p?: number;
376
- }) => PasswordHasher<{
377
- hash: string;
378
- salt: string;
379
- N: number;
380
- r: number;
381
- p: number;
382
- }>;
383
- //#endregion
384
- export { PBKDF2Hasher, PasswordChangeError, PasswordChangeState, PasswordConfig, PasswordHasher, PasswordLoginError, PasswordProvider, PasswordRegisterError, PasswordRegisterState, PasswordUserData, ScryptHasher };