@absolutejs/auth 0.27.0-beta.10 → 0.27.0-beta.12

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.
@@ -0,0 +1,27 @@
1
+ export type AuthEventName = 'postLogin' | 'postLogout' | 'postMfa' | 'postOauthCallback' | 'postRegister' | 'preLogin' | 'preRegister';
2
+ export type AuthActionContext<UserType> = {
3
+ email?: string;
4
+ event: AuthEventName;
5
+ ip?: string;
6
+ metadata?: Record<string, unknown>;
7
+ user?: UserType;
8
+ userAgent?: string;
9
+ };
10
+ export type AuthActionResult = {
11
+ kind: 'deny';
12
+ reason: string;
13
+ } | {
14
+ kind: 'pass';
15
+ } | {
16
+ kind: 'redirect';
17
+ url: string;
18
+ };
19
+ export type AuthAction<UserType> = {
20
+ event: AuthEventName | AuthEventName[];
21
+ handler: (context: AuthActionContext<UserType>) => AuthActionResult | Promise<AuthActionResult>;
22
+ name: string;
23
+ };
24
+ export type AuthPipeline<UserType> = {
25
+ run: (event: AuthEventName, context: Omit<AuthActionContext<UserType>, 'event'>) => Promise<AuthActionResult>;
26
+ };
27
+ export declare const createActionPipeline: <UserType>(actions: AuthAction<UserType>[]) => AuthPipeline<UserType>;
@@ -0,0 +1,258 @@
1
+ export type AuthClientError = {
2
+ body: unknown;
3
+ message: string;
4
+ status: number;
5
+ };
6
+ export type AuthClientResult<T> = {
7
+ data: null;
8
+ error: AuthClientError;
9
+ } | {
10
+ data: T;
11
+ error: null;
12
+ };
13
+ export type AuthClientRoutes = {
14
+ emailVerify?: string;
15
+ emailVerifyRequest?: string;
16
+ login?: string;
17
+ magicLinkRequest?: string;
18
+ magicLinkVerify?: string;
19
+ mfaChallenge?: string;
20
+ mfaSetup?: string;
21
+ mfaVerifySetup?: string;
22
+ passkeyAuthenticateOptions?: string;
23
+ passkeyAuthenticateVerify?: string;
24
+ passkeyList?: string;
25
+ passkeyRegisterOptions?: string;
26
+ passkeyRegisterVerify?: string;
27
+ passkeyRemove?: string;
28
+ passwordReset?: string;
29
+ passwordResetRequest?: string;
30
+ register?: string;
31
+ sessions?: string;
32
+ signout?: string;
33
+ };
34
+ export type AuthClientConfig = {
35
+ baseUrl?: string;
36
+ credentials?: RequestCredentials;
37
+ fetch?: typeof fetch;
38
+ routes?: AuthClientRoutes;
39
+ };
40
+ export declare const createAuthClient: ({ baseUrl, credentials, fetch: fetchImpl, routes }?: AuthClientConfig) => {
41
+ emailVerification: {
42
+ request: (body: {
43
+ email: string;
44
+ }) => Promise<{
45
+ data: null;
46
+ error: AuthClientError;
47
+ } | {
48
+ data: {
49
+ ok: true;
50
+ };
51
+ error: null;
52
+ }>;
53
+ verify: (body: {
54
+ token: string;
55
+ }) => Promise<{
56
+ data: null;
57
+ error: AuthClientError;
58
+ } | {
59
+ data: {
60
+ ok: true;
61
+ };
62
+ error: null;
63
+ }>;
64
+ };
65
+ mfa: {
66
+ challenge: (body: {
67
+ code: string;
68
+ }) => Promise<{
69
+ data: null;
70
+ error: AuthClientError;
71
+ } | {
72
+ data: {
73
+ status: "authenticated";
74
+ };
75
+ error: null;
76
+ }>;
77
+ setup: () => Promise<{
78
+ data: null;
79
+ error: AuthClientError;
80
+ } | {
81
+ data: {
82
+ secret: string;
83
+ uri: string;
84
+ };
85
+ error: null;
86
+ }>;
87
+ verifySetup: (body: {
88
+ code: string;
89
+ }) => Promise<{
90
+ data: null;
91
+ error: AuthClientError;
92
+ } | {
93
+ data: {
94
+ backupCodes: string[];
95
+ };
96
+ error: null;
97
+ }>;
98
+ };
99
+ passkeys: {
100
+ authenticateOptions: () => Promise<{
101
+ data: null;
102
+ error: AuthClientError;
103
+ } | {
104
+ data: unknown;
105
+ error: null;
106
+ }>;
107
+ authenticateVerify: (response: unknown) => Promise<{
108
+ data: null;
109
+ error: AuthClientError;
110
+ } | {
111
+ data: {
112
+ status: "authenticated";
113
+ };
114
+ error: null;
115
+ }>;
116
+ list: () => Promise<{
117
+ data: null;
118
+ error: AuthClientError;
119
+ } | {
120
+ data: unknown[];
121
+ error: null;
122
+ }>;
123
+ registerOptions: () => Promise<{
124
+ data: null;
125
+ error: AuthClientError;
126
+ } | {
127
+ data: unknown;
128
+ error: null;
129
+ }>;
130
+ registerVerify: (response: unknown) => Promise<{
131
+ data: null;
132
+ error: AuthClientError;
133
+ } | {
134
+ data: {
135
+ ok: true;
136
+ };
137
+ error: null;
138
+ }>;
139
+ remove: (credentialId: string) => Promise<{
140
+ data: null;
141
+ error: AuthClientError;
142
+ } | {
143
+ data: {
144
+ ok: true;
145
+ };
146
+ error: null;
147
+ }>;
148
+ };
149
+ passwordless: {
150
+ requestMagicLink: (body: {
151
+ email: string;
152
+ }) => Promise<{
153
+ data: null;
154
+ error: AuthClientError;
155
+ } | {
156
+ data: {
157
+ ok: true;
158
+ };
159
+ error: null;
160
+ }>;
161
+ verifyMagicLink: (body: {
162
+ token: string;
163
+ }) => Promise<{
164
+ data: null;
165
+ error: AuthClientError;
166
+ } | {
167
+ data: {
168
+ status: "authenticated";
169
+ };
170
+ error: null;
171
+ }>;
172
+ };
173
+ passwordReset: {
174
+ confirm: (body: {
175
+ password: string;
176
+ token: string;
177
+ }) => Promise<{
178
+ data: null;
179
+ error: AuthClientError;
180
+ } | {
181
+ data: {
182
+ ok: true;
183
+ };
184
+ error: null;
185
+ }>;
186
+ request: (body: {
187
+ email: string;
188
+ }) => Promise<{
189
+ data: null;
190
+ error: AuthClientError;
191
+ } | {
192
+ data: {
193
+ ok: true;
194
+ };
195
+ error: null;
196
+ }>;
197
+ };
198
+ sessions: {
199
+ list: () => Promise<{
200
+ data: null;
201
+ error: AuthClientError;
202
+ } | {
203
+ data: unknown[];
204
+ error: null;
205
+ }>;
206
+ revoke: (sessionId: string) => Promise<{
207
+ data: null;
208
+ error: AuthClientError;
209
+ } | {
210
+ data: {
211
+ ok: true;
212
+ };
213
+ error: null;
214
+ }>;
215
+ };
216
+ signIn: {
217
+ email: (body: {
218
+ email: string;
219
+ password: string;
220
+ }) => Promise<{
221
+ data: null;
222
+ error: AuthClientError;
223
+ } | {
224
+ data: {
225
+ passwordCompromised?: boolean;
226
+ status: "authenticated" | "mfa_required";
227
+ };
228
+ error: null;
229
+ }>;
230
+ };
231
+ signUp: {
232
+ email: (body: {
233
+ email: string;
234
+ password: string;
235
+ [extra: string]: unknown;
236
+ }) => Promise<{
237
+ data: null;
238
+ error: AuthClientError;
239
+ } | {
240
+ data: {
241
+ status: "authenticated";
242
+ } | {
243
+ status: "verification_required";
244
+ };
245
+ error: null;
246
+ }>;
247
+ };
248
+ signOut: () => Promise<{
249
+ data: null;
250
+ error: AuthClientError;
251
+ } | {
252
+ data: {
253
+ ok: true;
254
+ } | null;
255
+ error: null;
256
+ }>;
257
+ };
258
+ export type AuthClient = ReturnType<typeof createAuthClient>;
@@ -0,0 +1 @@
1
+ export * from './createAuthClient';
@@ -0,0 +1,127 @@
1
+ // @bun
2
+ // src/client/createAuthClient.ts
3
+ var DEFAULT_ROUTES = {
4
+ emailVerify: "/auth/verify-email",
5
+ emailVerifyRequest: "/auth/verify-email/request",
6
+ login: "/auth/login",
7
+ magicLinkRequest: "/auth/passwordless/magic-link",
8
+ magicLinkVerify: "/auth/passwordless/magic-link/verify",
9
+ mfaChallenge: "/auth/mfa/totp/challenge",
10
+ mfaSetup: "/auth/mfa/totp/setup",
11
+ mfaVerifySetup: "/auth/mfa/totp/verify",
12
+ passkeyAuthenticateOptions: "/auth/webauthn/authenticate/options",
13
+ passkeyAuthenticateVerify: "/auth/webauthn/authenticate/verify",
14
+ passkeyList: "/auth/webauthn/credentials",
15
+ passkeyRegisterOptions: "/auth/webauthn/register/options",
16
+ passkeyRegisterVerify: "/auth/webauthn/register/verify",
17
+ passkeyRemove: "/auth/webauthn/credentials",
18
+ passwordReset: "/auth/reset-password",
19
+ passwordResetRequest: "/auth/reset-password/request",
20
+ register: "/auth/register",
21
+ sessions: "/auth/sessions",
22
+ signout: "/auth/signout"
23
+ };
24
+ var succeed = (data) => ({
25
+ data,
26
+ error: null
27
+ });
28
+ var fail = (error) => ({
29
+ data: null,
30
+ error
31
+ });
32
+ var errorFor = (response, body) => ({
33
+ body,
34
+ message: typeof body === "string" ? body : readMessage(body) ?? response.statusText,
35
+ status: response.status
36
+ });
37
+ var createAuthClient = ({
38
+ baseUrl = "",
39
+ credentials = "same-origin",
40
+ fetch: fetchImpl = fetch,
41
+ routes
42
+ } = {}) => {
43
+ const resolvedRoutes = {
44
+ ...DEFAULT_ROUTES,
45
+ ...routes
46
+ };
47
+ const request = async (path, init) => {
48
+ try {
49
+ const response = await fetchImpl(`${baseUrl}${path}`, {
50
+ credentials,
51
+ ...init
52
+ });
53
+ const text = await response.text();
54
+ const body = text === "" ? null : safeJson(text);
55
+ if (!response.ok)
56
+ return fail(errorFor(response, body));
57
+ return succeed(body);
58
+ } catch (caught) {
59
+ const message = caught instanceof Error ? caught.message : "network";
60
+ return fail({ body: null, message, status: 0 });
61
+ }
62
+ };
63
+ const post = (path, body, method = "POST") => request(path, {
64
+ body: body === undefined ? undefined : JSON.stringify(body),
65
+ headers: body === undefined ? undefined : { "content-type": "application/json" },
66
+ method
67
+ });
68
+ const get = (path) => request(path, { method: "GET" });
69
+ const del = (path) => request(path, { method: "DELETE" });
70
+ return {
71
+ emailVerification: {
72
+ request: (body) => post(resolvedRoutes.emailVerifyRequest, body),
73
+ verify: (body) => post(resolvedRoutes.emailVerify, body)
74
+ },
75
+ mfa: {
76
+ challenge: (body) => post(resolvedRoutes.mfaChallenge, body),
77
+ setup: () => post(resolvedRoutes.mfaSetup),
78
+ verifySetup: (body) => post(resolvedRoutes.mfaVerifySetup, body)
79
+ },
80
+ passkeys: {
81
+ authenticateOptions: () => post(resolvedRoutes.passkeyAuthenticateOptions),
82
+ authenticateVerify: (response) => post(resolvedRoutes.passkeyAuthenticateVerify, response),
83
+ list: () => get(resolvedRoutes.passkeyList),
84
+ registerOptions: () => post(resolvedRoutes.passkeyRegisterOptions),
85
+ registerVerify: (response) => post(resolvedRoutes.passkeyRegisterVerify, response),
86
+ remove: (credentialId) => del(`${resolvedRoutes.passkeyRemove}/${encodeURIComponent(credentialId)}`)
87
+ },
88
+ passwordless: {
89
+ requestMagicLink: (body) => post(resolvedRoutes.magicLinkRequest, body),
90
+ verifyMagicLink: (body) => post(resolvedRoutes.magicLinkVerify, body)
91
+ },
92
+ passwordReset: {
93
+ confirm: (body) => post(resolvedRoutes.passwordReset, body),
94
+ request: (body) => post(resolvedRoutes.passwordResetRequest, body)
95
+ },
96
+ sessions: {
97
+ list: () => get(resolvedRoutes.sessions),
98
+ revoke: (sessionId) => del(`${resolvedRoutes.sessions}/${encodeURIComponent(sessionId)}`)
99
+ },
100
+ signIn: {
101
+ email: (body) => post(resolvedRoutes.login, body)
102
+ },
103
+ signUp: {
104
+ email: (body) => post(resolvedRoutes.register, body)
105
+ },
106
+ signOut: () => post(resolvedRoutes.signout)
107
+ };
108
+ };
109
+ var safeJson = (text) => {
110
+ try {
111
+ return JSON.parse(text);
112
+ } catch {
113
+ return text;
114
+ }
115
+ };
116
+ var readMessage = (body) => {
117
+ if (typeof body !== "object" || body === null)
118
+ return;
119
+ const message = Reflect.get(body, "message");
120
+ return typeof message === "string" ? message : undefined;
121
+ };
122
+ export {
123
+ createAuthClient
124
+ };
125
+
126
+ //# debugId=AA9996133C04E1BA64756E2164756E21
127
+ //# sourceMappingURL=index.js.map
@@ -0,0 +1,10 @@
1
+ {
2
+ "version": 3,
3
+ "sources": ["../src/client/createAuthClient.ts"],
4
+ "sourcesContent": [
5
+ "// Framework-agnostic client SDK over the auth endpoints. Thin fetch wrappers with\n// configurable routes, a uniform `{ data, error }` return, and same-origin cookies on by\n// default — the primitive the React hooks (`./react`) and future Vue/Solid composables wrap.\n// HTMX is the special case (declarative server fragments via `./htmx`); for every other UI\n// framework the natural primitive is this client + your framework's reactivity.\n\nexport type AuthClientError = {\n\tbody: unknown;\n\tmessage: string;\n\tstatus: number;\n};\n\nexport type AuthClientResult<T> =\n\t| { data: null; error: AuthClientError }\n\t| { data: T; error: null };\n\n// Each entry is the URL the consumer's auth() mounted that flow at. Defaults match the\n// package defaults; override to match your own custom routes.\nexport type AuthClientRoutes = {\n\temailVerify?: string;\n\temailVerifyRequest?: string;\n\tlogin?: string;\n\tmagicLinkRequest?: string;\n\tmagicLinkVerify?: string;\n\tmfaChallenge?: string;\n\tmfaSetup?: string;\n\tmfaVerifySetup?: string;\n\tpasskeyAuthenticateOptions?: string;\n\tpasskeyAuthenticateVerify?: string;\n\tpasskeyList?: string;\n\tpasskeyRegisterOptions?: string;\n\tpasskeyRegisterVerify?: string;\n\tpasskeyRemove?: string;\n\tpasswordReset?: string;\n\tpasswordResetRequest?: string;\n\tregister?: string;\n\tsessions?: string;\n\tsignout?: string;\n};\n\nconst DEFAULT_ROUTES: Required<AuthClientRoutes> = {\n\temailVerify: '/auth/verify-email',\n\temailVerifyRequest: '/auth/verify-email/request',\n\tlogin: '/auth/login',\n\tmagicLinkRequest: '/auth/passwordless/magic-link',\n\tmagicLinkVerify: '/auth/passwordless/magic-link/verify',\n\tmfaChallenge: '/auth/mfa/totp/challenge',\n\tmfaSetup: '/auth/mfa/totp/setup',\n\tmfaVerifySetup: '/auth/mfa/totp/verify',\n\tpasskeyAuthenticateOptions: '/auth/webauthn/authenticate/options',\n\tpasskeyAuthenticateVerify: '/auth/webauthn/authenticate/verify',\n\tpasskeyList: '/auth/webauthn/credentials',\n\tpasskeyRegisterOptions: '/auth/webauthn/register/options',\n\tpasskeyRegisterVerify: '/auth/webauthn/register/verify',\n\tpasskeyRemove: '/auth/webauthn/credentials',\n\tpasswordReset: '/auth/reset-password',\n\tpasswordResetRequest: '/auth/reset-password/request',\n\tregister: '/auth/register',\n\tsessions: '/auth/sessions',\n\tsignout: '/auth/signout'\n};\n\nexport type AuthClientConfig = {\n\tbaseUrl?: string;\n\tcredentials?: RequestCredentials;\n\tfetch?: typeof fetch;\n\troutes?: AuthClientRoutes;\n};\n\nconst succeed = <T>(data: T): AuthClientResult<T> => ({\n\tdata,\n\terror: null\n});\n\nconst fail = (error: AuthClientError): AuthClientResult<never> => ({\n\tdata: null,\n\terror\n});\n\nconst errorFor = (response: Response, body: unknown): AuthClientError => ({\n\tbody,\n\tmessage:\n\t\ttypeof body === 'string'\n\t\t\t? body\n\t\t\t: (readMessage(body) ?? response.statusText),\n\tstatus: response.status\n});\n\nexport const createAuthClient = ({\n\tbaseUrl = '',\n\tcredentials = 'same-origin',\n\tfetch: fetchImpl = fetch,\n\troutes\n}: AuthClientConfig = {}) => {\n\tconst resolvedRoutes: Required<AuthClientRoutes> = {\n\t\t...DEFAULT_ROUTES,\n\t\t...routes\n\t};\n\n\tconst request = async <T>(path: string, init: RequestInit) => {\n\t\ttry {\n\t\t\tconst response = await fetchImpl(`${baseUrl}${path}`, {\n\t\t\t\tcredentials,\n\t\t\t\t...init\n\t\t\t});\n\t\t\tconst text = await response.text();\n\t\t\tconst body: unknown = text === '' ? null : safeJson(text);\n\t\t\tif (!response.ok) return fail(errorFor(response, body));\n\n\t\t\t// Trust the caller's expectation at the deserialization boundary.\n\t\t\t// eslint-disable-next-line @typescript-eslint/consistent-type-assertions -- HTTP response is unknown until parsed; the call site declares the expected T\n\t\t\treturn succeed(body as T);\n\t\t} catch (caught) {\n\t\t\tconst message = caught instanceof Error ? caught.message : 'network';\n\n\t\t\treturn fail({ body: null, message, status: 0 });\n\t\t}\n\t};\n\n\tconst post = <T>(path: string, body?: unknown, method = 'POST') =>\n\t\trequest<T>(path, {\n\t\t\tbody: body === undefined ? undefined : JSON.stringify(body),\n\t\t\theaders:\n\t\t\t\tbody === undefined ? undefined : { 'content-type': 'application/json' },\n\t\t\tmethod\n\t\t});\n\n\tconst get = <T>(path: string) => request<T>(path, { method: 'GET' });\n\n\tconst del = <T>(path: string) => request<T>(path, { method: 'DELETE' });\n\n\treturn {\n\t\temailVerification: {\n\t\t\trequest: (body: { email: string }) =>\n\t\t\t\tpost<{ ok: true }>(resolvedRoutes.emailVerifyRequest, body),\n\t\t\tverify: (body: { token: string }) =>\n\t\t\t\tpost<{ ok: true }>(resolvedRoutes.emailVerify, body)\n\t\t},\n\t\tmfa: {\n\t\t\tchallenge: (body: { code: string }) =>\n\t\t\t\tpost<{ status: 'authenticated' }>(resolvedRoutes.mfaChallenge, body),\n\t\t\tsetup: () =>\n\t\t\t\tpost<{ secret: string; uri: string }>(resolvedRoutes.mfaSetup),\n\t\t\tverifySetup: (body: { code: string }) =>\n\t\t\t\tpost<{ backupCodes: string[] }>(\n\t\t\t\t\tresolvedRoutes.mfaVerifySetup,\n\t\t\t\t\tbody\n\t\t\t\t)\n\t\t},\n\t\tpasskeys: {\n\t\t\tauthenticateOptions: () =>\n\t\t\t\tpost<unknown>(resolvedRoutes.passkeyAuthenticateOptions),\n\t\t\tauthenticateVerify: (response: unknown) =>\n\t\t\t\tpost<{ status: 'authenticated' }>(\n\t\t\t\t\tresolvedRoutes.passkeyAuthenticateVerify,\n\t\t\t\t\tresponse\n\t\t\t\t),\n\t\t\tlist: () => get<unknown[]>(resolvedRoutes.passkeyList),\n\t\t\tregisterOptions: () =>\n\t\t\t\tpost<unknown>(resolvedRoutes.passkeyRegisterOptions),\n\t\t\tregisterVerify: (response: unknown) =>\n\t\t\t\tpost<{ ok: true }>(resolvedRoutes.passkeyRegisterVerify, response),\n\t\t\tremove: (credentialId: string) =>\n\t\t\t\tdel<{ ok: true }>(\n\t\t\t\t\t`${resolvedRoutes.passkeyRemove}/${encodeURIComponent(credentialId)}`\n\t\t\t\t)\n\t\t},\n\t\tpasswordless: {\n\t\t\trequestMagicLink: (body: { email: string }) =>\n\t\t\t\tpost<{ ok: true }>(resolvedRoutes.magicLinkRequest, body),\n\t\t\tverifyMagicLink: (body: { token: string }) =>\n\t\t\t\tpost<{ status: 'authenticated' }>(\n\t\t\t\t\tresolvedRoutes.magicLinkVerify,\n\t\t\t\t\tbody\n\t\t\t\t)\n\t\t},\n\t\tpasswordReset: {\n\t\t\tconfirm: (body: { password: string; token: string }) =>\n\t\t\t\tpost<{ ok: true }>(resolvedRoutes.passwordReset, body),\n\t\t\trequest: (body: { email: string }) =>\n\t\t\t\tpost<{ ok: true }>(resolvedRoutes.passwordResetRequest, body)\n\t\t},\n\t\tsessions: {\n\t\t\tlist: () => get<unknown[]>(resolvedRoutes.sessions),\n\t\t\trevoke: (sessionId: string) =>\n\t\t\t\tdel<{ ok: true }>(\n\t\t\t\t\t`${resolvedRoutes.sessions}/${encodeURIComponent(sessionId)}`\n\t\t\t\t)\n\t\t},\n\t\tsignIn: {\n\t\t\temail: (body: { email: string; password: string }) =>\n\t\t\t\tpost<{\n\t\t\t\t\tpasswordCompromised?: boolean;\n\t\t\t\t\tstatus: 'authenticated' | 'mfa_required';\n\t\t\t\t}>(resolvedRoutes.login, body)\n\t\t},\n\t\tsignUp: {\n\t\t\temail: (body: {\n\t\t\t\temail: string;\n\t\t\t\tpassword: string;\n\t\t\t\t[extra: string]: unknown;\n\t\t\t}) =>\n\t\t\t\tpost<\n\t\t\t\t\t| { status: 'authenticated' }\n\t\t\t\t\t| { status: 'verification_required' }\n\t\t\t\t>(resolvedRoutes.register, body)\n\t\t},\n\t\tsignOut: () => post<{ ok: true } | null>(resolvedRoutes.signout)\n\t};\n};\n\nconst safeJson = (text: string) => {\n\ttry {\n\t\t// eslint-disable-next-line @typescript-eslint/consistent-type-assertions -- deserialization boundary\n\t\treturn JSON.parse(text) as unknown;\n\t} catch {\n\t\treturn text;\n\t}\n};\n\nconst readMessage = (body: unknown) => {\n\tif (typeof body !== 'object' || body === null) return undefined;\n\tconst message: unknown = Reflect.get(body, 'message');\n\n\treturn typeof message === 'string' ? message : undefined;\n};\n\nexport type AuthClient = ReturnType<typeof createAuthClient>;\n"
6
+ ],
7
+ "mappings": "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",
8
+ "debugId": "AA9996133C04E1BA64756E2164756E21",
9
+ "names": []
10
+ }
@@ -0,0 +1,62 @@
1
+ import type { AuthClient, AuthClientError } from './createAuthClient';
2
+ type Mutator<Args, Data> = (args: Args) => Promise<{
3
+ data: Data | null;
4
+ error: AuthClientError | null;
5
+ }>;
6
+ type MutationState<Args, Data> = {
7
+ data: Data | null;
8
+ error: AuthClientError | null;
9
+ isPending: boolean;
10
+ mutate: Mutator<Args, Data>;
11
+ reset: () => void;
12
+ };
13
+ export declare const useMagicLink: (client: AuthClient) => MutationState<{
14
+ email: string;
15
+ }, {
16
+ ok: true;
17
+ }>;
18
+ export declare const useMfaChallenge: (client: AuthClient) => MutationState<{
19
+ code: string;
20
+ }, {
21
+ status: "authenticated";
22
+ }>;
23
+ export declare const usePasswordReset: (client: AuthClient) => MutationState<{
24
+ email: string;
25
+ }, {
26
+ ok: true;
27
+ }>;
28
+ export declare const useSessions: (client: AuthClient) => {
29
+ data: unknown[] | null;
30
+ error: AuthClientError | null;
31
+ isPending: boolean;
32
+ refetch: () => Promise<void>;
33
+ revoke: (sessionId: string) => Promise<{
34
+ data: null;
35
+ error: AuthClientError;
36
+ } | {
37
+ data: {
38
+ ok: true;
39
+ };
40
+ error: null;
41
+ }>;
42
+ };
43
+ export declare const useSignIn: (client: AuthClient) => MutationState<{
44
+ email: string;
45
+ password: string;
46
+ }, {
47
+ passwordCompromised?: boolean;
48
+ status: "authenticated" | "mfa_required";
49
+ }>;
50
+ export declare const useSignOut: (client: AuthClient) => MutationState<unknown, {
51
+ ok: true;
52
+ }>;
53
+ export declare const useSignUp: (client: AuthClient) => MutationState<{
54
+ [extra: string]: unknown;
55
+ email: string;
56
+ password: string;
57
+ }, {
58
+ status: "authenticated";
59
+ } | {
60
+ status: "verification_required";
61
+ }>;
62
+ export {};
@@ -0,0 +1,75 @@
1
+ // @bun
2
+ // src/client/react.ts
3
+ import { useCallback, useEffect, useRef, useState } from "react";
4
+ var useMutation = (run) => {
5
+ const [data, setData] = useState(null);
6
+ const [error, setError] = useState(null);
7
+ const [isPending, setIsPending] = useState(false);
8
+ const mountedRef = useRef(true);
9
+ useEffect(() => () => {
10
+ mountedRef.current = false;
11
+ }, []);
12
+ const mutate = useCallback(async (args) => {
13
+ setIsPending(true);
14
+ setError(null);
15
+ const result = await run(args);
16
+ if (mountedRef.current) {
17
+ setData(result.data);
18
+ setError(result.error);
19
+ setIsPending(false);
20
+ }
21
+ return result;
22
+ }, [run]);
23
+ const reset = useCallback(() => {
24
+ setData(null);
25
+ setError(null);
26
+ setIsPending(false);
27
+ }, []);
28
+ return { data, error, isPending, mutate, reset };
29
+ };
30
+ var useMagicLink = (client) => useMutation(client.passwordless.requestMagicLink);
31
+ var useMfaChallenge = (client) => useMutation(client.mfa.challenge);
32
+ var usePasswordReset = (client) => useMutation(client.passwordReset.request);
33
+ var useSessions = (client) => {
34
+ const [data, setData] = useState(null);
35
+ const [error, setError] = useState(null);
36
+ const [isPending, setIsPending] = useState(true);
37
+ const mountedRef = useRef(true);
38
+ useEffect(() => () => {
39
+ mountedRef.current = false;
40
+ }, []);
41
+ const refetch = useCallback(async () => {
42
+ setIsPending(true);
43
+ const result = await client.sessions.list();
44
+ if (mountedRef.current) {
45
+ setData(result.data);
46
+ setError(result.error);
47
+ setIsPending(false);
48
+ }
49
+ }, [client]);
50
+ useEffect(() => {
51
+ refetch();
52
+ }, [refetch]);
53
+ const revoke = useCallback(async (sessionId) => {
54
+ const result = await client.sessions.revoke(sessionId);
55
+ if (result.error === null)
56
+ await refetch();
57
+ return result;
58
+ }, [client, refetch]);
59
+ return { data, error, isPending, refetch, revoke };
60
+ };
61
+ var useSignIn = (client) => useMutation(client.signIn.email);
62
+ var useSignOut = (client) => useMutation(client.signOut);
63
+ var useSignUp = (client) => useMutation(client.signUp.email);
64
+ export {
65
+ useSignUp,
66
+ useSignOut,
67
+ useSignIn,
68
+ useSessions,
69
+ usePasswordReset,
70
+ useMfaChallenge,
71
+ useMagicLink
72
+ };
73
+
74
+ //# debugId=6E80ACAADF4D834764756E2164756E21
75
+ //# sourceMappingURL=react.js.map
@@ -0,0 +1,10 @@
1
+ {
2
+ "version": 3,
3
+ "sources": ["../src/client/react.ts"],
4
+ "sourcesContent": [
5
+ "// Thin React hooks over `createAuthClient`. Same `{ data, error }` shape; the hook adds\n// `isPending` state and a stable mutator. Bring your own form/UI — these are primitives, not\n// components. Composables (Vue/Solid/Svelte) will follow the same pattern over the same client.\n\nimport { useCallback, useEffect, useRef, useState } from 'react';\nimport type { AuthClient, AuthClientError } from './createAuthClient';\n\ntype Mutator<Args, Data> = (\n\targs: Args\n) => Promise<{ data: Data | null; error: AuthClientError | null }>;\n\ntype MutationState<Args, Data> = {\n\tdata: Data | null;\n\terror: AuthClientError | null;\n\tisPending: boolean;\n\tmutate: Mutator<Args, Data>;\n\treset: () => void;\n};\n\n// Generic mutation hook. The other hooks are 1–2 line specializations of this — kept private\n// here so consumers see the cohesive named API and don't depend on this shape.\nconst useMutation = <Args, Data>(\n\trun: Mutator<Args, Data>\n): MutationState<Args, Data> => {\n\tconst [data, setData] = useState<Data | null>(null);\n\tconst [error, setError] = useState<AuthClientError | null>(null);\n\tconst [isPending, setIsPending] = useState(false);\n\tconst mountedRef = useRef(true);\n\tuseEffect(\n\t\t() => () => {\n\t\t\tmountedRef.current = false;\n\t\t},\n\t\t[]\n\t);\n\n\tconst mutate: Mutator<Args, Data> = useCallback(\n\t\tasync (args) => {\n\t\t\tsetIsPending(true);\n\t\t\tsetError(null);\n\t\t\tconst result = await run(args);\n\t\t\tif (mountedRef.current) {\n\t\t\t\tsetData(result.data);\n\t\t\t\tsetError(result.error);\n\t\t\t\tsetIsPending(false);\n\t\t\t}\n\n\t\t\treturn result;\n\t\t},\n\t\t[run]\n\t);\n\n\tconst reset = useCallback(() => {\n\t\tsetData(null);\n\t\tsetError(null);\n\t\tsetIsPending(false);\n\t}, []);\n\n\treturn { data, error, isPending, mutate, reset };\n};\n\nexport const useMagicLink = (client: AuthClient) =>\n\tuseMutation(client.passwordless.requestMagicLink);\n\nexport const useMfaChallenge = (client: AuthClient) =>\n\tuseMutation(client.mfa.challenge);\n\nexport const usePasswordReset = (client: AuthClient) =>\n\tuseMutation(client.passwordReset.request);\n\n// Query hook for the user's active sessions; refetch() reruns it. The shape matches the\n// mutation hooks closely (isPending/error/data) so the consumer can render one way.\nexport const useSessions = (client: AuthClient) => {\n\tconst [data, setData] = useState<unknown[] | null>(null);\n\tconst [error, setError] = useState<AuthClientError | null>(null);\n\tconst [isPending, setIsPending] = useState(true);\n\tconst mountedRef = useRef(true);\n\tuseEffect(\n\t\t() => () => {\n\t\t\tmountedRef.current = false;\n\t\t},\n\t\t[]\n\t);\n\n\tconst refetch = useCallback(async () => {\n\t\tsetIsPending(true);\n\t\tconst result = await client.sessions.list();\n\t\tif (mountedRef.current) {\n\t\t\tsetData(result.data);\n\t\t\tsetError(result.error);\n\t\t\tsetIsPending(false);\n\t\t}\n\t}, [client]);\n\n\tuseEffect(() => {\n\t\tvoid refetch();\n\t}, [refetch]);\n\n\tconst revoke = useCallback(\n\t\tasync (sessionId: string) => {\n\t\t\tconst result = await client.sessions.revoke(sessionId);\n\t\t\tif (result.error === null) await refetch();\n\n\t\t\treturn result;\n\t\t},\n\t\t[client, refetch]\n\t);\n\n\treturn { data, error, isPending, refetch, revoke };\n};\n\nexport const useSignIn = (client: AuthClient) =>\n\tuseMutation(client.signIn.email);\n\nexport const useSignOut = (client: AuthClient) => useMutation(client.signOut);\n\nexport const useSignUp = (client: AuthClient) =>\n\tuseMutation(client.signUp.email);\n"
6
+ ],
7
+ "mappings": ";;AAIA;AAiBA,IAAM,cAAc,CACnB,QAC+B;AAAA,EAC/B,OAAO,MAAM,WAAW,SAAsB,IAAI;AAAA,EAClD,OAAO,OAAO,YAAY,SAAiC,IAAI;AAAA,EAC/D,OAAO,WAAW,gBAAgB,SAAS,KAAK;AAAA,EAChD,MAAM,aAAa,OAAO,IAAI;AAAA,EAC9B,UACC,MAAM,MAAM;AAAA,IACX,WAAW,UAAU;AAAA,KAEtB,CAAC,CACF;AAAA,EAEA,MAAM,SAA8B,YACnC,OAAO,SAAS;AAAA,IACf,aAAa,IAAI;AAAA,IACjB,SAAS,IAAI;AAAA,IACb,MAAM,SAAS,MAAM,IAAI,IAAI;AAAA,IAC7B,IAAI,WAAW,SAAS;AAAA,MACvB,QAAQ,OAAO,IAAI;AAAA,MACnB,SAAS,OAAO,KAAK;AAAA,MACrB,aAAa,KAAK;AAAA,IACnB;AAAA,IAEA,OAAO;AAAA,KAER,CAAC,GAAG,CACL;AAAA,EAEA,MAAM,QAAQ,YAAY,MAAM;AAAA,IAC/B,QAAQ,IAAI;AAAA,IACZ,SAAS,IAAI;AAAA,IACb,aAAa,KAAK;AAAA,KAChB,CAAC,CAAC;AAAA,EAEL,OAAO,EAAE,MAAM,OAAO,WAAW,QAAQ,MAAM;AAAA;AAGzC,IAAM,eAAe,CAAC,WAC5B,YAAY,OAAO,aAAa,gBAAgB;AAE1C,IAAM,kBAAkB,CAAC,WAC/B,YAAY,OAAO,IAAI,SAAS;AAE1B,IAAM,mBAAmB,CAAC,WAChC,YAAY,OAAO,cAAc,OAAO;AAIlC,IAAM,cAAc,CAAC,WAAuB;AAAA,EAClD,OAAO,MAAM,WAAW,SAA2B,IAAI;AAAA,EACvD,OAAO,OAAO,YAAY,SAAiC,IAAI;AAAA,EAC/D,OAAO,WAAW,gBAAgB,SAAS,IAAI;AAAA,EAC/C,MAAM,aAAa,OAAO,IAAI;AAAA,EAC9B,UACC,MAAM,MAAM;AAAA,IACX,WAAW,UAAU;AAAA,KAEtB,CAAC,CACF;AAAA,EAEA,MAAM,UAAU,YAAY,YAAY;AAAA,IACvC,aAAa,IAAI;AAAA,IACjB,MAAM,SAAS,MAAM,OAAO,SAAS,KAAK;AAAA,IAC1C,IAAI,WAAW,SAAS;AAAA,MACvB,QAAQ,OAAO,IAAI;AAAA,MACnB,SAAS,OAAO,KAAK;AAAA,MACrB,aAAa,KAAK;AAAA,IACnB;AAAA,KACE,CAAC,MAAM,CAAC;AAAA,EAEX,UAAU,MAAM;AAAA,IACV,QAAQ;AAAA,KACX,CAAC,OAAO,CAAC;AAAA,EAEZ,MAAM,SAAS,YACd,OAAO,cAAsB;AAAA,IAC5B,MAAM,SAAS,MAAM,OAAO,SAAS,OAAO,SAAS;AAAA,IACrD,IAAI,OAAO,UAAU;AAAA,MAAM,MAAM,QAAQ;AAAA,IAEzC,OAAO;AAAA,KAER,CAAC,QAAQ,OAAO,CACjB;AAAA,EAEA,OAAO,EAAE,MAAM,OAAO,WAAW,SAAS,OAAO;AAAA;AAG3C,IAAM,YAAY,CAAC,WACzB,YAAY,OAAO,OAAO,KAAK;AAEzB,IAAM,aAAa,CAAC,WAAuB,YAAY,OAAO,OAAO;AAErE,IAAM,YAAY,CAAC,WACzB,YAAY,OAAO,OAAO,KAAK;",
8
+ "debugId": "6E80ACAADF4D834764756E2164756E21",
9
+ "names": []
10
+ }
package/dist/index.d.ts CHANGED
@@ -13450,9 +13450,9 @@ export declare const auth: <UserType>({ providersConfiguration, authorizeRoute,
13450
13450
  body: unknown;
13451
13451
  params: {};
13452
13452
  query: {
13453
- nonce?: string | undefined;
13454
13453
  client_id?: string | undefined;
13455
13454
  scope?: string | undefined;
13455
+ nonce?: string | undefined;
13456
13456
  code_challenge?: string | undefined;
13457
13457
  code_challenge_method?: string | undefined;
13458
13458
  redirect_uri?: string | undefined;
@@ -13478,10 +13478,10 @@ export declare const auth: <UserType>({ providersConfiguration, authorizeRoute,
13478
13478
  [x: string]: {
13479
13479
  post: {
13480
13480
  body: {
13481
- audience?: string | undefined;
13482
- resource?: string | undefined;
13483
13481
  client_id?: string | undefined;
13484
13482
  scope?: string | undefined;
13483
+ audience?: string | undefined;
13484
+ resource?: string | undefined;
13485
13485
  refresh_token?: string | undefined;
13486
13486
  client_secret?: string | undefined;
13487
13487
  grant_type?: string | undefined;
@@ -14635,8 +14635,13 @@ export declare const auth: <UserType>({ providersConfiguration, authorizeRoute,
14635
14635
  standaloneSchema: {};
14636
14636
  response: {};
14637
14637
  }>>;
14638
+ export * from './actions';
14638
14639
  export * from './types';
14639
14640
  export * from './typebox';
14641
+ export * from './vault/config';
14642
+ export * from './vault/types';
14643
+ export { createInMemoryVaultStore } from './vault/inMemoryVaultStore';
14644
+ export { createNeonVaultStore, createPostgresVaultStore, vaultEntriesTable } from './vault/postgresVaultStore';
14640
14645
  export type { AuthSessionStore } from './session/types';
14641
14646
  export { isAuthIntent, isUserSessionId, isValidUser } from './typeGuards';
14642
14647
  export { AuthIdentityConflictError } from './errors';