@draftlab/auth 0.15.0 → 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 -24
  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 -21
  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 -8
  114. package/dist/types/storage/turso.d.ts.map +1 -0
  115. package/dist/{storage/unstorage.d.mts → types/storage/unstorage.d.ts} +12 -11
  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 -13
  154. package/dist/types/util.d.ts.map +1 -0
  155. package/package.json +10 -16
  156. package/dist/adapters/node.d.mts +0 -18
  157. package/dist/adapters/node.mjs +0 -69
  158. package/dist/allow.mjs +0 -63
  159. package/dist/client.d.mts +0 -456
  160. package/dist/client.mjs +0 -283
  161. package/dist/core.d.mts +0 -110
  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 -111
  171. package/dist/provider/apple.mjs +0 -164
  172. package/dist/provider/code.d.mts +0 -228
  173. package/dist/provider/code.mjs +0 -246
  174. package/dist/provider/discord.d.mts +0 -146
  175. package/dist/provider/discord.mjs +0 -156
  176. package/dist/provider/facebook.d.mts +0 -142
  177. package/dist/provider/facebook.mjs +0 -150
  178. package/dist/provider/github.d.mts +0 -140
  179. package/dist/provider/github.mjs +0 -169
  180. package/dist/provider/gitlab.d.mts +0 -106
  181. package/dist/provider/gitlab.mjs +0 -147
  182. package/dist/provider/google.d.mts +0 -112
  183. package/dist/provider/google.mjs +0 -109
  184. package/dist/provider/linkedin.d.mts +0 -132
  185. package/dist/provider/linkedin.mjs +0 -142
  186. package/dist/provider/magiclink.d.mts +0 -89
  187. package/dist/provider/magiclink.mjs +0 -143
  188. package/dist/provider/microsoft.d.mts +0 -178
  189. package/dist/provider/microsoft.mjs +0 -177
  190. package/dist/provider/oauth2.d.mts +0 -176
  191. package/dist/provider/oauth2.mjs +0 -222
  192. package/dist/provider/passkey.d.mts +0 -104
  193. package/dist/provider/passkey.mjs +0 -320
  194. package/dist/provider/password.d.mts +0 -412
  195. package/dist/provider/password.mjs +0 -363
  196. package/dist/provider/provider.d.mts +0 -227
  197. package/dist/provider/provider.mjs +0 -44
  198. package/dist/provider/reddit.d.mts +0 -107
  199. package/dist/provider/reddit.mjs +0 -127
  200. package/dist/provider/slack.d.mts +0 -114
  201. package/dist/provider/slack.mjs +0 -138
  202. package/dist/provider/spotify.d.mts +0 -113
  203. package/dist/provider/spotify.mjs +0 -135
  204. package/dist/provider/totp.d.mts +0 -112
  205. package/dist/provider/totp.mjs +0 -191
  206. package/dist/provider/twitch.d.mts +0 -108
  207. package/dist/provider/twitch.mjs +0 -131
  208. package/dist/provider/vercel.d.mts +0 -177
  209. package/dist/provider/vercel.mjs +0 -230
  210. package/dist/random.mjs +0 -86
  211. package/dist/revocation.d.mts +0 -55
  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 -62
  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 -169
  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 -12
  243. package/dist/toolkit/providers/facebook.mjs +0 -16
  244. package/dist/toolkit/providers/github.d.mts +0 -12
  245. package/dist/toolkit/providers/github.mjs +0 -16
  246. package/dist/toolkit/providers/google.d.mts +0 -12
  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 -30
  255. package/dist/ui/base.mjs +0 -407
  256. package/dist/ui/code.d.mts +0 -43
  257. package/dist/ui/code.mjs +0 -173
  258. package/dist/ui/form.d.mts +0 -32
  259. package/dist/ui/form.mjs +0 -49
  260. package/dist/ui/icon.d.mts +0 -58
  261. package/dist/ui/icon.mjs +0 -247
  262. package/dist/ui/magiclink.d.mts +0 -41
  263. package/dist/ui/magiclink.mjs +0 -152
  264. package/dist/ui/passkey.d.mts +0 -27
  265. package/dist/ui/passkey.mjs +0 -323
  266. package/dist/ui/password.d.mts +0 -42
  267. package/dist/ui/password.mjs +0 -402
  268. package/dist/ui/select.d.mts +0 -34
  269. package/dist/ui/select.mjs +0 -98
  270. package/dist/ui/totp.d.mts +0 -34
  271. package/dist/ui/totp.mjs +0 -270
  272. package/dist/util.mjs +0 -128
@@ -0,0 +1,288 @@
1
+ /**
2
+ * PIN code authentication provider for Draft Auth.
3
+ * Supports flexible claim-based authentication via email, phone, or custom identifiers.
4
+ *
5
+ * ## Quick Setup
6
+ *
7
+ * ```ts
8
+ * import { CodeUI } from "@draftlab/auth/ui/code"
9
+ * import { CodeProvider } from "@draftlab/auth/provider/code"
10
+ *
11
+ * export default issuer({
12
+ * providers: {
13
+ * code: CodeProvider(
14
+ * CodeUI({
15
+ * copy: {
16
+ * code_info: "We'll send a PIN code to your email"
17
+ * },
18
+ * sendCode: async (claims, code) => {
19
+ * try {
20
+ * await sendEmail(claims.email, `Your code: ${code}`)
21
+ * } catch {
22
+ * return { type: "invalid_claim", key: "delivery", value: "Failed to send code" }
23
+ * }
24
+ * }
25
+ * })
26
+ * )
27
+ * }
28
+ * })
29
+ * ```
30
+ *
31
+ * ## Custom Configuration
32
+ *
33
+ * ```ts
34
+ * const customCodeProvider = CodeProvider({
35
+ * length: 4, // 4-digit PIN instead of default 6
36
+ * request: async (req, state, form, error) => {
37
+ * return new Response(renderCodePage(state, form, error))
38
+ * },
39
+ * sendCode: async (claims, code) => {
40
+ * try {
41
+ * if (claims.email) {
42
+ * await emailService.send(claims.email, code)
43
+ * } else if (claims.phone) {
44
+ * await smsService.send(claims.phone, code)
45
+ * } else {
46
+ * return { type: "invalid_claim", key: "email", value: "Email or phone number is required" }
47
+ * }
48
+ * } catch {
49
+ * return { type: "invalid_claim", key: "delivery", value: "Failed to send code" }
50
+ * }
51
+ * }
52
+ * })
53
+ * ```
54
+ *
55
+ * ## Features
56
+ *
57
+ * - **Flexible claims**: Support any claim type (email, phone, username, etc.)
58
+ * - **Configurable PIN length**: 4-6 digit codes typically
59
+ * - **Resend functionality**: Built-in code resend capability
60
+ * - **Custom UI**: Full control over the authentication interface
61
+ * - **Error handling**: Comprehensive error states for different failure modes
62
+ *
63
+ * ## Flow States
64
+ *
65
+ * The provider manages a two-step authentication flow:
66
+ *
67
+ * 1. **Start**: User enters their claim (email, phone, etc.)
68
+ * 2. **Code**: User enters the PIN code sent to their claim
69
+ *
70
+ * ## User Data
71
+ *
72
+ * ```ts
73
+ * success: async (ctx, value) => {
74
+ * if (value.provider === "code") {
75
+ * // User's email: value.claims.email
76
+ * // User's phone (if provided): value.claims.phone
77
+ * // Any other claims collected during the flow
78
+ * }
79
+ * }
80
+ * ```
81
+ *
82
+ * @packageDocumentation
83
+ */
84
+ import type { Provider } from "./provider";
85
+ /**
86
+ * Configuration options for the PIN code authentication provider.
87
+ *
88
+ * @template Claims - Type of claims collected during authentication (email, phone, etc.)
89
+ */
90
+ export interface CodeProviderConfig<Claims extends Record<string, string> = Record<string, string>> {
91
+ /**
92
+ * The length of the generated PIN code.
93
+ * Common values are 4, 6, or 8 digits.
94
+ *
95
+ * @default 6
96
+ *
97
+ * @example
98
+ * ```ts
99
+ * {
100
+ * length: 4 // 4-digit PIN for easier entry
101
+ * }
102
+ * ```
103
+ */
104
+ readonly length?: number;
105
+ /**
106
+ * Request handler for rendering the authentication UI.
107
+ * Handles both the initial claim collection and PIN code entry screens.
108
+ *
109
+ * @param req - The HTTP request object
110
+ * @param state - Current authentication state (start or code verification)
111
+ * @param form - Form data from POST requests (if any)
112
+ * @param error - Authentication error to display (if any)
113
+ * @returns Promise resolving to the authentication page response
114
+ *
115
+ * @example
116
+ * ```ts
117
+ * request: async (req, state, form, error) => {
118
+ * if (state.type === 'start') {
119
+ * return new Response(renderClaimForm(form, error))
120
+ * } else {
121
+ * return new Response(renderCodeForm(state.claims.email, error))
122
+ * }
123
+ * }
124
+ * ```
125
+ */
126
+ request: (req: Request, state: CodeProviderState, form?: FormData, error?: CodeProviderError) => Promise<Response>;
127
+ /**
128
+ * Callback for sending PIN codes to users via their preferred method.
129
+ * Should handle delivery via email, SMS, or other communication channels.
130
+ *
131
+ * @param claims - User claims containing contact information
132
+ * @param code - The generated PIN code to send
133
+ *
134
+ * @example
135
+ * ```ts
136
+ * sendCode: async (claims, code) => {
137
+ * await emailService.send({
138
+ * to: claims.email,
139
+ * subject: 'Your verification code',
140
+ * text: `Your PIN code is: ${code}`
141
+ * })
142
+ * }
143
+ * ```
144
+ */
145
+ sendCode: (claims: Claims, code: string) => Promise<void>;
146
+ }
147
+ /**
148
+ * Authentication flow states for the PIN code provider.
149
+ * The provider transitions between these states during authentication.
150
+ */
151
+ export type CodeProviderState = {
152
+ /** Initial state: user enters their claims (email, phone, etc.) */
153
+ readonly type: "start";
154
+ } | {
155
+ /** Code verification state: user enters the PIN code */
156
+ readonly type: "code";
157
+ /** Whether this is a code resend request */
158
+ readonly resend?: boolean;
159
+ /** The generated PIN code for verification */
160
+ readonly code: string;
161
+ /** User claims collected during the start phase */
162
+ readonly claims: Record<string, string>;
163
+ };
164
+ /**
165
+ * Possible errors during PIN code authentication.
166
+ */
167
+ export type CodeProviderError = {
168
+ /** The entered PIN code is incorrect */
169
+ readonly type: "invalid_code";
170
+ } | {
171
+ /** A user claim is invalid or missing */
172
+ readonly type: "invalid_claim";
173
+ /** The claim field that failed validation */
174
+ readonly key: string;
175
+ /** The invalid value or error description */
176
+ readonly value: string;
177
+ };
178
+ /**
179
+ * User data returned by successful PIN code authentication.
180
+ *
181
+ * @template Claims - Type of claims collected during authentication
182
+ */
183
+ export interface CodeUserData<Claims extends Record<string, string> = Record<string, string>> {
184
+ /** The verified claims collected during authentication */
185
+ readonly claims: Claims;
186
+ }
187
+ /**
188
+ * Creates a PIN code authentication provider.
189
+ * Implements a flexible claim-based authentication flow with PIN verification.
190
+ *
191
+ * @template Claims - Type of claims to collect (email, phone, username, etc.)
192
+ * @param config - PIN code provider configuration
193
+ * @returns Provider instance implementing PIN code authentication
194
+ *
195
+ * @example
196
+ * ```ts
197
+ * // Email-based PIN authentication
198
+ * const emailCodeProvider = CodeProvider<{ email: string }>({
199
+ * length: 6,
200
+ * request: async (req, state, form, error) => {
201
+ * if (state.type === 'start') {
202
+ * return new Response(renderEmailForm(form?.get('email'), error))
203
+ * } else {
204
+ * return new Response(renderPinForm(state.claims.email, error, state.resend))
205
+ * }
206
+ * },
207
+ * sendCode: async (claims, code) => {
208
+ * if (!claims.email || !isValidEmail(claims.email)) {
209
+ * return {
210
+ * type: "invalid_claim",
211
+ * key: "email",
212
+ * value: "Invalid email address"
213
+ * }
214
+ * }
215
+ *
216
+ * try {
217
+ * await emailService.send(claims.email, `Your verification code: ${code}`)
218
+ * } catch {
219
+ * return {
220
+ * type: "invalid_claim",
221
+ * key: "delivery",
222
+ * value: "Failed to send code"
223
+ * }
224
+ * }
225
+ * }
226
+ * })
227
+ *
228
+ * // Multi-channel PIN authentication (email or phone)
229
+ * const flexibleCodeProvider = CodeProvider<{ email?: string; phone?: string }>({
230
+ * length: 4,
231
+ * request: async (req, state, form, error) => {
232
+ * if (state.type === 'start') {
233
+ * return new Response(renderContactForm(form, error))
234
+ * } else {
235
+ * const contact = state.claims.email || state.claims.phone
236
+ * return new Response(renderPinForm(contact, error))
237
+ * }
238
+ * },
239
+ * sendCode: async (claims, code) => {
240
+ * try {
241
+ * if (claims.email) {
242
+ * await emailService.send(claims.email, `PIN: ${code}`)
243
+ * } else if (claims.phone) {
244
+ * await smsService.send(claims.phone, `PIN: ${code}`)
245
+ * } else {
246
+ * return {
247
+ * type: "invalid_claim",
248
+ * key: "email",
249
+ * value: "Provide either email or phone number"
250
+ * }
251
+ * }
252
+ * } catch {
253
+ * return {
254
+ * type: "invalid_claim",
255
+ * key: "delivery",
256
+ * value: "Failed to send code"
257
+ * }
258
+ * }
259
+ * }
260
+ * })
261
+ *
262
+ * // Usage in issuer
263
+ * export default issuer({
264
+ * providers: {
265
+ * email: emailCodeProvider,
266
+ * flexible: flexibleCodeProvider
267
+ * },
268
+ * success: async (ctx, value) => {
269
+ * if (value.provider === "code") {
270
+ * const email = value.claims.email
271
+ * const phone = value.claims.phone
272
+ *
273
+ * // Look up or create user based on verified claims
274
+ * const userId = await findOrCreateUser({ email, phone })
275
+ *
276
+ * return ctx.subject("user", { userId, email, phone })
277
+ * }
278
+ * }
279
+ * })
280
+ * ```
281
+ */
282
+ export declare const CodeProvider: <Claims extends Record<string, string> = Record<string, string>>(config: CodeProviderConfig<Claims>) => Provider<CodeUserData<Claims>>;
283
+ /**
284
+ * Type helper for CodeProvider configuration options.
285
+ * @internal
286
+ */
287
+ export type CodeProviderOptions = Parameters<typeof CodeProvider>[0];
288
+ //# sourceMappingURL=code.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"code.d.ts","sourceRoot":"","sources":["../../../src/provider/code.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;GAkFG;AAIH,OAAO,KAAK,EAAE,QAAQ,EAAE,MAAM,YAAY,CAAA;AAE1C;;;;GAIG;AACH,MAAM,WAAW,kBAAkB,CAClC,MAAM,SAAS,MAAM,CAAC,MAAM,EAAE,MAAM,CAAC,GAAG,MAAM,CAAC,MAAM,EAAE,MAAM,CAAC;IAE9D;;;;;;;;;;;;OAYG;IACH,QAAQ,CAAC,MAAM,CAAC,EAAE,MAAM,CAAA;IAExB;;;;;;;;;;;;;;;;;;;;OAoBG;IACH,OAAO,EAAE,CACR,GAAG,EAAE,OAAO,EACZ,KAAK,EAAE,iBAAiB,EACxB,IAAI,CAAC,EAAE,QAAQ,EACf,KAAK,CAAC,EAAE,iBAAiB,KACrB,OAAO,CAAC,QAAQ,CAAC,CAAA;IAEtB;;;;;;;;;;;;;;;;;OAiBG;IACH,QAAQ,EAAE,CAAC,MAAM,EAAE,MAAM,EAAE,IAAI,EAAE,MAAM,KAAK,OAAO,CAAC,IAAI,CAAC,CAAA;CACzD;AAED;;;GAGG;AACH,MAAM,MAAM,iBAAiB,GAC1B;IACA,mEAAmE;IACnE,QAAQ,CAAC,IAAI,EAAE,OAAO,CAAA;CACrB,GACD;IACA,wDAAwD;IACxD,QAAQ,CAAC,IAAI,EAAE,MAAM,CAAA;IACrB,4CAA4C;IAC5C,QAAQ,CAAC,MAAM,CAAC,EAAE,OAAO,CAAA;IACzB,8CAA8C;IAC9C,QAAQ,CAAC,IAAI,EAAE,MAAM,CAAA;IACrB,mDAAmD;IACnD,QAAQ,CAAC,MAAM,EAAE,MAAM,CAAC,MAAM,EAAE,MAAM,CAAC,CAAA;CACtC,CAAA;AAEJ;;GAEG;AACH,MAAM,MAAM,iBAAiB,GAC1B;IACA,wCAAwC;IACxC,QAAQ,CAAC,IAAI,EAAE,cAAc,CAAA;CAC5B,GACD;IACA,yCAAyC;IACzC,QAAQ,CAAC,IAAI,EAAE,eAAe,CAAA;IAC9B,6CAA6C;IAC7C,QAAQ,CAAC,GAAG,EAAE,MAAM,CAAA;IACpB,6CAA6C;IAC7C,QAAQ,CAAC,KAAK,EAAE,MAAM,CAAA;CACrB,CAAA;AAEJ;;;;GAIG;AACH,MAAM,WAAW,YAAY,CAAC,MAAM,SAAS,MAAM,CAAC,MAAM,EAAE,MAAM,CAAC,GAAG,MAAM,CAAC,MAAM,EAAE,MAAM,CAAC;IAC3F,0DAA0D;IAC1D,QAAQ,CAAC,MAAM,EAAE,MAAM,CAAA;CACvB;AAED;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;GA8FG;AACH,eAAO,MAAM,YAAY,GAAI,MAAM,SAAS,MAAM,CAAC,MAAM,EAAE,MAAM,CAAC,GAAG,MAAM,CAAC,MAAM,EAAE,MAAM,CAAC,EAC1F,QAAQ,kBAAkB,CAAC,MAAM,CAAC,KAChC,QAAQ,CAAC,YAAY,CAAC,MAAM,CAAC,CA6G/B,CAAA;AAED;;;GAGG;AACH,MAAM,MAAM,mBAAmB,GAAG,UAAU,CAAC,OAAO,YAAY,CAAC,CAAC,CAAC,CAAC,CAAA"}
@@ -0,0 +1,206 @@
1
+ /**
2
+ * Discord OAuth 2.0 authentication provider for Draft Auth.
3
+ * Provides access tokens for calling Discord APIs on behalf of users.
4
+ *
5
+ * ## Quick Setup
6
+ *
7
+ * ```ts
8
+ * import { DiscordProvider } from "@draftlab/auth/provider/discord"
9
+ *
10
+ * export default issuer({
11
+ * basePath: "/auth", // Important for callback URL
12
+ * providers: {
13
+ * discord: DiscordProvider({
14
+ * clientID: process.env.DISCORD_CLIENT_ID,
15
+ * clientSecret: process.env.DISCORD_CLIENT_SECRET,
16
+ * scopes: ["identify", "email", "guilds"]
17
+ * })
18
+ * }
19
+ * })
20
+ * ```
21
+ *
22
+ * **Callback URL Pattern**: `{baseURL}{basePath}/{provider}/callback`
23
+ * - Development: `http://localhost:3000/auth/discord/callback`
24
+ * - Production: `https://yourapp.com/auth/discord/callback`
25
+ *
26
+ * Register this URL in your Discord Developer Portal.
27
+ *
28
+ * ## Common Scopes
29
+ *
30
+ * - `identify` - Access to user's basic account information
31
+ * - `email` - Access to user's email address
32
+ * - `guilds` - Access to user's guilds (servers)
33
+ * - `guilds.join` - Ability to join user to guilds
34
+ * - `gdm.join` - Ability to join user to group DMs
35
+ * - `connections` - Access to user's connections (Steam, YouTube, etc.)
36
+ * - `guilds.members.read` - Read guild member information
37
+ * - `bot` - For bot applications (requires additional setup)
38
+ *
39
+ * ## User Data Access
40
+ *
41
+ * ```ts
42
+ * success: async (ctx, value) => {
43
+ * if (value.provider === "discord") {
44
+ * const accessToken = value.tokenset.access
45
+ *
46
+ * // Fetch user information
47
+ * const userResponse = await fetch('https://discord.com/api/users/@me', {
48
+ * headers: { Authorization: `Bearer ${accessToken}` }
49
+ * })
50
+ * const user = await userResponse.json()
51
+ *
52
+ * // Fetch user guilds (requires guilds scope)
53
+ * const guildsResponse = await fetch('https://discord.com/api/users/@me/guilds', {
54
+ * headers: { Authorization: `Bearer ${accessToken}` }
55
+ * })
56
+ * const guilds = await guildsResponse.json()
57
+ *
58
+ * // User info: user.username + user.discriminator
59
+ * // Avatar: `https://cdn.discordapp.com/avatars/${user.id}/${user.avatar}.png`
60
+ * }
61
+ * }
62
+ * ```
63
+ *
64
+ * @packageDocumentation
65
+ */
66
+ import { type Oauth2WrappedConfig } from "./oauth2";
67
+ /**
68
+ * Configuration options for Discord OAuth 2.0 provider.
69
+ * Extends the base OAuth 2.0 configuration with Discord-specific documentation.
70
+ */
71
+ export interface DiscordConfig extends Oauth2WrappedConfig {
72
+ /**
73
+ * Discord OAuth 2.0 client ID from Discord Developer Portal.
74
+ * Found in your Discord application settings.
75
+ *
76
+ * @example
77
+ * ```ts
78
+ * {
79
+ * clientID: "1234567890123456789"
80
+ * }
81
+ * ```
82
+ */
83
+ readonly clientID: string;
84
+ /**
85
+ * Discord OAuth 2.0 client secret from Discord Developer Portal.
86
+ * Keep this secure and never expose it to client-side code.
87
+ *
88
+ * @example
89
+ * ```ts
90
+ * {
91
+ * clientSecret: process.env.DISCORD_CLIENT_SECRET
92
+ * }
93
+ * ```
94
+ */
95
+ readonly clientSecret: string;
96
+ /**
97
+ * Discord OAuth scopes to request access for.
98
+ * Determines what data and actions your app can access.
99
+ *
100
+ * @example
101
+ * ```ts
102
+ * {
103
+ * scopes: [
104
+ * "identify", // Basic user information
105
+ * "email", // Email address
106
+ * "guilds", // User's Discord servers
107
+ * "connections" // Connected accounts (Steam, etc.)
108
+ * ]
109
+ * }
110
+ * ```
111
+ */
112
+ readonly scopes: string[];
113
+ /**
114
+ * Additional query parameters for Discord OAuth authorization.
115
+ * Useful for Discord-specific options like permissions.
116
+ *
117
+ * @example
118
+ * ```ts
119
+ * {
120
+ * query: {
121
+ * permissions: "8", // Administrator permission
122
+ * guild_id: "123456789", // Pre-select specific guild
123
+ * disable_guild_select: "true" // Disable guild selection
124
+ * }
125
+ * }
126
+ * ```
127
+ */
128
+ readonly query?: Record<string, string>;
129
+ }
130
+ /**
131
+ * Creates a Discord OAuth 2.0 authentication provider.
132
+ * Use this when you need access tokens to call Discord APIs on behalf of the user.
133
+ *
134
+ * @param config - Discord OAuth 2.0 configuration
135
+ * @returns OAuth 2.0 provider configured for Discord
136
+ *
137
+ * @example
138
+ * ```ts
139
+ * // Basic Discord authentication
140
+ * const basicDiscord = DiscordProvider({
141
+ * clientID: process.env.DISCORD_CLIENT_ID,
142
+ * clientSecret: process.env.DISCORD_CLIENT_SECRET
143
+ * })
144
+ *
145
+ * // Discord with specific scopes
146
+ * const discordWithScopes = DiscordProvider({
147
+ * clientID: process.env.DISCORD_CLIENT_ID,
148
+ * clientSecret: process.env.DISCORD_CLIENT_SECRET,
149
+ * scopes: [
150
+ * "identify",
151
+ * "email",
152
+ * "guilds",
153
+ * "connections"
154
+ * ]
155
+ * })
156
+ *
157
+ * // Discord bot integration
158
+ * const discordBot = DiscordProvider({
159
+ * clientID: process.env.DISCORD_CLIENT_ID,
160
+ * clientSecret: process.env.DISCORD_CLIENT_SECRET,
161
+ * scopes: ["bot", "guilds"],
162
+ * query: {
163
+ * permissions: "2048" // Send Messages permission
164
+ * }
165
+ * })
166
+ *
167
+ * // Using the access token to fetch data
168
+ * export default issuer({
169
+ * providers: { discord: discordWithScopes },
170
+ * success: async (ctx, value) => {
171
+ * if (value.provider === "discord") {
172
+ * const token = value.tokenset.access
173
+ *
174
+ * // Get user profile
175
+ * const userRes = await fetch('https://discord.com/api/users/@me', {
176
+ * headers: { Authorization: `Bearer ${token}` }
177
+ * })
178
+ * const user = await userRes.json()
179
+ *
180
+ * // Get user guilds (if guilds scope granted)
181
+ * const guildsRes = await fetch('https://discord.com/api/users/@me/guilds', {
182
+ * headers: { Authorization: `Bearer ${token}` }
183
+ * })
184
+ * const guilds = await guildsRes.json()
185
+ *
186
+ * return ctx.subject("user", {
187
+ * discordId: user.id,
188
+ * username: user.username,
189
+ * discriminator: user.discriminator,
190
+ * email: user.email,
191
+ * avatar: user.avatar ? `https://cdn.discordapp.com/avatars/${user.id}/${user.avatar}.png` : null,
192
+ * guildCount: guilds.length
193
+ * })
194
+ * }
195
+ * }
196
+ * })
197
+ * ```
198
+ *
199
+ * **Callback URL Pattern**: `{baseURL}{basePath}/{provider}/callback`
200
+ * - Development: `http://localhost:3000/auth/discord/callback`
201
+ * - Production: `https://yourapp.com/auth/discord/callback`
202
+ *
203
+ * Register this URL in your Discord Developer Portal.
204
+ */
205
+ export declare const DiscordProvider: (config: DiscordConfig) => import("./provider").Provider<import("./oauth2").Oauth2UserData>;
206
+ //# sourceMappingURL=discord.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"discord.d.ts","sourceRoot":"","sources":["../../../src/provider/discord.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;GAgEG;AAEH,OAAO,EAAkB,KAAK,mBAAmB,EAAE,MAAM,UAAU,CAAA;AAEnE;;;GAGG;AACH,MAAM,WAAW,aAAc,SAAQ,mBAAmB;IACzD;;;;;;;;;;OAUG;IACH,QAAQ,CAAC,QAAQ,EAAE,MAAM,CAAA;IAEzB;;;;;;;;;;OAUG;IACH,QAAQ,CAAC,YAAY,EAAE,MAAM,CAAA;IAE7B;;;;;;;;;;;;;;;OAeG;IACH,QAAQ,CAAC,MAAM,EAAE,MAAM,EAAE,CAAA;IAEzB;;;;;;;;;;;;;;OAcG;IACH,QAAQ,CAAC,KAAK,CAAC,EAAE,MAAM,CAAC,MAAM,EAAE,MAAM,CAAC,CAAA;CACvC;AAED;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;GA0EG;AACH,eAAO,MAAM,eAAe,GAAI,QAAQ,aAAa,qEASpD,CAAA"}
@@ -0,0 +1,200 @@
1
+ /**
2
+ * Facebook OAuth 2.0 authentication provider for Draft Auth.
3
+ * Provides access tokens for calling Facebook Graph API on behalf of users.
4
+ *
5
+ * ## Quick Setup
6
+ *
7
+ * ```ts
8
+ * import { FacebookProvider } from "@draftlab/auth/provider/facebook"
9
+ *
10
+ * export default issuer({
11
+ * basePath: "/auth", // Important for callback URL
12
+ * providers: {
13
+ * facebook: FacebookProvider({
14
+ * clientID: process.env.FACEBOOK_APP_ID,
15
+ * clientSecret: process.env.FACEBOOK_APP_SECRET,
16
+ * scopes: ["email", "public_profile", "user_friends"]
17
+ * })
18
+ * }
19
+ * })
20
+ * ```
21
+ *
22
+ * **Callback URL Pattern**: `{baseURL}{basePath}/{provider}/callback`
23
+ * - Development: `http://localhost:3000/auth/facebook/callback`
24
+ * - Production: `https://yourapp.com/auth/facebook/callback`
25
+ *
26
+ * Register this URL in your Facebook App Dashboard.
27
+ *
28
+ * ## Configuration Options
29
+ *
30
+ * - Access tokens for Facebook Graph API calls
31
+ * - Support for various Facebook permissions
32
+ * - Access to user data, posts, friends, etc.
33
+ *
34
+ * ## Common Facebook Permissions
35
+ *
36
+ * - `public_profile` - Basic profile information (name, picture, etc.)
37
+ * - `email` - User's email address
38
+ * - `user_friends` - List of user's friends who also use your app
39
+ * - `user_posts` - User's posts on their timeline
40
+ * - `user_photos` - User's photos and albums
41
+ * - `pages_read_engagement` - Read engagement data for Pages
42
+ *
43
+ * ## User Data Access
44
+ *
45
+ * ```ts
46
+ * success: async (ctx, value) => {
47
+ * if (value.provider === "facebook") {
48
+ * const accessToken = value.tokenset.access
49
+ *
50
+ * // Fetch user profile from Graph API
51
+ * const profileResponse = await fetch(
52
+ * `https://graph.facebook.com/me?fields=id,name,email,picture&access_token=${accessToken}`
53
+ * )
54
+ * const profile = await profileResponse.json()
55
+ *
56
+ * // User info: `${profile.name} (${profile.email})`
57
+ * // Facebook ID: profile.id
58
+ * }
59
+ * }
60
+ * ```
61
+ *
62
+ * @packageDocumentation
63
+ */
64
+ import { type Oauth2WrappedConfig } from "./oauth2";
65
+ /**
66
+ * Configuration options for Facebook OAuth 2.0 provider.
67
+ * Extends the base OAuth 2.0 configuration with Facebook-specific documentation.
68
+ */
69
+ export interface FacebookConfig extends Oauth2WrappedConfig {
70
+ /**
71
+ * Facebook App ID from your Facebook App Dashboard.
72
+ * This is the public identifier for your Facebook application.
73
+ *
74
+ * @example
75
+ * ```ts
76
+ * {
77
+ * clientID: "1234567890123456"
78
+ * }
79
+ * ```
80
+ */
81
+ readonly clientID: string;
82
+ /**
83
+ * Facebook App Secret from your Facebook App Dashboard.
84
+ * Keep this secure and never expose it to client-side code.
85
+ *
86
+ * @example
87
+ * ```ts
88
+ * {
89
+ * clientSecret: process.env.FACEBOOK_APP_SECRET
90
+ * }
91
+ * ```
92
+ */
93
+ readonly clientSecret: string;
94
+ /**
95
+ * Facebook permissions to request during login.
96
+ * Determines what data your app can access from the user's Facebook account.
97
+ *
98
+ * @example
99
+ * ```ts
100
+ * {
101
+ * scopes: [
102
+ * "email", // User's email address
103
+ * "public_profile", // Basic profile info
104
+ * "user_friends", // User's friends list
105
+ * "user_posts" // User's timeline posts
106
+ * ]
107
+ * }
108
+ * ```
109
+ */
110
+ readonly scopes: string[];
111
+ /**
112
+ * Additional query parameters for Facebook OAuth authorization.
113
+ * Useful for Facebook-specific options like response type or display mode.
114
+ *
115
+ * @example
116
+ * ```ts
117
+ * {
118
+ * query: {
119
+ * display: "popup", // Show login in popup
120
+ * auth_type: "rerequest", // Force permission re-request
121
+ * state: "custom-state" // Custom state parameter
122
+ * }
123
+ * }
124
+ * ```
125
+ */
126
+ readonly query?: Record<string, string>;
127
+ }
128
+ /**
129
+ * Creates a Facebook OAuth 2.0 authentication provider.
130
+ * Use this when you need access tokens to call Facebook Graph API on behalf of the user.
131
+ *
132
+ * @param config - Facebook OAuth 2.0 configuration
133
+ * @returns OAuth 2.0 provider configured for Facebook
134
+ *
135
+ * @example
136
+ * ```ts
137
+ * // Basic Facebook authentication
138
+ * const basicFacebook = FacebookProvider({
139
+ * clientID: process.env.FACEBOOK_APP_ID,
140
+ * clientSecret: process.env.FACEBOOK_APP_SECRET,
141
+ * scopes: ["email", "public_profile"]
142
+ * })
143
+ *
144
+ * // Facebook with extended permissions
145
+ * const extendedFacebook = FacebookProvider({
146
+ * clientID: process.env.FACEBOOK_APP_ID,
147
+ * clientSecret: process.env.FACEBOOK_APP_SECRET,
148
+ * scopes: [
149
+ * "email",
150
+ * "public_profile",
151
+ * "user_friends",
152
+ * "user_posts",
153
+ * "user_photos"
154
+ * ],
155
+ * query: {
156
+ * display: "popup",
157
+ * auth_type: "rerequest" // Force permission approval
158
+ * }
159
+ * })
160
+ *
161
+ * // Using the access token for Graph API calls
162
+ * export default issuer({
163
+ * providers: { facebook: extendedFacebook },
164
+ * success: async (ctx, value) => {
165
+ * if (value.provider === "facebook") {
166
+ * const token = value.tokenset.access
167
+ *
168
+ * // Get user profile with custom fields
169
+ * const profileRes = await fetch(
170
+ * `https://graph.facebook.com/me?fields=id,name,email,picture.width(200),friends&access_token=${token}`
171
+ * )
172
+ * const profile = await profileRes.json()
173
+ *
174
+ * // Get user's posts (if permission granted)
175
+ * const postsRes = await fetch(
176
+ * `https://graph.facebook.com/me/posts?access_token=${token}`
177
+ * )
178
+ * const posts = await postsRes.json()
179
+ *
180
+ * return ctx.subject("user", {
181
+ * facebookId: profile.id,
182
+ * name: profile.name,
183
+ * email: profile.email,
184
+ * picture: profile.picture?.data?.url,
185
+ * friendsCount: profile.friends?.summary?.total_count || 0,
186
+ * postsCount: posts.data?.length || 0
187
+ * })
188
+ * }
189
+ * }
190
+ * })
191
+ * ```
192
+ *
193
+ * **Callback URL Pattern**: `{baseURL}{basePath}/{provider}/callback`
194
+ * - Development: `http://localhost:3000/auth/facebook/callback`
195
+ * - Production: `https://yourapp.com/auth/facebook/callback`
196
+ *
197
+ * Register this URL in your Facebook App Dashboard.
198
+ */
199
+ export declare const FacebookProvider: (config: FacebookConfig) => import("./provider").Provider<import("./oauth2").Oauth2UserData>;
200
+ //# sourceMappingURL=facebook.d.ts.map