@draftlab/auth 0.0.3 → 0.1.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.
- package/dist/allow.d.ts +58 -1
- package/dist/allow.js +61 -2
- package/dist/client.d.ts +2 -3
- package/dist/client.js +2 -2
- package/dist/core.d.ts +128 -8
- package/dist/core.js +496 -12
- package/dist/error.d.ts +242 -1
- package/dist/error.js +235 -1
- package/dist/index.d.ts +1 -8
- package/dist/index.js +1 -12
- package/dist/keys.d.ts +1 -1
- package/dist/keys.js +138 -3
- package/dist/pkce.js +160 -1
- package/dist/provider/code.d.ts +227 -3
- package/dist/provider/code.js +27 -14
- package/dist/provider/facebook.d.ts +2 -3
- package/dist/provider/facebook.js +1 -5
- package/dist/provider/github.d.ts +2 -3
- package/dist/provider/github.js +1 -5
- package/dist/provider/google.d.ts +2 -3
- package/dist/provider/google.js +1 -5
- package/dist/provider/oauth2.d.ts +175 -3
- package/dist/provider/oauth2.js +153 -5
- package/dist/provider/password.d.ts +384 -3
- package/dist/provider/password.js +4 -4
- package/dist/provider/provider.d.ts +226 -2
- package/dist/random.js +85 -1
- package/dist/storage/memory.d.ts +2 -2
- package/dist/storage/memory.js +1 -1
- package/dist/storage/storage.d.ts +161 -1
- package/dist/storage/storage.js +60 -1
- package/dist/storage/turso.d.ts +1 -1
- package/dist/storage/turso.js +1 -1
- package/dist/storage/unstorage.d.ts +2 -2
- package/dist/storage/unstorage.js +2 -2
- package/dist/subject.d.ts +61 -2
- package/dist/themes/theme.d.ts +208 -1
- package/dist/themes/theme.js +118 -1
- package/dist/ui/base.d.ts +22 -35
- package/dist/ui/base.js +388 -3
- package/dist/ui/code.d.ts +22 -137
- package/dist/ui/code.js +199 -161
- package/dist/ui/form.d.ts +8 -6
- package/dist/ui/form.js +57 -1
- package/dist/ui/icon.d.ts +7 -84
- package/dist/ui/icon.js +69 -2
- package/dist/ui/password.d.ts +30 -37
- package/dist/ui/password.js +340 -237
- package/dist/ui/select.d.ts +19 -218
- package/dist/ui/select.js +91 -4
- package/dist/util.d.ts +71 -1
- package/dist/util.js +106 -1
- package/package.json +5 -3
- package/dist/allow-CixonwTW.d.ts +0 -59
- package/dist/allow-DX5cehSc.js +0 -63
- package/dist/base-DRutbxgL.js +0 -422
- package/dist/code-DJxdFR7p.d.ts +0 -212
- package/dist/core-BZHEAefX.d.ts +0 -129
- package/dist/core-CDM5o4rs.js +0 -498
- package/dist/error-CWAdNAzm.d.ts +0 -243
- package/dist/error-DgAKK7b2.js +0 -237
- package/dist/form-6XKM_cOk.js +0 -61
- package/dist/icon-Ci5uqGB_.js +0 -192
- package/dist/keys-EEfxEGfO.js +0 -140
- package/dist/oauth2-B7-6Z7Lc.js +0 -155
- package/dist/oauth2-CXHukHf2.d.ts +0 -176
- package/dist/password-C4KLmO0O.d.ts +0 -385
- package/dist/pkce-276Za_rZ.js +0 -162
- package/dist/provider-tndlqCzp.d.ts +0 -227
- package/dist/random-SXMYlaVr.js +0 -87
- package/dist/select-BjySLL8I.js +0 -280
- package/dist/storage-BEaqEPNQ.js +0 -62
- package/dist/storage-CxKerLlc.d.ts +0 -162
- package/dist/subject-DMIMVtaT.d.ts +0 -62
- package/dist/theme-C9by7VXf.d.ts +0 -209
- package/dist/theme-CswaLtbW.js +0 -120
- package/dist/util-CSdHUFOo.js +0 -108
- package/dist/util-DbSKG1Xm.d.ts +0 -72
package/dist/base-DRutbxgL.js
DELETED
|
@@ -1,422 +0,0 @@
|
|
|
1
|
-
import { getTheme } from "./theme-CswaLtbW.js";
|
|
2
|
-
|
|
3
|
-
//#region src/ui/base.ts
|
|
4
|
-
const css = `@import url("https://unpkg.com/tailwindcss@3.4.15/src/css/preflight.css");
|
|
5
|
-
|
|
6
|
-
:root {
|
|
7
|
-
--color-background-dark: #0e0e11;
|
|
8
|
-
--color-background-light: #ffffff;
|
|
9
|
-
--color-primary-dark: #6772e5;
|
|
10
|
-
--color-primary-light: #6772e5;
|
|
11
|
-
|
|
12
|
-
--color-background-success-dark: oklch(0.3 0.04 172);
|
|
13
|
-
--color-background-success-light: oklch(
|
|
14
|
-
from var(--color-background-success-dark) 0.83 c h
|
|
15
|
-
);
|
|
16
|
-
--color-success-dark: oklch(
|
|
17
|
-
from var(--color-background-success-dark) 0.92 c h
|
|
18
|
-
);
|
|
19
|
-
--color-success-light: oklch(
|
|
20
|
-
from var(--color-background-success-dark) 0.25 c h
|
|
21
|
-
);
|
|
22
|
-
|
|
23
|
-
--color-background-error-dark: oklch(0.32 0.07 15);
|
|
24
|
-
--color-background-error-light: oklch(
|
|
25
|
-
from var(--color-background-error-dark) 0.92 c h
|
|
26
|
-
);
|
|
27
|
-
--color-error-dark: oklch(from var(--color-background-error-dark) 0.92 c h);
|
|
28
|
-
--color-error-light: oklch(from var(--color-background-error-dark) 0.25 c h);
|
|
29
|
-
|
|
30
|
-
--border-radius: 0;
|
|
31
|
-
|
|
32
|
-
--color-background: var(--color-background-dark);
|
|
33
|
-
--color-primary: var(--color-primary-dark);
|
|
34
|
-
|
|
35
|
-
--color-background-success: var(--color-background-success-dark);
|
|
36
|
-
--color-success: var(--color-success-dark);
|
|
37
|
-
--color-background-error: var(--color-background-error-dark);
|
|
38
|
-
--color-error: var(--color-error-dark);
|
|
39
|
-
|
|
40
|
-
@media (prefers-color-scheme: light) {
|
|
41
|
-
--color-background: var(--color-background-light);
|
|
42
|
-
--color-primary: var(--color-primary-light);
|
|
43
|
-
|
|
44
|
-
--color-background-success: var(--color-background-success-light);
|
|
45
|
-
--color-success: var(--color-success-light);
|
|
46
|
-
--color-background-error: var(--color-background-error-light);
|
|
47
|
-
--color-error: var(--color-error-light);
|
|
48
|
-
}
|
|
49
|
-
|
|
50
|
-
--color-high: oklch(
|
|
51
|
-
from var(--color-background) clamp(0, calc((l - 0.714) * -1000), 1) 0 0
|
|
52
|
-
);
|
|
53
|
-
--color-low: oklch(
|
|
54
|
-
from var(--color-background) clamp(0, calc((l - 0.714) * 1000), 1) 0 0
|
|
55
|
-
);
|
|
56
|
-
--lightness-high: color-mix(
|
|
57
|
-
in oklch,
|
|
58
|
-
var(--color-high) 0%,
|
|
59
|
-
oklch(var(--color-high) 0 0)
|
|
60
|
-
);
|
|
61
|
-
--lightness-low: color-mix(
|
|
62
|
-
in oklch,
|
|
63
|
-
var(--color-low) 0%,
|
|
64
|
-
oklch(var(--color-low) 0 0)
|
|
65
|
-
);
|
|
66
|
-
--font-family:
|
|
67
|
-
ui-sans-serif, system-ui, sans-serif, "Apple Color Emoji", "Segoe UI Emoji",
|
|
68
|
-
"Segoe UI Symbol", "Noto Color Emoji";
|
|
69
|
-
--font-scale: 1;
|
|
70
|
-
|
|
71
|
-
--font-size-xs: calc(0.75rem * var(--font-scale));
|
|
72
|
-
--font-size-sm: calc(0.875rem * var(--font-scale));
|
|
73
|
-
--font-size-md: calc(1rem * var(--font-scale));
|
|
74
|
-
--font-size-lg: calc(1.125rem * var(--font-scale));
|
|
75
|
-
--font-size-xl: calc(1.25rem * var(--font-scale));
|
|
76
|
-
--font-size-2xl: calc(1.5rem * var(--font-scale));
|
|
77
|
-
}
|
|
78
|
-
|
|
79
|
-
[data-component="root"] {
|
|
80
|
-
font-family: var(--font-family);
|
|
81
|
-
background-color: var(--color-background);
|
|
82
|
-
padding: 1rem;
|
|
83
|
-
color: white;
|
|
84
|
-
position: absolute;
|
|
85
|
-
inset: 0;
|
|
86
|
-
display: flex;
|
|
87
|
-
align-items: center;
|
|
88
|
-
justify-content: center;
|
|
89
|
-
flex-direction: column;
|
|
90
|
-
user-select: none;
|
|
91
|
-
color: var(--color-high);
|
|
92
|
-
}
|
|
93
|
-
|
|
94
|
-
[data-component="center"] {
|
|
95
|
-
width: 380px;
|
|
96
|
-
display: flex;
|
|
97
|
-
flex-direction: column;
|
|
98
|
-
gap: 1.5rem;
|
|
99
|
-
}
|
|
100
|
-
|
|
101
|
-
[data-component="center"][data-size="small"] {
|
|
102
|
-
width: 300px;
|
|
103
|
-
}
|
|
104
|
-
|
|
105
|
-
[data-component="link"] {
|
|
106
|
-
text-decoration: underline;
|
|
107
|
-
text-underline-offset: 0.125rem;
|
|
108
|
-
font-weight: 600;
|
|
109
|
-
}
|
|
110
|
-
|
|
111
|
-
[data-component="label"] {
|
|
112
|
-
display: flex;
|
|
113
|
-
gap: 0.75rem;
|
|
114
|
-
flex-direction: column;
|
|
115
|
-
font-size: var(--font-size-xs);
|
|
116
|
-
}
|
|
117
|
-
|
|
118
|
-
[data-component="logo"] {
|
|
119
|
-
margin: 0 auto;
|
|
120
|
-
height: 2.5rem;
|
|
121
|
-
width: auto;
|
|
122
|
-
display: none;
|
|
123
|
-
}
|
|
124
|
-
|
|
125
|
-
@media (prefers-color-scheme: light) {
|
|
126
|
-
[data-component="logo"][data-mode="light"] {
|
|
127
|
-
display: block;
|
|
128
|
-
}
|
|
129
|
-
}
|
|
130
|
-
|
|
131
|
-
@media (prefers-color-scheme: dark) {
|
|
132
|
-
[data-component="logo"][data-mode="dark"] {
|
|
133
|
-
display: block;
|
|
134
|
-
}
|
|
135
|
-
}
|
|
136
|
-
|
|
137
|
-
[data-component="logo-default"] {
|
|
138
|
-
margin: 0 auto;
|
|
139
|
-
height: 2.5rem;
|
|
140
|
-
width: auto;
|
|
141
|
-
}
|
|
142
|
-
|
|
143
|
-
@media (prefers-color-scheme: light) {
|
|
144
|
-
[data-component="logo-default"] {
|
|
145
|
-
color: var(--color-high);
|
|
146
|
-
}
|
|
147
|
-
}
|
|
148
|
-
|
|
149
|
-
@media (prefers-color-scheme: dark) {
|
|
150
|
-
[data-component="logo-default"] {
|
|
151
|
-
color: var(--color-high);
|
|
152
|
-
}
|
|
153
|
-
}
|
|
154
|
-
|
|
155
|
-
[data-component="input"] {
|
|
156
|
-
width: 100%;
|
|
157
|
-
height: 2.5rem;
|
|
158
|
-
padding: 0 1rem;
|
|
159
|
-
border: 1px solid transparent;
|
|
160
|
-
--background: oklch(
|
|
161
|
-
from var(--color-background)
|
|
162
|
-
calc(l + (-0.06 * clamp(0, calc((l - 0.714) * 1000), 1) + 0.03)) c h
|
|
163
|
-
);
|
|
164
|
-
background: var(--background);
|
|
165
|
-
border-color: oklch(
|
|
166
|
-
from var(--color-background)
|
|
167
|
-
calc(
|
|
168
|
-
clamp(
|
|
169
|
-
0.22,
|
|
170
|
-
l +
|
|
171
|
-
(-0.12 * clamp(0, calc((l - 0.714) * 1000), 1) + 0.06),
|
|
172
|
-
0.88
|
|
173
|
-
)
|
|
174
|
-
)
|
|
175
|
-
c h
|
|
176
|
-
);
|
|
177
|
-
border-radius: calc(var(--border-radius) * 0.25rem);
|
|
178
|
-
font-size: var(--font-size-sm);
|
|
179
|
-
outline: none;
|
|
180
|
-
}
|
|
181
|
-
|
|
182
|
-
[data-component="input"]:focus {
|
|
183
|
-
border-color: oklch(
|
|
184
|
-
from var(--color-background)
|
|
185
|
-
calc(
|
|
186
|
-
clamp(
|
|
187
|
-
0.3,
|
|
188
|
-
l +
|
|
189
|
-
(-0.2 * clamp(0, calc((l - 0.714) * 1000), 1) + 0.1),
|
|
190
|
-
0.7
|
|
191
|
-
)
|
|
192
|
-
)
|
|
193
|
-
c h
|
|
194
|
-
);
|
|
195
|
-
}
|
|
196
|
-
|
|
197
|
-
[data-component="input"]:user-invalid:not(:focus) {
|
|
198
|
-
border-color: oklch(0.4 0.09 7.91);
|
|
199
|
-
}
|
|
200
|
-
|
|
201
|
-
[data-component="button"] {
|
|
202
|
-
height: 2.5rem;
|
|
203
|
-
cursor: pointer;
|
|
204
|
-
border: 0;
|
|
205
|
-
font-weight: 500;
|
|
206
|
-
font-size: var(--font-size-sm);
|
|
207
|
-
border-radius: calc(var(--border-radius) * 0.25rem);
|
|
208
|
-
display: flex;
|
|
209
|
-
gap: 0.75rem;
|
|
210
|
-
align-items: center;
|
|
211
|
-
justify-content: center;
|
|
212
|
-
background: var(--color-primary);
|
|
213
|
-
color: oklch(
|
|
214
|
-
from var(--color-primary) clamp(0, calc((l - 0.714) * -1000), 1) 0 0
|
|
215
|
-
);
|
|
216
|
-
}
|
|
217
|
-
|
|
218
|
-
[data-component="button"][data-color="ghost"] {
|
|
219
|
-
background: transparent;
|
|
220
|
-
color: var(--color-high);
|
|
221
|
-
border: 1px solid
|
|
222
|
-
oklch(
|
|
223
|
-
from var(--color-background)
|
|
224
|
-
calc(
|
|
225
|
-
clamp(
|
|
226
|
-
0.22,
|
|
227
|
-
l +
|
|
228
|
-
(-0.12 * clamp(0, calc((l - 0.714) * 1000), 1) + 0.06),
|
|
229
|
-
0.88
|
|
230
|
-
)
|
|
231
|
-
)
|
|
232
|
-
c h
|
|
233
|
-
);
|
|
234
|
-
}
|
|
235
|
-
|
|
236
|
-
[data-component="button"] [data-slot="icon"] {
|
|
237
|
-
width: 16px;
|
|
238
|
-
height: 16px;
|
|
239
|
-
}
|
|
240
|
-
|
|
241
|
-
[data-component="button"] [data-slot="icon"] svg {
|
|
242
|
-
width: 100%;
|
|
243
|
-
height: 100%;
|
|
244
|
-
}
|
|
245
|
-
|
|
246
|
-
[data-component="form"] {
|
|
247
|
-
max-width: 100%;
|
|
248
|
-
display: flex;
|
|
249
|
-
flex-direction: column;
|
|
250
|
-
gap: 1rem;
|
|
251
|
-
margin: 0;
|
|
252
|
-
}
|
|
253
|
-
|
|
254
|
-
[data-component="form-alert"] {
|
|
255
|
-
height: 2.5rem;
|
|
256
|
-
display: flex;
|
|
257
|
-
align-items: center;
|
|
258
|
-
padding: 0 1rem;
|
|
259
|
-
border-radius: calc(var(--border-radius) * 0.25rem);
|
|
260
|
-
background: var(--color-background-error);
|
|
261
|
-
color: var(--color-error);
|
|
262
|
-
text-align: left;
|
|
263
|
-
font-size: 0.75rem;
|
|
264
|
-
gap: 0.5rem;
|
|
265
|
-
}
|
|
266
|
-
|
|
267
|
-
[data-component="form-alert"][data-color="success"] {
|
|
268
|
-
background: var(--color-background-success);
|
|
269
|
-
color: var(--color-success);
|
|
270
|
-
}
|
|
271
|
-
|
|
272
|
-
[data-component="form-alert"][data-color="success"] [data-slot="icon-success"] {
|
|
273
|
-
display: block;
|
|
274
|
-
}
|
|
275
|
-
[data-component="form-alert"][data-color="success"] [data-slot="icon-danger"] {
|
|
276
|
-
display: none;
|
|
277
|
-
}
|
|
278
|
-
|
|
279
|
-
[data-component="form-alert"]:has([data-slot="message"]:empty) {
|
|
280
|
-
display: none;
|
|
281
|
-
}
|
|
282
|
-
|
|
283
|
-
[data-component="form-alert"] [data-slot="icon-success"],
|
|
284
|
-
[data-component="form-alert"] [data-slot="icon-danger"] {
|
|
285
|
-
width: 1rem;
|
|
286
|
-
height: 1rem;
|
|
287
|
-
}
|
|
288
|
-
[data-component="form-alert"] [data-slot="icon-success"] {
|
|
289
|
-
display: none;
|
|
290
|
-
}
|
|
291
|
-
|
|
292
|
-
[data-component="form-footer"] {
|
|
293
|
-
display: flex;
|
|
294
|
-
gap: 1rem;
|
|
295
|
-
font-size: 0.75rem;
|
|
296
|
-
align-items: center;
|
|
297
|
-
justify-content: center;
|
|
298
|
-
}
|
|
299
|
-
|
|
300
|
-
[data-component="form-footer"]:has(> :nth-child(2)) {
|
|
301
|
-
justify-content: space-between;
|
|
302
|
-
}
|
|
303
|
-
`;
|
|
304
|
-
/**
|
|
305
|
-
* Main layout component that wraps all authentication UI screens.
|
|
306
|
-
* Handles theming, logo display, and provides consistent styling.
|
|
307
|
-
*
|
|
308
|
-
* @param props - Layout props including children and optional size
|
|
309
|
-
* @returns Complete HTML document as a string with theming and branding applied
|
|
310
|
-
*/
|
|
311
|
-
const Layout = (props) => {
|
|
312
|
-
const theme = getTheme();
|
|
313
|
-
/**
|
|
314
|
-
* Gets a theme value for a specific key and color mode.
|
|
315
|
-
* Handles both string values and light/dark object configurations.
|
|
316
|
-
*/
|
|
317
|
-
const getThemeValue = (key, mode) => {
|
|
318
|
-
if (!theme?.[key]) return;
|
|
319
|
-
if (typeof theme[key] === "string") return theme[key];
|
|
320
|
-
return theme[key][mode];
|
|
321
|
-
};
|
|
322
|
-
/**
|
|
323
|
-
* Calculates border radius value based on theme configuration.
|
|
324
|
-
*/
|
|
325
|
-
const getBorderRadius = () => {
|
|
326
|
-
switch (theme?.radius) {
|
|
327
|
-
case "none": return "0";
|
|
328
|
-
case "sm": return "1";
|
|
329
|
-
case "md": return "1.25";
|
|
330
|
-
case "lg": return "1.5";
|
|
331
|
-
case "full": return "1000000000001";
|
|
332
|
-
default: return "1";
|
|
333
|
-
}
|
|
334
|
-
};
|
|
335
|
-
/**
|
|
336
|
-
* Checks if both light and dark logo variants are available.
|
|
337
|
-
*/
|
|
338
|
-
const hasCustomLogo = Boolean(getThemeValue("logo", "light") && getThemeValue("logo", "dark"));
|
|
339
|
-
/**
|
|
340
|
-
* CSS custom properties for theming.
|
|
341
|
-
*/
|
|
342
|
-
const themeStyles = [
|
|
343
|
-
`--color-background-light: ${getThemeValue("background", "light") || ""}`,
|
|
344
|
-
`--color-background-dark: ${getThemeValue("background", "dark") || ""}`,
|
|
345
|
-
`--color-primary-light: ${getThemeValue("primary", "light") || ""}`,
|
|
346
|
-
`--color-primary-dark: ${getThemeValue("primary", "dark") || ""}`,
|
|
347
|
-
`--font-family: ${theme?.font?.family || ""}`,
|
|
348
|
-
`--font-scale: ${theme?.font?.scale || ""}`,
|
|
349
|
-
`--border-radius: ${getBorderRadius()}`
|
|
350
|
-
].join("; ");
|
|
351
|
-
const faviconHtml = theme?.favicon ? `<link href="${theme.favicon}" rel="icon" />` : `
|
|
352
|
-
<link href="https://openauth.js.org/favicon.ico" rel="icon" sizes="48x48" />
|
|
353
|
-
<link href="https://openauth.js.org/favicon.svg" media="(prefers-color-scheme: light)" rel="icon" />
|
|
354
|
-
<link href="https://openauth.js.org/favicon-dark.svg" media="(prefers-color-scheme: dark)" rel="icon" />
|
|
355
|
-
<link href="https://openauth.js.org/favicon.svg" rel="shortcut icon" type="image/svg+xml" />
|
|
356
|
-
`;
|
|
357
|
-
const logoHtml = hasCustomLogo ? `
|
|
358
|
-
<img
|
|
359
|
-
alt="Logo Light"
|
|
360
|
-
data-component="logo"
|
|
361
|
-
data-mode="light"
|
|
362
|
-
src="${getThemeValue("logo", "light") || ""}"
|
|
363
|
-
/>
|
|
364
|
-
<img
|
|
365
|
-
alt="Logo Dark"
|
|
366
|
-
data-component="logo"
|
|
367
|
-
data-mode="dark"
|
|
368
|
-
src="${getThemeValue("logo", "dark") || ""}"
|
|
369
|
-
/>
|
|
370
|
-
` : DefaultDraftAuthLogo();
|
|
371
|
-
const childrenHtml = props.children || "";
|
|
372
|
-
return `
|
|
373
|
-
<!DOCTYPE html>
|
|
374
|
-
<html lang="en" style="${themeStyles}">
|
|
375
|
-
<head>
|
|
376
|
-
<title>${theme?.title || "Draft Auth"}</title>
|
|
377
|
-
<meta charset="utf-8" />
|
|
378
|
-
<meta content="width=device-width, initial-scale=1" name="viewport" />
|
|
379
|
-
|
|
380
|
-
${faviconHtml}
|
|
381
|
-
|
|
382
|
-
<!-- Base CSS styles -->
|
|
383
|
-
<style>${css}</style>
|
|
384
|
-
|
|
385
|
-
<!-- Custom theme CSS if provided -->
|
|
386
|
-
${theme?.css ? `<style>${theme.css}</style>` : ""}
|
|
387
|
-
</head>
|
|
388
|
-
<body>
|
|
389
|
-
<div data-component="root">
|
|
390
|
-
<div data-component="center" data-size="${props.size || ""}">
|
|
391
|
-
${logoHtml}
|
|
392
|
-
${childrenHtml}
|
|
393
|
-
</div>
|
|
394
|
-
</div>
|
|
395
|
-
</body>
|
|
396
|
-
</html>
|
|
397
|
-
`;
|
|
398
|
-
};
|
|
399
|
-
/**
|
|
400
|
-
* Default Draft Auth logo component.
|
|
401
|
-
* Used when no custom logo is provided in the theme configuration.
|
|
402
|
-
*/
|
|
403
|
-
const DefaultDraftAuthLogo = () => `
|
|
404
|
-
<svg
|
|
405
|
-
aria-label="Draft Auth Logo"
|
|
406
|
-
data-component="logo-default"
|
|
407
|
-
fill="none"
|
|
408
|
-
height="51"
|
|
409
|
-
viewBox="0 0 51 51"
|
|
410
|
-
width="51"
|
|
411
|
-
xmlns="http://www.w3.org/2000/svg"
|
|
412
|
-
>
|
|
413
|
-
<title>Draft Auth Logo</title>
|
|
414
|
-
<path
|
|
415
|
-
d="M0 50.2303V0.12854H50.1017V50.2303H0ZM3.08002 11.8326H11.7041V3.20856H3.08002V11.8326ZM14.8526 11.8326H23.4766V3.20856H14.8526V11.8326ZM26.5566 11.8326H35.1807V3.20856H26.5566V11.8326ZM38.3292 11.8326H47.0217V3.20856H38.3292V11.8326ZM3.08002 23.6052H11.7041V14.9811H3.08002V23.6052ZM14.8526 23.6052H23.4766V14.9811H14.8526V23.6052ZM26.5566 23.6052H35.1807V14.9811H26.5566V23.6052ZM38.3292 23.6052H47.0217V14.9811H38.3292V23.6052ZM3.08002 35.3092H11.7041V26.6852H3.08002V35.3092ZM14.8526 35.3092H23.4766V26.6852H14.8526V35.3092ZM26.5566 35.3092H35.1807V26.6852H26.5566V35.3092ZM38.3292 35.3092H47.0217V26.6852H38.3292V35.3092ZM3.08002 47.1502H11.7041V38.3893H3.08002V47.1502ZM14.8526 47.1502H23.4766V38.3893H14.8526V47.1502ZM26.5566 47.1502H35.1807V38.3893H26.5566V47.1502ZM38.3292 47.1502H47.0217V38.3893H38.3292V47.1502Z"
|
|
416
|
-
fill="currentColor"
|
|
417
|
-
/>
|
|
418
|
-
</svg>
|
|
419
|
-
`;
|
|
420
|
-
|
|
421
|
-
//#endregion
|
|
422
|
-
export { Layout };
|
package/dist/code-DJxdFR7p.d.ts
DELETED
|
@@ -1,212 +0,0 @@
|
|
|
1
|
-
import { Provider } from "./provider-tndlqCzp.js";
|
|
2
|
-
|
|
3
|
-
//#region src/provider/code.d.ts
|
|
4
|
-
|
|
5
|
-
/**
|
|
6
|
-
* Configuration options for the PIN code authentication provider.
|
|
7
|
-
*
|
|
8
|
-
* @template Claims - Type of claims collected during authentication (email, phone, etc.)
|
|
9
|
-
*/
|
|
10
|
-
interface CodeProviderConfig<Claims extends Record<string, string> = Record<string, string>> {
|
|
11
|
-
/**
|
|
12
|
-
* The length of the generated PIN code.
|
|
13
|
-
* Common values are 4, 6, or 8 digits.
|
|
14
|
-
*
|
|
15
|
-
* @default 6
|
|
16
|
-
*
|
|
17
|
-
* @example
|
|
18
|
-
* ```ts
|
|
19
|
-
* {
|
|
20
|
-
* length: 4 // 4-digit PIN for easier entry
|
|
21
|
-
* }
|
|
22
|
-
* ```
|
|
23
|
-
*/
|
|
24
|
-
readonly length?: number;
|
|
25
|
-
/**
|
|
26
|
-
* Request handler for rendering the authentication UI.
|
|
27
|
-
* Handles both the initial claim collection and PIN code entry screens.
|
|
28
|
-
*
|
|
29
|
-
* @param req - The HTTP request object
|
|
30
|
-
* @param state - Current authentication state (start or code verification)
|
|
31
|
-
* @param form - Form data from POST requests (if any)
|
|
32
|
-
* @param error - Authentication error to display (if any)
|
|
33
|
-
* @returns Promise resolving to the authentication page response
|
|
34
|
-
*
|
|
35
|
-
* @example
|
|
36
|
-
* ```ts
|
|
37
|
-
* request: async (req, state, form, error) => {
|
|
38
|
-
* if (state.type === 'start') {
|
|
39
|
-
* return new Response(renderClaimForm(form, error))
|
|
40
|
-
* } else {
|
|
41
|
-
* return new Response(renderCodeForm(state.claims.email, error))
|
|
42
|
-
* }
|
|
43
|
-
* }
|
|
44
|
-
* ```
|
|
45
|
-
*/
|
|
46
|
-
request: (req: Request, state: CodeProviderState, form?: FormData, error?: CodeProviderError) => Promise<Response>;
|
|
47
|
-
/**
|
|
48
|
-
* Callback for sending PIN codes to users via their preferred method.
|
|
49
|
-
* Should handle delivery via email, SMS, or other communication channels.
|
|
50
|
-
*
|
|
51
|
-
* @param claims - User claims containing contact information
|
|
52
|
-
* @param code - The generated PIN code to send
|
|
53
|
-
* @returns Promise resolving to undefined on success, or error object on failure
|
|
54
|
-
*
|
|
55
|
-
* @example
|
|
56
|
-
* ```ts
|
|
57
|
-
* sendCode: async (claims, code) => {
|
|
58
|
-
* try {
|
|
59
|
-
* if (claims.email) {
|
|
60
|
-
* await emailService.send({
|
|
61
|
-
* to: claims.email,
|
|
62
|
-
* subject: 'Your verification code',
|
|
63
|
-
* text: `Your PIN code is: ${code}`
|
|
64
|
-
* })
|
|
65
|
-
* } else if (claims.phone) {
|
|
66
|
-
* await smsService.send(claims.phone, `PIN: ${code}`)
|
|
67
|
-
* } else {
|
|
68
|
-
* return {
|
|
69
|
-
* type: "invalid_claim",
|
|
70
|
-
* key: "contact",
|
|
71
|
-
* value: "No email or phone provided"
|
|
72
|
-
* }
|
|
73
|
-
* }
|
|
74
|
-
* } catch (error) {
|
|
75
|
-
* return {
|
|
76
|
-
* type: "invalid_claim",
|
|
77
|
-
* key: "delivery",
|
|
78
|
-
* value: "Failed to send code"
|
|
79
|
-
* }
|
|
80
|
-
* }
|
|
81
|
-
* }
|
|
82
|
-
* ```
|
|
83
|
-
*/
|
|
84
|
-
sendCode: (claims: Claims, code: string) => Promise<CodeProviderError | undefined>;
|
|
85
|
-
}
|
|
86
|
-
/**
|
|
87
|
-
* Authentication flow states for the PIN code provider.
|
|
88
|
-
* The provider transitions between these states during authentication.
|
|
89
|
-
*/
|
|
90
|
-
type CodeProviderState = {
|
|
91
|
-
/** Initial state: user enters their claims (email, phone, etc.) */
|
|
92
|
-
readonly type: "start";
|
|
93
|
-
} | {
|
|
94
|
-
/** Code verification state: user enters the PIN code */
|
|
95
|
-
readonly type: "code";
|
|
96
|
-
/** Whether this is a code resend request */
|
|
97
|
-
readonly resend?: boolean;
|
|
98
|
-
/** The generated PIN code for verification */
|
|
99
|
-
readonly code: string;
|
|
100
|
-
/** User claims collected during the start phase */
|
|
101
|
-
readonly claims: Record<string, string>;
|
|
102
|
-
};
|
|
103
|
-
/**
|
|
104
|
-
* Possible errors during PIN code authentication.
|
|
105
|
-
*/
|
|
106
|
-
type CodeProviderError = {
|
|
107
|
-
/** The entered PIN code is incorrect */
|
|
108
|
-
readonly type: "invalid_code";
|
|
109
|
-
} | {
|
|
110
|
-
/** A user claim is invalid or missing */
|
|
111
|
-
readonly type: "invalid_claim";
|
|
112
|
-
/** The claim field that failed validation */
|
|
113
|
-
readonly key: string;
|
|
114
|
-
/** The invalid value or error description */
|
|
115
|
-
readonly value: string;
|
|
116
|
-
};
|
|
117
|
-
/**
|
|
118
|
-
* User data returned by successful PIN code authentication.
|
|
119
|
-
*
|
|
120
|
-
* @template Claims - Type of claims collected during authentication
|
|
121
|
-
*/
|
|
122
|
-
interface CodeUserData<Claims extends Record<string, string> = Record<string, string>> {
|
|
123
|
-
/** The verified claims collected during authentication */
|
|
124
|
-
readonly claims: Claims;
|
|
125
|
-
}
|
|
126
|
-
/**
|
|
127
|
-
* Creates a PIN code authentication provider.
|
|
128
|
-
* Implements a flexible claim-based authentication flow with PIN verification.
|
|
129
|
-
*
|
|
130
|
-
* @template Claims - Type of claims to collect (email, phone, username, etc.)
|
|
131
|
-
* @param config - PIN code provider configuration
|
|
132
|
-
* @returns Provider instance implementing PIN code authentication
|
|
133
|
-
*
|
|
134
|
-
* @example
|
|
135
|
-
* ```ts
|
|
136
|
-
* // Email-based PIN authentication
|
|
137
|
-
* const emailCodeProvider = CodeProvider<{ email: string }>({
|
|
138
|
-
* length: 6,
|
|
139
|
-
* request: async (req, state, form, error) => {
|
|
140
|
-
* if (state.type === 'start') {
|
|
141
|
-
* return new Response(renderEmailForm(form?.get('email'), error))
|
|
142
|
-
* } else {
|
|
143
|
-
* return new Response(renderPinForm(state.claims.email, error, state.resend))
|
|
144
|
-
* }
|
|
145
|
-
* },
|
|
146
|
-
* sendCode: async (claims, code) => {
|
|
147
|
-
* if (!claims.email || !isValidEmail(claims.email)) {
|
|
148
|
-
* return {
|
|
149
|
-
* type: "invalid_claim",
|
|
150
|
-
* key: "email",
|
|
151
|
-
* value: "Invalid email address"
|
|
152
|
-
* }
|
|
153
|
-
* }
|
|
154
|
-
*
|
|
155
|
-
* await emailService.send(claims.email, `Your verification code: ${code}`)
|
|
156
|
-
* }
|
|
157
|
-
* })
|
|
158
|
-
*
|
|
159
|
-
* // Multi-channel PIN authentication (email or phone)
|
|
160
|
-
* const flexibleCodeProvider = CodeProvider<{ email?: string; phone?: string }>({
|
|
161
|
-
* length: 4,
|
|
162
|
-
* request: async (req, state, form, error) => {
|
|
163
|
-
* if (state.type === 'start') {
|
|
164
|
-
* return new Response(renderContactForm(form, error))
|
|
165
|
-
* } else {
|
|
166
|
-
* const contact = state.claims.email || state.claims.phone
|
|
167
|
-
* return new Response(renderPinForm(contact, error))
|
|
168
|
-
* }
|
|
169
|
-
* },
|
|
170
|
-
* sendCode: async (claims, code) => {
|
|
171
|
-
* if (claims.email) {
|
|
172
|
-
* await emailService.send(claims.email, `PIN: ${code}`)
|
|
173
|
-
* } else if (claims.phone) {
|
|
174
|
-
* await smsService.send(claims.phone, `PIN: ${code}`)
|
|
175
|
-
* } else {
|
|
176
|
-
* return {
|
|
177
|
-
* type: "invalid_claim",
|
|
178
|
-
* key: "contact",
|
|
179
|
-
* value: "Provide either email or phone number"
|
|
180
|
-
* }
|
|
181
|
-
* }
|
|
182
|
-
* }
|
|
183
|
-
* })
|
|
184
|
-
*
|
|
185
|
-
* // Usage in issuer
|
|
186
|
-
* export default issuer({
|
|
187
|
-
* providers: {
|
|
188
|
-
* email: emailCodeProvider,
|
|
189
|
-
* flexible: flexibleCodeProvider
|
|
190
|
-
* },
|
|
191
|
-
* success: async (ctx, value) => {
|
|
192
|
-
* if (value.provider === "code") {
|
|
193
|
-
* const email = value.claims.email
|
|
194
|
-
* const phone = value.claims.phone
|
|
195
|
-
*
|
|
196
|
-
* // Look up or create user based on verified claims
|
|
197
|
-
* const userId = await findOrCreateUser({ email, phone })
|
|
198
|
-
*
|
|
199
|
-
* return ctx.subject("user", { userId, email, phone })
|
|
200
|
-
* }
|
|
201
|
-
* }
|
|
202
|
-
* })
|
|
203
|
-
* ```
|
|
204
|
-
*/
|
|
205
|
-
declare const CodeProvider: <Claims extends Record<string, string> = Record<string, string>>(config: CodeProviderConfig<Claims>) => Provider<CodeUserData<Claims>>;
|
|
206
|
-
/**
|
|
207
|
-
* Type helper for CodeProvider configuration options.
|
|
208
|
-
* @internal
|
|
209
|
-
*/
|
|
210
|
-
type CodeProviderOptions = Parameters<typeof CodeProvider>[0];
|
|
211
|
-
//#endregion
|
|
212
|
-
export { CodeProvider, CodeProviderConfig, CodeProviderError, CodeProviderOptions, CodeProviderState, CodeUserData };
|