next-lite-auth 0.1.0 → 0.1.2

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
@@ -2,6 +2,8 @@
2
2
 
3
3
  Lightweight JWT auth for Next.js using static JSON users — no database required.
4
4
 
5
+ **[Documentation](https://amide-init.github.io/next-lite-auth/)**
6
+
5
7
  > **Not for production.** Designed for demos, OSS projects, internal tools, and quick Vercel deployments.
6
8
 
7
9
  ---
@@ -12,6 +14,7 @@ Lightweight JWT auth for Next.js using static JSON users — no database require
12
14
  - Next.js >= 13
13
15
  - React >= 18
14
16
  - TypeScript
17
+ - Tailwind CSS + shadcn/ui (for built-in login UI)
15
18
 
16
19
  ---
17
20
 
@@ -23,194 +26,123 @@ pnpm add next-lite-auth jose
23
26
 
24
27
  ---
25
28
 
26
- ## Setup
29
+ ## Setup in 3 steps
27
30
 
28
- ### 1. Create your auth instance
31
+ ### 1. Create `auth.ts` at your project root
29
32
 
30
33
  ```ts
31
- // lib/auth.ts
32
34
  import { createLiteAuth } from "next-lite-auth";
33
35
 
34
- export const auth = createLiteAuth({
36
+ export const { handlers, middleware, getUserFromCookies } = createLiteAuth({
35
37
  users: [
36
38
  { email: "admin@example.com", password: "secret", role: "admin", name: "Admin" },
37
- { email: "user@example.com", password: "pass123", role: "user", name: "User" },
38
39
  ],
39
40
  jwtSecret: process.env.JWT_SECRET!,
40
- cookieName: "lite-auth-token", // optional, this is the default
41
41
  });
42
42
  ```
43
43
 
44
- ### 2. Add route handlers
45
-
46
- ```ts
47
- // app/api/auth/login/route.ts
48
- import { auth } from "@/lib/auth";
49
- export const POST = auth.handlers.login;
50
-
51
- // app/api/auth/logout/route.ts
52
- import { auth } from "@/lib/auth";
53
- export const POST = auth.handlers.logout;
54
-
55
- // app/api/auth/me/route.ts
56
- import { auth } from "@/lib/auth";
57
- export const GET = auth.handlers.me;
44
+ ```bash
45
+ # .env.local
46
+ JWT_SECRET=your-random-secret-here
58
47
  ```
59
48
 
60
- ### 3. Add middleware
49
+ ### 2. Add one route file
61
50
 
62
51
  ```ts
63
- // middleware.ts
64
- import { auth } from "@/lib/auth";
65
-
66
- export default auth.middleware({
67
- protect: ["/dashboard", "/settings"],
68
- redirectTo: "/login", // optional, default is "/login"
69
- });
70
-
71
- export const config = {
72
- matcher: ["/((?!_next|api/auth).*)"],
73
- };
52
+ // app/api/auth/[...liteauth]/route.ts
53
+ import { handlers } from "@/auth";
54
+ export const { GET, POST } = handlers;
74
55
  ```
75
56
 
76
- ### 4. Use on the client
57
+ ### 3. Wrap root layout
77
58
 
78
59
  ```tsx
79
- "use client";
80
-
81
- import { useLiteAuth } from "next-lite-auth/client";
82
-
83
- export default function LoginPage() {
84
- const { user, loading, login, logout } = useLiteAuth();
85
-
86
- if (loading) return <p>Loading...</p>;
87
-
88
- if (user) {
89
- return (
90
- <div>
91
- <p>Hello, {user.name ?? user.email}</p>
92
- <button onClick={logout}>Logout</button>
93
- </div>
94
- );
95
- }
60
+ // app/layout.tsx
61
+ import { LiteAuthProvider } from "next-lite-auth/client";
96
62
 
63
+ export default function RootLayout({ children }: { children: React.ReactNode }) {
97
64
  return (
98
- <form
99
- onSubmit={async (e) => {
100
- e.preventDefault();
101
- const form = e.currentTarget;
102
- const result = await login({
103
- email: form.email.value,
104
- password: form.password.value,
105
- });
106
- if (result.error) alert(result.error);
107
- }}
108
- >
109
- <input name="email" type="email" placeholder="Email" />
110
- <input name="password" type="password" placeholder="Password" />
111
- <button type="submit">Login</button>
112
- </form>
65
+ <html>
66
+ <body>
67
+ <LiteAuthProvider protect={["/dashboard", "/settings"]}>
68
+ {children}
69
+ </LiteAuthProvider>
70
+ </body>
71
+ </html>
113
72
  );
114
73
  }
115
74
  ```
116
75
 
117
- ### 5. Read user on the server
118
-
119
- ```ts
120
- // app/dashboard/page.tsx
121
- import { cookies } from "next/headers";
122
- import { auth } from "@/lib/auth";
123
-
124
- export default async function DashboardPage() {
125
- const user = await auth.getUserFromCookies(cookies());
126
- return <p>Welcome, {user?.name}</p>;
127
- }
128
- ```
76
+ **Done.** Visiting a protected route while logged out automatically shows the built-in login UI. After login, the original page renders instantly — no redirects, no separate login page needed.
129
77
 
130
78
  ---
131
79
 
132
- ## API Reference
80
+ ## Tailwind setup
133
81
 
134
- ### `createLiteAuth(config)`
135
-
136
- | Option | Type | Required | Description |
137
- |---|---|---|---|
138
- | `users` | `User[]` | Yes | Hardcoded list of users |
139
- | `jwtSecret` | `string` | Yes | Secret used to sign JWTs |
140
- | `cookieName` | `string` | No | Cookie name (default: `"lite-auth-token"`) |
141
-
142
- Returns `{ handlers, middleware, getUserFromCookies }`.
143
-
144
- ---
145
-
146
- ### `User` type
82
+ Add the library to your Tailwind `content` config so login UI styles are included:
147
83
 
148
84
  ```ts
149
- type User = {
150
- email: string;
151
- password: string;
152
- role?: string;
153
- name?: string;
154
- };
85
+ // tailwind.config.ts
86
+ content: [
87
+ "./app/**/*.{ts,tsx}",
88
+ "./node_modules/next-lite-auth/dist/**/*.{js,mjs}",
89
+ ]
155
90
  ```
156
91
 
157
92
  ---
158
93
 
159
- ### `auth.handlers`
160
-
161
- | Handler | Method | Route |
162
- |---|---|---|
163
- | `login` | POST | `/api/auth/login` |
164
- | `logout` | POST | `/api/auth/logout` |
165
- | `me` | GET | `/api/auth/me` |
166
-
167
- ---
168
-
169
- ### `auth.middleware(options)`
94
+ ## Optional: server-side middleware
170
95
 
171
- | Option | Type | Default | Description |
172
- |---|---|---|---|
173
- | `protect` | `string[]` | — | Route prefixes to protect |
174
- | `redirectTo` | `string` | `"/login"` | Where to redirect unauthenticated users |
96
+ ```ts
97
+ // middleware.ts
98
+ import { middleware } from "@/auth";
99
+ export default middleware({ protect: ["/dashboard", "/settings"] });
175
100
 
176
- Appends `?from=<pathname>` to the redirect URL.
101
+ export const config = {
102
+ matcher: ["/((?!_next|api/auth).*)"],
103
+ };
104
+ ```
177
105
 
178
106
  ---
179
107
 
180
- ### `auth.getUserFromCookies(cookies)`
181
-
182
- Server-side helper. Accepts Next.js `cookies()` and returns the current `PublicUser` or `null`.
108
+ ## Use anywhere
183
109
 
184
- ---
185
-
186
- ### `useLiteAuth(options?)`
110
+ ```tsx
111
+ "use client";
112
+ import { useLiteAuth } from "next-lite-auth/client";
187
113
 
188
- Client hook. Fetches `/api/auth/me` on mount.
114
+ export function Navbar() {
115
+ const { user, logout } = useLiteAuth();
116
+ if (!user) return null;
117
+ return (
118
+ <div>
119
+ <span>{user.name ?? user.email}</span>
120
+ <button onClick={logout}>Logout</button>
121
+ </div>
122
+ );
123
+ }
124
+ ```
189
125
 
190
126
  ```ts
191
- const { user, loading, login, logout } = useLiteAuth({
192
- loginPath: "/api/auth/login", // optional
193
- logoutPath: "/api/auth/logout", // optional
194
- mePath: "/api/auth/me", // optional
195
- });
196
- ```
127
+ // Server Component
128
+ import { cookies } from "next/headers";
129
+ import { getUserFromCookies } from "@/auth";
197
130
 
198
- | Return | Type | Description |
199
- |---|---|---|
200
- | `user` | `PublicUser \| null` | Current authenticated user |
201
- | `loading` | `boolean` | True while fetching session |
202
- | `login(creds)` | `Promise<{ error?: string }>` | Logs in and sets user state |
203
- | `logout()` | `Promise<void>` | Clears cookie and user state |
131
+ const user = await getUserFromCookies(cookies());
132
+ ```
204
133
 
205
134
  ---
206
135
 
207
- ## Non-Goals
136
+ ## API
208
137
 
209
- - OAuth / social login
210
- - Signup / registration
211
- - Password reset
212
- - Role-based access control
213
- - Production-grade security
138
+ | Export | Description |
139
+ |---|---|
140
+ | `createLiteAuth(config)` | Factory — returns `handlers`, `middleware`, `getUserFromCookies` |
141
+ | `handlers.GET / POST` | Catch-all route handlers |
142
+ | `middleware(options)` | Edge middleware for server-side route protection |
143
+ | `getUserFromCookies(cookies)` | Server-side session helper |
144
+ | `LiteAuthProvider` | Root provider — manages session and auto-shows login UI |
145
+ | `useLiteAuth()` | Hook — `user`, `loading`, `login`, `logout` |
214
146
 
215
147
  ---
216
148
 
package/dist/client.d.mts CHANGED
@@ -1,3 +1,6 @@
1
+ import * as react_jsx_runtime from 'react/jsx-runtime';
2
+ import { ReactNode } from 'react';
3
+
1
4
  type User = {
2
5
  email: string;
3
6
  password: string;
@@ -6,25 +9,31 @@ type User = {
6
9
  };
7
10
  type PublicUser = Omit<User, "password">;
8
11
 
9
- type LiteAuthState = {
12
+ type LiteAuthContextValue = {
10
13
  user: PublicUser | null;
11
14
  loading: boolean;
12
- };
13
- type LoginCredentials = {
14
- email: string;
15
- password: string;
16
- };
17
- type UseLiteAuthReturn = LiteAuthState & {
18
- login: (credentials: LoginCredentials) => Promise<{
15
+ login: (creds: {
16
+ email: string;
17
+ password: string;
18
+ }) => Promise<{
19
19
  error?: string;
20
20
  }>;
21
21
  logout: () => Promise<void>;
22
22
  };
23
- type UseLiteAuthOptions = {
23
+ type LiteAuthProviderProps = {
24
+ children: ReactNode;
25
+ protect?: string[];
24
26
  loginPath?: string;
25
27
  logoutPath?: string;
26
28
  mePath?: string;
27
29
  };
28
- declare function useLiteAuth(options?: UseLiteAuthOptions): UseLiteAuthReturn;
30
+ declare function LiteAuthProvider({ children, protect, loginPath, logoutPath, mePath, }: LiteAuthProviderProps): react_jsx_runtime.JSX.Element;
31
+ declare function useLiteAuth(): LiteAuthContextValue;
32
+
33
+ type LiteLoginPageProps = {
34
+ title?: string;
35
+ description?: string;
36
+ };
37
+ declare function LiteLoginPage({ title, description, }: LiteLoginPageProps): react_jsx_runtime.JSX.Element;
29
38
 
30
- export { useLiteAuth };
39
+ export { LiteAuthProvider, LiteLoginPage, useLiteAuth };
package/dist/client.d.ts CHANGED
@@ -1,3 +1,6 @@
1
+ import * as react_jsx_runtime from 'react/jsx-runtime';
2
+ import { ReactNode } from 'react';
3
+
1
4
  type User = {
2
5
  email: string;
3
6
  password: string;
@@ -6,25 +9,31 @@ type User = {
6
9
  };
7
10
  type PublicUser = Omit<User, "password">;
8
11
 
9
- type LiteAuthState = {
12
+ type LiteAuthContextValue = {
10
13
  user: PublicUser | null;
11
14
  loading: boolean;
12
- };
13
- type LoginCredentials = {
14
- email: string;
15
- password: string;
16
- };
17
- type UseLiteAuthReturn = LiteAuthState & {
18
- login: (credentials: LoginCredentials) => Promise<{
15
+ login: (creds: {
16
+ email: string;
17
+ password: string;
18
+ }) => Promise<{
19
19
  error?: string;
20
20
  }>;
21
21
  logout: () => Promise<void>;
22
22
  };
23
- type UseLiteAuthOptions = {
23
+ type LiteAuthProviderProps = {
24
+ children: ReactNode;
25
+ protect?: string[];
24
26
  loginPath?: string;
25
27
  logoutPath?: string;
26
28
  mePath?: string;
27
29
  };
28
- declare function useLiteAuth(options?: UseLiteAuthOptions): UseLiteAuthReturn;
30
+ declare function LiteAuthProvider({ children, protect, loginPath, logoutPath, mePath, }: LiteAuthProviderProps): react_jsx_runtime.JSX.Element;
31
+ declare function useLiteAuth(): LiteAuthContextValue;
32
+
33
+ type LiteLoginPageProps = {
34
+ title?: string;
35
+ description?: string;
36
+ };
37
+ declare function LiteLoginPage({ title, description, }: LiteLoginPageProps): react_jsx_runtime.JSX.Element;
29
38
 
30
- export { useLiteAuth };
39
+ export { LiteAuthProvider, LiteLoginPage, useLiteAuth };
package/dist/client.js CHANGED
@@ -20,23 +20,123 @@ var __toCommonJS = (mod) => __copyProps(__defProp({}, "__esModule", { value: tru
20
20
  // src/client/index.ts
21
21
  var client_exports = {};
22
22
  __export(client_exports, {
23
+ LiteAuthProvider: () => LiteAuthProvider,
24
+ LiteLoginPage: () => LiteLoginPage,
23
25
  useLiteAuth: () => useLiteAuth
24
26
  });
25
27
  module.exports = __toCommonJS(client_exports);
26
28
 
27
- // src/client/useLiteAuth.ts
29
+ // src/client/LiteAuthProvider.tsx
30
+ var import_react2 = require("react");
31
+ var import_navigation = require("next/navigation");
32
+
33
+ // src/client/LiteLoginPage.tsx
28
34
  var import_react = require("react");
29
- function useLiteAuth(options = {}) {
30
- const {
31
- loginPath = "/api/auth/login",
32
- logoutPath = "/api/auth/logout",
33
- mePath = "/api/auth/me"
34
- } = options;
35
- const [state, setState] = (0, import_react.useState)({ user: null, loading: true });
36
- (0, import_react.useEffect)(() => {
37
- fetch(mePath).then((r) => r.json()).then(({ user }) => setState({ user: user ?? null, loading: false })).catch(() => setState({ user: null, loading: false }));
35
+ var import_jsx_runtime = require("react/jsx-runtime");
36
+ function LiteLoginPage({
37
+ title = "Sign in",
38
+ description = "Enter your credentials to continue"
39
+ }) {
40
+ const { login } = useLiteAuth();
41
+ const [error, setError] = (0, import_react.useState)("");
42
+ const [loading, setLoading] = (0, import_react.useState)(false);
43
+ async function handleSubmit(e) {
44
+ e.preventDefault();
45
+ setError("");
46
+ setLoading(true);
47
+ const form = e.currentTarget;
48
+ const result = await login({
49
+ email: form.elements.namedItem("email").value,
50
+ password: form.elements.namedItem("password").value
51
+ });
52
+ setLoading(false);
53
+ if (result.error) {
54
+ setError(result.error);
55
+ }
56
+ }
57
+ return /* @__PURE__ */ (0, import_jsx_runtime.jsx)("div", { className: "min-h-screen flex items-center justify-center bg-background px-4", children: /* @__PURE__ */ (0, import_jsx_runtime.jsxs)("div", { className: "w-full max-w-sm space-y-6", children: [
58
+ /* @__PURE__ */ (0, import_jsx_runtime.jsxs)("div", { className: "space-y-1 text-center", children: [
59
+ /* @__PURE__ */ (0, import_jsx_runtime.jsx)("h1", { className: "text-2xl font-semibold tracking-tight", children: title }),
60
+ /* @__PURE__ */ (0, import_jsx_runtime.jsx)("p", { className: "text-sm text-muted-foreground", children: description })
61
+ ] }),
62
+ /* @__PURE__ */ (0, import_jsx_runtime.jsxs)("div", { className: "rounded-xl border bg-card text-card-foreground shadow-sm p-6 space-y-4", children: [
63
+ error && /* @__PURE__ */ (0, import_jsx_runtime.jsx)("div", { className: "rounded-md bg-destructive/10 px-3 py-2 text-sm text-destructive", children: error }),
64
+ /* @__PURE__ */ (0, import_jsx_runtime.jsxs)("form", { onSubmit: handleSubmit, className: "space-y-4", children: [
65
+ /* @__PURE__ */ (0, import_jsx_runtime.jsxs)("div", { className: "space-y-1.5", children: [
66
+ /* @__PURE__ */ (0, import_jsx_runtime.jsx)("label", { htmlFor: "email", className: "text-sm font-medium leading-none", children: "Email" }),
67
+ /* @__PURE__ */ (0, import_jsx_runtime.jsx)(
68
+ "input",
69
+ {
70
+ id: "email",
71
+ name: "email",
72
+ type: "email",
73
+ required: true,
74
+ autoComplete: "email",
75
+ placeholder: "you@example.com",
76
+ className: "flex h-9 w-full rounded-md border border-input bg-transparent px-3 py-1 text-sm shadow-sm transition-colors placeholder:text-muted-foreground focus-visible:outline-none focus-visible:ring-1 focus-visible:ring-ring disabled:cursor-not-allowed disabled:opacity-50"
77
+ }
78
+ )
79
+ ] }),
80
+ /* @__PURE__ */ (0, import_jsx_runtime.jsxs)("div", { className: "space-y-1.5", children: [
81
+ /* @__PURE__ */ (0, import_jsx_runtime.jsx)("label", { htmlFor: "password", className: "text-sm font-medium leading-none", children: "Password" }),
82
+ /* @__PURE__ */ (0, import_jsx_runtime.jsx)(
83
+ "input",
84
+ {
85
+ id: "password",
86
+ name: "password",
87
+ type: "password",
88
+ required: true,
89
+ autoComplete: "current-password",
90
+ placeholder: "\u2022\u2022\u2022\u2022\u2022\u2022\u2022\u2022",
91
+ className: "flex h-9 w-full rounded-md border border-input bg-transparent px-3 py-1 text-sm shadow-sm transition-colors placeholder:text-muted-foreground focus-visible:outline-none focus-visible:ring-1 focus-visible:ring-ring disabled:cursor-not-allowed disabled:opacity-50"
92
+ }
93
+ )
94
+ ] }),
95
+ /* @__PURE__ */ (0, import_jsx_runtime.jsx)(
96
+ "button",
97
+ {
98
+ type: "submit",
99
+ disabled: loading,
100
+ className: "inline-flex h-9 w-full items-center justify-center rounded-md bg-primary px-4 py-2 text-sm font-medium text-primary-foreground shadow hover:bg-primary/90 focus-visible:outline-none focus-visible:ring-1 focus-visible:ring-ring disabled:pointer-events-none disabled:opacity-50 transition-colors",
101
+ children: loading ? "Signing in\u2026" : "Sign in"
102
+ }
103
+ )
104
+ ] })
105
+ ] }),
106
+ /* @__PURE__ */ (0, import_jsx_runtime.jsxs)("p", { className: "text-center text-xs text-muted-foreground", children: [
107
+ "Powered by",
108
+ " ",
109
+ /* @__PURE__ */ (0, import_jsx_runtime.jsx)(
110
+ "a",
111
+ {
112
+ href: "https://github.com/amide-init/next-lite-auth",
113
+ target: "_blank",
114
+ rel: "noopener noreferrer",
115
+ className: "underline underline-offset-4 hover:text-primary transition-colors",
116
+ children: "next-lite-auth"
117
+ }
118
+ )
119
+ ] })
120
+ ] }) });
121
+ }
122
+
123
+ // src/client/LiteAuthProvider.tsx
124
+ var import_jsx_runtime2 = require("react/jsx-runtime");
125
+ var LiteAuthContext = (0, import_react2.createContext)(null);
126
+ function LiteAuthProvider({
127
+ children,
128
+ protect = [],
129
+ loginPath = "/api/auth/login",
130
+ logoutPath = "/api/auth/logout",
131
+ mePath = "/api/auth/me"
132
+ }) {
133
+ const [user, setUser] = (0, import_react2.useState)(null);
134
+ const [loading, setLoading] = (0, import_react2.useState)(true);
135
+ const pathname = (0, import_navigation.usePathname)();
136
+ (0, import_react2.useEffect)(() => {
137
+ fetch(mePath).then((r) => r.json()).then(({ user: user2 }) => setUser(user2 ?? null)).catch(() => setUser(null)).finally(() => setLoading(false));
38
138
  }, [mePath]);
39
- const login = (0, import_react.useCallback)(
139
+ const login = (0, import_react2.useCallback)(
40
140
  async ({ email, password }) => {
41
141
  const res = await fetch(loginPath, {
42
142
  method: "POST",
@@ -45,19 +145,36 @@ function useLiteAuth(options = {}) {
45
145
  });
46
146
  const data = await res.json();
47
147
  if (!res.ok) return { error: data.error ?? "Login failed" };
48
- setState({ user: data.user, loading: false });
148
+ setUser(data.user);
49
149
  return {};
50
150
  },
51
151
  [loginPath]
52
152
  );
53
- const logout = (0, import_react.useCallback)(async () => {
153
+ const logout = (0, import_react2.useCallback)(async () => {
54
154
  await fetch(logoutPath, { method: "POST" });
55
- setState({ user: null, loading: false });
155
+ setUser(null);
56
156
  }, [logoutPath]);
57
- return { ...state, login, logout };
157
+ const value = { user, loading, login, logout };
158
+ const isProtected = protect.some(
159
+ (p) => pathname === p || pathname.startsWith(p + "/")
160
+ );
161
+ if (loading) {
162
+ return /* @__PURE__ */ (0, import_jsx_runtime2.jsx)(LiteAuthContext.Provider, { value, children });
163
+ }
164
+ if (!user && isProtected) {
165
+ return /* @__PURE__ */ (0, import_jsx_runtime2.jsx)(LiteAuthContext.Provider, { value, children: /* @__PURE__ */ (0, import_jsx_runtime2.jsx)(LiteLoginPage, {}) });
166
+ }
167
+ return /* @__PURE__ */ (0, import_jsx_runtime2.jsx)(LiteAuthContext.Provider, { value, children });
168
+ }
169
+ function useLiteAuth() {
170
+ const ctx = (0, import_react2.useContext)(LiteAuthContext);
171
+ if (!ctx) throw new Error("useLiteAuth must be used inside <LiteAuthProvider>");
172
+ return ctx;
58
173
  }
59
174
  // Annotate the CommonJS export names for ESM import in node:
60
175
  0 && (module.exports = {
176
+ LiteAuthProvider,
177
+ LiteLoginPage,
61
178
  useLiteAuth
62
179
  });
63
180
  //# sourceMappingURL=client.js.map
@@ -1 +1 @@
1
- {"version":3,"sources":["../src/client/index.ts","../src/client/useLiteAuth.ts"],"sourcesContent":["export { useLiteAuth } from \"./useLiteAuth\";\n","\"use client\";\n\nimport { useState, useEffect, useCallback } from \"react\";\nimport { PublicUser } from \"../core/types\";\n\ntype LiteAuthState = {\n user: PublicUser | null;\n loading: boolean;\n};\n\ntype LoginCredentials = {\n email: string;\n password: string;\n};\n\ntype UseLiteAuthReturn = LiteAuthState & {\n login: (credentials: LoginCredentials) => Promise<{ error?: string }>;\n logout: () => Promise<void>;\n};\n\ntype UseLiteAuthOptions = {\n loginPath?: string;\n logoutPath?: string;\n mePath?: string;\n};\n\nexport function useLiteAuth(options: UseLiteAuthOptions = {}): UseLiteAuthReturn {\n const {\n loginPath = \"/api/auth/login\",\n logoutPath = \"/api/auth/logout\",\n mePath = \"/api/auth/me\",\n } = options;\n\n const [state, setState] = useState<LiteAuthState>({ user: null, loading: true });\n\n useEffect(() => {\n fetch(mePath)\n .then((r) => r.json())\n .then(({ user }) => setState({ user: user ?? null, loading: false }))\n .catch(() => setState({ user: null, loading: false }));\n }, [mePath]);\n\n const login = useCallback(\n async ({ email, password }: LoginCredentials) => {\n const res = await fetch(loginPath, {\n method: \"POST\",\n headers: { \"Content-Type\": \"application/json\" },\n body: JSON.stringify({ email, password }),\n });\n const data = await res.json();\n if (!res.ok) return { error: data.error ?? \"Login failed\" };\n setState({ user: data.user, loading: false });\n return {};\n },\n [loginPath]\n );\n\n const logout = useCallback(async () => {\n await fetch(logoutPath, { method: \"POST\" });\n setState({ user: null, loading: false });\n }, [logoutPath]);\n\n return { ...state, login, logout };\n}\n"],"mappings":";;;;;;;;;;;;;;;;;;;;AAAA;AAAA;AAAA;AAAA;AAAA;;;ACEA,mBAAiD;AAwB1C,SAAS,YAAY,UAA8B,CAAC,GAAsB;AAC/E,QAAM;AAAA,IACJ,YAAY;AAAA,IACZ,aAAa;AAAA,IACb,SAAS;AAAA,EACX,IAAI;AAEJ,QAAM,CAAC,OAAO,QAAQ,QAAI,uBAAwB,EAAE,MAAM,MAAM,SAAS,KAAK,CAAC;AAE/E,8BAAU,MAAM;AACd,UAAM,MAAM,EACT,KAAK,CAAC,MAAM,EAAE,KAAK,CAAC,EACpB,KAAK,CAAC,EAAE,KAAK,MAAM,SAAS,EAAE,MAAM,QAAQ,MAAM,SAAS,MAAM,CAAC,CAAC,EACnE,MAAM,MAAM,SAAS,EAAE,MAAM,MAAM,SAAS,MAAM,CAAC,CAAC;AAAA,EACzD,GAAG,CAAC,MAAM,CAAC;AAEX,QAAM,YAAQ;AAAA,IACZ,OAAO,EAAE,OAAO,SAAS,MAAwB;AAC/C,YAAM,MAAM,MAAM,MAAM,WAAW;AAAA,QACjC,QAAQ;AAAA,QACR,SAAS,EAAE,gBAAgB,mBAAmB;AAAA,QAC9C,MAAM,KAAK,UAAU,EAAE,OAAO,SAAS,CAAC;AAAA,MAC1C,CAAC;AACD,YAAM,OAAO,MAAM,IAAI,KAAK;AAC5B,UAAI,CAAC,IAAI,GAAI,QAAO,EAAE,OAAO,KAAK,SAAS,eAAe;AAC1D,eAAS,EAAE,MAAM,KAAK,MAAM,SAAS,MAAM,CAAC;AAC5C,aAAO,CAAC;AAAA,IACV;AAAA,IACA,CAAC,SAAS;AAAA,EACZ;AAEA,QAAM,aAAS,0BAAY,YAAY;AACrC,UAAM,MAAM,YAAY,EAAE,QAAQ,OAAO,CAAC;AAC1C,aAAS,EAAE,MAAM,MAAM,SAAS,MAAM,CAAC;AAAA,EACzC,GAAG,CAAC,UAAU,CAAC;AAEf,SAAO,EAAE,GAAG,OAAO,OAAO,OAAO;AACnC;","names":[]}
1
+ {"version":3,"sources":["../src/client/index.ts","../src/client/LiteAuthProvider.tsx","../src/client/LiteLoginPage.tsx"],"sourcesContent":["export { LiteAuthProvider, useLiteAuth } from \"./LiteAuthProvider\";\nexport { LiteLoginPage } from \"./LiteLoginPage\";\n","\"use client\";\n\nimport { createContext, useContext, useState, useEffect, useCallback, ReactNode } from \"react\";\nimport { usePathname } from \"next/navigation\";\nimport { PublicUser } from \"../core/types\";\nimport { LiteLoginPage } from \"./LiteLoginPage\";\n\ntype LiteAuthContextValue = {\n user: PublicUser | null;\n loading: boolean;\n login: (creds: { email: string; password: string }) => Promise<{ error?: string }>;\n logout: () => Promise<void>;\n};\n\nconst LiteAuthContext = createContext<LiteAuthContextValue | null>(null);\n\ntype LiteAuthProviderProps = {\n children: ReactNode;\n protect?: string[];\n loginPath?: string;\n logoutPath?: string;\n mePath?: string;\n};\n\nexport function LiteAuthProvider({\n children,\n protect = [],\n loginPath = \"/api/auth/login\",\n logoutPath = \"/api/auth/logout\",\n mePath = \"/api/auth/me\",\n}: LiteAuthProviderProps) {\n const [user, setUser] = useState<PublicUser | null>(null);\n const [loading, setLoading] = useState(true);\n const pathname = usePathname();\n\n useEffect(() => {\n fetch(mePath)\n .then((r) => r.json())\n .then(({ user }) => setUser(user ?? null))\n .catch(() => setUser(null))\n .finally(() => setLoading(false));\n }, [mePath]);\n\n const login = useCallback(\n async ({ email, password }: { email: string; password: string }) => {\n const res = await fetch(loginPath, {\n method: \"POST\",\n headers: { \"Content-Type\": \"application/json\" },\n body: JSON.stringify({ email, password }),\n });\n const data = await res.json();\n if (!res.ok) return { error: data.error ?? \"Login failed\" };\n setUser(data.user);\n return {};\n },\n [loginPath]\n );\n\n const logout = useCallback(async () => {\n await fetch(logoutPath, { method: \"POST\" });\n setUser(null);\n }, [logoutPath]);\n\n const value = { user, loading, login, logout };\n\n const isProtected = protect.some(\n (p) => pathname === p || pathname.startsWith(p + \"/\")\n );\n\n if (loading) {\n return (\n <LiteAuthContext.Provider value={value}>\n {children}\n </LiteAuthContext.Provider>\n );\n }\n\n if (!user && isProtected) {\n return (\n <LiteAuthContext.Provider value={value}>\n <LiteLoginPage />\n </LiteAuthContext.Provider>\n );\n }\n\n return (\n <LiteAuthContext.Provider value={value}>\n {children}\n </LiteAuthContext.Provider>\n );\n}\n\nexport function useLiteAuth(): LiteAuthContextValue {\n const ctx = useContext(LiteAuthContext);\n if (!ctx) throw new Error(\"useLiteAuth must be used inside <LiteAuthProvider>\");\n return ctx;\n}\n","\"use client\";\n\nimport { FormEvent, useState } from \"react\";\nimport { useLiteAuth } from \"./LiteAuthProvider\";\n\ntype LiteLoginPageProps = {\n title?: string;\n description?: string;\n};\n\nexport function LiteLoginPage({\n title = \"Sign in\",\n description = \"Enter your credentials to continue\",\n}: LiteLoginPageProps) {\n const { login } = useLiteAuth();\n const [error, setError] = useState(\"\");\n const [loading, setLoading] = useState(false);\n\n async function handleSubmit(e: FormEvent<HTMLFormElement>) {\n e.preventDefault();\n setError(\"\");\n setLoading(true);\n\n const form = e.currentTarget;\n const result = await login({\n email: (form.elements.namedItem(\"email\") as HTMLInputElement).value,\n password: (form.elements.namedItem(\"password\") as HTMLInputElement).value,\n });\n\n setLoading(false);\n\n if (result.error) {\n setError(result.error);\n }\n // no redirect needed — login() sets user in context,\n // LiteAuthProvider re-renders children automatically\n }\n\n return (\n <div className=\"min-h-screen flex items-center justify-center bg-background px-4\">\n <div className=\"w-full max-w-sm space-y-6\">\n\n <div className=\"space-y-1 text-center\">\n <h1 className=\"text-2xl font-semibold tracking-tight\">{title}</h1>\n <p className=\"text-sm text-muted-foreground\">{description}</p>\n </div>\n\n <div className=\"rounded-xl border bg-card text-card-foreground shadow-sm p-6 space-y-4\">\n {error && (\n <div className=\"rounded-md bg-destructive/10 px-3 py-2 text-sm text-destructive\">\n {error}\n </div>\n )}\n\n <form onSubmit={handleSubmit} className=\"space-y-4\">\n <div className=\"space-y-1.5\">\n <label htmlFor=\"email\" className=\"text-sm font-medium leading-none\">\n Email\n </label>\n <input\n id=\"email\"\n name=\"email\"\n type=\"email\"\n required\n autoComplete=\"email\"\n placeholder=\"you@example.com\"\n className=\"flex h-9 w-full rounded-md border border-input bg-transparent px-3 py-1 text-sm shadow-sm transition-colors placeholder:text-muted-foreground focus-visible:outline-none focus-visible:ring-1 focus-visible:ring-ring disabled:cursor-not-allowed disabled:opacity-50\"\n />\n </div>\n\n <div className=\"space-y-1.5\">\n <label htmlFor=\"password\" className=\"text-sm font-medium leading-none\">\n Password\n </label>\n <input\n id=\"password\"\n name=\"password\"\n type=\"password\"\n required\n autoComplete=\"current-password\"\n placeholder=\"••••••••\"\n className=\"flex h-9 w-full rounded-md border border-input bg-transparent px-3 py-1 text-sm shadow-sm transition-colors placeholder:text-muted-foreground focus-visible:outline-none focus-visible:ring-1 focus-visible:ring-ring disabled:cursor-not-allowed disabled:opacity-50\"\n />\n </div>\n\n <button\n type=\"submit\"\n disabled={loading}\n className=\"inline-flex h-9 w-full items-center justify-center rounded-md bg-primary px-4 py-2 text-sm font-medium text-primary-foreground shadow hover:bg-primary/90 focus-visible:outline-none focus-visible:ring-1 focus-visible:ring-ring disabled:pointer-events-none disabled:opacity-50 transition-colors\"\n >\n {loading ? \"Signing in…\" : \"Sign in\"}\n </button>\n </form>\n </div>\n\n <p className=\"text-center text-xs text-muted-foreground\">\n Powered by{\" \"}\n <a\n href=\"https://github.com/amide-init/next-lite-auth\"\n target=\"_blank\"\n rel=\"noopener noreferrer\"\n className=\"underline underline-offset-4 hover:text-primary transition-colors\"\n >\n next-lite-auth\n </a>\n </p>\n\n </div>\n </div>\n );\n}\n"],"mappings":"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","names":["import_react","import_jsx_runtime","user"]}
package/dist/client.mjs CHANGED
@@ -1,14 +1,112 @@
1
- // src/client/useLiteAuth.ts
2
- import { useState, useEffect, useCallback } from "react";
3
- function useLiteAuth(options = {}) {
4
- const {
5
- loginPath = "/api/auth/login",
6
- logoutPath = "/api/auth/logout",
7
- mePath = "/api/auth/me"
8
- } = options;
9
- const [state, setState] = useState({ user: null, loading: true });
1
+ // src/client/LiteAuthProvider.tsx
2
+ import { createContext, useContext, useState as useState2, useEffect, useCallback } from "react";
3
+ import { usePathname } from "next/navigation";
4
+
5
+ // src/client/LiteLoginPage.tsx
6
+ import { useState } from "react";
7
+ import { jsx, jsxs } from "react/jsx-runtime";
8
+ function LiteLoginPage({
9
+ title = "Sign in",
10
+ description = "Enter your credentials to continue"
11
+ }) {
12
+ const { login } = useLiteAuth();
13
+ const [error, setError] = useState("");
14
+ const [loading, setLoading] = useState(false);
15
+ async function handleSubmit(e) {
16
+ e.preventDefault();
17
+ setError("");
18
+ setLoading(true);
19
+ const form = e.currentTarget;
20
+ const result = await login({
21
+ email: form.elements.namedItem("email").value,
22
+ password: form.elements.namedItem("password").value
23
+ });
24
+ setLoading(false);
25
+ if (result.error) {
26
+ setError(result.error);
27
+ }
28
+ }
29
+ return /* @__PURE__ */ jsx("div", { className: "min-h-screen flex items-center justify-center bg-background px-4", children: /* @__PURE__ */ jsxs("div", { className: "w-full max-w-sm space-y-6", children: [
30
+ /* @__PURE__ */ jsxs("div", { className: "space-y-1 text-center", children: [
31
+ /* @__PURE__ */ jsx("h1", { className: "text-2xl font-semibold tracking-tight", children: title }),
32
+ /* @__PURE__ */ jsx("p", { className: "text-sm text-muted-foreground", children: description })
33
+ ] }),
34
+ /* @__PURE__ */ jsxs("div", { className: "rounded-xl border bg-card text-card-foreground shadow-sm p-6 space-y-4", children: [
35
+ error && /* @__PURE__ */ jsx("div", { className: "rounded-md bg-destructive/10 px-3 py-2 text-sm text-destructive", children: error }),
36
+ /* @__PURE__ */ jsxs("form", { onSubmit: handleSubmit, className: "space-y-4", children: [
37
+ /* @__PURE__ */ jsxs("div", { className: "space-y-1.5", children: [
38
+ /* @__PURE__ */ jsx("label", { htmlFor: "email", className: "text-sm font-medium leading-none", children: "Email" }),
39
+ /* @__PURE__ */ jsx(
40
+ "input",
41
+ {
42
+ id: "email",
43
+ name: "email",
44
+ type: "email",
45
+ required: true,
46
+ autoComplete: "email",
47
+ placeholder: "you@example.com",
48
+ className: "flex h-9 w-full rounded-md border border-input bg-transparent px-3 py-1 text-sm shadow-sm transition-colors placeholder:text-muted-foreground focus-visible:outline-none focus-visible:ring-1 focus-visible:ring-ring disabled:cursor-not-allowed disabled:opacity-50"
49
+ }
50
+ )
51
+ ] }),
52
+ /* @__PURE__ */ jsxs("div", { className: "space-y-1.5", children: [
53
+ /* @__PURE__ */ jsx("label", { htmlFor: "password", className: "text-sm font-medium leading-none", children: "Password" }),
54
+ /* @__PURE__ */ jsx(
55
+ "input",
56
+ {
57
+ id: "password",
58
+ name: "password",
59
+ type: "password",
60
+ required: true,
61
+ autoComplete: "current-password",
62
+ placeholder: "\u2022\u2022\u2022\u2022\u2022\u2022\u2022\u2022",
63
+ className: "flex h-9 w-full rounded-md border border-input bg-transparent px-3 py-1 text-sm shadow-sm transition-colors placeholder:text-muted-foreground focus-visible:outline-none focus-visible:ring-1 focus-visible:ring-ring disabled:cursor-not-allowed disabled:opacity-50"
64
+ }
65
+ )
66
+ ] }),
67
+ /* @__PURE__ */ jsx(
68
+ "button",
69
+ {
70
+ type: "submit",
71
+ disabled: loading,
72
+ className: "inline-flex h-9 w-full items-center justify-center rounded-md bg-primary px-4 py-2 text-sm font-medium text-primary-foreground shadow hover:bg-primary/90 focus-visible:outline-none focus-visible:ring-1 focus-visible:ring-ring disabled:pointer-events-none disabled:opacity-50 transition-colors",
73
+ children: loading ? "Signing in\u2026" : "Sign in"
74
+ }
75
+ )
76
+ ] })
77
+ ] }),
78
+ /* @__PURE__ */ jsxs("p", { className: "text-center text-xs text-muted-foreground", children: [
79
+ "Powered by",
80
+ " ",
81
+ /* @__PURE__ */ jsx(
82
+ "a",
83
+ {
84
+ href: "https://github.com/amide-init/next-lite-auth",
85
+ target: "_blank",
86
+ rel: "noopener noreferrer",
87
+ className: "underline underline-offset-4 hover:text-primary transition-colors",
88
+ children: "next-lite-auth"
89
+ }
90
+ )
91
+ ] })
92
+ ] }) });
93
+ }
94
+
95
+ // src/client/LiteAuthProvider.tsx
96
+ import { jsx as jsx2 } from "react/jsx-runtime";
97
+ var LiteAuthContext = createContext(null);
98
+ function LiteAuthProvider({
99
+ children,
100
+ protect = [],
101
+ loginPath = "/api/auth/login",
102
+ logoutPath = "/api/auth/logout",
103
+ mePath = "/api/auth/me"
104
+ }) {
105
+ const [user, setUser] = useState2(null);
106
+ const [loading, setLoading] = useState2(true);
107
+ const pathname = usePathname();
10
108
  useEffect(() => {
11
- fetch(mePath).then((r) => r.json()).then(({ user }) => setState({ user: user ?? null, loading: false })).catch(() => setState({ user: null, loading: false }));
109
+ fetch(mePath).then((r) => r.json()).then(({ user: user2 }) => setUser(user2 ?? null)).catch(() => setUser(null)).finally(() => setLoading(false));
12
110
  }, [mePath]);
13
111
  const login = useCallback(
14
112
  async ({ email, password }) => {
@@ -19,18 +117,35 @@ function useLiteAuth(options = {}) {
19
117
  });
20
118
  const data = await res.json();
21
119
  if (!res.ok) return { error: data.error ?? "Login failed" };
22
- setState({ user: data.user, loading: false });
120
+ setUser(data.user);
23
121
  return {};
24
122
  },
25
123
  [loginPath]
26
124
  );
27
125
  const logout = useCallback(async () => {
28
126
  await fetch(logoutPath, { method: "POST" });
29
- setState({ user: null, loading: false });
127
+ setUser(null);
30
128
  }, [logoutPath]);
31
- return { ...state, login, logout };
129
+ const value = { user, loading, login, logout };
130
+ const isProtected = protect.some(
131
+ (p) => pathname === p || pathname.startsWith(p + "/")
132
+ );
133
+ if (loading) {
134
+ return /* @__PURE__ */ jsx2(LiteAuthContext.Provider, { value, children });
135
+ }
136
+ if (!user && isProtected) {
137
+ return /* @__PURE__ */ jsx2(LiteAuthContext.Provider, { value, children: /* @__PURE__ */ jsx2(LiteLoginPage, {}) });
138
+ }
139
+ return /* @__PURE__ */ jsx2(LiteAuthContext.Provider, { value, children });
140
+ }
141
+ function useLiteAuth() {
142
+ const ctx = useContext(LiteAuthContext);
143
+ if (!ctx) throw new Error("useLiteAuth must be used inside <LiteAuthProvider>");
144
+ return ctx;
32
145
  }
33
146
  export {
147
+ LiteAuthProvider,
148
+ LiteLoginPage,
34
149
  useLiteAuth
35
150
  };
36
151
  //# sourceMappingURL=client.mjs.map
@@ -1 +1 @@
1
- {"version":3,"sources":["../src/client/useLiteAuth.ts"],"sourcesContent":["\"use client\";\n\nimport { useState, useEffect, useCallback } from \"react\";\nimport { PublicUser } from \"../core/types\";\n\ntype LiteAuthState = {\n user: PublicUser | null;\n loading: boolean;\n};\n\ntype LoginCredentials = {\n email: string;\n password: string;\n};\n\ntype UseLiteAuthReturn = LiteAuthState & {\n login: (credentials: LoginCredentials) => Promise<{ error?: string }>;\n logout: () => Promise<void>;\n};\n\ntype UseLiteAuthOptions = {\n loginPath?: string;\n logoutPath?: string;\n mePath?: string;\n};\n\nexport function useLiteAuth(options: UseLiteAuthOptions = {}): UseLiteAuthReturn {\n const {\n loginPath = \"/api/auth/login\",\n logoutPath = \"/api/auth/logout\",\n mePath = \"/api/auth/me\",\n } = options;\n\n const [state, setState] = useState<LiteAuthState>({ user: null, loading: true });\n\n useEffect(() => {\n fetch(mePath)\n .then((r) => r.json())\n .then(({ user }) => setState({ user: user ?? null, loading: false }))\n .catch(() => setState({ user: null, loading: false }));\n }, [mePath]);\n\n const login = useCallback(\n async ({ email, password }: LoginCredentials) => {\n const res = await fetch(loginPath, {\n method: \"POST\",\n headers: { \"Content-Type\": \"application/json\" },\n body: JSON.stringify({ email, password }),\n });\n const data = await res.json();\n if (!res.ok) return { error: data.error ?? \"Login failed\" };\n setState({ user: data.user, loading: false });\n return {};\n },\n [loginPath]\n );\n\n const logout = useCallback(async () => {\n await fetch(logoutPath, { method: \"POST\" });\n setState({ user: null, loading: false });\n }, [logoutPath]);\n\n return { ...state, login, logout };\n}\n"],"mappings":";AAEA,SAAS,UAAU,WAAW,mBAAmB;AAwB1C,SAAS,YAAY,UAA8B,CAAC,GAAsB;AAC/E,QAAM;AAAA,IACJ,YAAY;AAAA,IACZ,aAAa;AAAA,IACb,SAAS;AAAA,EACX,IAAI;AAEJ,QAAM,CAAC,OAAO,QAAQ,IAAI,SAAwB,EAAE,MAAM,MAAM,SAAS,KAAK,CAAC;AAE/E,YAAU,MAAM;AACd,UAAM,MAAM,EACT,KAAK,CAAC,MAAM,EAAE,KAAK,CAAC,EACpB,KAAK,CAAC,EAAE,KAAK,MAAM,SAAS,EAAE,MAAM,QAAQ,MAAM,SAAS,MAAM,CAAC,CAAC,EACnE,MAAM,MAAM,SAAS,EAAE,MAAM,MAAM,SAAS,MAAM,CAAC,CAAC;AAAA,EACzD,GAAG,CAAC,MAAM,CAAC;AAEX,QAAM,QAAQ;AAAA,IACZ,OAAO,EAAE,OAAO,SAAS,MAAwB;AAC/C,YAAM,MAAM,MAAM,MAAM,WAAW;AAAA,QACjC,QAAQ;AAAA,QACR,SAAS,EAAE,gBAAgB,mBAAmB;AAAA,QAC9C,MAAM,KAAK,UAAU,EAAE,OAAO,SAAS,CAAC;AAAA,MAC1C,CAAC;AACD,YAAM,OAAO,MAAM,IAAI,KAAK;AAC5B,UAAI,CAAC,IAAI,GAAI,QAAO,EAAE,OAAO,KAAK,SAAS,eAAe;AAC1D,eAAS,EAAE,MAAM,KAAK,MAAM,SAAS,MAAM,CAAC;AAC5C,aAAO,CAAC;AAAA,IACV;AAAA,IACA,CAAC,SAAS;AAAA,EACZ;AAEA,QAAM,SAAS,YAAY,YAAY;AACrC,UAAM,MAAM,YAAY,EAAE,QAAQ,OAAO,CAAC;AAC1C,aAAS,EAAE,MAAM,MAAM,SAAS,MAAM,CAAC;AAAA,EACzC,GAAG,CAAC,UAAU,CAAC;AAEf,SAAO,EAAE,GAAG,OAAO,OAAO,OAAO;AACnC;","names":[]}
1
+ {"version":3,"sources":["../src/client/LiteAuthProvider.tsx","../src/client/LiteLoginPage.tsx"],"sourcesContent":["\"use client\";\n\nimport { createContext, useContext, useState, useEffect, useCallback, ReactNode } from \"react\";\nimport { usePathname } from \"next/navigation\";\nimport { PublicUser } from \"../core/types\";\nimport { LiteLoginPage } from \"./LiteLoginPage\";\n\ntype LiteAuthContextValue = {\n user: PublicUser | null;\n loading: boolean;\n login: (creds: { email: string; password: string }) => Promise<{ error?: string }>;\n logout: () => Promise<void>;\n};\n\nconst LiteAuthContext = createContext<LiteAuthContextValue | null>(null);\n\ntype LiteAuthProviderProps = {\n children: ReactNode;\n protect?: string[];\n loginPath?: string;\n logoutPath?: string;\n mePath?: string;\n};\n\nexport function LiteAuthProvider({\n children,\n protect = [],\n loginPath = \"/api/auth/login\",\n logoutPath = \"/api/auth/logout\",\n mePath = \"/api/auth/me\",\n}: LiteAuthProviderProps) {\n const [user, setUser] = useState<PublicUser | null>(null);\n const [loading, setLoading] = useState(true);\n const pathname = usePathname();\n\n useEffect(() => {\n fetch(mePath)\n .then((r) => r.json())\n .then(({ user }) => setUser(user ?? null))\n .catch(() => setUser(null))\n .finally(() => setLoading(false));\n }, [mePath]);\n\n const login = useCallback(\n async ({ email, password }: { email: string; password: string }) => {\n const res = await fetch(loginPath, {\n method: \"POST\",\n headers: { \"Content-Type\": \"application/json\" },\n body: JSON.stringify({ email, password }),\n });\n const data = await res.json();\n if (!res.ok) return { error: data.error ?? \"Login failed\" };\n setUser(data.user);\n return {};\n },\n [loginPath]\n );\n\n const logout = useCallback(async () => {\n await fetch(logoutPath, { method: \"POST\" });\n setUser(null);\n }, [logoutPath]);\n\n const value = { user, loading, login, logout };\n\n const isProtected = protect.some(\n (p) => pathname === p || pathname.startsWith(p + \"/\")\n );\n\n if (loading) {\n return (\n <LiteAuthContext.Provider value={value}>\n {children}\n </LiteAuthContext.Provider>\n );\n }\n\n if (!user && isProtected) {\n return (\n <LiteAuthContext.Provider value={value}>\n <LiteLoginPage />\n </LiteAuthContext.Provider>\n );\n }\n\n return (\n <LiteAuthContext.Provider value={value}>\n {children}\n </LiteAuthContext.Provider>\n );\n}\n\nexport function useLiteAuth(): LiteAuthContextValue {\n const ctx = useContext(LiteAuthContext);\n if (!ctx) throw new Error(\"useLiteAuth must be used inside <LiteAuthProvider>\");\n return ctx;\n}\n","\"use client\";\n\nimport { FormEvent, useState } from \"react\";\nimport { useLiteAuth } from \"./LiteAuthProvider\";\n\ntype LiteLoginPageProps = {\n title?: string;\n description?: string;\n};\n\nexport function LiteLoginPage({\n title = \"Sign in\",\n description = \"Enter your credentials to continue\",\n}: LiteLoginPageProps) {\n const { login } = useLiteAuth();\n const [error, setError] = useState(\"\");\n const [loading, setLoading] = useState(false);\n\n async function handleSubmit(e: FormEvent<HTMLFormElement>) {\n e.preventDefault();\n setError(\"\");\n setLoading(true);\n\n const form = e.currentTarget;\n const result = await login({\n email: (form.elements.namedItem(\"email\") as HTMLInputElement).value,\n password: (form.elements.namedItem(\"password\") as HTMLInputElement).value,\n });\n\n setLoading(false);\n\n if (result.error) {\n setError(result.error);\n }\n // no redirect needed — login() sets user in context,\n // LiteAuthProvider re-renders children automatically\n }\n\n return (\n <div className=\"min-h-screen flex items-center justify-center bg-background px-4\">\n <div className=\"w-full max-w-sm space-y-6\">\n\n <div className=\"space-y-1 text-center\">\n <h1 className=\"text-2xl font-semibold tracking-tight\">{title}</h1>\n <p className=\"text-sm text-muted-foreground\">{description}</p>\n </div>\n\n <div className=\"rounded-xl border bg-card text-card-foreground shadow-sm p-6 space-y-4\">\n {error && (\n <div className=\"rounded-md bg-destructive/10 px-3 py-2 text-sm text-destructive\">\n {error}\n </div>\n )}\n\n <form onSubmit={handleSubmit} className=\"space-y-4\">\n <div className=\"space-y-1.5\">\n <label htmlFor=\"email\" className=\"text-sm font-medium leading-none\">\n Email\n </label>\n <input\n id=\"email\"\n name=\"email\"\n type=\"email\"\n required\n autoComplete=\"email\"\n placeholder=\"you@example.com\"\n className=\"flex h-9 w-full rounded-md border border-input bg-transparent px-3 py-1 text-sm shadow-sm transition-colors placeholder:text-muted-foreground focus-visible:outline-none focus-visible:ring-1 focus-visible:ring-ring disabled:cursor-not-allowed disabled:opacity-50\"\n />\n </div>\n\n <div className=\"space-y-1.5\">\n <label htmlFor=\"password\" className=\"text-sm font-medium leading-none\">\n Password\n </label>\n <input\n id=\"password\"\n name=\"password\"\n type=\"password\"\n required\n autoComplete=\"current-password\"\n placeholder=\"••••••••\"\n className=\"flex h-9 w-full rounded-md border border-input bg-transparent px-3 py-1 text-sm shadow-sm transition-colors placeholder:text-muted-foreground focus-visible:outline-none focus-visible:ring-1 focus-visible:ring-ring disabled:cursor-not-allowed disabled:opacity-50\"\n />\n </div>\n\n <button\n type=\"submit\"\n disabled={loading}\n className=\"inline-flex h-9 w-full items-center justify-center rounded-md bg-primary px-4 py-2 text-sm font-medium text-primary-foreground shadow hover:bg-primary/90 focus-visible:outline-none focus-visible:ring-1 focus-visible:ring-ring disabled:pointer-events-none disabled:opacity-50 transition-colors\"\n >\n {loading ? \"Signing in…\" : \"Sign in\"}\n </button>\n </form>\n </div>\n\n <p className=\"text-center text-xs text-muted-foreground\">\n Powered by{\" \"}\n <a\n href=\"https://github.com/amide-init/next-lite-auth\"\n target=\"_blank\"\n rel=\"noopener noreferrer\"\n className=\"underline underline-offset-4 hover:text-primary transition-colors\"\n >\n next-lite-auth\n </a>\n </p>\n\n </div>\n </div>\n );\n}\n"],"mappings":"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","names":["useState","jsx","useState","user"]}
package/dist/index.d.mts CHANGED
@@ -16,9 +16,8 @@ type LiteAuthConfig = {
16
16
 
17
17
  declare function createLiteAuth(config: LiteAuthConfig): {
18
18
  handlers: {
19
- login: (req: next_server.NextRequest) => Promise<next_server.NextResponse>;
20
- logout: (_req: next_server.NextRequest) => Promise<next_server.NextResponse>;
21
- me: (req: next_server.NextRequest) => Promise<next_server.NextResponse>;
19
+ GET: (req: next_server.NextRequest) => Promise<next_server.NextResponse>;
20
+ POST: (req: next_server.NextRequest) => Promise<next_server.NextResponse>;
22
21
  };
23
22
  middleware: (options: {
24
23
  protect: string[];
package/dist/index.d.ts CHANGED
@@ -16,9 +16,8 @@ type LiteAuthConfig = {
16
16
 
17
17
  declare function createLiteAuth(config: LiteAuthConfig): {
18
18
  handlers: {
19
- login: (req: next_server.NextRequest) => Promise<next_server.NextResponse>;
20
- logout: (_req: next_server.NextRequest) => Promise<next_server.NextResponse>;
21
- me: (req: next_server.NextRequest) => Promise<next_server.NextResponse>;
19
+ GET: (req: next_server.NextRequest) => Promise<next_server.NextResponse>;
20
+ POST: (req: next_server.NextRequest) => Promise<next_server.NextResponse>;
22
21
  };
23
22
  middleware: (options: {
24
23
  protect: string[];
package/dist/index.js CHANGED
@@ -45,8 +45,8 @@ async function verifyToken(token, secret) {
45
45
  }
46
46
 
47
47
  // src/server/handlers.ts
48
- function makeLoginHandler(ctx) {
49
- return async function loginHandler(req) {
48
+ function makeHandlers(ctx) {
49
+ async function login(req) {
50
50
  let body;
51
51
  try {
52
52
  body = await req.json();
@@ -70,34 +70,33 @@ function makeLoginHandler(ctx) {
70
70
  sameSite: "lax",
71
71
  secure: process.env.NODE_ENV === "production",
72
72
  maxAge: 60 * 60 * 24 * 7
73
- // 7 days
74
73
  });
75
74
  return res;
76
- };
77
- }
78
- function makeLogoutHandler(ctx) {
79
- return async function logoutHandler(_req) {
75
+ }
76
+ async function logout(_req) {
80
77
  const res = import_server.NextResponse.json({ ok: true });
81
- res.cookies.set(ctx.cookieName, "", {
82
- httpOnly: true,
83
- path: "/",
84
- maxAge: 0
85
- });
78
+ res.cookies.set(ctx.cookieName, "", { httpOnly: true, path: "/", maxAge: 0 });
86
79
  return res;
87
- };
88
- }
89
- function makeMeHandler(ctx) {
90
- return async function meHandler(req) {
80
+ }
81
+ async function me(req) {
91
82
  const token = req.cookies.get(ctx.cookieName)?.value;
92
- if (!token) {
93
- return import_server.NextResponse.json({ user: null }, { status: 401 });
94
- }
83
+ if (!token) return import_server.NextResponse.json({ user: null }, { status: 401 });
95
84
  const user = await verifyToken(token, ctx.jwtSecret);
96
- if (!user) {
97
- return import_server.NextResponse.json({ user: null }, { status: 401 });
98
- }
85
+ if (!user) return import_server.NextResponse.json({ user: null }, { status: 401 });
99
86
  return import_server.NextResponse.json({ user });
100
- };
87
+ }
88
+ async function GET(req) {
89
+ const action = req.nextUrl.pathname.split("/").pop();
90
+ if (action === "me") return me(req);
91
+ return import_server.NextResponse.json({ error: "Not found" }, { status: 404 });
92
+ }
93
+ async function POST(req) {
94
+ const action = req.nextUrl.pathname.split("/").pop();
95
+ if (action === "login") return login(req);
96
+ if (action === "logout") return logout(req);
97
+ return import_server.NextResponse.json({ error: "Not found" }, { status: 404 });
98
+ }
99
+ return { GET, POST };
101
100
  }
102
101
 
103
102
  // src/server/getUserFromCookies.ts
@@ -142,11 +141,7 @@ function createLiteAuth(config) {
142
141
  cookieName: config.cookieName ?? "lite-auth-token"
143
142
  };
144
143
  return {
145
- handlers: {
146
- login: makeLoginHandler(ctx),
147
- logout: makeLogoutHandler(ctx),
148
- me: makeMeHandler(ctx)
149
- },
144
+ handlers: makeHandlers(ctx),
150
145
  middleware: makeMiddleware(ctx),
151
146
  getUserFromCookies: getUserFromCookies(ctx)
152
147
  };
package/dist/index.js.map CHANGED
@@ -1 +1 @@
1
- {"version":3,"sources":["../src/index.ts","../src/server/handlers.ts","../src/server/jwt.ts","../src/server/getUserFromCookies.ts","../src/middleware/index.ts","../src/core/createLiteAuth.ts"],"sourcesContent":["export { createLiteAuth } from \"./core/createLiteAuth\";\nexport type { User, PublicUser, LiteAuthConfig } from \"./core/types\";\n","import { NextRequest, NextResponse } from \"next/server\";\nimport { LiteAuthContext } from \"../core/types\";\nimport { signToken, verifyToken } from \"./jwt\";\n\nexport function makeLoginHandler(ctx: LiteAuthContext) {\n return async function loginHandler(req: NextRequest): Promise<NextResponse> {\n let body: { email?: string; password?: string };\n try {\n body = await req.json();\n } catch {\n return NextResponse.json({ error: \"Invalid JSON\" }, { status: 400 });\n }\n\n const { email, password } = body;\n if (!email || !password) {\n return NextResponse.json({ error: \"Email and password are required\" }, { status: 400 });\n }\n\n const user = ctx.users.find((u) => u.email === email && u.password === password);\n if (!user) {\n return NextResponse.json({ error: \"Invalid credentials\" }, { status: 401 });\n }\n\n const { password: _, ...publicUser } = user;\n const token = await signToken(publicUser, ctx.jwtSecret);\n\n const res = NextResponse.json({ user: publicUser });\n res.cookies.set(ctx.cookieName, token, {\n httpOnly: true,\n path: \"/\",\n sameSite: \"lax\",\n secure: process.env.NODE_ENV === \"production\",\n maxAge: 60 * 60 * 24 * 7, // 7 days\n });\n return res;\n };\n}\n\nexport function makeLogoutHandler(ctx: LiteAuthContext) {\n return async function logoutHandler(_req: NextRequest): Promise<NextResponse> {\n const res = NextResponse.json({ ok: true });\n res.cookies.set(ctx.cookieName, \"\", {\n httpOnly: true,\n path: \"/\",\n maxAge: 0,\n });\n return res;\n };\n}\n\nexport function makeMeHandler(ctx: LiteAuthContext) {\n return async function meHandler(req: NextRequest): Promise<NextResponse> {\n const token = req.cookies.get(ctx.cookieName)?.value;\n if (!token) {\n return NextResponse.json({ user: null }, { status: 401 });\n }\n\n const user = await verifyToken(token, ctx.jwtSecret);\n if (!user) {\n return NextResponse.json({ user: null }, { status: 401 });\n }\n\n return NextResponse.json({ user });\n };\n}\n","import { SignJWT, jwtVerify } from \"jose\";\nimport { PublicUser } from \"../core/types\";\n\nfunction getSecret(secret: string) {\n return new TextEncoder().encode(secret);\n}\n\nexport async function signToken(user: PublicUser, secret: string): Promise<string> {\n return new SignJWT({ ...user })\n .setProtectedHeader({ alg: \"HS256\" })\n .setIssuedAt()\n .setExpirationTime(\"7d\")\n .sign(getSecret(secret));\n}\n\nexport async function verifyToken(token: string, secret: string): Promise<PublicUser | null> {\n try {\n const { payload } = await jwtVerify(token, getSecret(secret));\n return payload as unknown as PublicUser;\n } catch {\n return null;\n }\n}\n","import { ReadonlyRequestCookies } from \"next/dist/server/web/spec-extension/adapters/request-cookies\";\nimport { LiteAuthContext, PublicUser } from \"../core/types\";\nimport { verifyToken } from \"./jwt\";\n\nexport function getUserFromCookies(ctx: LiteAuthContext) {\n return async function (cookies: ReadonlyRequestCookies): Promise<PublicUser | null> {\n const token = cookies.get(ctx.cookieName)?.value;\n if (!token) return null;\n return verifyToken(token, ctx.jwtSecret);\n };\n}\n","import { NextRequest, NextResponse } from \"next/server\";\nimport { LiteAuthContext } from \"../core/types\";\nimport { verifyToken } from \"../server/jwt\";\n\ntype MiddlewareOptions = {\n protect: string[];\n redirectTo?: string;\n};\n\nexport function makeMiddleware(ctx: LiteAuthContext) {\n return function middleware(options: MiddlewareOptions) {\n return async function (req: NextRequest): Promise<NextResponse> {\n const { protect, redirectTo = \"/login\" } = options;\n const { pathname } = req.nextUrl;\n\n const isProtected = protect.some(\n (pattern) => pathname === pattern || pathname.startsWith(pattern + \"/\")\n );\n\n if (!isProtected) {\n return NextResponse.next();\n }\n\n const token = req.cookies.get(ctx.cookieName)?.value;\n if (token) {\n const user = await verifyToken(token, ctx.jwtSecret);\n if (user) return NextResponse.next();\n }\n\n const loginUrl = new URL(redirectTo, req.url);\n loginUrl.searchParams.set(\"from\", pathname);\n return NextResponse.redirect(loginUrl);\n };\n };\n}\n","import { LiteAuthConfig, LiteAuthContext } from \"./types\";\nimport { makeLoginHandler, makeLogoutHandler, makeMeHandler, getUserFromCookies } from \"../server\";\nimport { makeMiddleware } from \"../middleware\";\n\nexport function createLiteAuth(config: LiteAuthConfig) {\n const ctx: LiteAuthContext = {\n users: config.users,\n jwtSecret: config.jwtSecret,\n cookieName: config.cookieName ?? \"lite-auth-token\",\n };\n\n return {\n handlers: {\n login: makeLoginHandler(ctx),\n logout: makeLogoutHandler(ctx),\n me: makeMeHandler(ctx),\n },\n middleware: makeMiddleware(ctx),\n getUserFromCookies: getUserFromCookies(ctx),\n };\n}\n"],"mappings":"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","names":["import_server"]}
1
+ {"version":3,"sources":["../src/index.ts","../src/server/handlers.ts","../src/server/jwt.ts","../src/server/getUserFromCookies.ts","../src/middleware/index.ts","../src/core/createLiteAuth.ts"],"sourcesContent":["export { createLiteAuth } from \"./core/createLiteAuth\";\nexport type { User, PublicUser, LiteAuthConfig } from \"./core/types\";\n","import { NextRequest, NextResponse } from \"next/server\";\nimport { LiteAuthContext } from \"../core/types\";\nimport { signToken, verifyToken } from \"./jwt\";\n\nexport function makeHandlers(ctx: LiteAuthContext) {\n async function login(req: NextRequest): Promise<NextResponse> {\n let body: { email?: string; password?: string };\n try {\n body = await req.json();\n } catch {\n return NextResponse.json({ error: \"Invalid JSON\" }, { status: 400 });\n }\n\n const { email, password } = body;\n if (!email || !password) {\n return NextResponse.json({ error: \"Email and password are required\" }, { status: 400 });\n }\n\n const user = ctx.users.find((u) => u.email === email && u.password === password);\n if (!user) {\n return NextResponse.json({ error: \"Invalid credentials\" }, { status: 401 });\n }\n\n const { password: _, ...publicUser } = user;\n const token = await signToken(publicUser, ctx.jwtSecret);\n\n const res = NextResponse.json({ user: publicUser });\n res.cookies.set(ctx.cookieName, token, {\n httpOnly: true,\n path: \"/\",\n sameSite: \"lax\",\n secure: process.env.NODE_ENV === \"production\",\n maxAge: 60 * 60 * 24 * 7,\n });\n return res;\n }\n\n async function logout(_req: NextRequest): Promise<NextResponse> {\n const res = NextResponse.json({ ok: true });\n res.cookies.set(ctx.cookieName, \"\", { httpOnly: true, path: \"/\", maxAge: 0 });\n return res;\n }\n\n async function me(req: NextRequest): Promise<NextResponse> {\n const token = req.cookies.get(ctx.cookieName)?.value;\n if (!token) return NextResponse.json({ user: null }, { status: 401 });\n const user = await verifyToken(token, ctx.jwtSecret);\n if (!user) return NextResponse.json({ user: null }, { status: 401 });\n return NextResponse.json({ user });\n }\n\n async function GET(req: NextRequest): Promise<NextResponse> {\n const action = req.nextUrl.pathname.split(\"/\").pop();\n if (action === \"me\") return me(req);\n return NextResponse.json({ error: \"Not found\" }, { status: 404 });\n }\n\n async function POST(req: NextRequest): Promise<NextResponse> {\n const action = req.nextUrl.pathname.split(\"/\").pop();\n if (action === \"login\") return login(req);\n if (action === \"logout\") return logout(req);\n return NextResponse.json({ error: \"Not found\" }, { status: 404 });\n }\n\n return { GET, POST };\n}\n","import { SignJWT, jwtVerify } from \"jose\";\nimport { PublicUser } from \"../core/types\";\n\nfunction getSecret(secret: string) {\n return new TextEncoder().encode(secret);\n}\n\nexport async function signToken(user: PublicUser, secret: string): Promise<string> {\n return new SignJWT({ ...user })\n .setProtectedHeader({ alg: \"HS256\" })\n .setIssuedAt()\n .setExpirationTime(\"7d\")\n .sign(getSecret(secret));\n}\n\nexport async function verifyToken(token: string, secret: string): Promise<PublicUser | null> {\n try {\n const { payload } = await jwtVerify(token, getSecret(secret));\n return payload as unknown as PublicUser;\n } catch {\n return null;\n }\n}\n","import { ReadonlyRequestCookies } from \"next/dist/server/web/spec-extension/adapters/request-cookies\";\nimport { LiteAuthContext, PublicUser } from \"../core/types\";\nimport { verifyToken } from \"./jwt\";\n\nexport function getUserFromCookies(ctx: LiteAuthContext) {\n return async function (cookies: ReadonlyRequestCookies): Promise<PublicUser | null> {\n const token = cookies.get(ctx.cookieName)?.value;\n if (!token) return null;\n return verifyToken(token, ctx.jwtSecret);\n };\n}\n","import { NextRequest, NextResponse } from \"next/server\";\nimport { LiteAuthContext } from \"../core/types\";\nimport { verifyToken } from \"../server/jwt\";\n\ntype MiddlewareOptions = {\n protect: string[];\n redirectTo?: string;\n};\n\nexport function makeMiddleware(ctx: LiteAuthContext) {\n return function middleware(options: MiddlewareOptions) {\n return async function (req: NextRequest): Promise<NextResponse> {\n const { protect, redirectTo = \"/login\" } = options;\n const { pathname } = req.nextUrl;\n\n const isProtected = protect.some(\n (pattern) => pathname === pattern || pathname.startsWith(pattern + \"/\")\n );\n\n if (!isProtected) {\n return NextResponse.next();\n }\n\n const token = req.cookies.get(ctx.cookieName)?.value;\n if (token) {\n const user = await verifyToken(token, ctx.jwtSecret);\n if (user) return NextResponse.next();\n }\n\n const loginUrl = new URL(redirectTo, req.url);\n loginUrl.searchParams.set(\"from\", pathname);\n return NextResponse.redirect(loginUrl);\n };\n };\n}\n","import { LiteAuthConfig, LiteAuthContext } from \"./types\";\nimport { makeHandlers, getUserFromCookies } from \"../server\";\nimport { makeMiddleware } from \"../middleware\";\n\nexport function createLiteAuth(config: LiteAuthConfig) {\n const ctx: LiteAuthContext = {\n users: config.users,\n jwtSecret: config.jwtSecret,\n cookieName: config.cookieName ?? \"lite-auth-token\",\n };\n\n return {\n handlers: makeHandlers(ctx),\n middleware: makeMiddleware(ctx),\n getUserFromCookies: getUserFromCookies(ctx),\n };\n}\n"],"mappings":"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","names":["import_server"]}
package/dist/index.mjs CHANGED
@@ -19,8 +19,8 @@ async function verifyToken(token, secret) {
19
19
  }
20
20
 
21
21
  // src/server/handlers.ts
22
- function makeLoginHandler(ctx) {
23
- return async function loginHandler(req) {
22
+ function makeHandlers(ctx) {
23
+ async function login(req) {
24
24
  let body;
25
25
  try {
26
26
  body = await req.json();
@@ -44,34 +44,33 @@ function makeLoginHandler(ctx) {
44
44
  sameSite: "lax",
45
45
  secure: process.env.NODE_ENV === "production",
46
46
  maxAge: 60 * 60 * 24 * 7
47
- // 7 days
48
47
  });
49
48
  return res;
50
- };
51
- }
52
- function makeLogoutHandler(ctx) {
53
- return async function logoutHandler(_req) {
49
+ }
50
+ async function logout(_req) {
54
51
  const res = NextResponse.json({ ok: true });
55
- res.cookies.set(ctx.cookieName, "", {
56
- httpOnly: true,
57
- path: "/",
58
- maxAge: 0
59
- });
52
+ res.cookies.set(ctx.cookieName, "", { httpOnly: true, path: "/", maxAge: 0 });
60
53
  return res;
61
- };
62
- }
63
- function makeMeHandler(ctx) {
64
- return async function meHandler(req) {
54
+ }
55
+ async function me(req) {
65
56
  const token = req.cookies.get(ctx.cookieName)?.value;
66
- if (!token) {
67
- return NextResponse.json({ user: null }, { status: 401 });
68
- }
57
+ if (!token) return NextResponse.json({ user: null }, { status: 401 });
69
58
  const user = await verifyToken(token, ctx.jwtSecret);
70
- if (!user) {
71
- return NextResponse.json({ user: null }, { status: 401 });
72
- }
59
+ if (!user) return NextResponse.json({ user: null }, { status: 401 });
73
60
  return NextResponse.json({ user });
74
- };
61
+ }
62
+ async function GET(req) {
63
+ const action = req.nextUrl.pathname.split("/").pop();
64
+ if (action === "me") return me(req);
65
+ return NextResponse.json({ error: "Not found" }, { status: 404 });
66
+ }
67
+ async function POST(req) {
68
+ const action = req.nextUrl.pathname.split("/").pop();
69
+ if (action === "login") return login(req);
70
+ if (action === "logout") return logout(req);
71
+ return NextResponse.json({ error: "Not found" }, { status: 404 });
72
+ }
73
+ return { GET, POST };
75
74
  }
76
75
 
77
76
  // src/server/getUserFromCookies.ts
@@ -116,11 +115,7 @@ function createLiteAuth(config) {
116
115
  cookieName: config.cookieName ?? "lite-auth-token"
117
116
  };
118
117
  return {
119
- handlers: {
120
- login: makeLoginHandler(ctx),
121
- logout: makeLogoutHandler(ctx),
122
- me: makeMeHandler(ctx)
123
- },
118
+ handlers: makeHandlers(ctx),
124
119
  middleware: makeMiddleware(ctx),
125
120
  getUserFromCookies: getUserFromCookies(ctx)
126
121
  };
@@ -1 +1 @@
1
- {"version":3,"sources":["../src/server/handlers.ts","../src/server/jwt.ts","../src/server/getUserFromCookies.ts","../src/middleware/index.ts","../src/core/createLiteAuth.ts"],"sourcesContent":["import { NextRequest, NextResponse } from \"next/server\";\nimport { LiteAuthContext } from \"../core/types\";\nimport { signToken, verifyToken } from \"./jwt\";\n\nexport function makeLoginHandler(ctx: LiteAuthContext) {\n return async function loginHandler(req: NextRequest): Promise<NextResponse> {\n let body: { email?: string; password?: string };\n try {\n body = await req.json();\n } catch {\n return NextResponse.json({ error: \"Invalid JSON\" }, { status: 400 });\n }\n\n const { email, password } = body;\n if (!email || !password) {\n return NextResponse.json({ error: \"Email and password are required\" }, { status: 400 });\n }\n\n const user = ctx.users.find((u) => u.email === email && u.password === password);\n if (!user) {\n return NextResponse.json({ error: \"Invalid credentials\" }, { status: 401 });\n }\n\n const { password: _, ...publicUser } = user;\n const token = await signToken(publicUser, ctx.jwtSecret);\n\n const res = NextResponse.json({ user: publicUser });\n res.cookies.set(ctx.cookieName, token, {\n httpOnly: true,\n path: \"/\",\n sameSite: \"lax\",\n secure: process.env.NODE_ENV === \"production\",\n maxAge: 60 * 60 * 24 * 7, // 7 days\n });\n return res;\n };\n}\n\nexport function makeLogoutHandler(ctx: LiteAuthContext) {\n return async function logoutHandler(_req: NextRequest): Promise<NextResponse> {\n const res = NextResponse.json({ ok: true });\n res.cookies.set(ctx.cookieName, \"\", {\n httpOnly: true,\n path: \"/\",\n maxAge: 0,\n });\n return res;\n };\n}\n\nexport function makeMeHandler(ctx: LiteAuthContext) {\n return async function meHandler(req: NextRequest): Promise<NextResponse> {\n const token = req.cookies.get(ctx.cookieName)?.value;\n if (!token) {\n return NextResponse.json({ user: null }, { status: 401 });\n }\n\n const user = await verifyToken(token, ctx.jwtSecret);\n if (!user) {\n return NextResponse.json({ user: null }, { status: 401 });\n }\n\n return NextResponse.json({ user });\n };\n}\n","import { SignJWT, jwtVerify } from \"jose\";\nimport { PublicUser } from \"../core/types\";\n\nfunction getSecret(secret: string) {\n return new TextEncoder().encode(secret);\n}\n\nexport async function signToken(user: PublicUser, secret: string): Promise<string> {\n return new SignJWT({ ...user })\n .setProtectedHeader({ alg: \"HS256\" })\n .setIssuedAt()\n .setExpirationTime(\"7d\")\n .sign(getSecret(secret));\n}\n\nexport async function verifyToken(token: string, secret: string): Promise<PublicUser | null> {\n try {\n const { payload } = await jwtVerify(token, getSecret(secret));\n return payload as unknown as PublicUser;\n } catch {\n return null;\n }\n}\n","import { ReadonlyRequestCookies } from \"next/dist/server/web/spec-extension/adapters/request-cookies\";\nimport { LiteAuthContext, PublicUser } from \"../core/types\";\nimport { verifyToken } from \"./jwt\";\n\nexport function getUserFromCookies(ctx: LiteAuthContext) {\n return async function (cookies: ReadonlyRequestCookies): Promise<PublicUser | null> {\n const token = cookies.get(ctx.cookieName)?.value;\n if (!token) return null;\n return verifyToken(token, ctx.jwtSecret);\n };\n}\n","import { NextRequest, NextResponse } from \"next/server\";\nimport { LiteAuthContext } from \"../core/types\";\nimport { verifyToken } from \"../server/jwt\";\n\ntype MiddlewareOptions = {\n protect: string[];\n redirectTo?: string;\n};\n\nexport function makeMiddleware(ctx: LiteAuthContext) {\n return function middleware(options: MiddlewareOptions) {\n return async function (req: NextRequest): Promise<NextResponse> {\n const { protect, redirectTo = \"/login\" } = options;\n const { pathname } = req.nextUrl;\n\n const isProtected = protect.some(\n (pattern) => pathname === pattern || pathname.startsWith(pattern + \"/\")\n );\n\n if (!isProtected) {\n return NextResponse.next();\n }\n\n const token = req.cookies.get(ctx.cookieName)?.value;\n if (token) {\n const user = await verifyToken(token, ctx.jwtSecret);\n if (user) return NextResponse.next();\n }\n\n const loginUrl = new URL(redirectTo, req.url);\n loginUrl.searchParams.set(\"from\", pathname);\n return NextResponse.redirect(loginUrl);\n };\n };\n}\n","import { LiteAuthConfig, LiteAuthContext } from \"./types\";\nimport { makeLoginHandler, makeLogoutHandler, makeMeHandler, getUserFromCookies } from \"../server\";\nimport { makeMiddleware } from \"../middleware\";\n\nexport function createLiteAuth(config: LiteAuthConfig) {\n const ctx: LiteAuthContext = {\n users: config.users,\n jwtSecret: config.jwtSecret,\n cookieName: config.cookieName ?? \"lite-auth-token\",\n };\n\n return {\n handlers: {\n login: makeLoginHandler(ctx),\n logout: makeLogoutHandler(ctx),\n me: makeMeHandler(ctx),\n },\n middleware: makeMiddleware(ctx),\n getUserFromCookies: getUserFromCookies(ctx),\n };\n}\n"],"mappings":"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","names":["NextResponse","NextResponse"]}
1
+ {"version":3,"sources":["../src/server/handlers.ts","../src/server/jwt.ts","../src/server/getUserFromCookies.ts","../src/middleware/index.ts","../src/core/createLiteAuth.ts"],"sourcesContent":["import { NextRequest, NextResponse } from \"next/server\";\nimport { LiteAuthContext } from \"../core/types\";\nimport { signToken, verifyToken } from \"./jwt\";\n\nexport function makeHandlers(ctx: LiteAuthContext) {\n async function login(req: NextRequest): Promise<NextResponse> {\n let body: { email?: string; password?: string };\n try {\n body = await req.json();\n } catch {\n return NextResponse.json({ error: \"Invalid JSON\" }, { status: 400 });\n }\n\n const { email, password } = body;\n if (!email || !password) {\n return NextResponse.json({ error: \"Email and password are required\" }, { status: 400 });\n }\n\n const user = ctx.users.find((u) => u.email === email && u.password === password);\n if (!user) {\n return NextResponse.json({ error: \"Invalid credentials\" }, { status: 401 });\n }\n\n const { password: _, ...publicUser } = user;\n const token = await signToken(publicUser, ctx.jwtSecret);\n\n const res = NextResponse.json({ user: publicUser });\n res.cookies.set(ctx.cookieName, token, {\n httpOnly: true,\n path: \"/\",\n sameSite: \"lax\",\n secure: process.env.NODE_ENV === \"production\",\n maxAge: 60 * 60 * 24 * 7,\n });\n return res;\n }\n\n async function logout(_req: NextRequest): Promise<NextResponse> {\n const res = NextResponse.json({ ok: true });\n res.cookies.set(ctx.cookieName, \"\", { httpOnly: true, path: \"/\", maxAge: 0 });\n return res;\n }\n\n async function me(req: NextRequest): Promise<NextResponse> {\n const token = req.cookies.get(ctx.cookieName)?.value;\n if (!token) return NextResponse.json({ user: null }, { status: 401 });\n const user = await verifyToken(token, ctx.jwtSecret);\n if (!user) return NextResponse.json({ user: null }, { status: 401 });\n return NextResponse.json({ user });\n }\n\n async function GET(req: NextRequest): Promise<NextResponse> {\n const action = req.nextUrl.pathname.split(\"/\").pop();\n if (action === \"me\") return me(req);\n return NextResponse.json({ error: \"Not found\" }, { status: 404 });\n }\n\n async function POST(req: NextRequest): Promise<NextResponse> {\n const action = req.nextUrl.pathname.split(\"/\").pop();\n if (action === \"login\") return login(req);\n if (action === \"logout\") return logout(req);\n return NextResponse.json({ error: \"Not found\" }, { status: 404 });\n }\n\n return { GET, POST };\n}\n","import { SignJWT, jwtVerify } from \"jose\";\nimport { PublicUser } from \"../core/types\";\n\nfunction getSecret(secret: string) {\n return new TextEncoder().encode(secret);\n}\n\nexport async function signToken(user: PublicUser, secret: string): Promise<string> {\n return new SignJWT({ ...user })\n .setProtectedHeader({ alg: \"HS256\" })\n .setIssuedAt()\n .setExpirationTime(\"7d\")\n .sign(getSecret(secret));\n}\n\nexport async function verifyToken(token: string, secret: string): Promise<PublicUser | null> {\n try {\n const { payload } = await jwtVerify(token, getSecret(secret));\n return payload as unknown as PublicUser;\n } catch {\n return null;\n }\n}\n","import { ReadonlyRequestCookies } from \"next/dist/server/web/spec-extension/adapters/request-cookies\";\nimport { LiteAuthContext, PublicUser } from \"../core/types\";\nimport { verifyToken } from \"./jwt\";\n\nexport function getUserFromCookies(ctx: LiteAuthContext) {\n return async function (cookies: ReadonlyRequestCookies): Promise<PublicUser | null> {\n const token = cookies.get(ctx.cookieName)?.value;\n if (!token) return null;\n return verifyToken(token, ctx.jwtSecret);\n };\n}\n","import { NextRequest, NextResponse } from \"next/server\";\nimport { LiteAuthContext } from \"../core/types\";\nimport { verifyToken } from \"../server/jwt\";\n\ntype MiddlewareOptions = {\n protect: string[];\n redirectTo?: string;\n};\n\nexport function makeMiddleware(ctx: LiteAuthContext) {\n return function middleware(options: MiddlewareOptions) {\n return async function (req: NextRequest): Promise<NextResponse> {\n const { protect, redirectTo = \"/login\" } = options;\n const { pathname } = req.nextUrl;\n\n const isProtected = protect.some(\n (pattern) => pathname === pattern || pathname.startsWith(pattern + \"/\")\n );\n\n if (!isProtected) {\n return NextResponse.next();\n }\n\n const token = req.cookies.get(ctx.cookieName)?.value;\n if (token) {\n const user = await verifyToken(token, ctx.jwtSecret);\n if (user) return NextResponse.next();\n }\n\n const loginUrl = new URL(redirectTo, req.url);\n loginUrl.searchParams.set(\"from\", pathname);\n return NextResponse.redirect(loginUrl);\n };\n };\n}\n","import { LiteAuthConfig, LiteAuthContext } from \"./types\";\nimport { makeHandlers, getUserFromCookies } from \"../server\";\nimport { makeMiddleware } from \"../middleware\";\n\nexport function createLiteAuth(config: LiteAuthConfig) {\n const ctx: LiteAuthContext = {\n users: config.users,\n jwtSecret: config.jwtSecret,\n cookieName: config.cookieName ?? \"lite-auth-token\",\n };\n\n return {\n handlers: makeHandlers(ctx),\n middleware: makeMiddleware(ctx),\n getUserFromCookies: getUserFromCookies(ctx),\n };\n}\n"],"mappings":"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","names":["NextResponse","NextResponse"]}
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "next-lite-auth",
3
- "version": "0.1.0",
3
+ "version": "0.1.2",
4
4
  "description": "Lightweight JWT auth for Next.js using static JSON users (no database)",
5
5
  "main": "./dist/index.js",
6
6
  "module": "./dist/index.mjs",
@@ -29,7 +29,13 @@
29
29
  },
30
30
  "peerDependencies": {
31
31
  "next": ">=13.0.0",
32
- "react": ">=18.0.0"
32
+ "react": ">=18.0.0",
33
+ "tailwindcss": ">=3.0.0"
34
+ },
35
+ "peerDependenciesMeta": {
36
+ "tailwindcss": {
37
+ "optional": true
38
+ }
33
39
  },
34
40
  "dependencies": {
35
41
  "jose": "^5.0.0"