@allem-sdk/auth 0.1.1 → 0.1.3

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
package/README.md CHANGED
@@ -3,6 +3,7 @@
3
3
  </p>
4
4
 
5
5
  <p align="center">
6
+ <a href="https://www.npmjs.com/package/@allem-sdk/auth"><img src="https://img.shields.io/npm/v/@allem-sdk/auth.svg" alt="npm version" /></a>
6
7
  <a href="https://github.com/kingofmit/allem-sdk/blob/main/LICENSE"><img src="https://img.shields.io/badge/license-MIT-blue.svg" alt="License" /></a>
7
8
  <img src="https://img.shields.io/badge/react-19-61dafb" alt="React 19" />
8
9
  <img src="https://img.shields.io/badge/typescript-strict-blue" alt="TypeScript" />
@@ -10,7 +11,7 @@
10
11
 
11
12
  # @allem-sdk/auth
12
13
 
13
- Authentication helpers for React. Provider-agnostic via an adapter interface works with any auth backend.
14
+ Authentication helpers for React. Provider-agnostic via an adapter interface that works with any auth backend.
14
15
 
15
16
  ## Installation
16
17
 
@@ -61,6 +62,33 @@ function Dashboard() {
61
62
  }
62
63
  ```
63
64
 
65
+ ## Built-in Adapters
66
+
67
+ Pre-built adapters for popular auth providers — no need to write your own:
68
+
69
+ ```tsx
70
+ import { supabaseAdapter, nextAuthAdapter, clerkAdapter } from "@allem-sdk/auth";
71
+ ```
72
+
73
+ | Adapter | Usage | Notes |
74
+ |---------|-------|-------|
75
+ | `supabaseAdapter(supabase)` | Pass your Supabase client | Wraps `signInWithPassword`, reads session/user |
76
+ | `nextAuthAdapter(options?)` | `{ basePath?: string }` | Fetches from `/api/auth/session`. Works with v4/v5 |
77
+ | `clerkAdapter(clerk)` | Pass the Clerk instance | Read-only — sign-in is handled by Clerk's `<SignIn />` |
78
+
79
+ ```tsx
80
+ // Supabase
81
+ import { createClient } from "@supabase/supabase-js";
82
+ const supabase = createClient(url, key);
83
+ <AuthProvider adapter={supabaseAdapter(supabase)}>
84
+
85
+ // NextAuth
86
+ <AuthProvider adapter={nextAuthAdapter()}>
87
+
88
+ // Clerk
89
+ <AuthProvider adapter={clerkAdapter(clerk)}>
90
+ ```
91
+
64
92
  ## Exports
65
93
 
66
94
  | Export | Type | Description |
@@ -69,6 +97,9 @@ function Dashboard() {
69
97
  | `useAuth` | Hook | Returns `user`, `status`, `isAuthenticated`, `isLoading`, `signIn`, `signOut` |
70
98
  | `useSession` | Hook | Returns `session` object and `update` function |
71
99
  | `ProtectedRoute` | Component | Renders children only when authenticated, with fallback support |
100
+ | `supabaseAdapter` | Factory | Adapter for Supabase auth |
101
+ | `nextAuthAdapter` | Factory | Adapter for NextAuth.js |
102
+ | `clerkAdapter` | Factory | Adapter for Clerk |
72
103
 
73
104
  ## Part of [Allem SDK](https://github.com/kingofmit/allem-sdk)
74
105
 
package/dist/index.d.mts CHANGED
@@ -48,4 +48,74 @@ interface ProtectedRouteProps {
48
48
  }
49
49
  declare function ProtectedRoute({ children, fallback, loadingFallback, }: ProtectedRouteProps): react_jsx_runtime.JSX.Element;
50
50
 
51
- export { type AuthAdapter, AuthProvider, type AuthProviderProps, type AuthSession, type AuthStatus, type AuthUser, ProtectedRoute, type ProtectedRouteProps, type UseAuthReturn, type UseSessionReturn, useAuth, useSession };
51
+ /**
52
+ * Supabase auth adapter. Wraps `@supabase/supabase-js` client.
53
+ *
54
+ * @example
55
+ * ```tsx
56
+ * import { createClient } from "@supabase/supabase-js";
57
+ * const supabase = createClient(url, key);
58
+ *
59
+ * <AuthProvider adapter={supabaseAdapter(supabase)}>
60
+ * ```
61
+ */
62
+ declare function supabaseAdapter(supabase: {
63
+ auth: {
64
+ getSession: () => Promise<{
65
+ data: {
66
+ session: unknown;
67
+ };
68
+ }>;
69
+ signInWithPassword: (creds: {
70
+ email: string;
71
+ password: string;
72
+ }) => Promise<{
73
+ data: {
74
+ session: unknown;
75
+ user: unknown;
76
+ };
77
+ error: unknown;
78
+ }>;
79
+ signOut: () => Promise<unknown>;
80
+ };
81
+ }): AuthAdapter;
82
+ /**
83
+ * NextAuth adapter. Works with NextAuth.js v4/v5 session endpoint.
84
+ *
85
+ * @example
86
+ * ```tsx
87
+ * <AuthProvider adapter={nextAuthAdapter()}>
88
+ * // or with custom base URL:
89
+ * <AuthProvider adapter={nextAuthAdapter({ basePath: "/api/auth" })}>
90
+ * ```
91
+ */
92
+ declare function nextAuthAdapter(options?: {
93
+ basePath?: string;
94
+ }): AuthAdapter;
95
+ /**
96
+ * Clerk adapter. Wraps `@clerk/clerk-react` hooks for use with AuthProvider.
97
+ *
98
+ * @example
99
+ * ```tsx
100
+ * import { useClerk, useUser } from "@clerk/clerk-react";
101
+ *
102
+ * // Pass the Clerk instance:
103
+ * <AuthProvider adapter={clerkAdapter(clerk)}>
104
+ * ```
105
+ */
106
+ declare function clerkAdapter(clerk: {
107
+ session: {
108
+ getToken: () => Promise<string | null>;
109
+ } | null;
110
+ user: {
111
+ id: string;
112
+ primaryEmailAddress?: {
113
+ emailAddress: string;
114
+ } | null;
115
+ fullName?: string | null;
116
+ imageUrl?: string | null;
117
+ } | null | undefined;
118
+ signOut: () => Promise<void>;
119
+ }): AuthAdapter;
120
+
121
+ export { type AuthAdapter, AuthProvider, type AuthProviderProps, type AuthSession, type AuthStatus, type AuthUser, ProtectedRoute, type ProtectedRouteProps, type UseAuthReturn, type UseSessionReturn, clerkAdapter, nextAuthAdapter, supabaseAdapter, useAuth, useSession };
package/dist/index.d.ts CHANGED
@@ -48,4 +48,74 @@ interface ProtectedRouteProps {
48
48
  }
49
49
  declare function ProtectedRoute({ children, fallback, loadingFallback, }: ProtectedRouteProps): react_jsx_runtime.JSX.Element;
50
50
 
51
- export { type AuthAdapter, AuthProvider, type AuthProviderProps, type AuthSession, type AuthStatus, type AuthUser, ProtectedRoute, type ProtectedRouteProps, type UseAuthReturn, type UseSessionReturn, useAuth, useSession };
51
+ /**
52
+ * Supabase auth adapter. Wraps `@supabase/supabase-js` client.
53
+ *
54
+ * @example
55
+ * ```tsx
56
+ * import { createClient } from "@supabase/supabase-js";
57
+ * const supabase = createClient(url, key);
58
+ *
59
+ * <AuthProvider adapter={supabaseAdapter(supabase)}>
60
+ * ```
61
+ */
62
+ declare function supabaseAdapter(supabase: {
63
+ auth: {
64
+ getSession: () => Promise<{
65
+ data: {
66
+ session: unknown;
67
+ };
68
+ }>;
69
+ signInWithPassword: (creds: {
70
+ email: string;
71
+ password: string;
72
+ }) => Promise<{
73
+ data: {
74
+ session: unknown;
75
+ user: unknown;
76
+ };
77
+ error: unknown;
78
+ }>;
79
+ signOut: () => Promise<unknown>;
80
+ };
81
+ }): AuthAdapter;
82
+ /**
83
+ * NextAuth adapter. Works with NextAuth.js v4/v5 session endpoint.
84
+ *
85
+ * @example
86
+ * ```tsx
87
+ * <AuthProvider adapter={nextAuthAdapter()}>
88
+ * // or with custom base URL:
89
+ * <AuthProvider adapter={nextAuthAdapter({ basePath: "/api/auth" })}>
90
+ * ```
91
+ */
92
+ declare function nextAuthAdapter(options?: {
93
+ basePath?: string;
94
+ }): AuthAdapter;
95
+ /**
96
+ * Clerk adapter. Wraps `@clerk/clerk-react` hooks for use with AuthProvider.
97
+ *
98
+ * @example
99
+ * ```tsx
100
+ * import { useClerk, useUser } from "@clerk/clerk-react";
101
+ *
102
+ * // Pass the Clerk instance:
103
+ * <AuthProvider adapter={clerkAdapter(clerk)}>
104
+ * ```
105
+ */
106
+ declare function clerkAdapter(clerk: {
107
+ session: {
108
+ getToken: () => Promise<string | null>;
109
+ } | null;
110
+ user: {
111
+ id: string;
112
+ primaryEmailAddress?: {
113
+ emailAddress: string;
114
+ } | null;
115
+ fullName?: string | null;
116
+ imageUrl?: string | null;
117
+ } | null | undefined;
118
+ signOut: () => Promise<void>;
119
+ }): AuthAdapter;
120
+
121
+ export { type AuthAdapter, AuthProvider, type AuthProviderProps, type AuthSession, type AuthStatus, type AuthUser, ProtectedRoute, type ProtectedRouteProps, type UseAuthReturn, type UseSessionReturn, clerkAdapter, nextAuthAdapter, supabaseAdapter, useAuth, useSession };
package/dist/index.js CHANGED
@@ -23,6 +23,9 @@ var index_exports = {};
23
23
  __export(index_exports, {
24
24
  AuthProvider: () => AuthProvider,
25
25
  ProtectedRoute: () => ProtectedRoute,
26
+ clerkAdapter: () => clerkAdapter,
27
+ nextAuthAdapter: () => nextAuthAdapter,
28
+ supabaseAdapter: () => supabaseAdapter,
26
29
  useAuth: () => useAuth,
27
30
  useSession: () => useSession
28
31
  });
@@ -111,10 +114,116 @@ function ProtectedRoute({
111
114
  if (status === "unauthenticated") return /* @__PURE__ */ (0, import_jsx_runtime2.jsx)(import_jsx_runtime2.Fragment, { children: fallback });
112
115
  return /* @__PURE__ */ (0, import_jsx_runtime2.jsx)(import_jsx_runtime2.Fragment, { children });
113
116
  }
117
+
118
+ // src/adapters.ts
119
+ function supabaseAdapter(supabase) {
120
+ return {
121
+ async getSession() {
122
+ const { data } = await supabase.auth.getSession();
123
+ const session = data.session;
124
+ if (!session) return { user: null, token: null, expiresAt: null };
125
+ const user = session.user;
126
+ return {
127
+ user: user ? {
128
+ id: String(user.id),
129
+ email: user.email,
130
+ name: user.user_metadata?.full_name,
131
+ image: user.user_metadata?.avatar_url
132
+ } : null,
133
+ token: session.access_token ?? null,
134
+ expiresAt: session.expires_at ? session.expires_at * 1e3 : null
135
+ };
136
+ },
137
+ async signIn(credentials) {
138
+ const { data, error } = await supabase.auth.signInWithPassword({
139
+ email: credentials.email,
140
+ password: credentials.password
141
+ });
142
+ if (error) throw error;
143
+ const user = data.user;
144
+ const session = data.session;
145
+ return {
146
+ user: user ? {
147
+ id: String(user.id),
148
+ email: user.email,
149
+ name: user.user_metadata?.full_name
150
+ } : null,
151
+ token: session ? session.access_token : null,
152
+ expiresAt: session?.expires_at ? session.expires_at * 1e3 : null
153
+ };
154
+ },
155
+ async signOut() {
156
+ await supabase.auth.signOut();
157
+ }
158
+ };
159
+ }
160
+ function nextAuthAdapter(options) {
161
+ const basePath = options?.basePath ?? "/api/auth";
162
+ return {
163
+ async getSession() {
164
+ const res = await fetch(`${basePath}/session`);
165
+ if (!res.ok) return { user: null, token: null, expiresAt: null };
166
+ const data = await res.json();
167
+ if (!data.user) return { user: null, token: null, expiresAt: null };
168
+ const user = data.user;
169
+ return {
170
+ user: {
171
+ id: String(user.id ?? user.email),
172
+ email: user.email,
173
+ name: user.name,
174
+ image: user.image
175
+ },
176
+ token: data.accessToken ?? null,
177
+ expiresAt: data.expires ? new Date(data.expires).getTime() : null
178
+ };
179
+ },
180
+ async signIn(credentials) {
181
+ const res = await fetch(`${basePath}/callback/credentials`, {
182
+ method: "POST",
183
+ headers: { "Content-Type": "application/json" },
184
+ body: JSON.stringify(credentials)
185
+ });
186
+ if (!res.ok) throw new Error("Sign in failed");
187
+ return this.getSession();
188
+ },
189
+ async signOut() {
190
+ await fetch(`${basePath}/signout`, { method: "POST" });
191
+ }
192
+ };
193
+ }
194
+ function clerkAdapter(clerk) {
195
+ return {
196
+ async getSession() {
197
+ if (!clerk.user) return { user: null, token: null, expiresAt: null };
198
+ const token = clerk.session ? await clerk.session.getToken() : null;
199
+ return {
200
+ user: {
201
+ id: clerk.user.id,
202
+ email: clerk.user.primaryEmailAddress?.emailAddress,
203
+ name: clerk.user.fullName ?? void 0,
204
+ image: clerk.user.imageUrl ?? void 0
205
+ },
206
+ token,
207
+ expiresAt: null
208
+ };
209
+ },
210
+ async signIn() {
211
+ throw new Error(
212
+ "Clerk manages sign-in via its own components. Use <SignIn /> from @clerk/clerk-react."
213
+ );
214
+ },
215
+ async signOut() {
216
+ await clerk.signOut();
217
+ }
218
+ };
219
+ }
114
220
  // Annotate the CommonJS export names for ESM import in node:
115
221
  0 && (module.exports = {
116
222
  AuthProvider,
117
223
  ProtectedRoute,
224
+ clerkAdapter,
225
+ nextAuthAdapter,
226
+ supabaseAdapter,
118
227
  useAuth,
119
228
  useSession
120
229
  });
package/dist/index.mjs CHANGED
@@ -83,9 +83,115 @@ function ProtectedRoute({
83
83
  if (status === "unauthenticated") return /* @__PURE__ */ jsx2(Fragment, { children: fallback });
84
84
  return /* @__PURE__ */ jsx2(Fragment, { children });
85
85
  }
86
+
87
+ // src/adapters.ts
88
+ function supabaseAdapter(supabase) {
89
+ return {
90
+ async getSession() {
91
+ const { data } = await supabase.auth.getSession();
92
+ const session = data.session;
93
+ if (!session) return { user: null, token: null, expiresAt: null };
94
+ const user = session.user;
95
+ return {
96
+ user: user ? {
97
+ id: String(user.id),
98
+ email: user.email,
99
+ name: user.user_metadata?.full_name,
100
+ image: user.user_metadata?.avatar_url
101
+ } : null,
102
+ token: session.access_token ?? null,
103
+ expiresAt: session.expires_at ? session.expires_at * 1e3 : null
104
+ };
105
+ },
106
+ async signIn(credentials) {
107
+ const { data, error } = await supabase.auth.signInWithPassword({
108
+ email: credentials.email,
109
+ password: credentials.password
110
+ });
111
+ if (error) throw error;
112
+ const user = data.user;
113
+ const session = data.session;
114
+ return {
115
+ user: user ? {
116
+ id: String(user.id),
117
+ email: user.email,
118
+ name: user.user_metadata?.full_name
119
+ } : null,
120
+ token: session ? session.access_token : null,
121
+ expiresAt: session?.expires_at ? session.expires_at * 1e3 : null
122
+ };
123
+ },
124
+ async signOut() {
125
+ await supabase.auth.signOut();
126
+ }
127
+ };
128
+ }
129
+ function nextAuthAdapter(options) {
130
+ const basePath = options?.basePath ?? "/api/auth";
131
+ return {
132
+ async getSession() {
133
+ const res = await fetch(`${basePath}/session`);
134
+ if (!res.ok) return { user: null, token: null, expiresAt: null };
135
+ const data = await res.json();
136
+ if (!data.user) return { user: null, token: null, expiresAt: null };
137
+ const user = data.user;
138
+ return {
139
+ user: {
140
+ id: String(user.id ?? user.email),
141
+ email: user.email,
142
+ name: user.name,
143
+ image: user.image
144
+ },
145
+ token: data.accessToken ?? null,
146
+ expiresAt: data.expires ? new Date(data.expires).getTime() : null
147
+ };
148
+ },
149
+ async signIn(credentials) {
150
+ const res = await fetch(`${basePath}/callback/credentials`, {
151
+ method: "POST",
152
+ headers: { "Content-Type": "application/json" },
153
+ body: JSON.stringify(credentials)
154
+ });
155
+ if (!res.ok) throw new Error("Sign in failed");
156
+ return this.getSession();
157
+ },
158
+ async signOut() {
159
+ await fetch(`${basePath}/signout`, { method: "POST" });
160
+ }
161
+ };
162
+ }
163
+ function clerkAdapter(clerk) {
164
+ return {
165
+ async getSession() {
166
+ if (!clerk.user) return { user: null, token: null, expiresAt: null };
167
+ const token = clerk.session ? await clerk.session.getToken() : null;
168
+ return {
169
+ user: {
170
+ id: clerk.user.id,
171
+ email: clerk.user.primaryEmailAddress?.emailAddress,
172
+ name: clerk.user.fullName ?? void 0,
173
+ image: clerk.user.imageUrl ?? void 0
174
+ },
175
+ token,
176
+ expiresAt: null
177
+ };
178
+ },
179
+ async signIn() {
180
+ throw new Error(
181
+ "Clerk manages sign-in via its own components. Use <SignIn /> from @clerk/clerk-react."
182
+ );
183
+ },
184
+ async signOut() {
185
+ await clerk.signOut();
186
+ }
187
+ };
188
+ }
86
189
  export {
87
190
  AuthProvider,
88
191
  ProtectedRoute,
192
+ clerkAdapter,
193
+ nextAuthAdapter,
194
+ supabaseAdapter,
89
195
  useAuth,
90
196
  useSession
91
197
  };
package/package.json CHANGED
@@ -1,7 +1,7 @@
1
1
  {
2
2
  "name": "@allem-sdk/auth",
3
- "version": "0.1.1",
4
- "description": "Authentication helpers for React session, protected routes, social login",
3
+ "version": "0.1.3",
4
+ "description": "React authentication hooks with session management and protected routes. Provider-agnostic adapter pattern. useAuth, useSession, ProtectedRoute.",
5
5
  "license": "MIT",
6
6
  "author": "Ahmed Allem",
7
7
  "main": "./dist/index.js",
@@ -39,11 +39,15 @@
39
39
  "keywords": [
40
40
  "allem-sdk",
41
41
  "react",
42
- "hooks",
42
+ "react-hooks",
43
43
  "auth",
44
44
  "authentication",
45
45
  "session",
46
- "protected-route"
46
+ "protected-route",
47
+ "login",
48
+ "useAuth",
49
+ "typescript",
50
+ "nextjs"
47
51
  ],
48
52
  "publishConfig": {
49
53
  "access": "public"