@fayz-ai/auth 0.1.6

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,9 @@
1
+ import type { AuthAdapter } from '@fayz-ai/core';
2
+ export interface MockUser {
3
+ id: string;
4
+ email: string;
5
+ fullName: string;
6
+ role?: string;
7
+ }
8
+ export declare function createMockAuthAdapter(mockUser?: MockUser): AuthAdapter;
9
+ //# sourceMappingURL=mock.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"mock.d.ts","sourceRoot":"","sources":["../../src/adapters/mock.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,WAAW,EAAyB,MAAM,eAAe,CAAA;AAEvE,MAAM,WAAW,QAAQ;IACvB,EAAE,EAAE,MAAM,CAAA;IACV,KAAK,EAAE,MAAM,CAAA;IACb,QAAQ,EAAE,MAAM,CAAA;IAChB,IAAI,CAAC,EAAE,MAAM,CAAA;CACd;AAoDD,wBAAgB,qBAAqB,CAAC,QAAQ,GAAE,QAA4B,GAAG,WAAW,CAoEzF"}
@@ -0,0 +1,9 @@
1
+ import { type SupabaseClient } from '@supabase/supabase-js';
2
+ import type { AuthAdapter } from '@fayz-ai/core';
3
+ export interface SupabaseAuthConfig {
4
+ supabaseUrl: string;
5
+ supabaseAnonKey: string;
6
+ supabaseClient?: SupabaseClient;
7
+ }
8
+ export declare function createSupabaseAuthAdapter(config: SupabaseAuthConfig): AuthAdapter;
9
+ //# sourceMappingURL=supabase.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"supabase.d.ts","sourceRoot":"","sources":["../../src/adapters/supabase.ts"],"names":[],"mappings":"AAAA,OAAO,EAAgB,KAAK,cAAc,EAAE,MAAM,uBAAuB,CAAA;AACzE,OAAO,KAAK,EAAE,WAAW,EAAuC,MAAM,eAAe,CAAA;AAErF,MAAM,WAAW,kBAAkB;IACjC,WAAW,EAAE,MAAM,CAAA;IACnB,eAAe,EAAE,MAAM,CAAA;IACvB,cAAc,CAAC,EAAE,cAAc,CAAA;CAChC;AAuCD,wBAAgB,yBAAyB,CAAC,MAAM,EAAE,kBAAkB,GAAG,WAAW,CA8EjF"}
@@ -0,0 +1,20 @@
1
+ import React from 'react';
2
+ import type { AuthAdapter, AuthProvider as OAuthProvider, AuthSession } from '@fayz-ai/core';
3
+ export interface AuthProviderProps {
4
+ adapter: AuthAdapter;
5
+ children: React.ReactNode;
6
+ }
7
+ export declare function AuthProvider({ adapter, children }: AuthProviderProps): React.JSX.Element;
8
+ export declare function useAuth(): {
9
+ user: import("@fayz-ai/core").AuthUser | null;
10
+ session: AuthSession | null;
11
+ isLoading: boolean;
12
+ isAuthenticated: boolean;
13
+ error: Error | null;
14
+ signIn: (email: string, password: string) => Promise<AuthSession>;
15
+ signUp: (email: string, password: string, fullName: string) => Promise<AuthSession>;
16
+ signOut: () => Promise<void>;
17
+ signInWithOAuth: (provider: OAuthProvider) => Promise<void>;
18
+ resetPassword: (email: string) => Promise<void>;
19
+ };
20
+ //# sourceMappingURL=context.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"context.d.ts","sourceRoot":"","sources":["../src/context.tsx"],"names":[],"mappings":"AAAA,OAAO,KAAuD,MAAM,OAAO,CAAA;AAC3E,OAAO,KAAK,EAAE,WAAW,EAAE,YAAY,IAAI,aAAa,EAAE,WAAW,EAAE,MAAM,eAAe,CAAA;AAqB5F,MAAM,WAAW,iBAAiB;IAChC,OAAO,EAAE,WAAW,CAAA;IACpB,QAAQ,EAAE,KAAK,CAAC,SAAS,CAAA;CAC1B;AAED,wBAAgB,YAAY,CAAC,EAAE,OAAO,EAAE,QAAQ,EAAE,EAAE,iBAAiB,qBAwGpE;AAMD,wBAAgB,OAAO;;;;;;oBAhIL,MAAM,YAAY,MAAM,KAAK,OAAO,CAAC,WAAW,CAAC;oBACjD,MAAM,YAAY,MAAM,YAAY,MAAM,KAAK,OAAO,CAAC,WAAW,CAAC;mBACpE,OAAO,CAAC,IAAI,CAAC;gCACA,aAAa,KAAK,OAAO,CAAC,IAAI,CAAC;2BACpC,MAAM,KAAK,OAAO,CAAC,IAAI,CAAC;EAgJhD"}
package/dist/index.cjs ADDED
@@ -0,0 +1,319 @@
1
+ 'use strict';
2
+
3
+ var supabaseJs = require('@supabase/supabase-js');
4
+ var zustand = require('zustand');
5
+ var react = require('react');
6
+ var jsxRuntime = require('react/jsx-runtime');
7
+
8
+ // src/adapters/supabase.ts
9
+ function mapSupabaseUser(supabaseUser) {
10
+ return {
11
+ id: supabaseUser.id,
12
+ email: supabaseUser.email ?? "",
13
+ fullName: supabaseUser.user_metadata?.["full_name"] ?? supabaseUser.user_metadata?.["name"] ?? "",
14
+ avatarUrl: supabaseUser.user_metadata?.["avatar_url"]
15
+ };
16
+ }
17
+ function mapSupabaseSession(session) {
18
+ return {
19
+ accessToken: session.access_token,
20
+ refreshToken: session.refresh_token,
21
+ expiresAt: session.expires_at ?? Math.floor(Date.now() / 1e3) + (session.expires_in ?? 3600),
22
+ user: mapSupabaseUser(session.user)
23
+ };
24
+ }
25
+ function createSupabaseAuthAdapter(config) {
26
+ const supabase = config.supabaseClient ?? supabaseJs.createClient(config.supabaseUrl, config.supabaseAnonKey);
27
+ return {
28
+ async getSession() {
29
+ const {
30
+ data: { session }
31
+ } = await supabase.auth.getSession();
32
+ if (!session) return null;
33
+ const mapped = mapSupabaseSession(session);
34
+ return { user: mapped.user, session: mapped };
35
+ },
36
+ onAuthStateChange(cb) {
37
+ const {
38
+ data: { subscription }
39
+ } = supabase.auth.onAuthStateChange((_event, session) => {
40
+ cb(session ? mapSupabaseUser(session.user) : null);
41
+ });
42
+ return () => subscription.unsubscribe();
43
+ },
44
+ async signIn(email, password) {
45
+ const { data, error } = await supabase.auth.signInWithPassword({ email, password });
46
+ if (error) throw error;
47
+ return mapSupabaseSession(data.session);
48
+ },
49
+ async signUp(email, password, fullName) {
50
+ const { data, error } = await supabase.auth.signUp({
51
+ email,
52
+ password,
53
+ options: { data: { full_name: fullName } }
54
+ });
55
+ if (error) throw error;
56
+ if (!data.session) {
57
+ if (!data.user) throw new Error("Signup failed: no user returned");
58
+ return {
59
+ accessToken: "",
60
+ refreshToken: "",
61
+ expiresAt: 0,
62
+ user: mapSupabaseUser(data.user)
63
+ };
64
+ }
65
+ return mapSupabaseSession(data.session);
66
+ },
67
+ async signOut() {
68
+ const { error } = await supabase.auth.signOut();
69
+ if (error) throw error;
70
+ },
71
+ async signInWithOAuth(provider) {
72
+ const { error } = await supabase.auth.signInWithOAuth({
73
+ provider,
74
+ options: {
75
+ redirectTo: typeof window !== "undefined" ? `${window.location.origin}/auth/callback` : void 0
76
+ }
77
+ });
78
+ if (error) throw error;
79
+ },
80
+ async resetPassword(email) {
81
+ const { error } = await supabase.auth.resetPasswordForEmail(email, {
82
+ redirectTo: typeof window !== "undefined" ? `${window.location.origin}/auth/reset-password` : void 0
83
+ });
84
+ if (error) throw error;
85
+ }
86
+ };
87
+ }
88
+
89
+ // src/adapters/mock.ts
90
+ var DEFAULT_MOCK_USER = {
91
+ id: "mock-user-id",
92
+ email: "demo@fayz.dev",
93
+ fullName: "Demo User",
94
+ role: "admin"
95
+ };
96
+ var STORAGE_KEY = "fayz:mock-auth";
97
+ function toAuthUser(mockUser) {
98
+ return {
99
+ id: mockUser.id,
100
+ email: mockUser.email,
101
+ fullName: mockUser.fullName
102
+ };
103
+ }
104
+ function createMockSession(user) {
105
+ return {
106
+ accessToken: `mock-token-${user.id}`,
107
+ refreshToken: `mock-refresh-${user.id}`,
108
+ expiresAt: Math.floor(Date.now() / 1e3) + 3600,
109
+ user
110
+ };
111
+ }
112
+ function getStored() {
113
+ try {
114
+ if (typeof localStorage === "undefined") return null;
115
+ const raw = localStorage.getItem(STORAGE_KEY);
116
+ if (!raw) return null;
117
+ return JSON.parse(raw);
118
+ } catch {
119
+ return null;
120
+ }
121
+ }
122
+ function setStored(data) {
123
+ try {
124
+ if (typeof localStorage === "undefined") return;
125
+ if (data) {
126
+ localStorage.setItem(STORAGE_KEY, JSON.stringify(data));
127
+ } else {
128
+ localStorage.removeItem(STORAGE_KEY);
129
+ }
130
+ } catch {
131
+ }
132
+ }
133
+ function createMockAuthAdapter(mockUser = DEFAULT_MOCK_USER) {
134
+ const listeners = /* @__PURE__ */ new Set();
135
+ function notifyListeners(user) {
136
+ for (const cb of listeners) cb(user);
137
+ }
138
+ return {
139
+ async getSession() {
140
+ return getStored();
141
+ },
142
+ onAuthStateChange(cb) {
143
+ listeners.add(cb);
144
+ return () => {
145
+ listeners.delete(cb);
146
+ };
147
+ },
148
+ async signIn(email, _password) {
149
+ const stored = getStored();
150
+ const user = stored && stored.user.email === email ? stored.user : {
151
+ id: email === mockUser.email ? mockUser.id : `mock-${email}`,
152
+ email,
153
+ fullName: email === mockUser.email ? mockUser.fullName : email.split("@")[0] ?? "Cliente"
154
+ };
155
+ const session = createMockSession(user);
156
+ setStored({ user, session });
157
+ notifyListeners(user);
158
+ return session;
159
+ },
160
+ async signUp(email, _password, fullName) {
161
+ const user = {
162
+ id: `mock-${email}`,
163
+ email,
164
+ fullName: fullName || (email.split("@")[0] ?? "Cliente")
165
+ };
166
+ const session = createMockSession(user);
167
+ setStored({ user, session });
168
+ notifyListeners(user);
169
+ return session;
170
+ },
171
+ async signOut() {
172
+ setStored(null);
173
+ notifyListeners(null);
174
+ },
175
+ async signInWithOAuth(_provider) {
176
+ const user = toAuthUser(mockUser);
177
+ const session = createMockSession(user);
178
+ setStored({ user, session });
179
+ notifyListeners(user);
180
+ },
181
+ async resetPassword(_email) {
182
+ }
183
+ };
184
+ }
185
+ var initialState = {
186
+ user: null,
187
+ session: null,
188
+ isLoading: true,
189
+ isAuthenticated: false,
190
+ error: null
191
+ };
192
+ var useAuthStore = zustand.create((set) => ({
193
+ ...initialState,
194
+ setUser: (user) => set({ user, isAuthenticated: user !== null }),
195
+ setSession: (session) => set({
196
+ session,
197
+ user: session?.user ?? null,
198
+ isAuthenticated: session !== null
199
+ }),
200
+ setLoading: (isLoading) => set({ isLoading }),
201
+ setError: (error) => set({ error }),
202
+ reset: () => set(initialState)
203
+ }));
204
+ var AuthContext = react.createContext(null);
205
+ function AuthProvider({ adapter, children }) {
206
+ const { setSession, setLoading, setError, reset } = useAuthStore();
207
+ const adapterRef = react.useRef(adapter);
208
+ adapterRef.current = adapter;
209
+ react.useEffect(() => {
210
+ let unsubscribe;
211
+ async function init() {
212
+ try {
213
+ setLoading(true);
214
+ const result = await adapterRef.current.getSession();
215
+ setSession(result?.session ?? null);
216
+ } catch (err) {
217
+ setError(err instanceof Error ? err : new Error(String(err)));
218
+ } finally {
219
+ setLoading(false);
220
+ }
221
+ unsubscribe = adapterRef.current.onAuthStateChange((user) => {
222
+ if (!user) {
223
+ reset();
224
+ setLoading(false);
225
+ }
226
+ });
227
+ }
228
+ void init();
229
+ return () => {
230
+ unsubscribe?.();
231
+ };
232
+ }, []);
233
+ const value = {
234
+ async signIn(email, password) {
235
+ setError(null);
236
+ try {
237
+ const session = await adapterRef.current.signIn(email, password);
238
+ setSession(session);
239
+ return session;
240
+ } catch (err) {
241
+ const error = err instanceof Error ? err : new Error(String(err));
242
+ setError(error);
243
+ throw error;
244
+ }
245
+ },
246
+ async signUp(email, password, fullName) {
247
+ setError(null);
248
+ try {
249
+ const session = await adapterRef.current.signUp(email, password, fullName);
250
+ setSession(session);
251
+ return session;
252
+ } catch (err) {
253
+ const error = err instanceof Error ? err : new Error(String(err));
254
+ setError(error);
255
+ throw error;
256
+ }
257
+ },
258
+ async signOut() {
259
+ setError(null);
260
+ try {
261
+ await adapterRef.current.signOut();
262
+ reset();
263
+ setLoading(false);
264
+ } catch (err) {
265
+ const error = err instanceof Error ? err : new Error(String(err));
266
+ setError(error);
267
+ throw error;
268
+ }
269
+ },
270
+ async signInWithOAuth(provider) {
271
+ setError(null);
272
+ try {
273
+ await adapterRef.current.signInWithOAuth(provider);
274
+ } catch (err) {
275
+ const error = err instanceof Error ? err : new Error(String(err));
276
+ setError(error);
277
+ throw error;
278
+ }
279
+ },
280
+ async resetPassword(email) {
281
+ setError(null);
282
+ try {
283
+ await adapterRef.current.resetPassword(email);
284
+ } catch (err) {
285
+ const error = err instanceof Error ? err : new Error(String(err));
286
+ setError(error);
287
+ throw error;
288
+ }
289
+ }
290
+ };
291
+ return /* @__PURE__ */ jsxRuntime.jsx(AuthContext.Provider, { value, children });
292
+ }
293
+ function useAuth() {
294
+ const ctx = react.useContext(AuthContext);
295
+ if (!ctx) {
296
+ throw new Error("useAuth must be used inside <AuthProvider>");
297
+ }
298
+ const { user, session, isLoading, isAuthenticated, error } = useAuthStore();
299
+ return {
300
+ user,
301
+ session,
302
+ isLoading,
303
+ isAuthenticated,
304
+ error,
305
+ signIn: ctx.signIn,
306
+ signUp: ctx.signUp,
307
+ signOut: ctx.signOut,
308
+ signInWithOAuth: ctx.signInWithOAuth,
309
+ resetPassword: ctx.resetPassword
310
+ };
311
+ }
312
+
313
+ exports.AuthProvider = AuthProvider;
314
+ exports.createMockAuthAdapter = createMockAuthAdapter;
315
+ exports.createSupabaseAuthAdapter = createSupabaseAuthAdapter;
316
+ exports.useAuth = useAuth;
317
+ exports.useAuthStore = useAuthStore;
318
+ //# sourceMappingURL=index.cjs.map
319
+ //# sourceMappingURL=index.cjs.map
@@ -0,0 +1 @@
1
+ {"version":3,"sources":["../src/adapters/supabase.ts","../src/adapters/mock.ts","../src/store.ts","../src/context.tsx"],"names":["createClient","create","createContext","useRef","useEffect","jsx","useContext"],"mappings":"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","file":"index.cjs","sourcesContent":["import { createClient, type SupabaseClient } from '@supabase/supabase-js'\nimport type { AuthAdapter, AuthUser, AuthSession, AuthProvider } from '@fayz-ai/core'\n\nexport interface SupabaseAuthConfig {\n supabaseUrl: string\n supabaseAnonKey: string\n supabaseClient?: SupabaseClient\n}\n\nfunction mapSupabaseUser(supabaseUser: {\n id: string\n email?: string | null\n created_at?: string\n updated_at?: string | null\n email_confirmed_at?: string | null\n user_metadata?: Record<string, unknown>\n app_metadata?: { providers?: string[]; provider?: string }\n}): AuthUser {\n return {\n id: supabaseUser.id,\n email: supabaseUser.email ?? '',\n fullName:\n (supabaseUser.user_metadata?.['full_name'] as string | undefined) ??\n (supabaseUser.user_metadata?.['name'] as string | undefined) ??\n '',\n avatarUrl: supabaseUser.user_metadata?.['avatar_url'] as string | undefined,\n }\n}\n\nfunction mapSupabaseSession(session: {\n access_token: string\n refresh_token?: string\n expires_at?: number\n expires_in?: number\n user: Parameters<typeof mapSupabaseUser>[0]\n}): AuthSession {\n return {\n accessToken: session.access_token,\n refreshToken: session.refresh_token,\n expiresAt:\n session.expires_at ??\n Math.floor(Date.now() / 1000) + (session.expires_in ?? 3600),\n user: mapSupabaseUser(session.user),\n }\n}\n\nexport function createSupabaseAuthAdapter(config: SupabaseAuthConfig): AuthAdapter {\n const supabase = config.supabaseClient ?? createClient(config.supabaseUrl, config.supabaseAnonKey)\n\n return {\n async getSession() {\n const {\n data: { session },\n } = await supabase.auth.getSession()\n if (!session) return null\n const mapped = mapSupabaseSession(session)\n return { user: mapped.user, session: mapped }\n },\n\n onAuthStateChange(cb) {\n const {\n data: { subscription },\n } = supabase.auth.onAuthStateChange((_event, session) => {\n cb(session ? mapSupabaseUser(session.user) : null)\n })\n return () => subscription.unsubscribe()\n },\n\n async signIn(email, password) {\n const { data, error } = await supabase.auth.signInWithPassword({ email, password })\n if (error) throw error\n return mapSupabaseSession(data.session)\n },\n\n async signUp(email, password, fullName) {\n const { data, error } = await supabase.auth.signUp({\n email,\n password,\n options: { data: { full_name: fullName } },\n })\n if (error) throw error\n\n // When email confirmation is required, session is null\n if (!data.session) {\n if (!data.user) throw new Error('Signup failed: no user returned')\n return {\n accessToken: '',\n refreshToken: '',\n expiresAt: 0,\n user: mapSupabaseUser(data.user),\n }\n }\n\n return mapSupabaseSession(data.session)\n },\n\n async signOut() {\n const { error } = await supabase.auth.signOut()\n if (error) throw error\n },\n\n async signInWithOAuth(provider: AuthProvider) {\n const { error } = await supabase.auth.signInWithOAuth({\n provider: provider as 'google' | 'github' | 'apple',\n options: {\n redirectTo:\n typeof window !== 'undefined'\n ? `${window.location.origin}/auth/callback`\n : undefined,\n },\n })\n if (error) throw error\n },\n\n async resetPassword(email) {\n const { error } = await supabase.auth.resetPasswordForEmail(email, {\n redirectTo:\n typeof window !== 'undefined'\n ? `${window.location.origin}/auth/reset-password`\n : undefined,\n })\n if (error) throw error\n },\n }\n}\n","import type { AuthAdapter, AuthUser, AuthSession } from '@fayz-ai/core'\n\nexport interface MockUser {\n id: string\n email: string\n fullName: string\n role?: string\n}\n\nconst DEFAULT_MOCK_USER: MockUser = {\n id: 'mock-user-id',\n email: 'demo@fayz.dev',\n fullName: 'Demo User',\n role: 'admin',\n}\n\nconst STORAGE_KEY = 'fayz:mock-auth'\n\nfunction toAuthUser(mockUser: MockUser): AuthUser {\n return {\n id: mockUser.id,\n email: mockUser.email,\n fullName: mockUser.fullName,\n }\n}\n\nfunction createMockSession(user: AuthUser): AuthSession {\n return {\n accessToken: `mock-token-${user.id}`,\n refreshToken: `mock-refresh-${user.id}`,\n expiresAt: Math.floor(Date.now() / 1000) + 3600,\n user,\n }\n}\n\nfunction getStored(): { user: AuthUser; session: AuthSession } | null {\n try {\n if (typeof localStorage === 'undefined') return null\n const raw = localStorage.getItem(STORAGE_KEY)\n if (!raw) return null\n return JSON.parse(raw) as { user: AuthUser; session: AuthSession }\n } catch {\n return null\n }\n}\n\nfunction setStored(data: { user: AuthUser; session: AuthSession } | null): void {\n try {\n if (typeof localStorage === 'undefined') return\n if (data) {\n localStorage.setItem(STORAGE_KEY, JSON.stringify(data))\n } else {\n localStorage.removeItem(STORAGE_KEY)\n }\n } catch {\n // SSR or storage unavailable — silently skip\n }\n}\n\nexport function createMockAuthAdapter(mockUser: MockUser = DEFAULT_MOCK_USER): AuthAdapter {\n const listeners = new Set<(user: AuthUser | null) => void>()\n\n function notifyListeners(user: AuthUser | null): void {\n for (const cb of listeners) cb(user)\n }\n\n return {\n async getSession() {\n return getStored()\n },\n\n onAuthStateChange(cb) {\n listeners.add(cb)\n return () => {\n listeners.delete(cb)\n }\n },\n\n async signIn(email, _password) {\n // Mock accepts any credentials, but the identity FOLLOWS the email —\n // storefront customers and saas users keep their own purchase/session\n // history instead of all becoming the configured demo user.\n const stored = getStored()\n const user: AuthUser =\n stored && stored.user.email === email\n ? stored.user\n : {\n id: email === mockUser.email ? mockUser.id : `mock-${email}`,\n email,\n fullName: email === mockUser.email ? mockUser.fullName : (email.split('@')[0] ?? 'Cliente'),\n }\n const session = createMockSession(user)\n setStored({ user, session })\n notifyListeners(user)\n return session\n },\n\n async signUp(email, _password, fullName) {\n // Mock signup creates a user from the provided details\n const user: AuthUser = {\n id: `mock-${email}`,\n email,\n fullName: fullName || (email.split('@')[0] ?? 'Cliente'),\n }\n const session = createMockSession(user)\n setStored({ user, session })\n notifyListeners(user)\n return session\n },\n\n async signOut() {\n setStored(null)\n notifyListeners(null)\n },\n\n async signInWithOAuth(_provider) {\n // Mock OAuth signs in as the configured user\n const user = toAuthUser(mockUser)\n const session = createMockSession(user)\n setStored({ user, session })\n notifyListeners(user)\n },\n\n async resetPassword(_email) {\n // No-op in mock\n },\n }\n}\n","import { create } from 'zustand'\nimport type { AuthUser, AuthSession } from '@fayz-ai/core'\n\nexport interface AuthState {\n user: AuthUser | null\n session: AuthSession | null\n isLoading: boolean\n isAuthenticated: boolean\n error: Error | null\n}\n\nexport interface AuthStore extends AuthState {\n setUser: (user: AuthUser | null) => void\n setSession: (session: AuthSession | null) => void\n setLoading: (isLoading: boolean) => void\n setError: (error: Error | null) => void\n reset: () => void\n}\n\nconst initialState: AuthState = {\n user: null,\n session: null,\n isLoading: true,\n isAuthenticated: false,\n error: null,\n}\n\nexport const useAuthStore = create<AuthStore>((set) => ({\n ...initialState,\n\n setUser: (user) =>\n set({ user, isAuthenticated: user !== null }),\n\n setSession: (session) =>\n set({\n session,\n user: session?.user ?? null,\n isAuthenticated: session !== null,\n }),\n\n setLoading: (isLoading) => set({ isLoading }),\n\n setError: (error) => set({ error }),\n\n reset: () => set(initialState),\n}))\n","import React, { createContext, useContext, useEffect, useRef } from 'react'\nimport type { AuthAdapter, AuthProvider as OAuthProvider, AuthSession } from '@fayz-ai/core'\nimport { useAuthStore } from './store'\n\n// ---------------------------------------------------------------------------\n// Context\n// ---------------------------------------------------------------------------\n\ninterface AuthContextValue {\n signIn: (email: string, password: string) => Promise<AuthSession>\n signUp: (email: string, password: string, fullName: string) => Promise<AuthSession>\n signOut: () => Promise<void>\n signInWithOAuth: (provider: OAuthProvider) => Promise<void>\n resetPassword: (email: string) => Promise<void>\n}\n\nconst AuthContext = createContext<AuthContextValue | null>(null)\n\n// ---------------------------------------------------------------------------\n// Provider\n// ---------------------------------------------------------------------------\n\nexport interface AuthProviderProps {\n adapter: AuthAdapter\n children: React.ReactNode\n}\n\nexport function AuthProvider({ adapter, children }: AuthProviderProps) {\n const { setSession, setLoading, setError, reset } = useAuthStore()\n\n // Keep a stable ref to the adapter so the effect only runs once on mount\n const adapterRef = useRef(adapter)\n adapterRef.current = adapter\n\n useEffect(() => {\n let unsubscribe: (() => void) | undefined\n\n async function init() {\n try {\n setLoading(true)\n const result = await adapterRef.current.getSession()\n setSession(result?.session ?? null)\n } catch (err) {\n setError(err instanceof Error ? err : new Error(String(err)))\n } finally {\n setLoading(false)\n }\n\n // Subscribe to future auth state changes\n unsubscribe = adapterRef.current.onAuthStateChange((user) => {\n if (!user) {\n reset()\n // Keep isLoading false after an explicit sign-out\n setLoading(false)\n }\n // Positive auth state changes are handled via setSession after signIn/signUp\n })\n }\n\n void init()\n\n return () => {\n unsubscribe?.()\n }\n // eslint-disable-next-line react-hooks/exhaustive-deps\n }, [])\n\n const value: AuthContextValue = {\n async signIn(email, password) {\n setError(null)\n try {\n const session = await adapterRef.current.signIn(email, password)\n setSession(session)\n return session\n } catch (err) {\n const error = err instanceof Error ? err : new Error(String(err))\n setError(error)\n throw error\n }\n },\n\n async signUp(email, password, fullName) {\n setError(null)\n try {\n const session = await adapterRef.current.signUp(email, password, fullName)\n setSession(session)\n return session\n } catch (err) {\n const error = err instanceof Error ? err : new Error(String(err))\n setError(error)\n throw error\n }\n },\n\n async signOut() {\n setError(null)\n try {\n await adapterRef.current.signOut()\n reset()\n setLoading(false)\n } catch (err) {\n const error = err instanceof Error ? err : new Error(String(err))\n setError(error)\n throw error\n }\n },\n\n async signInWithOAuth(provider) {\n setError(null)\n try {\n await adapterRef.current.signInWithOAuth(provider)\n } catch (err) {\n const error = err instanceof Error ? err : new Error(String(err))\n setError(error)\n throw error\n }\n },\n\n async resetPassword(email) {\n setError(null)\n try {\n await adapterRef.current.resetPassword(email)\n } catch (err) {\n const error = err instanceof Error ? err : new Error(String(err))\n setError(error)\n throw error\n }\n },\n }\n\n return <AuthContext.Provider value={value}>{children}</AuthContext.Provider>\n}\n\n// ---------------------------------------------------------------------------\n// Hook\n// ---------------------------------------------------------------------------\n\nexport function useAuth() {\n const ctx = useContext(AuthContext)\n if (!ctx) {\n throw new Error('useAuth must be used inside <AuthProvider>')\n }\n\n const { user, session, isLoading, isAuthenticated, error } = useAuthStore()\n\n return {\n user,\n session,\n isLoading,\n isAuthenticated,\n error,\n signIn: ctx.signIn,\n signUp: ctx.signUp,\n signOut: ctx.signOut,\n signInWithOAuth: ctx.signInWithOAuth,\n resetPassword: ctx.resetPassword,\n }\n}\n"]}
@@ -0,0 +1,9 @@
1
+ export { createSupabaseAuthAdapter } from './adapters/supabase';
2
+ export type { SupabaseAuthConfig } from './adapters/supabase';
3
+ export { createMockAuthAdapter } from './adapters/mock';
4
+ export type { MockUser } from './adapters/mock';
5
+ export { useAuthStore } from './store';
6
+ export type { AuthState, AuthStore } from './store';
7
+ export { AuthProvider, useAuth } from './context';
8
+ export type { AuthProviderProps } from './context';
9
+ //# sourceMappingURL=index.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../src/index.ts"],"names":[],"mappings":"AACA,OAAO,EAAE,yBAAyB,EAAE,MAAM,qBAAqB,CAAA;AAC/D,YAAY,EAAE,kBAAkB,EAAE,MAAM,qBAAqB,CAAA;AAE7D,OAAO,EAAE,qBAAqB,EAAE,MAAM,iBAAiB,CAAA;AACvD,YAAY,EAAE,QAAQ,EAAE,MAAM,iBAAiB,CAAA;AAG/C,OAAO,EAAE,YAAY,EAAE,MAAM,SAAS,CAAA;AACtC,YAAY,EAAE,SAAS,EAAE,SAAS,EAAE,MAAM,SAAS,CAAA;AAGnD,OAAO,EAAE,YAAY,EAAE,OAAO,EAAE,MAAM,WAAW,CAAA;AACjD,YAAY,EAAE,iBAAiB,EAAE,MAAM,WAAW,CAAA"}
package/dist/index.js ADDED
@@ -0,0 +1,313 @@
1
+ import { createClient } from '@supabase/supabase-js';
2
+ import { create } from 'zustand';
3
+ import { createContext, useRef, useEffect, useContext } from 'react';
4
+ import { jsx } from 'react/jsx-runtime';
5
+
6
+ // src/adapters/supabase.ts
7
+ function mapSupabaseUser(supabaseUser) {
8
+ return {
9
+ id: supabaseUser.id,
10
+ email: supabaseUser.email ?? "",
11
+ fullName: supabaseUser.user_metadata?.["full_name"] ?? supabaseUser.user_metadata?.["name"] ?? "",
12
+ avatarUrl: supabaseUser.user_metadata?.["avatar_url"]
13
+ };
14
+ }
15
+ function mapSupabaseSession(session) {
16
+ return {
17
+ accessToken: session.access_token,
18
+ refreshToken: session.refresh_token,
19
+ expiresAt: session.expires_at ?? Math.floor(Date.now() / 1e3) + (session.expires_in ?? 3600),
20
+ user: mapSupabaseUser(session.user)
21
+ };
22
+ }
23
+ function createSupabaseAuthAdapter(config) {
24
+ const supabase = config.supabaseClient ?? createClient(config.supabaseUrl, config.supabaseAnonKey);
25
+ return {
26
+ async getSession() {
27
+ const {
28
+ data: { session }
29
+ } = await supabase.auth.getSession();
30
+ if (!session) return null;
31
+ const mapped = mapSupabaseSession(session);
32
+ return { user: mapped.user, session: mapped };
33
+ },
34
+ onAuthStateChange(cb) {
35
+ const {
36
+ data: { subscription }
37
+ } = supabase.auth.onAuthStateChange((_event, session) => {
38
+ cb(session ? mapSupabaseUser(session.user) : null);
39
+ });
40
+ return () => subscription.unsubscribe();
41
+ },
42
+ async signIn(email, password) {
43
+ const { data, error } = await supabase.auth.signInWithPassword({ email, password });
44
+ if (error) throw error;
45
+ return mapSupabaseSession(data.session);
46
+ },
47
+ async signUp(email, password, fullName) {
48
+ const { data, error } = await supabase.auth.signUp({
49
+ email,
50
+ password,
51
+ options: { data: { full_name: fullName } }
52
+ });
53
+ if (error) throw error;
54
+ if (!data.session) {
55
+ if (!data.user) throw new Error("Signup failed: no user returned");
56
+ return {
57
+ accessToken: "",
58
+ refreshToken: "",
59
+ expiresAt: 0,
60
+ user: mapSupabaseUser(data.user)
61
+ };
62
+ }
63
+ return mapSupabaseSession(data.session);
64
+ },
65
+ async signOut() {
66
+ const { error } = await supabase.auth.signOut();
67
+ if (error) throw error;
68
+ },
69
+ async signInWithOAuth(provider) {
70
+ const { error } = await supabase.auth.signInWithOAuth({
71
+ provider,
72
+ options: {
73
+ redirectTo: typeof window !== "undefined" ? `${window.location.origin}/auth/callback` : void 0
74
+ }
75
+ });
76
+ if (error) throw error;
77
+ },
78
+ async resetPassword(email) {
79
+ const { error } = await supabase.auth.resetPasswordForEmail(email, {
80
+ redirectTo: typeof window !== "undefined" ? `${window.location.origin}/auth/reset-password` : void 0
81
+ });
82
+ if (error) throw error;
83
+ }
84
+ };
85
+ }
86
+
87
+ // src/adapters/mock.ts
88
+ var DEFAULT_MOCK_USER = {
89
+ id: "mock-user-id",
90
+ email: "demo@fayz.dev",
91
+ fullName: "Demo User",
92
+ role: "admin"
93
+ };
94
+ var STORAGE_KEY = "fayz:mock-auth";
95
+ function toAuthUser(mockUser) {
96
+ return {
97
+ id: mockUser.id,
98
+ email: mockUser.email,
99
+ fullName: mockUser.fullName
100
+ };
101
+ }
102
+ function createMockSession(user) {
103
+ return {
104
+ accessToken: `mock-token-${user.id}`,
105
+ refreshToken: `mock-refresh-${user.id}`,
106
+ expiresAt: Math.floor(Date.now() / 1e3) + 3600,
107
+ user
108
+ };
109
+ }
110
+ function getStored() {
111
+ try {
112
+ if (typeof localStorage === "undefined") return null;
113
+ const raw = localStorage.getItem(STORAGE_KEY);
114
+ if (!raw) return null;
115
+ return JSON.parse(raw);
116
+ } catch {
117
+ return null;
118
+ }
119
+ }
120
+ function setStored(data) {
121
+ try {
122
+ if (typeof localStorage === "undefined") return;
123
+ if (data) {
124
+ localStorage.setItem(STORAGE_KEY, JSON.stringify(data));
125
+ } else {
126
+ localStorage.removeItem(STORAGE_KEY);
127
+ }
128
+ } catch {
129
+ }
130
+ }
131
+ function createMockAuthAdapter(mockUser = DEFAULT_MOCK_USER) {
132
+ const listeners = /* @__PURE__ */ new Set();
133
+ function notifyListeners(user) {
134
+ for (const cb of listeners) cb(user);
135
+ }
136
+ return {
137
+ async getSession() {
138
+ return getStored();
139
+ },
140
+ onAuthStateChange(cb) {
141
+ listeners.add(cb);
142
+ return () => {
143
+ listeners.delete(cb);
144
+ };
145
+ },
146
+ async signIn(email, _password) {
147
+ const stored = getStored();
148
+ const user = stored && stored.user.email === email ? stored.user : {
149
+ id: email === mockUser.email ? mockUser.id : `mock-${email}`,
150
+ email,
151
+ fullName: email === mockUser.email ? mockUser.fullName : email.split("@")[0] ?? "Cliente"
152
+ };
153
+ const session = createMockSession(user);
154
+ setStored({ user, session });
155
+ notifyListeners(user);
156
+ return session;
157
+ },
158
+ async signUp(email, _password, fullName) {
159
+ const user = {
160
+ id: `mock-${email}`,
161
+ email,
162
+ fullName: fullName || (email.split("@")[0] ?? "Cliente")
163
+ };
164
+ const session = createMockSession(user);
165
+ setStored({ user, session });
166
+ notifyListeners(user);
167
+ return session;
168
+ },
169
+ async signOut() {
170
+ setStored(null);
171
+ notifyListeners(null);
172
+ },
173
+ async signInWithOAuth(_provider) {
174
+ const user = toAuthUser(mockUser);
175
+ const session = createMockSession(user);
176
+ setStored({ user, session });
177
+ notifyListeners(user);
178
+ },
179
+ async resetPassword(_email) {
180
+ }
181
+ };
182
+ }
183
+ var initialState = {
184
+ user: null,
185
+ session: null,
186
+ isLoading: true,
187
+ isAuthenticated: false,
188
+ error: null
189
+ };
190
+ var useAuthStore = create((set) => ({
191
+ ...initialState,
192
+ setUser: (user) => set({ user, isAuthenticated: user !== null }),
193
+ setSession: (session) => set({
194
+ session,
195
+ user: session?.user ?? null,
196
+ isAuthenticated: session !== null
197
+ }),
198
+ setLoading: (isLoading) => set({ isLoading }),
199
+ setError: (error) => set({ error }),
200
+ reset: () => set(initialState)
201
+ }));
202
+ var AuthContext = createContext(null);
203
+ function AuthProvider({ adapter, children }) {
204
+ const { setSession, setLoading, setError, reset } = useAuthStore();
205
+ const adapterRef = useRef(adapter);
206
+ adapterRef.current = adapter;
207
+ useEffect(() => {
208
+ let unsubscribe;
209
+ async function init() {
210
+ try {
211
+ setLoading(true);
212
+ const result = await adapterRef.current.getSession();
213
+ setSession(result?.session ?? null);
214
+ } catch (err) {
215
+ setError(err instanceof Error ? err : new Error(String(err)));
216
+ } finally {
217
+ setLoading(false);
218
+ }
219
+ unsubscribe = adapterRef.current.onAuthStateChange((user) => {
220
+ if (!user) {
221
+ reset();
222
+ setLoading(false);
223
+ }
224
+ });
225
+ }
226
+ void init();
227
+ return () => {
228
+ unsubscribe?.();
229
+ };
230
+ }, []);
231
+ const value = {
232
+ async signIn(email, password) {
233
+ setError(null);
234
+ try {
235
+ const session = await adapterRef.current.signIn(email, password);
236
+ setSession(session);
237
+ return session;
238
+ } catch (err) {
239
+ const error = err instanceof Error ? err : new Error(String(err));
240
+ setError(error);
241
+ throw error;
242
+ }
243
+ },
244
+ async signUp(email, password, fullName) {
245
+ setError(null);
246
+ try {
247
+ const session = await adapterRef.current.signUp(email, password, fullName);
248
+ setSession(session);
249
+ return session;
250
+ } catch (err) {
251
+ const error = err instanceof Error ? err : new Error(String(err));
252
+ setError(error);
253
+ throw error;
254
+ }
255
+ },
256
+ async signOut() {
257
+ setError(null);
258
+ try {
259
+ await adapterRef.current.signOut();
260
+ reset();
261
+ setLoading(false);
262
+ } catch (err) {
263
+ const error = err instanceof Error ? err : new Error(String(err));
264
+ setError(error);
265
+ throw error;
266
+ }
267
+ },
268
+ async signInWithOAuth(provider) {
269
+ setError(null);
270
+ try {
271
+ await adapterRef.current.signInWithOAuth(provider);
272
+ } catch (err) {
273
+ const error = err instanceof Error ? err : new Error(String(err));
274
+ setError(error);
275
+ throw error;
276
+ }
277
+ },
278
+ async resetPassword(email) {
279
+ setError(null);
280
+ try {
281
+ await adapterRef.current.resetPassword(email);
282
+ } catch (err) {
283
+ const error = err instanceof Error ? err : new Error(String(err));
284
+ setError(error);
285
+ throw error;
286
+ }
287
+ }
288
+ };
289
+ return /* @__PURE__ */ jsx(AuthContext.Provider, { value, children });
290
+ }
291
+ function useAuth() {
292
+ const ctx = useContext(AuthContext);
293
+ if (!ctx) {
294
+ throw new Error("useAuth must be used inside <AuthProvider>");
295
+ }
296
+ const { user, session, isLoading, isAuthenticated, error } = useAuthStore();
297
+ return {
298
+ user,
299
+ session,
300
+ isLoading,
301
+ isAuthenticated,
302
+ error,
303
+ signIn: ctx.signIn,
304
+ signUp: ctx.signUp,
305
+ signOut: ctx.signOut,
306
+ signInWithOAuth: ctx.signInWithOAuth,
307
+ resetPassword: ctx.resetPassword
308
+ };
309
+ }
310
+
311
+ export { AuthProvider, createMockAuthAdapter, createSupabaseAuthAdapter, useAuth, useAuthStore };
312
+ //# sourceMappingURL=index.js.map
313
+ //# sourceMappingURL=index.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"sources":["../src/adapters/supabase.ts","../src/adapters/mock.ts","../src/store.ts","../src/context.tsx"],"names":[],"mappings":"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","file":"index.js","sourcesContent":["import { createClient, type SupabaseClient } from '@supabase/supabase-js'\nimport type { AuthAdapter, AuthUser, AuthSession, AuthProvider } from '@fayz-ai/core'\n\nexport interface SupabaseAuthConfig {\n supabaseUrl: string\n supabaseAnonKey: string\n supabaseClient?: SupabaseClient\n}\n\nfunction mapSupabaseUser(supabaseUser: {\n id: string\n email?: string | null\n created_at?: string\n updated_at?: string | null\n email_confirmed_at?: string | null\n user_metadata?: Record<string, unknown>\n app_metadata?: { providers?: string[]; provider?: string }\n}): AuthUser {\n return {\n id: supabaseUser.id,\n email: supabaseUser.email ?? '',\n fullName:\n (supabaseUser.user_metadata?.['full_name'] as string | undefined) ??\n (supabaseUser.user_metadata?.['name'] as string | undefined) ??\n '',\n avatarUrl: supabaseUser.user_metadata?.['avatar_url'] as string | undefined,\n }\n}\n\nfunction mapSupabaseSession(session: {\n access_token: string\n refresh_token?: string\n expires_at?: number\n expires_in?: number\n user: Parameters<typeof mapSupabaseUser>[0]\n}): AuthSession {\n return {\n accessToken: session.access_token,\n refreshToken: session.refresh_token,\n expiresAt:\n session.expires_at ??\n Math.floor(Date.now() / 1000) + (session.expires_in ?? 3600),\n user: mapSupabaseUser(session.user),\n }\n}\n\nexport function createSupabaseAuthAdapter(config: SupabaseAuthConfig): AuthAdapter {\n const supabase = config.supabaseClient ?? createClient(config.supabaseUrl, config.supabaseAnonKey)\n\n return {\n async getSession() {\n const {\n data: { session },\n } = await supabase.auth.getSession()\n if (!session) return null\n const mapped = mapSupabaseSession(session)\n return { user: mapped.user, session: mapped }\n },\n\n onAuthStateChange(cb) {\n const {\n data: { subscription },\n } = supabase.auth.onAuthStateChange((_event, session) => {\n cb(session ? mapSupabaseUser(session.user) : null)\n })\n return () => subscription.unsubscribe()\n },\n\n async signIn(email, password) {\n const { data, error } = await supabase.auth.signInWithPassword({ email, password })\n if (error) throw error\n return mapSupabaseSession(data.session)\n },\n\n async signUp(email, password, fullName) {\n const { data, error } = await supabase.auth.signUp({\n email,\n password,\n options: { data: { full_name: fullName } },\n })\n if (error) throw error\n\n // When email confirmation is required, session is null\n if (!data.session) {\n if (!data.user) throw new Error('Signup failed: no user returned')\n return {\n accessToken: '',\n refreshToken: '',\n expiresAt: 0,\n user: mapSupabaseUser(data.user),\n }\n }\n\n return mapSupabaseSession(data.session)\n },\n\n async signOut() {\n const { error } = await supabase.auth.signOut()\n if (error) throw error\n },\n\n async signInWithOAuth(provider: AuthProvider) {\n const { error } = await supabase.auth.signInWithOAuth({\n provider: provider as 'google' | 'github' | 'apple',\n options: {\n redirectTo:\n typeof window !== 'undefined'\n ? `${window.location.origin}/auth/callback`\n : undefined,\n },\n })\n if (error) throw error\n },\n\n async resetPassword(email) {\n const { error } = await supabase.auth.resetPasswordForEmail(email, {\n redirectTo:\n typeof window !== 'undefined'\n ? `${window.location.origin}/auth/reset-password`\n : undefined,\n })\n if (error) throw error\n },\n }\n}\n","import type { AuthAdapter, AuthUser, AuthSession } from '@fayz-ai/core'\n\nexport interface MockUser {\n id: string\n email: string\n fullName: string\n role?: string\n}\n\nconst DEFAULT_MOCK_USER: MockUser = {\n id: 'mock-user-id',\n email: 'demo@fayz.dev',\n fullName: 'Demo User',\n role: 'admin',\n}\n\nconst STORAGE_KEY = 'fayz:mock-auth'\n\nfunction toAuthUser(mockUser: MockUser): AuthUser {\n return {\n id: mockUser.id,\n email: mockUser.email,\n fullName: mockUser.fullName,\n }\n}\n\nfunction createMockSession(user: AuthUser): AuthSession {\n return {\n accessToken: `mock-token-${user.id}`,\n refreshToken: `mock-refresh-${user.id}`,\n expiresAt: Math.floor(Date.now() / 1000) + 3600,\n user,\n }\n}\n\nfunction getStored(): { user: AuthUser; session: AuthSession } | null {\n try {\n if (typeof localStorage === 'undefined') return null\n const raw = localStorage.getItem(STORAGE_KEY)\n if (!raw) return null\n return JSON.parse(raw) as { user: AuthUser; session: AuthSession }\n } catch {\n return null\n }\n}\n\nfunction setStored(data: { user: AuthUser; session: AuthSession } | null): void {\n try {\n if (typeof localStorage === 'undefined') return\n if (data) {\n localStorage.setItem(STORAGE_KEY, JSON.stringify(data))\n } else {\n localStorage.removeItem(STORAGE_KEY)\n }\n } catch {\n // SSR or storage unavailable — silently skip\n }\n}\n\nexport function createMockAuthAdapter(mockUser: MockUser = DEFAULT_MOCK_USER): AuthAdapter {\n const listeners = new Set<(user: AuthUser | null) => void>()\n\n function notifyListeners(user: AuthUser | null): void {\n for (const cb of listeners) cb(user)\n }\n\n return {\n async getSession() {\n return getStored()\n },\n\n onAuthStateChange(cb) {\n listeners.add(cb)\n return () => {\n listeners.delete(cb)\n }\n },\n\n async signIn(email, _password) {\n // Mock accepts any credentials, but the identity FOLLOWS the email —\n // storefront customers and saas users keep their own purchase/session\n // history instead of all becoming the configured demo user.\n const stored = getStored()\n const user: AuthUser =\n stored && stored.user.email === email\n ? stored.user\n : {\n id: email === mockUser.email ? mockUser.id : `mock-${email}`,\n email,\n fullName: email === mockUser.email ? mockUser.fullName : (email.split('@')[0] ?? 'Cliente'),\n }\n const session = createMockSession(user)\n setStored({ user, session })\n notifyListeners(user)\n return session\n },\n\n async signUp(email, _password, fullName) {\n // Mock signup creates a user from the provided details\n const user: AuthUser = {\n id: `mock-${email}`,\n email,\n fullName: fullName || (email.split('@')[0] ?? 'Cliente'),\n }\n const session = createMockSession(user)\n setStored({ user, session })\n notifyListeners(user)\n return session\n },\n\n async signOut() {\n setStored(null)\n notifyListeners(null)\n },\n\n async signInWithOAuth(_provider) {\n // Mock OAuth signs in as the configured user\n const user = toAuthUser(mockUser)\n const session = createMockSession(user)\n setStored({ user, session })\n notifyListeners(user)\n },\n\n async resetPassword(_email) {\n // No-op in mock\n },\n }\n}\n","import { create } from 'zustand'\nimport type { AuthUser, AuthSession } from '@fayz-ai/core'\n\nexport interface AuthState {\n user: AuthUser | null\n session: AuthSession | null\n isLoading: boolean\n isAuthenticated: boolean\n error: Error | null\n}\n\nexport interface AuthStore extends AuthState {\n setUser: (user: AuthUser | null) => void\n setSession: (session: AuthSession | null) => void\n setLoading: (isLoading: boolean) => void\n setError: (error: Error | null) => void\n reset: () => void\n}\n\nconst initialState: AuthState = {\n user: null,\n session: null,\n isLoading: true,\n isAuthenticated: false,\n error: null,\n}\n\nexport const useAuthStore = create<AuthStore>((set) => ({\n ...initialState,\n\n setUser: (user) =>\n set({ user, isAuthenticated: user !== null }),\n\n setSession: (session) =>\n set({\n session,\n user: session?.user ?? null,\n isAuthenticated: session !== null,\n }),\n\n setLoading: (isLoading) => set({ isLoading }),\n\n setError: (error) => set({ error }),\n\n reset: () => set(initialState),\n}))\n","import React, { createContext, useContext, useEffect, useRef } from 'react'\nimport type { AuthAdapter, AuthProvider as OAuthProvider, AuthSession } from '@fayz-ai/core'\nimport { useAuthStore } from './store'\n\n// ---------------------------------------------------------------------------\n// Context\n// ---------------------------------------------------------------------------\n\ninterface AuthContextValue {\n signIn: (email: string, password: string) => Promise<AuthSession>\n signUp: (email: string, password: string, fullName: string) => Promise<AuthSession>\n signOut: () => Promise<void>\n signInWithOAuth: (provider: OAuthProvider) => Promise<void>\n resetPassword: (email: string) => Promise<void>\n}\n\nconst AuthContext = createContext<AuthContextValue | null>(null)\n\n// ---------------------------------------------------------------------------\n// Provider\n// ---------------------------------------------------------------------------\n\nexport interface AuthProviderProps {\n adapter: AuthAdapter\n children: React.ReactNode\n}\n\nexport function AuthProvider({ adapter, children }: AuthProviderProps) {\n const { setSession, setLoading, setError, reset } = useAuthStore()\n\n // Keep a stable ref to the adapter so the effect only runs once on mount\n const adapterRef = useRef(adapter)\n adapterRef.current = adapter\n\n useEffect(() => {\n let unsubscribe: (() => void) | undefined\n\n async function init() {\n try {\n setLoading(true)\n const result = await adapterRef.current.getSession()\n setSession(result?.session ?? null)\n } catch (err) {\n setError(err instanceof Error ? err : new Error(String(err)))\n } finally {\n setLoading(false)\n }\n\n // Subscribe to future auth state changes\n unsubscribe = adapterRef.current.onAuthStateChange((user) => {\n if (!user) {\n reset()\n // Keep isLoading false after an explicit sign-out\n setLoading(false)\n }\n // Positive auth state changes are handled via setSession after signIn/signUp\n })\n }\n\n void init()\n\n return () => {\n unsubscribe?.()\n }\n // eslint-disable-next-line react-hooks/exhaustive-deps\n }, [])\n\n const value: AuthContextValue = {\n async signIn(email, password) {\n setError(null)\n try {\n const session = await adapterRef.current.signIn(email, password)\n setSession(session)\n return session\n } catch (err) {\n const error = err instanceof Error ? err : new Error(String(err))\n setError(error)\n throw error\n }\n },\n\n async signUp(email, password, fullName) {\n setError(null)\n try {\n const session = await adapterRef.current.signUp(email, password, fullName)\n setSession(session)\n return session\n } catch (err) {\n const error = err instanceof Error ? err : new Error(String(err))\n setError(error)\n throw error\n }\n },\n\n async signOut() {\n setError(null)\n try {\n await adapterRef.current.signOut()\n reset()\n setLoading(false)\n } catch (err) {\n const error = err instanceof Error ? err : new Error(String(err))\n setError(error)\n throw error\n }\n },\n\n async signInWithOAuth(provider) {\n setError(null)\n try {\n await adapterRef.current.signInWithOAuth(provider)\n } catch (err) {\n const error = err instanceof Error ? err : new Error(String(err))\n setError(error)\n throw error\n }\n },\n\n async resetPassword(email) {\n setError(null)\n try {\n await adapterRef.current.resetPassword(email)\n } catch (err) {\n const error = err instanceof Error ? err : new Error(String(err))\n setError(error)\n throw error\n }\n },\n }\n\n return <AuthContext.Provider value={value}>{children}</AuthContext.Provider>\n}\n\n// ---------------------------------------------------------------------------\n// Hook\n// ---------------------------------------------------------------------------\n\nexport function useAuth() {\n const ctx = useContext(AuthContext)\n if (!ctx) {\n throw new Error('useAuth must be used inside <AuthProvider>')\n }\n\n const { user, session, isLoading, isAuthenticated, error } = useAuthStore()\n\n return {\n user,\n session,\n isLoading,\n isAuthenticated,\n error,\n signIn: ctx.signIn,\n signUp: ctx.signUp,\n signOut: ctx.signOut,\n signInWithOAuth: ctx.signInWithOAuth,\n resetPassword: ctx.resetPassword,\n }\n}\n"]}
@@ -0,0 +1,17 @@
1
+ import type { AuthUser, AuthSession } from '@fayz-ai/core';
2
+ export interface AuthState {
3
+ user: AuthUser | null;
4
+ session: AuthSession | null;
5
+ isLoading: boolean;
6
+ isAuthenticated: boolean;
7
+ error: Error | null;
8
+ }
9
+ export interface AuthStore extends AuthState {
10
+ setUser: (user: AuthUser | null) => void;
11
+ setSession: (session: AuthSession | null) => void;
12
+ setLoading: (isLoading: boolean) => void;
13
+ setError: (error: Error | null) => void;
14
+ reset: () => void;
15
+ }
16
+ export declare const useAuthStore: import("zustand").UseBoundStore<import("zustand").StoreApi<AuthStore>>;
17
+ //# sourceMappingURL=store.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"store.d.ts","sourceRoot":"","sources":["../src/store.ts"],"names":[],"mappings":"AACA,OAAO,KAAK,EAAE,QAAQ,EAAE,WAAW,EAAE,MAAM,eAAe,CAAA;AAE1D,MAAM,WAAW,SAAS;IACxB,IAAI,EAAE,QAAQ,GAAG,IAAI,CAAA;IACrB,OAAO,EAAE,WAAW,GAAG,IAAI,CAAA;IAC3B,SAAS,EAAE,OAAO,CAAA;IAClB,eAAe,EAAE,OAAO,CAAA;IACxB,KAAK,EAAE,KAAK,GAAG,IAAI,CAAA;CACpB;AAED,MAAM,WAAW,SAAU,SAAQ,SAAS;IAC1C,OAAO,EAAE,CAAC,IAAI,EAAE,QAAQ,GAAG,IAAI,KAAK,IAAI,CAAA;IACxC,UAAU,EAAE,CAAC,OAAO,EAAE,WAAW,GAAG,IAAI,KAAK,IAAI,CAAA;IACjD,UAAU,EAAE,CAAC,SAAS,EAAE,OAAO,KAAK,IAAI,CAAA;IACxC,QAAQ,EAAE,CAAC,KAAK,EAAE,KAAK,GAAG,IAAI,KAAK,IAAI,CAAA;IACvC,KAAK,EAAE,MAAM,IAAI,CAAA;CAClB;AAUD,eAAO,MAAM,YAAY,wEAkBtB,CAAA"}
package/package.json ADDED
@@ -0,0 +1,45 @@
1
+ {
2
+ "name": "@fayz-ai/auth",
3
+ "version": "0.1.6",
4
+ "description": "Fayz SDK auth — pluggable authentication adapters with React hooks",
5
+ "type": "module",
6
+ "main": "./src/index.ts",
7
+ "module": "./src/index.ts",
8
+ "types": "./src/index.ts",
9
+ "exports": {
10
+ ".": {
11
+ "source": "./src/index.ts",
12
+ "types": "./src/index.ts",
13
+ "import": "./dist/index.js",
14
+ "require": "./dist/index.cjs"
15
+ }
16
+ },
17
+ "files": [
18
+ "dist",
19
+ "src"
20
+ ],
21
+ "peerDependencies": {
22
+ "react": "^18.0.0 || ^19.0.0"
23
+ },
24
+ "dependencies": {
25
+ "@supabase/supabase-js": "^2.45.0",
26
+ "zustand": "^4.5.0",
27
+ "@fayz-ai/core": "^0.1.6"
28
+ },
29
+ "devDependencies": {
30
+ "@types/react": "^18.3.0",
31
+ "react": "^18.3.0",
32
+ "tsup": "^8.2.0",
33
+ "typescript": "^5.5.0"
34
+ },
35
+ "license": "MIT",
36
+ "publishConfig": {
37
+ "access": "public"
38
+ },
39
+ "scripts": {
40
+ "build": "tsup && tsc --emitDeclarationOnly --declaration --declarationMap --noEmit false",
41
+ "dev": "tsup --watch",
42
+ "typecheck": "tsc --noEmit",
43
+ "clean": "rm -rf dist"
44
+ }
45
+ }
@@ -0,0 +1,128 @@
1
+ import type { AuthAdapter, AuthUser, AuthSession } from '@fayz-ai/core'
2
+
3
+ export interface MockUser {
4
+ id: string
5
+ email: string
6
+ fullName: string
7
+ role?: string
8
+ }
9
+
10
+ const DEFAULT_MOCK_USER: MockUser = {
11
+ id: 'mock-user-id',
12
+ email: 'demo@fayz.dev',
13
+ fullName: 'Demo User',
14
+ role: 'admin',
15
+ }
16
+
17
+ const STORAGE_KEY = 'fayz:mock-auth'
18
+
19
+ function toAuthUser(mockUser: MockUser): AuthUser {
20
+ return {
21
+ id: mockUser.id,
22
+ email: mockUser.email,
23
+ fullName: mockUser.fullName,
24
+ }
25
+ }
26
+
27
+ function createMockSession(user: AuthUser): AuthSession {
28
+ return {
29
+ accessToken: `mock-token-${user.id}`,
30
+ refreshToken: `mock-refresh-${user.id}`,
31
+ expiresAt: Math.floor(Date.now() / 1000) + 3600,
32
+ user,
33
+ }
34
+ }
35
+
36
+ function getStored(): { user: AuthUser; session: AuthSession } | null {
37
+ try {
38
+ if (typeof localStorage === 'undefined') return null
39
+ const raw = localStorage.getItem(STORAGE_KEY)
40
+ if (!raw) return null
41
+ return JSON.parse(raw) as { user: AuthUser; session: AuthSession }
42
+ } catch {
43
+ return null
44
+ }
45
+ }
46
+
47
+ function setStored(data: { user: AuthUser; session: AuthSession } | null): void {
48
+ try {
49
+ if (typeof localStorage === 'undefined') return
50
+ if (data) {
51
+ localStorage.setItem(STORAGE_KEY, JSON.stringify(data))
52
+ } else {
53
+ localStorage.removeItem(STORAGE_KEY)
54
+ }
55
+ } catch {
56
+ // SSR or storage unavailable — silently skip
57
+ }
58
+ }
59
+
60
+ export function createMockAuthAdapter(mockUser: MockUser = DEFAULT_MOCK_USER): AuthAdapter {
61
+ const listeners = new Set<(user: AuthUser | null) => void>()
62
+
63
+ function notifyListeners(user: AuthUser | null): void {
64
+ for (const cb of listeners) cb(user)
65
+ }
66
+
67
+ return {
68
+ async getSession() {
69
+ return getStored()
70
+ },
71
+
72
+ onAuthStateChange(cb) {
73
+ listeners.add(cb)
74
+ return () => {
75
+ listeners.delete(cb)
76
+ }
77
+ },
78
+
79
+ async signIn(email, _password) {
80
+ // Mock accepts any credentials, but the identity FOLLOWS the email —
81
+ // storefront customers and saas users keep their own purchase/session
82
+ // history instead of all becoming the configured demo user.
83
+ const stored = getStored()
84
+ const user: AuthUser =
85
+ stored && stored.user.email === email
86
+ ? stored.user
87
+ : {
88
+ id: email === mockUser.email ? mockUser.id : `mock-${email}`,
89
+ email,
90
+ fullName: email === mockUser.email ? mockUser.fullName : (email.split('@')[0] ?? 'Cliente'),
91
+ }
92
+ const session = createMockSession(user)
93
+ setStored({ user, session })
94
+ notifyListeners(user)
95
+ return session
96
+ },
97
+
98
+ async signUp(email, _password, fullName) {
99
+ // Mock signup creates a user from the provided details
100
+ const user: AuthUser = {
101
+ id: `mock-${email}`,
102
+ email,
103
+ fullName: fullName || (email.split('@')[0] ?? 'Cliente'),
104
+ }
105
+ const session = createMockSession(user)
106
+ setStored({ user, session })
107
+ notifyListeners(user)
108
+ return session
109
+ },
110
+
111
+ async signOut() {
112
+ setStored(null)
113
+ notifyListeners(null)
114
+ },
115
+
116
+ async signInWithOAuth(_provider) {
117
+ // Mock OAuth signs in as the configured user
118
+ const user = toAuthUser(mockUser)
119
+ const session = createMockSession(user)
120
+ setStored({ user, session })
121
+ notifyListeners(user)
122
+ },
123
+
124
+ async resetPassword(_email) {
125
+ // No-op in mock
126
+ },
127
+ }
128
+ }
@@ -0,0 +1,125 @@
1
+ import { createClient, type SupabaseClient } from '@supabase/supabase-js'
2
+ import type { AuthAdapter, AuthUser, AuthSession, AuthProvider } from '@fayz-ai/core'
3
+
4
+ export interface SupabaseAuthConfig {
5
+ supabaseUrl: string
6
+ supabaseAnonKey: string
7
+ supabaseClient?: SupabaseClient
8
+ }
9
+
10
+ function mapSupabaseUser(supabaseUser: {
11
+ id: string
12
+ email?: string | null
13
+ created_at?: string
14
+ updated_at?: string | null
15
+ email_confirmed_at?: string | null
16
+ user_metadata?: Record<string, unknown>
17
+ app_metadata?: { providers?: string[]; provider?: string }
18
+ }): AuthUser {
19
+ return {
20
+ id: supabaseUser.id,
21
+ email: supabaseUser.email ?? '',
22
+ fullName:
23
+ (supabaseUser.user_metadata?.['full_name'] as string | undefined) ??
24
+ (supabaseUser.user_metadata?.['name'] as string | undefined) ??
25
+ '',
26
+ avatarUrl: supabaseUser.user_metadata?.['avatar_url'] as string | undefined,
27
+ }
28
+ }
29
+
30
+ function mapSupabaseSession(session: {
31
+ access_token: string
32
+ refresh_token?: string
33
+ expires_at?: number
34
+ expires_in?: number
35
+ user: Parameters<typeof mapSupabaseUser>[0]
36
+ }): AuthSession {
37
+ return {
38
+ accessToken: session.access_token,
39
+ refreshToken: session.refresh_token,
40
+ expiresAt:
41
+ session.expires_at ??
42
+ Math.floor(Date.now() / 1000) + (session.expires_in ?? 3600),
43
+ user: mapSupabaseUser(session.user),
44
+ }
45
+ }
46
+
47
+ export function createSupabaseAuthAdapter(config: SupabaseAuthConfig): AuthAdapter {
48
+ const supabase = config.supabaseClient ?? createClient(config.supabaseUrl, config.supabaseAnonKey)
49
+
50
+ return {
51
+ async getSession() {
52
+ const {
53
+ data: { session },
54
+ } = await supabase.auth.getSession()
55
+ if (!session) return null
56
+ const mapped = mapSupabaseSession(session)
57
+ return { user: mapped.user, session: mapped }
58
+ },
59
+
60
+ onAuthStateChange(cb) {
61
+ const {
62
+ data: { subscription },
63
+ } = supabase.auth.onAuthStateChange((_event, session) => {
64
+ cb(session ? mapSupabaseUser(session.user) : null)
65
+ })
66
+ return () => subscription.unsubscribe()
67
+ },
68
+
69
+ async signIn(email, password) {
70
+ const { data, error } = await supabase.auth.signInWithPassword({ email, password })
71
+ if (error) throw error
72
+ return mapSupabaseSession(data.session)
73
+ },
74
+
75
+ async signUp(email, password, fullName) {
76
+ const { data, error } = await supabase.auth.signUp({
77
+ email,
78
+ password,
79
+ options: { data: { full_name: fullName } },
80
+ })
81
+ if (error) throw error
82
+
83
+ // When email confirmation is required, session is null
84
+ if (!data.session) {
85
+ if (!data.user) throw new Error('Signup failed: no user returned')
86
+ return {
87
+ accessToken: '',
88
+ refreshToken: '',
89
+ expiresAt: 0,
90
+ user: mapSupabaseUser(data.user),
91
+ }
92
+ }
93
+
94
+ return mapSupabaseSession(data.session)
95
+ },
96
+
97
+ async signOut() {
98
+ const { error } = await supabase.auth.signOut()
99
+ if (error) throw error
100
+ },
101
+
102
+ async signInWithOAuth(provider: AuthProvider) {
103
+ const { error } = await supabase.auth.signInWithOAuth({
104
+ provider: provider as 'google' | 'github' | 'apple',
105
+ options: {
106
+ redirectTo:
107
+ typeof window !== 'undefined'
108
+ ? `${window.location.origin}/auth/callback`
109
+ : undefined,
110
+ },
111
+ })
112
+ if (error) throw error
113
+ },
114
+
115
+ async resetPassword(email) {
116
+ const { error } = await supabase.auth.resetPasswordForEmail(email, {
117
+ redirectTo:
118
+ typeof window !== 'undefined'
119
+ ? `${window.location.origin}/auth/reset-password`
120
+ : undefined,
121
+ })
122
+ if (error) throw error
123
+ },
124
+ }
125
+ }
@@ -0,0 +1,158 @@
1
+ import React, { createContext, useContext, useEffect, useRef } from 'react'
2
+ import type { AuthAdapter, AuthProvider as OAuthProvider, AuthSession } from '@fayz-ai/core'
3
+ import { useAuthStore } from './store'
4
+
5
+ // ---------------------------------------------------------------------------
6
+ // Context
7
+ // ---------------------------------------------------------------------------
8
+
9
+ interface AuthContextValue {
10
+ signIn: (email: string, password: string) => Promise<AuthSession>
11
+ signUp: (email: string, password: string, fullName: string) => Promise<AuthSession>
12
+ signOut: () => Promise<void>
13
+ signInWithOAuth: (provider: OAuthProvider) => Promise<void>
14
+ resetPassword: (email: string) => Promise<void>
15
+ }
16
+
17
+ const AuthContext = createContext<AuthContextValue | null>(null)
18
+
19
+ // ---------------------------------------------------------------------------
20
+ // Provider
21
+ // ---------------------------------------------------------------------------
22
+
23
+ export interface AuthProviderProps {
24
+ adapter: AuthAdapter
25
+ children: React.ReactNode
26
+ }
27
+
28
+ export function AuthProvider({ adapter, children }: AuthProviderProps) {
29
+ const { setSession, setLoading, setError, reset } = useAuthStore()
30
+
31
+ // Keep a stable ref to the adapter so the effect only runs once on mount
32
+ const adapterRef = useRef(adapter)
33
+ adapterRef.current = adapter
34
+
35
+ useEffect(() => {
36
+ let unsubscribe: (() => void) | undefined
37
+
38
+ async function init() {
39
+ try {
40
+ setLoading(true)
41
+ const result = await adapterRef.current.getSession()
42
+ setSession(result?.session ?? null)
43
+ } catch (err) {
44
+ setError(err instanceof Error ? err : new Error(String(err)))
45
+ } finally {
46
+ setLoading(false)
47
+ }
48
+
49
+ // Subscribe to future auth state changes
50
+ unsubscribe = adapterRef.current.onAuthStateChange((user) => {
51
+ if (!user) {
52
+ reset()
53
+ // Keep isLoading false after an explicit sign-out
54
+ setLoading(false)
55
+ }
56
+ // Positive auth state changes are handled via setSession after signIn/signUp
57
+ })
58
+ }
59
+
60
+ void init()
61
+
62
+ return () => {
63
+ unsubscribe?.()
64
+ }
65
+ // eslint-disable-next-line react-hooks/exhaustive-deps
66
+ }, [])
67
+
68
+ const value: AuthContextValue = {
69
+ async signIn(email, password) {
70
+ setError(null)
71
+ try {
72
+ const session = await adapterRef.current.signIn(email, password)
73
+ setSession(session)
74
+ return session
75
+ } catch (err) {
76
+ const error = err instanceof Error ? err : new Error(String(err))
77
+ setError(error)
78
+ throw error
79
+ }
80
+ },
81
+
82
+ async signUp(email, password, fullName) {
83
+ setError(null)
84
+ try {
85
+ const session = await adapterRef.current.signUp(email, password, fullName)
86
+ setSession(session)
87
+ return session
88
+ } catch (err) {
89
+ const error = err instanceof Error ? err : new Error(String(err))
90
+ setError(error)
91
+ throw error
92
+ }
93
+ },
94
+
95
+ async signOut() {
96
+ setError(null)
97
+ try {
98
+ await adapterRef.current.signOut()
99
+ reset()
100
+ setLoading(false)
101
+ } catch (err) {
102
+ const error = err instanceof Error ? err : new Error(String(err))
103
+ setError(error)
104
+ throw error
105
+ }
106
+ },
107
+
108
+ async signInWithOAuth(provider) {
109
+ setError(null)
110
+ try {
111
+ await adapterRef.current.signInWithOAuth(provider)
112
+ } catch (err) {
113
+ const error = err instanceof Error ? err : new Error(String(err))
114
+ setError(error)
115
+ throw error
116
+ }
117
+ },
118
+
119
+ async resetPassword(email) {
120
+ setError(null)
121
+ try {
122
+ await adapterRef.current.resetPassword(email)
123
+ } catch (err) {
124
+ const error = err instanceof Error ? err : new Error(String(err))
125
+ setError(error)
126
+ throw error
127
+ }
128
+ },
129
+ }
130
+
131
+ return <AuthContext.Provider value={value}>{children}</AuthContext.Provider>
132
+ }
133
+
134
+ // ---------------------------------------------------------------------------
135
+ // Hook
136
+ // ---------------------------------------------------------------------------
137
+
138
+ export function useAuth() {
139
+ const ctx = useContext(AuthContext)
140
+ if (!ctx) {
141
+ throw new Error('useAuth must be used inside <AuthProvider>')
142
+ }
143
+
144
+ const { user, session, isLoading, isAuthenticated, error } = useAuthStore()
145
+
146
+ return {
147
+ user,
148
+ session,
149
+ isLoading,
150
+ isAuthenticated,
151
+ error,
152
+ signIn: ctx.signIn,
153
+ signUp: ctx.signUp,
154
+ signOut: ctx.signOut,
155
+ signInWithOAuth: ctx.signInWithOAuth,
156
+ resetPassword: ctx.resetPassword,
157
+ }
158
+ }
package/src/index.ts ADDED
@@ -0,0 +1,14 @@
1
+ // Adapters
2
+ export { createSupabaseAuthAdapter } from './adapters/supabase'
3
+ export type { SupabaseAuthConfig } from './adapters/supabase'
4
+
5
+ export { createMockAuthAdapter } from './adapters/mock'
6
+ export type { MockUser } from './adapters/mock'
7
+
8
+ // Store
9
+ export { useAuthStore } from './store'
10
+ export type { AuthState, AuthStore } from './store'
11
+
12
+ // Context & hook
13
+ export { AuthProvider, useAuth } from './context'
14
+ export type { AuthProviderProps } from './context'
package/src/store.ts ADDED
@@ -0,0 +1,46 @@
1
+ import { create } from 'zustand'
2
+ import type { AuthUser, AuthSession } from '@fayz-ai/core'
3
+
4
+ export interface AuthState {
5
+ user: AuthUser | null
6
+ session: AuthSession | null
7
+ isLoading: boolean
8
+ isAuthenticated: boolean
9
+ error: Error | null
10
+ }
11
+
12
+ export interface AuthStore extends AuthState {
13
+ setUser: (user: AuthUser | null) => void
14
+ setSession: (session: AuthSession | null) => void
15
+ setLoading: (isLoading: boolean) => void
16
+ setError: (error: Error | null) => void
17
+ reset: () => void
18
+ }
19
+
20
+ const initialState: AuthState = {
21
+ user: null,
22
+ session: null,
23
+ isLoading: true,
24
+ isAuthenticated: false,
25
+ error: null,
26
+ }
27
+
28
+ export const useAuthStore = create<AuthStore>((set) => ({
29
+ ...initialState,
30
+
31
+ setUser: (user) =>
32
+ set({ user, isAuthenticated: user !== null }),
33
+
34
+ setSession: (session) =>
35
+ set({
36
+ session,
37
+ user: session?.user ?? null,
38
+ isAuthenticated: session !== null,
39
+ }),
40
+
41
+ setLoading: (isLoading) => set({ isLoading }),
42
+
43
+ setError: (error) => set({ error }),
44
+
45
+ reset: () => set(initialState),
46
+ }))